A collection of articles, ideas, and rambling from a guy who wrote some software that one time.

Friday, June 15, 2007

Ultimate Quality 功夫 System

Often it is the means that justify the ends: Goals advance technique and technique survives even when goal structures crumble.
- Alan Perlis, Epigram 64, "Epigrams in Programming"
How does a computer programmer get better at computer programming?

In a very broad sense, there is some consensus on the answer to this question.  It's like the answer any other skill.  "Do a lot of it."  Much like other skills, though, while necessary, this condition is not sufficient.  If you want to get really good at punching, you can punch a brick with your thumb inside your first ten thousand times, and someone who has learned to do it correctly and had a fraction of the equivalent amount of practice will be a lot better at punching than you.

So, to expand on that consensus, to get better at programming, you have to learn to do it right, and then do a lot of it, hopefully with someone correcting your mistakes and helping you do it better each time.  Like any other kind of serious training.

This concept is pretty old.  Shortly after the dawn of time, the dragon god-emperor pioneered this concept when he invented a martial art that is now popularly known as "Kung Fu", or, literally, "achievement through great effort".  The term does not necessarily refer specifically to martial arts, and can (in both Chinese and English) refer simply to the fact that someone has achieved something exceptional through a lot of effort and practice.

Specious metaphors between computer programming and martial arts (and various eastern philosophies) have existed for almost as long as computer programming itself.  As a cocky and callow youth, I occasionally had these metaphors generously applied to me, but they rang hollow even in my hubristic state of mind.  I knew that despite any talents I might have, at the very least, I hadn't spent a lifetime of effort achieving a near-supernatural mastery of computers.  I had just messed around with C++ and Java a little bit.  The appellation of "master" was inappropriate, but I didn't know how one really did go about getting to that point.  I had already met a few folks in the programming profession who were old, but certainly not yet wise, and I wanted to learn how not to end up like that.
Whenever two programmers meet to criticize their programs, both are silent.
- Alan Perlis, Epigram 101, "Epigrams in Programming"
I first noticed that the parallel between UQDS and these various arts and philosophies when a friend observing Divmod from afar mentioned that our review process was intimidating.  Intrigued, I conducted a straw poll among my programming friends who are not deeply immersed in the eternal struggle of the Twisted or Divmod codebases, and found that there was a fairly consistent impression: the exchange of comments between authors and reviewers was highly unusual, intimidating, and impressive.

It's unusual because most people cannot read code well enough to comment in as much depth.  Code review is becoming more popular, but it's still rare.  Even intense, newfangled "Agile" processes like Extreme Programming focus more on discussing code as it's being created than reading code which has already been written.

The exchange is intimidating because many of the comments are extremely fine-grained and not very forgiving.  It isn't uncommon to see comments about a tiny private method missing documentation, or test coverage doesn't hit a single error condition.  This causes the reader to muse on the ways in which their own code would fail if it were subjected to such intense scrutiny.

Finally, the exchange is impressive because the factors which make it intimidating make the programmers doing it seem extremely skilled.  If you're looking at work which is being subjected to criticism only on details which seem insignificant, it implies that it is in every other way correct.  To some extent this impression is illusory, because the reviewers are only human and may be missing more important things.  For something as complex and intricate as software, though, it's impressive assuming that the reviewers tried at all.

I can't pretend that UQDS is an entirely unique process in this regard.  The Python and Subversion projects practice regular code reviews in public, and those are just the ones I know off the top of my head.  This isn't a phenomenon unique to open source either - I know that both Canonical and Google do fairly comprehensive code review on their closed-source products.  I've heard milder expressions of awe - although perhaps they were only milder because they came from friends - about those projects and companies.

While it isn't unique, UQDS is particularly intense.  Some other processes try to be "reasonable" - which is, on the face of it, a reasonable thing to do.  Small, "obviously correct" fixes are sometimes allowed without tests.  "Security" fixes are sometimes allowed in for expediency because of their urgency.  Some committers are sometimes exempt.  Some reviews are done after the fact.  Documentation is often optional, since reviews are meant to enforce correctness, not every aspect of quality.  For better or worse, UQDS sets out a much stricter guidelines: everything must be tested.  Everything must be documented.  Nobody is allowed to bypass the process.

