You must manage what you can’t measure

by Rob Galanakis on 8/08/2014

We all know the quote:

You can’t manage what you can’t measure.

The quote is often incorrectly attributed to W. Edwards Deming. Thank goodness, because that sentiment is absolutely ridiculous, and Deming is one of my heroes. In fact, a more accurate Deming quote is:

The most important figures that one needs for management are unknown or unknowable… but successful management must nevertheless take account of them.

It’s very important to understand how absurd the “can’t manage what you can’t measure” idea is. It leads to articles like this:

It is an old management adage that is accurate today. Unless you measure something you don’t know if it is getting better or worse.

No, it wasn’t accurate when Peter Drucker promoted it, and it isn’t accurate today. This quote is so counter intuitive, I’m not sure it became popular. Are your managers idiots? Are your employees automatons? Do you believe you can measure everything about your business? That the more you measure, the more successful you will be?

If you want to truly engage with employees as empowered and creative individuals, you must manage what you can’t measure. If you want to create a learning organization optimized for long-term health, you must manage what you can’t measure. To forget this is to engage in one of the great sins of management.

An absolutely wonderful book on this topic is Measuring and Managing Performance in Organizations. I really encourage anyone who believes that measurement is a prerequisite for management read it. It explains, with anecdotes, statistics, and logic, how depending on measurement will lead to deep organizational problems.

1 Comment

Portland, here we come!

by Rob Galanakis on 6/08/2014

Tomorrow, my family leaves on a four day trip to begin a new life in Portland, OR, as the Engineering Manager at real-estate startup I am incredibly excited to join the company for all sorts of reasons (the role, product, team, founders, location, pretty much everything). It’ll also allow me to focus on what I’m most passionate about: engineering and development management. So there should be fertile topics for new blog posts, though I suspect the purely engineering or Python-centric posts will get fewer (except for goless, which I plan to maintain).

Now for the heavy stuff. In addition to a new chapter opening, several chapters are finally closing. Since deciding to leave Iceland earlier this year, life has been a depressing adventure. After a promising start at CCP Atlanta, the studio was shut down. This caused us to become homeless. We were 2 days from closing on a house (for which we lost a very large amount of earnest money). So a few days later we drove to Austin and moved in with my in-laws for about 2 months. I found a new job at The Foundry, but I ended up not enjoying working remotely. I was looking for a new job just a few weeks after starting (the job was just for a 3 month contract so they were aware I was looking). We left my in-laws mid-June and moved into their lake house, which I describe as 30 minutes outside of nowhere (over an hour into Austin). We haven’t had running water for weeks due to pump-house problems. My wife and son have gotten cabin fever, unable to make friends with a culture we don’t seem very compatible with. I haven’t been able to give a concise answer to “where I live” or “where I work” since March. Moving costs keep building. My son is behind on his vaccinations due to moving around. It’s been the most difficult time of our lives.

And oh my god is it hot outside.

So here’s to a new job, a new city, a new start. See you on the other side!


Code separators and headers are more than a matter of style

by Rob Galanakis on 4/08/2014

IDontCareIfYouPreferPascalCase, ifCamelCaseIsForYou, or_if_you_prefer_lowercase_underscores. They all have their merits. However, there is one element of many style guides that I have come to vehemently disagree with: function/class headers* and separators. I bring it up because I’ve encountered them in pretty much every codebase I’ve worked with, but never found it difficult to convince people to stop using them.

Many people have the belief that there’s no inherent superiority between having and not having headers and separators. Separators vs. no separators is like PascalCase vs. camelCase. “It’s just the way it is, follow the guide, be consistent.”

It’s a reasonable opinion, but wrong.

Headers and separators are more like the comments that say #Open the file directly above the line that says with open(somepath) as f. Or more likely, a comment that says #Don't write the file yet above the line that says requests.get(someurl). Wait, what does that comment refer to? No idea, because someone edited the code but not the comment.

We’ve known these sorts of comments are harmful for a long time. They involve out-of-band, redundant information that quickly rots. Having to create purely formal, redundant information (“a new function becomes here!”) is extra work that cannot be justified. Headers and separators are the same. “Added missing separator above function” is a commit message no one should ever have to write or read. Separators and headers are not a debate about readability. They are harmful because they are an impediment to changing code.

Please, if you use separators and headers, stop it immediately, or at least listen to the next jerk that comes in and wants to stop using them.

* : I am also against file headers, but I know they can be useful in some cases, such as when your code is mingled with client code and it can be important for people to know what code came from where. I can tolerate overhead that has a demonstrable benefit.


Everyone should take vacation at the same time

by Rob Galanakis on 31/07/2014

Throughout my career I’ve always seen people struggle with taking vacation. People are too wrapped up in what they’re doing. Managers can’t allow critical people to go missing. There are weeks of trepidation and handover and “I don’t know how to fix that” emails. To a large extent, this can be fixed with shared code ownership, comprehensive automated testing, and all those types of good development practices. I have a better idea, which I saw in great use at CCP (which for a long time did not have those good development practices):

Everyone vacations at the same time.

In Iceland, this was a cultural thing. From what I understand, employers aren’t allowed to deny you vacation between May and September. Everyone goes on vacation in July. The office is empty. Things just go relatively smoothly as no one expects anything to get done during July (its a great time for side projects). This “July slowdown” wasn’t limited to CCP, as people who need visa renewals in the summer no doubt learn.

In Atlanta, the studio just closed down for two weeks in July.

In both cases, there may be a skeleton crew to keep things running, people on call, etc. Its just that no one expects anything non-immediate to get done. This has many benefits: its easier to plan for, office costs are cheaper, there’s a single silent period rather than months of rolling disruption, everyone takes a refreshing vacation, and much more. It’s pretty much the only vacation policy I’ve seen that was largely resilient to the pressures that keep people from taking vacation. To be sure, some people were screwed over by bad managers, but (in contrast to most other management offenses) this was largely due to particular managers and not underlying cultural causes.

If you see the people around you failing to take the proper vacations everyone needs to keep going, I’d encourage you to try having everyone go on vacation at the same time.


Practical Maya Programming with Python is Published

by Rob Galanakis on 28/07/2014

My book, Practical Maya Programming with Python has been finally published! Please check it out and tell me what you think. I hope you will find it sufficiently-but-not-overly opinionated :) It is about as personal as a technical book can get, being distilled from years of mentoring many technical artists and programmers, which is a very intimate experience. It also grows from my belief and observation that becoming a better programmer will, due to all sorts of indirect benefits, help make you a better person.

If you are using Python as a scripting language in a larger application- a game engine, productivity software, 3D software, even a monolithic codebase that no longer feels like Python- there’s a lot of relevant material here about turning those environments into more standard and traditional Python development environments, which give you better tools and velocity. The Maya knowledge required is minimal for much of the book. Wrapping a procedural undo system with context managers or decorators is universal. A short quote from the Preface:

This book is not a reference. It is not a cookbook, and it is not a comprehensive guide to Maya’s Python API. It is a book that will teach you how to write better Python code for use inside of Maya. It will unearth interesting ways of using Maya and Python to create amazing things that wouldn’t be possible otherwise. While there is plenty of code in this book that I encourage you to copy and adapt, this book is not about providing recipes. It is a book to teach skills and enable.

Finally, to those who pre-ordered, I’m truly sorry for all the delays. They’re unacceptable. I hope you’ll buy and enjoy the book anyway. At least I now have a real-world education on the perils of working with the wrong publisher, and won’t be making that same mistake again.

Thanks and happy reading!
Rob Galanakis


goless 0.7 released, with Python3 support and bug fixes

by Rob Galanakis on 25/07/2014

goless version 0.7.0 is out on PyPI. goless facilitates writing Go language style concurrent programs in Python, including functionality for channels, select, and goroutines.

