Masters, Not Managers

plane.jpgIf you watch one of those famous chefs on TV, you get the impression that cooking is both, fun and easy. A chef knows instinctively how to combine spices and how long the meat has to stay in the oven to be just perfect. That’s a clear sign of true mastery: masters have become one with their tools, materials, and processes; to a layman everything they do looks so simple.

What the audience usually fails to realize is that these chefs are not just great cooks and entertainers: they are also entrepreneurs, managers, and coaches. They usually run at least one big gourmet restaurant, they do the marketing and goods procurement, they write books, they hire people and train apprentices such that they someday can become great cooks, too. To sum it up, they are experts at their craft and possess other important skills at the same time.

Contrast this to a traditional software company, were you have managers managing people and developers doing the programming. Managers usually don’t do any coding and probably haven’t done much coding in their life. Most likely, they are the least-qualified to write solid, production-quality code. And yet they are in charge of strategic decisions, including hiring new developers. A master chef, however, is the most-qualified person to do the cooking and because of this is the most-qualified person to make strategic decisions.

In my view, a traditional non-coding software manager is a relic of the industrial age. The obvious waste is that such a manager does not actively contribute to the main asset, ie. working software. But there is more: not being a skilled software developer with first-hand up-to-date experience, a manage-only manager will face difficulties in many areas: first in finding and selecting talented people; second, in being a mentor and role-model for developers and third, in convincingly educating upper management about intrinsic software-related problems. Especially the latter weakness is a constant source for disappointment and grief in many companies.

The classic apprentice/journeyman/master model has proven timeless over centuries. It promotes people who master their craft and have the right management and social skills. Possibly the biggest advantage is that in such a system managers (“masters”) are still allowed to pursue their craft. Being able to do what one loves to do the most is good from a motivational point of view and leads to continuous dissemination of knowledge and best practices.

The Code is the Design, Baby!

What exactly is the “design” of a software system? Is it a detailed UML diagram? Is it 300 pages of prose? I recently came across an article from 1992 by Jack W. Reeves, mentioned in an interview on the subject of TDD; in his article, Jack argues that the design is actually the source code itself.

What!? The code is the design? This proposition is surprising at first, but not really if you think about it: only the tested and debugged code is a precise description of how the system should behave, how it should be built. And the process of “building” a software system is merely the feeding of the code to tools like make, Ant, compilers and linkers. Thus, “designing” software is hard, building software is straightforward.

Often, people demand that the design should be a UML diagram, something that is easy to read and comprehend by anyone. However, for any non-trivial system, the diagram(s) would become at least as complicated as the real code. It’s always the same: you start out with a couple of classes that have only a few relations, and everything looks nice; but when you finally have 200 classes you suddenly cannot see the forest for the trees anymore. UML is good for highlighting certain parts and aspects of a system, but a complete specification, one that can be handed down to the “code monkeys” is a myth. Even the author of the most successful UML book ever, Martin Fowler, is very skeptical about UML as a blueprint design tool. As Fred Brooks pointed out long ago: “software is not inherently embedded in space and has no ready geometric representation” (like hardware or buildings do).

There are technical issues, too. How do multiple “designers” collaborate on a UML design? How do they create parallel versions and merge conflicts? How do they keep track of variants? Countless tools exist for designs based on plain-text (aka. source code); next to nothing exists for UML.

Why do so many folks fall prey for this “everything-has-to-be-designed-in-UML” idea? Some (most likely managers or sales people) simply confuse programming with typing. Others (most likely developers that never got the hang of programming), want to introduce a white-collar/blue-collar developer system. Yet others think that there must be a method (in this case UML) that would render a complex system in such a way that it can be understood fully by anyone (including managers, sales people and developers who never got the hang of programming).

The design of a modern airplane comprises hundreds of thousands of pages. Nobody can and must comprehend everything. But even laymen can look at the 3D model and understand a lot: ah, this is where the engines are, and yep, here we have the anti-lock brake system and, boy-oh-boy, here we have the flight controller.

