Archive of articles classified as' "Tech Artists"

Back home

What do you want next?

24/02/2015

We are focusing on A and B, and in a month or so we’ll start focusing on C, while also keeping focus on A and B.

Sound familiar?

When we do prioritization at work, I insist we have a single column of priorities or coarse features. In other words, “what do you want delivered next?”*

If a team or person isn’t working on one of the top two or three priorities, they’re doing unimportant, and possibly counter-productive, work. You’d be amazed how many people are working on things someone arbitrarily said was important, which aren’t inline with actual priorities.

You’d be even more amazed how unimportant most “high priority” work is when it needs to be stacked along with everything else. A feature can easily sit at the number 4 spot for months. Just be careful work doesn’t move up the queue just because it’s been in the queue. I don’t think this is a problem, though, because when you tell a product person “we are only executing on the next 2 things to deliver” they are going to have to make hard decisions.

I’ve worked on projects from 10 to 500 people, and generally the times we were humming along was when we had one or two priorities. We ended up producing crap when we had n priorities (where n is often the number of people or teams). Big teams don’t mean more priorities. It is just the granularity of the priorities that changes.

This sort of rigid, columnar prioritization communicates to product people that work only gets done when it’s at the top of the column. I’ve run across countless people, both managers and developers, who just sort of, well, expect that stuff just sort of, well, gets done, somehow. And generally it appears as if things are getting done, until everyone finds out they weren’t really. Are there significant bugs in some old system? It’s not fixed until it’s a priority. Is that new system still unpolished? It’s not improved until it’s a priority. Want to build something that requires some serious infrastructure? Well, that infrastructure stays at the top of the column until it’s done, to the exclusion of other work. Do you want good tools? Well, it means you aren’t going to get features.

It’s an extremely simple and powerful technique, and I highly recommend it if you are having trouble coordinating a product group.


* This doesn’t include ongoing product support, small fixes, and improvements. I think you need a way to handle this outside of normal feature development teams, with some sort of “live support” that can react quickly. A topic for another post.

No Comments

Automated testing shows a respect for employees

1/02/2015

In the tech-artists.org G+ community page there was a comment on a thread about unit testing:

A key factor in TA tools is the speed at which we need to deliver them, and our audience is considerably smaller than, say, engine tools code. Therefor it becomes somewhat hard to justify the time spent on writing the unit tests, and then maintaining them as the tools change or are ported or updated to match new APIs.

In other words: Testing is great, but we don’t have time for it. Or the common alternative: Testing is great, but it’s not feasible to test what we’re doing.

Codebases without tests manifest themselves in teams that are stressed and overworked due to an ever-increasing workload and firefighting. Velocity goes down over time. Meanwhile, I’ve never known a team with thorough test coverage that delivered slower than a team without automated tests. In fact I’ve observed teams that had no tests and crunched constantly, added tests and became predictable and successful, then removed the tests after idiotic leadership decisions to artificially increase velocity, and watched their velocity drop way down once the testing infrastructure, and especially culture, fell into disrepair.

Companies that do not require automated tests do not respect their employees, and do not care about the long-term health of the company. It’s that simple (or they are incompetent, which is equally likely). We know that no testing results in stress, overwork, and reduced quality. We know that more testing results in more predictability, higher quality, and happier teams. I would love to blame management, but I see this nonchalant attitude about testing just as often among developers.

The “do it fast without tests, or do it slow with tests” attitude is not just wrong, but poisonous. You are going to be the one dealing with your technical debt. You are the bottleneck on call because your stuff breaks. You are the one who doesn’t get to work on new stuff because you spend all your time maintaining your old crap. You are the one who is crunching to tread water on velocity.

I have a simple rule: I will not work at a job that doesn’t have automated testing (or would be in any way inhibited instituting it as the first order of business).

  • I have this rule because I love myself and my family. There are enough unavoidable opportunities to interrupt evenings and weekends for work reasons. It is irresponsible to add more ways for things to break.
  • I have this rule because I care for the people I work with. I want them to have the same option for work-life balance, and work with me for a long time.
  • I have this rule because I want the company I’ve decided to invest in (employment is the most profound investment!) to be successful in the long term. Not until the end of the quarter, or even until I leave, but for a long, long time.
4 Comments

Building Sphinx documentation for unfriendly code

11/01/2015