It isn't all roses.  Especially when a contributor needs to update an area of code not originally developed under this regime, it can be frustrating to need to document and test and correct code that isn't really related to their goal.  Sometimes the overabundance of the opportunity for review creates interminable discussions about a design, when there is really a need to just go with a solution that works for now.  There may be some room to adjust the constraints to place less of a burden on those who want to contribute small improvements, and that's difficult without compromising on overall quality.

Despite their drawbacks, these rules plus a public ticket tracker add up to something that the industry of martial arts has known about the power of for quite some time: the exhibition.  If you're going to run a martial arts studio you need to attract students, and to do that you need to "wow" people every so often.  Martial arts are about defense, mind-body integration, health and fitness, and self-discipline, but putting that on a poster isn't going to fill up the thursday evening class.  Sometimes you need to get your school together and show off just how bad you would be able to kick some ass with your skills, you know, just in case anybody was wondering.

I am quite proud of the fact that I've received numerous unsolicited comments about the quality of the code itself within certain parts of Divmod and Twisted.  Like any programmer I've received my share of complaints about my work, too (especially the stuff that precedes all this intense review), but as Steve Yegge famously observed, most programmers who are famous for their programs don't actually write programs; they write about programs, or they wrote some programs nobody has the code to.

I'm almost more pleased with the idea that I could help pave the way for programming to have some real rock-stars on the merit of their code than the idea of being a rock-star myself.
Dealing with failure is easy: Work hard to improve. Success is also easy to handle: You've solved the wrong problem. Work hard to improve.
- Alan Perlis, Epigram 101, "Epigrams in Programming"
To close, there are a couple of skills that I think UQDS promotes which there might be other ways to promote.  If you want to develop a competing "school", these are things to think about:
  • Reading code.  Open source is great because you can read the code, but UQDS gives you a reason to do the reading.  Not just skim, not participate in the writing, but really read and analyze.
  • Communicating with other programmers.  Another thing that UQDS has in common with a martial art is that it's adversarial.  You throw the "punch" of a patch, the reviewer "blocks" with a branch, and so on.  You don't need to be a social butterfly to get this right, but you do need to be very focused on the technical communication skills required to explain your ideas.
  • Testing.  Test-driven development is an excellent trend.  UQDS doesn't have much to add to that beyond enforcing it, and making the application of TDD the easiest way to get through reviews which deal with issues like test coverage.  (If you test everything before you write it, of course your tests are going to cover everything before you put it into review.)
I'm not a martial artist.  The closest I've come was years ago when I was a fencer, and although I hope to pick up a sword again some time soon, I am no expert.  Still, I have a great deal of respect for Kung Fu, and I hear a fair amount about it from a fellow I know who did some training in it, and I think this is a bit more accurate of a comparison than the earlier attempts that I mentioned; so if you're a twelfth dan grand master in ultimate ninjitsu, please don't explode my head with your psychic powers if you think I'm wrong.

A disagreement in the comments would be sufficient.

11 comments:

corydodt said...

Where I've found UQDS intimidating, it's been because of the slowness of the procedural hurdles, not the difficulty of doing it or the cross-programmer interactions required.

So how can we get a 10th-dan ninja on our side? I want an API for exploding heads. Maybe some kind of Amazon Mechanical Turk thing, but with psychic ninjas on the other end.

smitty1e said...

I like to look at the fact that information is a fluid.
We carve it up into discrete chunks to manipulate it in RAM and persist it on media, but that is an existential necessity, not an essential truth about the information.
If you look at books on programming language theory, and I have a couple, though I've only even done one toy project that gets into parse/lex ideas, there are a dozen or so concepts that are common to languages. That's it. Nothing more. A MicroSoft can trot out a Delegate or something, but it's all been done.
At the architecture level, you have the GoF book, and its 20-something patterns. What are they all about? Figuring out where to put the state.
Have you looked at Haskell? While I'm a n00b there, too, I must say its radical distinction between pure and stateful is a real mind-ripper.