I forgot to blog about 0.6 at the start of July, which brought Python 3.3 and 3.4 support to goless (#17). I will support pypy3 as soon as Travis supports it.

Version 0.7 includes:
– A “fix” for a gevent problem on Windows (socket must be imported!). #28
– Errors in the case of a deadlock will be more informative. For example, if the last greenlet/tasklet tries to do a blocking send or recv, a DeadlockError will be raised, instead of the underlying error being raised. #25
– goless now has a small exception hierarchy instead of exposing the underlying errors.
– Better PyPy stackless support. #29 can be called with (case1, case2, case3), etc., in addition to a list of cases (ie, ([case1, case2, case3])). #22

Thanks to Michael Az for several contributions to this release.

Happy concurrent programming!

No Comments

goless now on PyPI

by Rob Galanakis on 12/06/2014

goless is now available on the Python Package Index: . You can do pip install goless and get Go-like primitives to use in Python, that runs atop gevent, PyPy, or Stackless Python. You can write code like:

channel = goless.chan()

def goroutine():
    while True:
        value = channel.recv()
        channel.send(value ** 2)

for i in xrange(2, 5):
    squared = channel.recv()
    print('%s squared is %s' % (i, squared))

# Output:
# 2 squared is 4
# 3 squared is 9
# 4 squared is 16

I’ve also ported the goless benchmarks to Go, for some basic comparisons to using goless on various Python runtimes (PyPy, CPython) and backends (gevent, stackless):

Thanks to Rui Carmo we have more extensive examples of how to use goless (but if you’ve done or read any Go, it should be relatively straightforward). Check them out in the examples folder:

And just a compatibility note (which is covered in the docs, and explained in the exception you get if you try to use goless without stackless or gevent available): goless works out of the box with PyPy (using in its stdlib) and Stackless Python. It works seamlessly with gevent and CPython 2.7. It works with PyPy and gevent if you use the tip of gevent and PyPy 2.2+. It will support Python 3 as soon as gevent does.

Thanks and if you use goless, I’m eager to hear your feedback!

No Comments

goless Benchmarks

by Rob Galanakis on 9/06/2014

I benchmarked how goless performs under different backends (goless is a library that provides a Go-like concurrency model for Python, on top of stackless, PyPy, or gevent). Here are the results, also available on the goless readthedocs page:

Platform Backend   Benchmark      Time
======== ========= ============== =======
PyPy     stackless chan_async     0.08400
CPython  stackless chan_async     0.18000
PyPy     gevent    chan_async     0.46800
CPython  gevent    chan_async     1.32000
~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~
PyPy     stackless chan_buff      0.08000
CPython  stackless chan_buff      0.18000
PyPy     gevent    chan_buff      1.02000
CPython  gevent    chan_buff      1.26000
~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~
PyPy     stackless chan_sync      0.04400
CPython  stackless chan_sync      0.18000
PyPy     gevent    chan_sync      0.44800
CPython  gevent    chan_sync      1.26000
~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~
PyPy     stackless select         0.06000
CPython  stackless select         0.38000
PyPy     gevent    select         0.60400
CPython  gevent    select         1.94000
~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~~~~~~ ~~~~~~~
PyPy     stackless select_default 0.00800
PyPy     gevent    select_default 0.01200
CPython  stackless select_default 0.19000
CPython  gevent    select_default 0.25000

The trends are that PyPy with its built-in stackless support is fastest, then Stackless Python (2-5x), then PyPy with gevent (5-10x), and finally CPython with gevent (15-30x).

Remember that these are benchmarks of goless itself; goless performance characteristics may be different in real applications. For example, if you have lots of C extensions, CPython/stackless may pull ahead due to stack switching.

If you’re using goless for anything, I’d love to get some benchmarks, and find out how it’s working, so please comment below, or create a GitHub issue.

Disclaimers: It’s possible that goless is inefficiently using gevent, but the backend-specific code is so simple I doubt it (see goless/goless/ These benchmarks are all done against Python 2.7. Also I am no benchmark master (especially with PyPy) so there may be problems, look over goless/ for benchmark code. These were done mostly for curiosity.

No Comments

Hiring your cake and eating it too

by Rob Galanakis on 6/06/2014

When evaluating candidates, I have always been a believer that cultural fit and potential to improve is more important than technical ability. Of course I like to review real code samples and give a programming test, but I rarely ask for whiteboard programming. I am not a master of algorithms or math and don’t have a CS background, so I don’t require that of most candidates*. As Five Thirty Eight explains and shows, people just want to date themselves.

This policy is amazingly ego-centric. But it’s also worked pretty well. Without exception, I’m proud of the hires I’ve had a primary stake in. But it is the best policy, at least for the type of work I’m doing?

I think I am a pretty darn good hire. Why would I want to exclude people like me? Well, the fact is that I’m not special. There are way more gifted people around than me. There are plenty of people who are a great fit, and are great leaders, managers, developers, and coaches, and are awesome at math and algorithms. Should I overlook myself to try and get someone better?

Clearly companies like Google can do this. There are anecdotes about people who they hired the second or third time around. People like Steve Yegge. On the other hand, there are plenty of managers that hire “to fill a seat.” Can every company interview like Google, and reject otherwise promising candidates that do not ace a challenging technical interview?

Who you choose to hire does not define what your company is, it defines what your company will become. If you give in and make unenthusiastic hires, your amazing company will be dragged into mediocrity. If you hold the line and hire only the best, you’ll continue to excel, if you can find people. In reality, most companies are somewhere in the middle.

The “best” policy is the one that fits your situation. In an isolated job market, you may choose to value fit and culture. A tight-knit culture may help retention, and make it easier for the inevitable low performers to improve. At a startup, you may have limited headcount, short timelines, and immediate technical needs. Cultural fit would be trumped by technical expertise and experience. On the other hand, cultural fit may be most important at an established company. The biggest risk is a dilution of the culture, and there are plenty of senior people around to do mentoring.

Recognizing what you should select for is much more important than simply always trying to be as selective as possible.

* Obviously there are exceptions. If you need expertise, you need expertise. My thoughts apply to the 80% case.

1 Comment

Optimize iteration length for feedback

by Rob Galanakis on 4/06/2014

If there is one theme that is weaved through all of Agile’s principles and practices, it is feedback. TDD. Pair programming. Continuous delivery. Stories. Estimation. Reviews. Retrospectives. On-site customers. Feedback comes up against and again. Feedback from code, the team, and users.

As I mentioned in my previous post, I am a big fan of short (one week) iterations. Feedback is why. If your team works in three-week sprints, and mine in one-week sprints, we have three times the feedback. I have three times the opportunities to learn and improve. While you debate whether to try something new in a future sprint, we try it out immediately and evaluate whether it’s working every week, until we accept or reject it. We become three times as good at estimation. We know in a third of the time you do that a solution to a problem works.

Perhaps in some situations one-week is too long. You could try two-day iterations early on with a new project and new team. Or perhaps, on a legacy project, even two weeks is too short and you don’t get enough work done to get good feedback. You can get faster feedback going to three week sprints, rather than having to wait four weeks (two two-week sprints). The point is to optimize for feedback. This means you should prefer shorter sprints, but there can be exceptions.

The benefit of feedback cannot be overemphasized. In a previous post, I said no single aspect of the Toyota Production System is more important than the others. That’s not entirely true. “Continuous Improvement” can bootstrap the other TPS components. You improve through getting feedback. It follows that you should do anything you can to get better and faster feedback.