Monday, April 6, 2009

Ballistic Programming

Last Wednesday I attended a talk at MIT from Larry Wall, the designer of the Perl programming language. The talk was entitled, "Ballistic Programming", but really it was excuse to talk about Life, the Universe, and Everything. And by everything I mean programming languages, their design, shortcomings and benefits, natural languages, grammar, and how his perspectives on all of these things impact the design of Perl.

Perhaps it's better to say that the talk was about "everything".

At any rate, the study of ballistics is literally about the art of projectiles. It's the source of the the term ballista, and it's based on the Greek verb for "to throw". Pretty much every sport involving a ball is a ballistic sport, as well as a few others, like the javelin toss and gun target practice. Ballistics is the art of throwing an object from one point to another, and the process works like this:
  • Select intended destination
  • Estimate force required to move object
  • Make attempt
  • Evaluate effectiveness
  • Correct next attempt using these results
Of course, this procedure applies just as well to programming as it does golf or basketball. Larry had an excellent set of diagrams explaining the two major theories of software project design. First, he showed Waterfall, a complete failure of a process in which each stage seamlessly and perfectly flows from one step the next with no backtracking. It's been known for decades that it doesn't work and causes projects to be over budget, but here's are the stages:
  • Specification (select destination)
  • Design (estimate force)
  • Implement (make attempt)
  • Test (evaluate)
  • Maintenance (correct)
The problem with waterfall is that it has no flexibility anywhere. Sometimes something will come up in implementation that demonstrates an issue with specifications or design, and those portions need to be corrected. But waterfall states that all the specifications have to be done first, then all the design, and so on. Either the whole project gets held up as flaws in the process are found, or the project is completed with flaws, producing something that no one needs and is impossible to maintain.

The other common methodology is known by the laden buzzphrase "Extreme Programming". The two main tenants of extreme programming are that you want lots of feedback loops so problems can be corrected as soon as possible, and that people should program in pairs. Since pair programming isn't relevant to the discussion at hand, I'll just give my two cents and let the issue rest. It's very useful for educating half of the pair and otherwise it's a waste of time, in that it takes more than twice as many worker-hours to do.

Larry Wall joked that in Extreme Programming, you start with the test which shows you how to implement the program. After you've implemented it, you can write your design document, and finally at the end of the project you can write the specifications. In other words, it's the reverse of Waterfall:
  • Test
  • Implement
  • Design
  • Specs
Naturally it's easy to run into problems early if you don't know what your design and specs will actually end up as. And just because you are constantly refactoring when you encounter a problem doesn't mean you refactored in the right way. Knowing something needs fixing is different from knowing how to fix it. Sometimes your next attempt isn't even an improvement on the last issue.

That said, it's is a clear improvement over Waterfall. It's easy for Extreme Programming to beat Waterfall in the same way that it's easy to beat a blind man in boxing. Just because you won doesn't mean you're any good.

Waterfall is always bad, but there's "good" Extreme Programming and "bad" Extreme Programming. Whether or not Extreme Programming works depends heavily on how you skip between the different ballistic steps. Sometimes you start in specs and move directly to implementation, then before you even get to test, you detect a problem in design. You fix the design problem, quickly make an implementation fix to reflect it, and then test it. In you can skip from any step to any other step if you are truly following the fast turn-around tenet to its optimum. In other words, Extreme Programming is just another name for:

Cowboy Coding

Losely put, Cowboy Coding is a system in which "every man does as he sees fit." No system can ever tell you the optimal way to construct the program. There will be speccing, design, implementation, and test, but who knows in what quantities and chronology. Good programmers just know from experience and intuition when to move to the next step. Now cowboy coding is used pejoratively by some programming methodology evangelists, especially those in the Agile community (a subset of extreme programming). When bad programmers try to use Cowboy Coding, the result is always a train wreck. But ironically it's the only good part of Extreme Programming, even if its proponents don't realize it. Think about it like this:

Software design metholodigies instruct programmers when to switch from one ballistic step to the next. Sometimes the methodology's suggestion is optimal and sometimes it is not. Good programmers will generally outperform the methodology's suggestions and almost never do worse. Bad programmers don't know why the next step is the correct one, so even if the methodology suggests the right step, their chances of doing the next step well are low.

You can lead a man to reason, but you can't make him think.

No amount of restriction on the software design process or programming language can turn bad programmers into good ones. They tried this with languages like Java and Python, and while they are fine languages, bad programmers still write equally horrific code in them. So you are better off optimizing your design process for the good programmers and letting natural selection weed out the bad ones.

No comments: