Code Craft Code Craft
 
 
 

Design by code

(February 5th, 2007)

Imagine if I handed you a Rubic’s Cube and asked you to find the series of moves needed to solve it, but without actually moving any of the sides. Could you do it? I couldn’t (or at least I couldn’t without using another Rubic’s Cube or devoting an obscene amount of time to it).

Give a Rubic’s Cube to someone and within a few seconds they will be moving the pieces. This is because experimentation is the primary basis of learning. Experimentation is how children learn to walk and speak and tie their shoes. It’s how you learn to throw a football or swing a cricket bat. If you take a glance down the list of “sciences” and ask yourself which ones you trust the most, it’ll be the ones that are the easiest to perform experiments in.

This same understanding of the power of experimentation should also be applied to software design. For a huge number of problems the best way to figure out how to solve the problem is by writing “experimental” code. When you start writing code you are moving the pieces of the Rubic’s cube. You are doing work that advances you towards a solution and simultaneously adds to your understanding of the problem. It helps you quickly discover what you don’t know and it focuses your mind on the practical issues involved in the problem. I call this process “design-by-code” because it treats the initial coding work as an integral part of designing the product.

One of the reasons Test Driven Design (TDD) is successful for so many people is that it engages developers in this learning by doing behavior pattern. It is a design-by-code practice. Writing the tests reveals the real nature of the problem much more quickly than any elaborate analysis can. This is also true of other lightweight development processes that emphasize early coding.

None of this means we disengage our minds and just write the first thing that pops in to our head. The correct behavior is to think through the problem and come up with the best alternative you can and then try to implement it. As you implement, or perhaps after you implement, you will gain insights which you must then factor back in to what you are doing. Some people distinguish TDD from Test First Design (TFD) by saying that TDD adds re-factoring. After you do the work you refractor it. I’m inclined to go further than saying you “refactor” after you write the code. I’d say you might even redesign after you’ve written the code. While refactoring is all you need in most cases, sometimes you need to go further.

TDD isn’t the only way to benefit from design-by-code. Any process that involves developers in a cycle of quick evaluation, followed by semi-experimental coding followed by re-evaluation and re-coding can be very successful. This is one reason I encourage non-agile organizations to include working models as a part of their design cycle. Rapid prototyping and design spikes are also well-known design-by-code practices. How you incorporate coding in to your design process may vary, but if writing code isn’t a big part of that process don’t be surprised if you have a hard time making all the pieces fit together.