Some Twitter friends were discussing how to get Sphinx to work with mayapy to build documentation for code that runs in Autodesk Maya. I’ve had to do this sort of thing extensively, for both Maya and editor/game code, and have even run an in-house Read The Docs server to host everything. I’ve learned a number of important lessons, but most relevant here is:

Always generate your documentation using vanilla Python. Never a custom interpreter.

There’s no philosophical reason for this*. I’ve just found it, by far, the path of least resistance. All you have to do is some mocking in conf.py:

import mock
for mod in ['maya.cmds', 'pymel.core']: # and whatever else you need
    sys.modules[mod] = mock.MagicMock()

(I do not have the code in front of me so this may be slightly wrong. Perhaps an ex-colleague from CCP can check what used to be in our conf.py.)

Now when Sphinx tries to import your module that has import pymel.core as pmc, it will work fine. That is, assuming your modules do not have some nasty side effects or logic on import requiring correctly functioning modules, which you should definitely avoid and is always unnecessary.

When your documentation generation breaks, it’s now a simple matter of adding a string in one place, rather than a several hour debugging session.

Don’t say I didn’t warn you!


* If anything, I’m philosophically more inclined to use mayapy. So that should tell you what sort of bogeymen await!

No Comments

Free Practical Maya Programming with Python eBooks

23/12/2014

Merry Christmas and happy holidays everyone,

Last week I asked my publisher if I could make the Practical Maya Programming with Python eBook totally free. I was told some good news and bad news.

The bad news is, they won’t make it free. The good news is, my editor said that Packt often runs free eBook campaigns, and would make the book part of the free campaign whenever they come up. I will blog here when they do (and also please tweet me @techartistsorg if I miss it).

If you can acquire a pirated copy of my book, I encourage you to do so. Packt does not use DRM as far as I know, so just ask a friend who has the book.

Sorry I can’t make it totally free right now, as much as I want to. It sucks to not have full control over something you have personally invested so much in, but I don’t have the energy to fight my publisher on this one (and the fact that they’re DRM-free makes this much less of an issue).

Enjoy, and please leave me a review on Amazon.

2 Comments

Qt Designer is harmful, exhibit A

11/12/2014

Last week, iker j. de los mozos posted a Qt tutorial on his blog. The post was retweeted a number of times, so I figure people liked it.

The post exemplifies what is wrong with the Qt Designer, and also how a little more investment in learning can pay dividends for your career.

I know it’s unfair to give people code reviews on things they just put out for free, but I consider it even worse to allow people to continue to use the Qt Designer with a clear conscience. I thank Ike for his post, and for syndicating his feed on Planet Tech Art, and hope that no one takes my writeup below personally. It’s not an attack on a person, it’s trying to point out there there is a much better way to do things.

There are 117 lines of Python code in Ike’s tool for locking and unlocking transformation attributes. This sounds like a small amount, but is for an experienced Pythonista it indicates huge waste. For comparison, the entire ZMQ-based request/reply client and server I built for Practical Maya Programming with Python is the same size or smaller (depending on the version). If we take a closer look at his code (see link above), we can see a ton of copy and pasted functionality. This is technically a separate concern from the use of the Designer, but in my experience the two go hand-in-hand. The duplication inherent in GUI tools carries over to the way you program.

Let’s look at some refactored code where we build the GUI in code (warning, I haven’t tried this code since I don’t have Maya on this machine):

from functools import partial
from PySide import QtGui
import pymel.core as pmc
import qthelpers

OPTIONS = [
    dict(label='Position', btn='POS', attr='translate'),
    dict(label='Rotation', btn='ROT', attr='rotate'),
    dict(label='Scale', btn='SCALE', attr='scale')
]

def setLock(obj, attr, value):
    obj.setAttr(attr, lock=value, keyable=not value)

def isAttrLocked(obj, attr):
    return obj.getAttr(attr, q=True, lock=True)

def toggleRowCallback(attr):
    obj = pmc.ls()[0]
    value = isAttrLocked(obj, attr + 'X')
    for axis in 'XYZ':
        setLock(obj, attr + axis, value)

def toggleCellCallback(attr, state):
    obj = pmc.ls()[0]
    setLock(obj, attr, state)

def makeRow(options):
    return qthelpers.row(
        [QtGui.QLabel(options['label'])] +
        map(lambda axis: qhelpers.checkbox(onCheck=partial(toggleCellCallback, options['attr'] + axis)), 'XYZ') +
        qhelpers.button(label='lock ' + options['btn'], onClick=partial(toggleRowCallback, options['attr']))
    )