Such design overview diagrams are very important for comprehension and communication and no source code can ever replace them. It’s important to have such a diagram (call it high-level design or system architecture diagram or whatever you like). If you want, you can draw it in UML but I suggest you don’t: UML is way too boring. Have a look at the Google Android architecture diagram — it’s shiny, it’s been reduced to the absolute minimum, it’s freakin’ awesome!

Is there a need for designers, anyway? I definitely think so! You need somebody who takes care of the big-picture technical decisions, like the high-level composition of a system, the coding conventions, the hardware decisions and so on. Let’s call this person the systems architect. And, of course, you need somebody who takes care of the look & feel, the user-interface, a Steve Jobs kind of person. And, last but not least, you need many small-to-medium scale “designers” who iteratively detail the “design” through so-called “programming” such that compilers, linkers and the like can build the rest easily.

Poor Man’s DIP

Sometimes a lower-layer component needs to invoke a service on a higher-layer component. Consider, for example, a timer component (T) that periodically calls a handler function in a user-interface component (U). Component T is probably part of the OS kernel and thus clearly “lower” than component U.

In this setting, there is an upward dependency from T to U; such upward dependencies are undesirable, at least if they are bound at compile-time. Implemented naively, there is a hard-coded call to the UI component like this:

Dependency lines that point up in a component diagram are not just ugly: they denote that the lower-layer component cannot be independently reused and tested.

The classic dependency inversion principle (DIP) is usually applied to solve this problem: instead of having a hard-coded function call in the timer to the handling component, the timer calls back on a function pointer that is set to the timer-handling routine in the initialization code of the higher-layer component:

Note that there is still a T to U dependency, but now this dependency is only present at run-time, which is OK, as this doesn’t hinder reuse and testability. The U to T compile-time dependency is quite natural and doesn’t violate any design principles. So, the undesirable compile-time dependency has been successfully inverted. The classic DIP recipe looks like this:

1. In T export a callback interface
2. In U implement the callback interface
3. In U (or some init/startup code) register the implementation with T
4. In T call back on the interface

When you are working in a constrained environment like embedded systems, you often cannot afford the memory and performance overhead that accompanies such late (run-time) binding, so you might try what I call the “Poor Man’s DIP”: simply export a “callback interface” as a function prototype and “implement” it by defining the function in the upper-layer component:

This pattern gives you most of the advantages of the classical (run-time bound) DIP but doesn’t incur any overhead. It can (and should) be applied whenever there is a dependency from a lower-layer component to an upper-layer component that doesn’t need to change at run-time but stays fixed throughout the lifetime of the application.

Breaking the Limits!

running.jpgHave you ever heard about Cliff Young? In case you haven’t here is his story…

For those who think that running a marathon is not challenging enough, there is the Sydney to Melbourne ultra-marathon: 875 kilometers across the hot Australian desert. This race is obviously only for the best of the top athletes and it usually takes them six to seven days to complete. Having gone through the pains of preparing and running a “normal” marathon myself I can only try to imagine what a race like that means.

Despite of these apparent tortures, in 1983, a 61-year-old farmer decided to take part in this race, wearing an old army jacket and gumboots. Spectators were worried that this poor guy wouldn’t survive the first hours of the race but when he left the stadium they gave him a big cheer anyway.

The race started and as expected, Cliff lagged way behind. After 20 hours, the first runners arrived at the camp, where they took a bite, got a massage and slept for about two hours (they typically stopped for a four hour break for every 20 hours of running). When Cliff arrived at the camp three hours later, he didn’t stop — he just continued to run. When a reporter asked him whether he didn’t want to have a break like the other athletes, Cliff responded that he was here to run and not to sleep.

He ran and ran. On the third day he decided to “sleep” for 25 minutes. Believe it or not: he arrived at the finishing line in Melbourne almost two days ahead of number two.

Amazing story, isn’t it? There a various slightly different versions of this story out there, but what they all have in common is that they stop here. What usually isn’t told is that the next year, 17 out of the 18 runners even exceeded Cliff’s record — all of a sudden, they had realized that it is possible to run the race without sleeping at all.

Cliff Young won the race because he challenged existing limits. Not really hard limits, like laws of nature, but arbitrary limits.

So the question is this: is something truly impossible or do we just think it is impossible because we haven’t tried before?

Regular Expressions — Sweetest Poison

It’s amazing how much time you can save by using regular expressions; it’s even more amazing how much time you can spend getting them to work correctly.

Because they are so powerful and easy to use, regexps can easily be misused, for instance by applying them to problems that are not “regular”, that is, where balancing is important:

Parsing problems like this are not suited for a regular expression matcher, as you need to retain state information and regexps simply cannot keep track of which blocks or braces are open or closed. In cases like this, what you really need is a parser. Period.

Alas, often people can’t be bothered writing a true parser, even if lex/yacc-like tools greatly simplify the work. And I’m guilty of this myself. Years ago I wrote a profiling tool for embedded systems. Since the embedded C code that I wanted to profile had to be instrumented (each function required enter/exit logging calls to get out the execution timing data) I needed to write a tool to do the job. I was not particularly interested in this job — hacking the actual performance analysis code was much more fun — so I decided, well, to go for a heuristic “parser” based on regexps.

In less than one hour I had cobbled together a little script that seemed to work fine. Over the next couple of months I had to spend endless hours fixing all the nasty corner cases; even today it doesn’t work in all circumstances! But I’ve learned my lessons: don’t use regexps when you need a true parser. Again, period.

But even if the problem is regular, people often define regexps sloppily. Look at the following example that checks if a .cfg file appears anywhere in a given string:

So let’s see what we’ve got here. We are obviously looking for a Windows-style absolute path: a single drive letter, followed by a colon and a backslash, followed by n optional directories (each of which followed by a backslash), followed by a mandatory filename that has a .cfg extension. Looks really neat…

These are the regexps people love to write and I don’t know how many times I’ve had to fix one because of this pathological “simplicity”. It might work today, but it is far from future-proof. Sooner or later the surrounding context will change and this regexp will match much more (or much less) than was intended.

Here a some of the major shortcomings:

– Using word characters \w is way too restrictive. According to the Windows long filename specification, a filename may contain any UTF-16 character, but for all practical purposes \w is really only a shortcut for [a-zA-Z0-9_]. If a filename contains a blank or umlaut, the expression won’t match anymore.

– Actually a corollary of the previous item: you cannot have partial relativity within an absolute path, e. g. C:\files\services\base\..\items\main.cfg would not match because the \w character class does not allow for dots.

– The regexp is not aligned on a word boundary, which means that if your editor happens to create backup files like C:\config\user.cfg~ they’ll match, too.

Often — but not always — using regexps means striking a careful balance between accuracy and convenience. It makes little sense to implement the complete Windows filename spec in a regexp. But investing a little energy to tighten them up usually pays off in spades. How about this?

At the cost of being only slightly more difficult to read, this solution is much more resilient to change due to the use of some good practices. First of all, it is easy do define a set of valid drive letters, so I used [a-zA-Z] instead of \w; second, the whole regexp is aligned on word boundaries, which means no more regexp over-/underruns and third, by stating that everything between separators (backslashes, in this case) is a series of non-separators we won’t run into “strange character” problems.

Next time you write a regexp think this: “I know that by using regexps I’m saving hours of development time, so I can afford to spend another 10 minutes to make them more robust”.

The Programmer Who Wrote Golden Code

Once upon a time, in the land of Foo, there was a programmer who wrote awesome code: free of defects, easy to read and maintain and yet efficient beyond compare. Everyone admired him and his works.

The word spread and the emperor was excited when he heard about the skills of the programmer. The emperor ordered him to come to his palace to work for him as his chief court programmer. The programmer obeyed and continued to write outstanding software — much to the delight of the emperor.

After some months, however, the emperor wanted to find out what exactly made the programmer so great and whether it was possible to instill his spirit into the other court programmers. So he observed the programmer and collected countless metrics. He also had the programmer attend many meetings in order to define rules and procedures for all court programmers to follow.

One day, the emperor noticed with horror that the programmer didn’t write golden code anymore; and neither did the other court programmers.

(with apologies to Aesop.)