15 Responses to “Design by code”

  1. Paul Davis Says:

    A very insightful article. I Especially like the metaphor with the rubic’s cube.
    At work (a DoD project) a manager tried to compare the scheduling to that of building an airplane. He wasn’t happy when I pointed out that most new aircraft are 2000% over budget and schedule. Hell, software looks great in comparison.
    Mentioning experimentation just shows the “science” in computer science. Although we always guesstimate schedules pretty well, we are still trying to predict innovation. Ask biologist some day, “how long will it take for your team to cure aids?” The answer, sometime between 3 months and 30 years.

  2. Michael Rowe Says:

    This sounds a lot like the Pragmatic Programmer’s “tracer bullet” idea: http://www.artima.com/intv/tracerP.html

  3. Gerry Says:

    I couldn’t agree more. I write about the benefits about prototyping on my website as well. Once you have prototyped, your depth of understand has increased dramatically.

  4. Greg Buchholz Says:

    Tests seem a lot like modeling relations between data, similar to simple facts in a Prolog database. Do you have any thoughts on using declarative languages for prototyping and/or an executable specification language?

  5. Sharad Sharma Says:

    I completely resonate with this post - very well said. I have stopped coding now but am re-discovering this whole notion of “experimental coding”, this time as a blogger! I find that writing is quite like coding. You never get it right right the first time. And as you write new doors in thinking open up and you end up with something different, and better, from what you started. In fact I wrote recently about how writing an essay-type blog (like mine) is the Agile Programming version of writing a book… http://orbitchange.com/blog/2007/01/05/codingvsblogging/

  6. Apoch Says:

    Spot on. I was actually thinking about writing on this very same topic myself the other day, although my example was to predict how a complex sculpture would collapse, within the context of debugging. If you want to find problems in code, you bang on it, run it, and see what happens with the data as it flows through the code; just staring at it and trying to visualize it is never enough (at least once you get past the really trivial hello-world programs).

  7. Thomas Shine Says:

    See this site

  8. cc Says:

    Your post reminds me of something I read not long ago…

    http://www.bookshelf.jp/texi/onlisp/onlisp_2.html#SEC7

  9. szeryf Says:

    I think that TDD is to programming what `scientific method’ was to science.

    In scientific method you state some thesis, prepare an experiment to verify it, conduct the experiment, gather, verify and interpret the results, then confirm the thesis or eliminate it. In programming you know the thesis (like `this method does that and that’) must be true (because you create laws rather than discover them). The experiment is your test. You conduct it until it yields desired outcome, changing the laws of universe (your code) rather than changing the thesis.

  10. Paul Davis Says:

    szeryf,
    I think you win the contest for “best metaphor”.
    Time to start printing t-shirts ;-)

  11. Stephane Grenier Says:

    Great article! I completely agree. I’ve never yet seen a larger software application that could be completely, and correctly, designed from the start using the waterfall model. It’s a great idea, but it just doesn’t work.

    The other thing to remember is that you need to go back and refactor what you changed. I’ve seen it too many times where refactorings are only partially done if at all. This is just as important. It’s also important to not just hack a solution within an architecture that no longer works, you really need to be smart about it and refactor it. Too many people are afraid of refactoring when they shouldn’t be…

  12. Aristotle Pagaltzis Says:

    The correct behavior is to think through the problem and come up with the best alternative you can and then try to implement it.

    The key point is, you do not know if the alternative you chose really is best. You may have gaps and flaws in your reasoning that you do not notice because humans make a lot of implicit assumptions when thinking. It is how human thinking works: we understand things in depth. We are not stupid. The valuable thing about a computer is that it is completely stupid. It makes absolutely no assumptions about anything. The necessity of being entirely unambiguous and utterly explicit when expressing your idea in code, then, forces you to discover the conceptual gaps that your mind’s eye was blind to.

    Quoting etensively from the preface of Structure and Interpretation of Classical Mechanics:

    Computational algorithms are used to communicate precisely some of the methods used in the analysis of dynamical phenomena. Expressing the methods of variational mechanics in a computer language forces them to be unambiguous and computationally effective. Computation requires us to be precise about the representation of mechanical and geometric notions as computational objects and permits us to represent explicitly the algorithms for manipulating these objects. Also, once formalized as a procedure, a mathematical idea becomes a tool that can be used directly to compute results.

    And from the conclusion:

    When we started we expected that using this approach to formulate mechanics would be easy. We quickly learned that many things we thought we understood we did not in fact understand. Our requirement that our mathematical notations be explicit and precise enough that they can be interpreted automatically, as by a computer, is very effective in uncovering puns and flaws in reasoning. The resulting struggle to make the mathematics precise, yet clear and computationally effective, lasted far longer than we anticipated. We learned a great deal about both mechanics and computation by this process.

    Note that, unsurprisingly, what they say right after the first paragraph I quoted reinforces what you say about designing by experimentation:

    Active exploration on the part of the student is an essential part of the learning experience. Our focus is on understanding the motion of systems; to learn about motion the student must actively explore the motion of systems through simulation and experiment. The exercises and projects are an integral part of the presentation.

    Indeed.

  13. FollowSteph.com » Latest Links Says:

    […] Design by code Excellent article on how coding should be done. Great analogy! […]

  14. fekzgsmp - Google Search Says:

    […] […]

  15. The Mu » Blog Archive » Coder culture Says:

    […] For example, there’s this whole “code then think” problem we face — not to be confused with code first then design. The problem of course with experimental coding is that laying down some source usually gets you into a rut, where you’re loathe to actually chuck out the failed experiment.  You want to keep it and make it better somehow.  If a bad bunch of source survives through to a final product, it always costs tons of money to fix — certainly more than thinking a little longer up front would have. […]

Leave a Reply