Beautiful code, test-first Jamis 24 Mar 2006

37 comments Latest by danielle

I was talking with a friend recently and discovered we have a failing in common: we both have a tendency towards a peculiar form of perfectionism. He was telling me how he feels like he has to sit and tweak his code over and over until it not only acts right, but looks right. It cannot be merely functional, it must be beautiful, as well.

I’d never before thought about it, but I realized that the way I keep this tendency from dominating me is to write my code test-first. I constrain the behavior of my unborn code with tests, and find that it leaves me free to consider the esthetics of the solution as I work. Otherwise, I have to waste effort playing with the cotton-candy cloud of requirements, making sure the code I’m writing is satisfying those nebulous demands, and that in turn distracts from the higher-level concerns.

This has the side-effect of making me happier and more productive in my job. When the code I’m working in is ugly, or messy, I’m less inclined to do good work there. It’s like having to hang a picture in a messy room—what does it matter if the picture is a little crooked, in the midst of so much chaos? It’s demoralizing.

On the other hand, if the code is clean, concise, and attractive, I will work harder to keep the code in that state. I’m happier doing it, too. My morale remains high.

I encouraged my friend to give test-first development a try, for a month. If you haven’t tried it for at least a full month, you ought to take the challenge, too.

37 comments so far (Jump to latest)

Paul Ingles 24 Mar 06

Not to mention that if you develop test-first you’ll have great test-coverage and the freedom to then refactor (beautify) your code safe in the knowledge you don’t break anything.

Test-first isn’t just about making sure the code works right though, it’s an aid to a design process that can evolve your thinking. Testable code is often better designed, so your API becomes beautiful too.

That’s the big reason I like Rails, it makes test-first web development such a joy.

Morten 24 Mar 06

David, I recall that you took that challenge once, how did you fare?

As for spending too much time on making the code looks right down to the last indentation - my code has been called “girl code” for the same reason..

not a programmer 24 Mar 06

so, for all the non-programming just-plain-curious readers… can someone explain what test-first coding means in plain english? Seems like an interesting discussion, I just want to be able to follow it :)

ramanan 24 Mar 06

You’d write the test cases your not-yet-written program is required to pass. If you were writing a program that counts words in a textfile, you’d write up a bunch of textfiles up that would test all the quirks invovled with counting words in a text file. The idea is that doing this upfront helps flesh out in your head what it is you’ll need to get done when you start coding. Also, doing so upfront means you have working test cases you can test against as you code.

James 24 Mar 06

@not a programmer

An analogy can be made about what test-code first is. Think of creating a specification for a widget. You want to somehow test that your widget is within specification, be it height, weight etc.

With test-code first methodology, what you do is creat the “test” for making sure your widget is within spec. (height, weight, color etc) first and THEN you create the widget.

Rob 24 Mar 06

Hmmm. I’d never thought about this, but I suffer from the same affliction as your friend. Might have to take that challenge. Are there any resources that can help someone trying to learn a new way of thinking figure out how to get started?

I understand that it’s a fairly intuitive thing, but some suggestions for how to re-train your brain in this way would be helpful.

John 24 Mar 06

I totally feel you on that! I recently tried this for the first time, and I dont think I could ever go back to the old way.

I have been learning Ruby, and Rails, and I wanted a random haiku generator for the cms I am developing for my site. I wrote all the haiku segments, and then went to work in Ruby. I had the whole thing done in about an hour.

Good Stuff!

Jamie Fehr 24 Mar 06

Well, now that I have been formerly challenged to write test first I will have to give it a shot. Wish me luck

M. Longfellow 24 Mar 06

What is a code test (I’m not a coder).

Alex Bunardzic 24 Mar 06

The analogy with hanging a picture in a messy room is right on. This is exactly how we all feel when dealing with messy code. What’s the point in tidying your portion up, if the surrounding ambiance is a pig sty? Very hard to get motivated and get the work done.

That’s why I’ve been extensivelly guilty of ‘beautifying’ my colleagues’ code. I cannot begin modifying someone’s code until I first go through it with a fine toothed comb and iron out even the smalles easthetic wrinkle. Then, I give it a final quick survey, and if it pleases my aesthetically snobbish eye, I agree that I’m ready for ‘real’ work. Otherwise, I cannot force myself to start modifying.

This, of course, is a double edged sword. Because when the modified code goes over to another developer, they then twist it and turn it to accommodate their particular aesthetics. And so the dance of deception contiues…

Regarding test-driven design: it can be deceptive. Beware falling into the ‘this is now bulletproof because it passes all my tests’ trap. Your tests are far from being exhaustive, no matter how big of a domain expert you are.

Chris Mear 24 Mar 06

i don’t quite get the link between writing tests first and resisting the temptation to waste time prettifying your code.

Are you saying that by writing tests first, it encourages you to write nice code in the first place? Or are you saying that tests-first focuses your mind away from trivialities and towards real results?

I mean, I can easily imagine writing some tests, then writing some good functional code, and then still wasting hours making it look nice.

Saulius 24 Mar 06

All this sounds nicely, but what about those situations when you need something done yesterday? In real life, you often do not have time for anything more than quick’n’dirty php code (hey, it is soo well suitable for that!). Customer wants to see a working system now, forget the nice code…

Paul Ingles 24 Mar 06

Writing code test-first focuses your mind on what you actually want and need, you end up not wasting time on unnecessary trivialties and blind-alleys. This can be further helped by working with someone else, pair programming in the agile methodology sense — something I’ve found _very_ useful.

Saulius: This is something I’ve directly experienced and on a number of occasions have been encouraged not to write tests. Every time it has come back to haunt us. Admittedly, this wasn’t just a simple site and thus couldn’t really be described as quick ‘n dirty, but the untested solution caused us hurt.

As for believing your code is bullet-proof once you’ve tested it, that is indeed a fallacy. However, the design-aspects of test-first development are more concerned with the concept of evolution and emergence — you worry yourself with what you need to solve and then go from there. You don’t spend time working on something you won’t need. And as I said previously, an easily-testable solution tends to be a better designed one. Things just fit together!

There’s nothing at all wrong with beautifying code, but I fear doing so without unit tests! Of course, should you obsess to the point that nothing else matters, your customers will not be impressed! Small baby-steps works nicely :)

Thomas 24 Mar 06

I completely agree with this methodology, HOWEVER, for most of us in industry - we are not developing new applications, we are actually maintaining old ones.

I agree with Chris Mear that I am having a difficult time seeing the connection between creating unit tests first and this helps to make ones code “beautiful”. (For what it’s worth, this is one thing that Python is great at - since it requires indents, in the most part everyones coding style is the same b/c of it).

Paul Ingles 24 Mar 06