def main():
    window = qthelpers.table(map(makeRow, OPTIONS), title='lockAndHide UI', base=QtGui.QMainWindow)
    window.show()

Why is this code better? Well, for starters, it’s less than a third of the size (37 lines) and there’s less duplication. These are very good things. When we want to change behavior- such as auto-updating the checkboxes when our selection changes- we can put it in one place, not nine or more.

So the code is better, but what other benefits are there to not using the Designer?
– We pull common primitives, like a “row” (QWidget with HBoxLayout) and “table” into a qthelpers module, so we can use this across all GUIs. This saves huge amounts of boilerplate over the long run, especially since we can customize what parameters we pass to it (like onClick being a callback).
– The GUI is clear from the code because the UI is built declaratively. I do not even need to load the UI into the Designer or run the code to understand it. I can just read the bottom few lines of the file and know what this looks like.
– You learn new things. We use functools.partial for currying, instead of explicit callbacks. This is more complicated to someone that only knows simple tools, but becomes an indispensable tool as you get more advanced. We are not programming in Turtle Graphics. We are using the wonderful language of Python. We should take advantage of that.

Again, I thank Ike for his blog post, and hope I haven’t upset anyone. Ike’s code is pretty consistent with the type of code I’ve seen from Technical Artists. It’s time to do better. Start by ditching the Designer and focusing on clean code.

5 Comments

PracticalMayaPython: RuntimeError: Internal C++ object (PySide.QtGui.QStatusBar) already deleted.

19/10/2014

TLDR: If you get that error for the code on page 163, see the fix at https://github.com/rgalanakis/practicalmayapython/pull/2/files

In August, reader Ric Williams noted:

I’m running Maya 2015 with Windows 7 64-bit. On page 163 when we open the GUI using a Shelf button, the GUI status bar does not work, (it works when called from outside Maya). This RuntimeError appears: RuntimeError: Internal C++ object (PySide.QtGui.QStatusBar) already deleted.

I no longer have Maya installed so I couldn’t debug it, but reader ragingViking (sorry, don’t know your real name!) contributed a fix to the book’s GitHub repository. You can see the fix here: https://github.com/rgalanakis/practicalmayapython/pull/2/files
And you can see the issue which has more explanation here: https://github.com/rgalanakis/practicalmayapython/issues/1

Thanks again to Ric and ragingViking. I did my best to test the code with various versions of Maya but definitely missed some things (especially those which required manual testing). If you find any other problems, please don’t hesitate to send me an email!

No Comments

Escaping the Windows prison

8/09/2014

My friend Brad Clark over at Rigging Dojo is organizing a course on Maya’s C++ API (I am assuming it is Maya but could be another program). He had a question about student access to Visual Studio, to which I responded:

As a programmer, the experience on Windows is pretty horrific. No built-in package manager. A shell scripting language designed in hell. A command line experience that is beyond frustrating. A tradition of closed-source and GUI-heavy tools that are difficult or impossible to automate. A dependence on the registry that still confounds me.

My eyes weren’t opened to this reality until I switched to Linux. I was on a Windows netbook that was barely working anymore. I installed Linux Mint XFCE and suddenly my machine was twice as fast. But the much more important thing that happened was exposure to modes of developing software that I didn’t even know existed (Python, Ruby, and Go made a lot more sense!). Programming in Windows felt like programming in prison. Developing on Linux made me a better programmer. Furthermore, If I didn’t end up learning the Linux tools and mindset on my own, working in the startup world would be basically impossible.

Programming on Windows revolves around Visual Studio and GUI tools. If you need evidence at how backwards Windows development is, look no further than Nuget. This was a revolution when it was released in 2010, changing the way .NET and Windows development was done. In reality, the release of Nuget was like electricity arriving in a remote village. It took ten years for C# to get a package manager. And it is for the rich villagers only: older versions of Visual Studio don’t work with Nuget.

The ultimate problems Windows creates are psychological. The technical differences change the way you think. It echoes the “your Python looks like Java” problem. Is the Windows mentality what we want students to take on? My last two jobs have been on Linux/OSX. I honestly cannot imagine having kept my head above water if I didn’t have a few years of self-taught Linux experience.

Windows still dominates in desktop OS popularity. That is all the more reason to make sure we are exposing student programmers to alternative ways of developing. I want new developers to be exposed to things outside the Microsoft ecosystem. It is too easy to become trapped in the Windows prison.