smitty1e said...

Shouldn't have used the word 'fact' in the first sentence. That was an opinion.

glyf said...

Writing in this arbitrarily changeable format is tricky. I had a whole section comparing the procedural difficulties to unpleasant aspects of training, but I cut it out because it was getting up into the "dozens of pages" size range. Briefly, while it's fun to watch two guys with crazy kung fu skills fighting at lightning speed, it's not so much fun to sit in horse stance for five hours and then keel over, unable to walk for a day.

Similarly you'll note that I placed an emphasis on the fact that this looks impressive from the outside. If you're in Divmod or the Twisted community, it's just the way things are getting done, and it has pros and cons.

As far as the ninja thing - I'm having trouble just finding a guy who can do HTML. We might have to wait on getting one of the most elite assassins in human history to commit murder for us for free.

corydodt said...

Doesn't have to be free. $0.20 per kilosplode?

jkakar said...

As far as I can tell we're pretty much using UQDS on the project I
work on. When I first started this job one of my coworkers said
something like, "I believe a good programmer is one who likes to read
code." At the time, I had little experience reading code and
generally found it an uncomfortable activity. It was an interesting
comment though, and the more I thought about the more it made sense.

Having now been involved in a project with a strict review process for
a little more than a year I can confidently say that my ability to
read and comprehend code is significantly better than it was. My
ability to write code has also improved but I believe mostly as a
result of better reading comprehension.

blackjml said...

In line with corydodt's comment, I don't find UQDS intimidating. I find it painful. It's hard work with few immediate rewards. This is because I'm fairly confident of my abilities as a programmer.

I haven't done very much physical training of any sort, let alone kung fu. I find it to be both intimidating *and* painful, because I lack confidence in myself and because it's hard work with few immediate rewards.

blackjml said...

> > It's important that there is an obvious place to discuss a proposed change (and a place to propose a change)...
> As far as I'm concerned, that is basically the definition of a "ticket tracker". You've got some work (a ticket) and you track (discuss, annotate, describe) it.

A change to software involves, at least:
* A reason for the change (+ discussion)
* A description of the change that needs to be made (+ discussion)
* A plan for how to make change (+ discussion)
* The changed code (+ discussion)

UQDS only mandates that the reason for the change (i.e. the initial bug or feature request) be recorded, along with a discussion of the changed code. It also provides a structured way to link from the discussion to the code itself.

In Twisted and Divmod practice, features are rarely specced out on Trac. They are more often specced out informally on mailing lists and on IRC.

I guess what I'm saying is that ticket trackers aren't all that.

blackjml said...

Coder: Here's a branch. Review it please.
Reviewer: OK.
...
Reviewer: It needs docstrings here, here and here.
Coder: Oops! I'll add those now.
...

Now, what happens? In UQDS, sometimes it's:
Coder: OK, I've written those docstrings. Review my changes please.
Reviewer: They look good, merge away.

But sometimes it can be:
Coder: Docstrings written. Please review.
Reviewer: You know, now that I come to think of it, everything in this branch sucks.

But what if instead it was:
Coder: OK, docstrings written. Do you need to review my changes?
Reviewer: Nah, that's OK. I've seen your other docstrings in this branch. I trust that you can write decent ones.

carmstro said...

Like Jamu, I'm quite happy with UQDS. Jamu explained the benefits of being a reviewer nicely, so I'll comment on the benefits of receiving review.

I'm definitely *not* confident enough in my ability as a programmer to believe that the reviews are not well worth it. In addition to simple checking of (almost) mechanical things like full test and documentation coverage, getting comments on design has helped me become a better programmer. In the three projects I've worked on that have switched to UQDS after having some non-UQDS development, I've seen a marked improvement not only in the quality of test coverage and documentation, but also a less-tangible improvement in the design.

blackjml said...

I hope you don't misunderstand me. I think code reviews rock, I just think that it's possible to do them better than in UQDS as practiced by Twisted / Divmod.