May 22, 2006
The last post about programmers and chefs reminded me of a point raised in the classic Pragmatic Progammers' presentation Herding Racehorses, Racing Sheep:
Instructions that are appropriate for a novice may be totally inappropriate for an expert. This is something I touched on a while back in Level 5 Means Never Having to Say You're Sorry. As James Bach said:
A maturity model is basically a gang of best practices hooked on crystal meth. In my maturity model of the industry, promoting a maturity model is mere level 2 behavior. By level 3, we outgrow it.
However, I do think Bach's views on this issue are unnecessarily black and white. The idea that a recipe (eg, a best practice, a methodology, or a maturity model) is completely worthless is just as wrongheaded as the idea that everything should be based on a strict recipe. In other words, even an expert chef may occasionally find it helpful to refer to a recipe card.
There's no reason these two models can't coexist. You should always start with the common denominator recipe, of course, but you may want to provide some alternative guidelines and ideas for those cooks who have outgrown traditional recipes, too. The point is to avoid an onerous, religious one-methodology-fits-all view of the world.
The image of the UNIX wizard used in Andy's presentation is striking. I researched the image and found this bit of history at unix.org:
The classic UNIX magic poster by Overacre was distributed at past USENIX conferences and featured a white bearded wizard with UNIX related things around him, for example a spool of thread, a black cat, a boot, a fork, pipes, buckets, a number of containers, labelled with things like tar, null, awk, uucp. There is even a 'C' container, and a partially obscured and broken 'B' container.The wizard is pouring mysterious liquids into a giant shell. Subsequent posters in the series included UNIX wars and UNIX views.
I can't find images of the other two posters, unfortunately, but you can see more of Gary Overacre's amazing art at his website.
Posted by Jeff Atwood
So by level 2 of the linked maturity model, you've outgrown level 2 of the Capability Maturity Model?
I guess what you're talking about is a bit like the jamie oliver cook books. Full of recipes, but he's always telling you to adjust to taste and change things about.
Just last week I reminded myself how different the rules are for novices and experts. I'm helping a new Java programmer come up to speed; she was working through a palindrome detector as an exercise. I helped her get to
for (int i = 0; i s.length / 2; ++i)
if (s.charAt(i) == s.charAt(s.length - i + 1))
and realized a couple of minutes later - mid-function returns are dangerous for the novice. I think it's the best approach for something like this, and I use it without thinking about it - but only because I have enough experience and enough of a safety net (unit tests) and I write small enough routines that it's not a risk. It's not something to teach a novice without pointing out the risks and the practices that ameliorate those risks.
I elaborated as soon as I could.
PS: Jeff, it's still choking on my bl0gsp0t url.
Ummm, !=, of course. And indented. But you get the idea.
A simple rule that avoids harmful interactions is: One exit point per function. I learned this rule early on and found it helpful, but I outgrew it
This is a perfect example. It's a good guideline, but it shouldn't be hard and fast rule.
Carl, I'm sorry about the bl0gspot issue. I get SO MUCH bl0gspot spam, you have no idea (and believe me, you don't want to know).. it gets tedious to block the domain prefixes.
I'll unblock it now.
I worked as a cook for many years (Chef is a managerial title). Cooks/Chefs *_read_* recipes all the time. It's a source of inspiration. They see different things in those recipes then a novice. A good cook can easily improvise without any written guide, but that does not mean written guides are useless.
Thanks, Jeff! Sorry for the hassle.
Matt, I take your point about common coding practices. And experienced programmers who make a habit of using difficult constructs - apparently as a way of showing off - really, really, make me mad. But I also feel that there are cases - I'll post one if I can think of a good example - where my advice to an experienced programmer would be different from my advice to a novice; I fear that the alternative really is lowest common denominator, and I don't like where that takes the code. Thanks for a stimulating discussion.
I'm not sure that I follow your argument Carl. Why are the rules different for novices and experts? I personally don't think that experts should be allowed to do things that novices aren't allowed to do. After all, a novice will be the one who probably has to maintain it once its done.
If it shouldn't be done by novices then it shouldn't be done by experts either. There should only be one set of rules.
And as a side note, returning from the middle of a function can be much cleaner at times than having a single point of return. Especially for things like preconditions and such in functions whose purpose is to return a boolean value. For your example it seems fine and I wouldn't tell a novice to do it any differently.
A beginner has a lot to keep track of. We all do, but much of what we need to keep track of has become second nature to experienced programmers. A simple rule that avoids harmful interactions is: One exit point per function. I learned this rule early on and found it helpful, but I outgrew it. It was helpful to me because I was writing long functions (at least by my standards today), and it ensured that any cleanup code at the tail ends of these long functions got called regardless of the code flow (because it always flowed to the end). This is a "training wheel" rule, and while I was happy with it at the time, I wouldn't teach it to new programmers today. But they still need the safety that rule offers; they don't know enough yet to simply understand the risks. The complicated interactions (say, between mid-function returns and cleanup code) are a more sophisticated subject than the simple rule.
The simple rule has its own complicated interactions, of course - in the above code you'd need an extra variable, initialized, and a boolean operation, making for a more complex function (only slightly, but it's not very complex to begin with). And I guess that's the primary reason I wouldn't teach that particular rule today.
But there are cases - I'm sorry, I can't think of an example offhand - where my rule for the novice would be different from my rule for the experienced developer. Where the additional knowledge needed to do it one way represented a small burden on the experienced developer, but an overwhelming burden on the novice. Which I think was Jeff's point in the first place.
Specifically regarding mid-function returns - I agree this is cleaner and the way I'd advise anyone to do it. But I'd give the advice to an experienced developer without embellishment, but consider it a mistake to have give such advice to a novice without caveats and a chat about the design implications.
But I think that your rule implies that all the coding that you do is "for you and you alone" which is rarely the case. Once a novice is exposed to your "expertly coded" solution, you have increased the chances of them screwing something up. In my mind you should always code for ease of maintenance which includes the assumption that someone less qualified will be working on it down the road. This doesn't mean that you have to code to the lowest common denominator. But I believe that the final solution should be something that is amiable to experts and novices alike.
Jeff... Jeff... Jeff!
So often you hover on the edge of insight. It's maddening to watch. So many things you see... and yet...
You have mischaracterized my views. They are not black and white in the way you suggest. I don't say that instructions are worthless. I would say that instructions are worthless for some purposes and contexts, yes, but that's not the same thing.
If you want complex cognitive behavior-- the kind required for success in any non-trivial software project-- instructions do not cause that behavior. If you think they do, look more closely. Look very closely at what is going on. Look closely at the skills required to follow instructions.
Now, if I am taking responsibility for the quality of someone's work, I might use explicit instructions as a tool to aid in getting the behavior that I want. But if I want high quality work without having to supervise someone at all, and that work is complex cognitive work (such as programming or testing) then complex cognitive skills are required. If you disagree, I'd love to see you demonstrate your point in detail, rather than caricaturing mine to such a degree that you feel no demonstration of your own view is required.
Novices may need instructions. My point would be that novices need instructions in the context of supervision. Novices need experiences in a supervised environment. Novices need not to be treated as little computers for you to program, or what you get will be bad work.
Try it and see for yourself. I spent eight years as a test manager, discovering that instructions don't help much.
Novices may need instructions. My point would be that novices need instructions in the context of supervision. Novices need experiences in a supervised environment.
And my point would be that hands-on supervision with a competent mentor is a luxury that novices rarely get!
I think we need to get a lot better at identifying methods of improvement for novices that don't require this unrealistic level of commitment.
Because if ..
- the only option for new cooks to improve is to work under Julia Child
- the only option for new programmers to improve is to work under Joel Spolsky
- the only option for new testers to improve is to work under James Bach
.. we're all totally screwed.
Sign me up... uh... except for the Julia Child sessions.
No offense Julia.
That is a beautiful picture. I hope that whoever drew it will create more.
I think you will make these projects into a success also!
Recipes and the standard way of preparing an item. Once you know how to prepare the item, you may no longer need the recipe. So novices may use recipes more than experienced chefs/programmers. Some recipes demand that they be followed to the letter, while others offer some flexibility. For example, consider baking a cake, probably precise measurement of flour, sugar, etc. is required to make the cake come out correctly. Now consider Chicken Piccata. This recipe call for a "dash" of salt, a "splash" of white wine. It is not as precise. You can still ruin it by putting in too much salt or wine, however.
Programming recipes are similiar in nature, some are precise, some not so precise. So, regardless of whether your a novice or expert, following the recipes is necessary. When people don't follow the recipes, the food doesn't taste good.
In programming, when recipes are not followed, code doesn't taste good because it is complex, bug prone, and difficult to support and remedy.