5 Comments

Metaprogramming with the type function

1/09/2014

In my book, Practical Maya Programming with Python, I use Python’s type function for dynamically creating custom Maya nodes based on specifications, such as input and output attributes. I really love the type function*, so I thought I’d post another cool use of it.

I recently wrote this gem as a way to dynamically create exception types from error codes (it was for a now-defunct REST client):

def get_errtype(code):
    errtype = _errtype_cache.get(code)
    if errtype is None:
        errtype = type('Error%s' % code, (FrameworkError,), {})
        _errtype_cache[code] = errtype
    return errtype

Next is an uncommon form of Python’s except statement. Its argument can be any expression that evaluates to a single exception type or sequence of exception types. You can actually call a function in the argument to except!

try:
    return framework.do_something()
except framework.catch(404):
    return None

The framework.catch function is below. It looks up (and potentially creates) error types based on the error codes being caught:

def catch(*codes):
    return [get_errtype(c) for c in codes]

This sort of utility is why I wrote the type of book I did. Learning how to program in Python instead of MEL is all well and good. But you need to really see what Python is capable of to make big strides. I hope that with a more advanced understanding of Python, 3D developers can start creating frameworks and libraries, just like PyMEL, that other developers will work with and on for many years to come.


* I love the type function for a vain reason. It’s more obscure than decorators, but not as difficult to understand as metaclasses.

No Comments

GeoCities and the Qt Designer

25/08/2014

In a review of my book, Practical Maya Programming with Python, reviewer W Boudville suggests my advice of avoiding the Qt Designer is backwards-looking and obsolete, such as writing assembler instead of C for better performance, or using a text file to design a circuit instead of a WYSIWYG editor. I am quite sure he (assuming it is a he) isn’t the only person with such reservations.

Unfortunately, the comparison is not at all fair. Here’s a more relevant allegory:

Hey, did you hear about this awesome thing called geocities? You can build a website by just dragging and dropping stuff, no programming required!

We’ve had WYSIWYG editors for the web for about two decades (or longer?), yet I’ve never run into a professional who works that way. I think WYSIWYG editors are great for people new to GUI programming or a GUI framework, or for mock-ups, but it’s much more effective to do production GUI work through code. Likewise, we’ve had visual programming systems for even longer, but we’ve not seen one that produces a result anyone would consider maintainable. Sure, we’ve had some luck creating state machine tools, but we are nowhere close for the more general purpose logic required in a UI. And even these state machine tools are only really useful when they have custom nodes written in code.

Finally, WYSIWYG editors can be useful in extremely verbose frameworks or languages. I wouldn’t want to use WinForms in C# without the Visual Studio Designer. Fortunately for Pythonistas, PySide and PyQt are not WinForms!

I have no doubt that at some point WYSIWYG editors will become useful for GUI programming. Perhaps it will require 3D displays or massively better libraries. I don’t know. But for today and the foreseeable future, I absolutely discourage the use of the Qt Designer for creating production GUIs with Python.

12 Comments

A short letter to a unit testing newcomer

18/08/2014

One of my friends asked how to get started with unit testing and Test Driven Development and figured I could write a short post. I also mention TDD a few times in my book so I think it could use some more attention.

I got started with unit testing when I wrote a smallish Python project, and realized I couldn’t maintain large Python projects without tests*. So I wrote unit tests for my code. I then quickly got into TDD. I don’t remember what resources I used, but there are plenty.

I’d encourage you to start unit testing by writing your code first, then the tests. As soon as this becomes easy and is paying off, start writing the tests first (TDD). You will come to appreciate that this is a powerful way of thinking and working. Even if you don’t ultimately stick with this approach, it is worth becoming skilled with it. You will uncover many suboptimal areas in your coding process that are otherwise extremely difficult to find and fix.

Keep in mind that learning TDD isn’t like already knowing Mercurial, then reading a book about Git**, and then being skilled with Git because you are skilled with Mercurial. You are embarking on a long journey, and will need to refer to many tutorials, blogs, and books. You will do some TDD, and look back on that code and process in a year and be horrified, just like you were when you started programming. Do not think of unit testing and TDD like learning a new framework or library. Think of it like learning how to program all over again.

So I don’t know exactly where to get started, only that you must, and keep going once you do start.


* I’d soon realize that no project was really maintainable without tests.

** Pro Git is my favorite Git book, by the way.

1 Comment