Thomas: A lot of my work in the past has been in maintaining code, after all, as soon as it’s written it’s essentially legacy. However, the key is to add tests as you go. I wouldn’t feel happy refactoring code without some kind of test. I’d thoroughly recommend Michael Feather’s “Working Effectively with Legacy Code” (http://www.amazon.com/exec/obidos/tg/detail/-/0131177052?v=glance) book for tips on how to work in a well-disciplined test-first way with legacy code.

Robert Hanson 24 Mar 06

Saulius said: “All this sounds nicely, but what about those situations when you need something done yesterday?”

This is one of those things that is difficult to explain if you haven’t done it. I get this question a lot, and it is hard to convince someone to test first.

I think that perhaps the only way to answer the question is to maybe ask one of you.

You do test your code, don’t you? Eventually?

With test-driven development you are just writing the tests first instead of last (evn if testing means running the app in the browser). The side-effect of testing first, which has been proven over and over, is that your code becomes cleaner, is easier to maintain, and has less defects. This last side effect is where you save all of your time.

The trick of course is that you need to learn HOW to test your code. This is the time consuming part, but it only needs to be done once. You need to learn how to use the testing tools for the language you work in. Once you have done this, the actual writing of tests takes very little time.

Bob Aman 24 Mar 06

Personally, I just need to test more, period. But I have to agree, my obsession with code beauty can really get in the way sometimes. Currently I’m wrestling with beauty/maintainability vs. performance.

Don Wilson 24 Mar 06

All of my code is perfectly clean because I develop faster the way I style my code. If I did it the easy way I would think way too much while developing.

Kyle 24 Mar 06

What do most people use for Ruby unit testing? Do people use:

http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html

What is the most popular library?

bleh 24 Mar 06

i find it hard to do test-heavy programming because often i’m just exploring an idea, figuring out if something is feasible and/or worth pursuing further.

rich 24 Mar 06

I have the same inclination. My CSS must be orderly looking, with the attributes in a very particular order within each rule (alphabetical) and everything nicely spaced, with comments describing briefly what a portion of the CSS refers to.

I think this stems from having good coding practices drummed into me at university, but i may have taken it to an extreme as I’ve never come across anyone who is quite as strict as myself when it comes to coding stylesheets.

Ryan Ripley 24 Mar 06

Why not borrow from the XP crowd….

“Make it work… then make it pretty…”

Seems more like a healthy balance.

—Ryan

Jeremy J 24 Mar 06

What do people tend to use for web testing outside Rake with Rails? (sorry, working with a large pre-existing python codebase) I’ve not seen any particularly good apps to do it, short of writing my own script that resets the test database and does testing through requests and regexps responses for expected words.

Vishi 24 Mar 06

Why repeat the ticket info in test again? Just make writing tests easier.

Fitnesse: http://fitnesse.org/FitNesse.OneMinuteDescription
and Seleniumn are a step in the right direction.

John D. Mitchell 24 Mar 06

For those wanting a good introduction to TDD, read a copy of Kent Beck’s book, Test Driven Development: By Example.

In terms of how e.g., TDD can help mitigate the obsessive-compulsive desire of perfection, the tests not only help direct what to (not) do but they also give very clear signals about when you’re done. This is especially the case when using (automated) acceptance tests — the acceptance tests are, by definition, the definition of “done.”

Rich Collins 25 Mar 06

I typically re-write code numerous times before I find what I want. Test driven development makes the prototyping / design process take WAY too long. I consider test driven development to be premature optimization.

You should write formalized tests to make sure features work before you release them. You should also write formalized tests to make sure updates don’t break things. You shouldn’t when you want to quickly try things out and see how they work.

Having said that, I still “test” my code to make sure my assumptions hold. Usually using the web browser or an interactive prompt. Test frameworks sometimes informal tests easy to carry out. Usually, they are a waste of time (rails functional tests come to mind).

mika 25 Mar 06

Is there any other seriously practised way than test-driven development? I don’t even know how I develop - noone showed me how to do it.

I code the program. I test it. If it works I add part 2. Isn’t that how it’s supposed to be?

ramanan 26 Mar 06

If it works I add part 2. Isn’t that how it’s supposed to be?

That is probably the simplest way to do things. There is a whole industry built around how to design, develop and test software. Google Software Engineering and you’ll see everyone has an opinion on the best way to do things.

Christophe Porteneuve aka TDD 27 Mar 06

Jamis,

Your metaphor about the messy room is very much along the lines of The Broken Window effect, discussed in the original Pragmatic Programmer book. It’s a very fundamental human behavioral issue.

On a sidenote, I love how Ruby code lets us express things elegantly and concisely, especially since consise+elegant code tends to perpetuate itself, precisely on account of nobody wanting to be the first gore-bringer in such a setting.

Mickslam23 27 Mar 06

Hi am a beginning developer, so I want to get this idea straight in my head. Ok, I guess I could use the test-first principle to test it, but..

These test cases, are they written into the code? I don’t undestand if they are explicit in the code, or if they are just a test case, like in your head. The pages I’ve browsed are a little beyond my level of Jargon.

If they are written into the code, how do you do this? Any links, pointers welcomed.

BTW - love this blog, site and products. Things are too hard to use right now, they should be easier.

Shawn Oster 28 Mar 06

Ryan Riply said…
Why not borrow from the XP crowd….
“Make it work… then make it pretty…”

For those that don’t know much about the XP methology they might think this is a slap it together and worry about making it pretty later, which is NOT what XP is.

Built into the concept of XP is part of what makes your code *work* is that it is *simple*. Once the code feels or “smells” messy then there is probably a problem. A better quote might be:

“Keep it simple, make it work, then add complexity”

Julien Couvreur 29 Mar 06

Test first not only gives you more freedom to re-factore, but it really guides you to writing modular and clean code.

I recently took a design patterns class and the most important thing that came out of it was the first coding principle: code should be testable. The reason for that is that testing is where most time is spent in the development lifecycle. If you follow this principle, you end up designing and writing good code.
You’ll find that the design patterns just “appear” in your code, when you keep testability as your goal when considering your options.

keith ray 29 Mar 06

TDD isn’t premature optimization because each test is dead-simple to write, and the test is by definition a “black box test” (because the code doesn’t exist yet.)

However, within a few minutes of writing a test, you write the code to pass the test.

And repeat. And refactor when you see duplicate logic or other code-smells.

You usually can try out various implementations without changing your tests. At least, that has been my experience.

Last time I wrote about TDD was … http://homepage.mac.com/keithray/blog/2006/02/25/

george 31 Mar 06

A different perspective on “girl code”:
As far as looks are concerned, I have personally experienced that my code is generally better formatted or well-formed than even some of the teachers’ at my school (Villanova). As far as my classmates are concerned, whenever I review a girl’s code it is an absolute mess. Of course I am aware that generally the “good looking” attribute is generally associated with the female sex, but in practice I have seen the opposite. As with all models, not everyone fits this form (and perhaps it is just the girls at Villanova whose code is not well-formed), but to me having my code be called “girl code” is an insult…

Julia 31 Mar 06

Interesting — I write a piece about this very thing recently called A Thing Well Made: “As a programmer I can strongly relate to this. There is very much a sense of craftsmanship when writing code. That fuzzy feeling when beautiful code works as you expected, and does it perfectly. The sense of having created something good in the world, something higher than mediocre, something that shines. Something to be proud of..” … then go on to talk about test-driven devt

Ed Kirwan 21 Apr 06

There are plenty of articles on code beauty out there, but they tend to fall down on two issues:

1) I’ve yet to see anyone post their code, showing us this beauty. SourceForge code is simply not that beautiful. Does anyone know of any code that someone’s published and thinks is beautiful?

2) I don’t know much about test-driven design, but I get the feeling that the tests that people write are very low-level tests, perhaps tests on methods. Do TDDers write entire test harnesses to test system-level behaviour before writing any code? The reason I ask is because I think there’s more beauty in design than in code; indeed that code is only beautiful in that it reflects a beautiful design. So if TDDers just write method-level tests, then I fail to see how TDDing makes beautiful code.

Just a thought …

.ed

danielle 10 Oct 06

u r all gay fucks

Post a comment

(Basic HTML is allowed)

NOTE: We'd rather not moderate, but off-topic, blatantly inflammatory, or otherwise inappropriate or vapid comments may be removed. Repeat offenders will be banned from commenting. Let's add value. Thank you.