Firstly, as a massive caveat to this post, let me say that I’ve only ever worked for two companies. I have worked on different teams within these, but nonetheless I realise I don’t have a wide range of experience here. This post details some observations based on my personal experience of pair programming over the last four years.
Last week I gave a lightning talk about my experiment with Test Driven Development.
It’s available on Vimeo here.
There were some clear advantages to the TDD approach to writing. In particular, writing the acceptance test first made me focus on exactly what I was trying to achieve. In some ways this is similar to writing an essay where the title is some statement you have to argue for and against to prove or disprove the notion.
Breaking the review down into units was super useful, although this is something I would always do when writing anyway, as in most cases each unit became a paragraph. I also found myself refactoring as I realised a unit was doing too much, and I separated it into multiple units. For example I started out with a single unit called ‘Plot’, which had separate tests for facts about the plot, my opinion, and the ending. This was clearly violating the single responsibility principle and doing too much so I broke it down into 3 separate units.
Perhaps more useful was breaking each unit down into tests, which meant I had to focus on simply fulfilling the test criteria. It is a useful approach in a situation where you have a strict word count imposed. Maybe a journalist could use the TDD technique for writing an article? Strict adherence to this rule of simplicity means avoiding waffle. Certainly I could have been more strict about this here. However while I agree that simplicity is important in writing, it is arguably more important in code. Good unit tests mean nicely decoupled classes, whereas writing the book review I felt I wanted a common thread linking it all together.
The major downside to the TDD technique is that writing is incredibly subjective. How on earth do you prove you’ve achieved something that is different for different people? Without constantly being able to run the acceptance test and just assuming that it was still failing I was not able to develop in small increments. This made me appreciate how useful automated tests are, something I have perhaps taken for granted before now.
I felt like I was having to take some big jumps to get to the next test, which means my tests were not driving my design. How different is this from writing software? You still have to make a decision about what to test, what test to write, etc. As long as you are strict about keeping the implementation as simple as possible, the code is still driven by the test.
I worry that I have I been less creative because I worked in this way, as I was forced to write only what was necessary for each test. In some ways the restriction here may have helped me be more creative, as I had to think about the minimum I could write in order to pass the test. Similarly in software development, by writing the minimum code to pass the test we often write code we would not have otherwise considered. Moreover any creativity you may have lost in the initial development you can add later when refactoring. By this point you have a safety net of regression tests. This is something I don’t have without automated (or at the very least, repeatable) tests.
As I had no real idea where or how to start writing the rigidity of the TDD approach helped me get something down on the page. Likewise when test driving software the act of writing a test focuses what you are going to do and limits the scope. This can help you get started, but if you already have lots of ideas the rigidity may slow you down.
Dan North has been talking for a while about the trade offs you make when doing TDD (loss of initial speed versus reliability and simplicity of designs). He also advocates the “spike and stabilise” method. I wonder if this would be a better approach for writing. I don’t feel that the acceptance test helped me go faster, because there was not an easily repeatable way to run it. It is certainly useful to define your objective before you start so you know what you are trying to achieve. But without an objective way of knowing that you have achieved it, this can never truly drive your design.
I have an acceptance test:
Given a review is written about a book
When I read the review
I know if I want to read the book.
To set up the given, I need a book and a review. I’ve picked Ender’s Game by Orson Scott-Card as this was the last book I read.
I need some sort of introduction where I tell you what the book is. There’s going to be something about the plot of the book. Something about the characters. Probably more in the middle, but definitely some sort of conclusion. I treated each of these things as a unit and test drove each one. Continue reading
I am often asked about how a history graduate ended up being a software developer. Usually I give some vague spiel about the parallels between the two (see my earlier post). A while back I got talking about TDD in the same breath, which led me to wonder: can I test drive an essay? It’s been too long since I’ve written an essay (and I can’t say I miss it), so I decided to test drive a book review instead.
Why do we need tests?
It’s the same reason I have brakes on my bike. The brakes allow me to go faster. More importantly, they allow me to go faster safely. I remember spending ages writing essays at university. Is TDD a technique I could have used to write my essays faster?
What exactly is Test Driven Development?
You write the test first and use the test to drive your development. Specifically you do as much development as needed to pass the test – and no more. In the case of writing a book review, the development is the writing itself. To write the test first you have to know what you want to achieve.
So what is the purpose of a book review?
A book review is something that tells you enough about the book that you can work out if you want to read it yourself or not.
My requirement then, is: As a user I want to know if I should read a particular book.
Therefore we have the following scenario:
Given a review is written about a book
When I read the review
I know if I want to read the book.
A while back my sister, who teaches at a secondary school, asked me to give a talk to her students about what I do. After some initial resistance (about six months), I decided I’d do it.
I started thinking about when I was at school and how I had no idea what I wanted to do with my life. In many ways I am none the wiser now, but I have found something that I enjoy doing, that challenges me, and that I can keep on learning as I do it. This may not always be the case, but it is for now. At school I just did as I was told. I got good grades, I went to a good uni, got a good degree. Then it was all a bit scary as I was suddenly on my own and free from the expectations of my parents and teachers / lecturers. There was a vague idea that I should get some sort of job / career, but it was a lot more fuzzy about what this should be and what ‘good’ actually meant in this context. Basically it was now a lot more about what I actually wanted rather than what other people wanted for me. And somehow I ended up going into IT and now I’m a software developer. Rather surprising for a history graduate, but it’s worked out pretty well.
There are a lot of parallels between writing a history essay and writing software that I would never have thought of. Essentially both consist of a problem that you need to solve. There are lots of ways the problem can be solved, but no ‘right’ way. The same rules apply in essay writing and software writing: clarity and simplicity are better than complexity and over-cleverness. I was once told that a mark of a good essay was if you could read it all at top speed (with as few pauses for breath as possible) and it still make sense. This doesn’t quite apply to software in the same way, but it’s pretty close. If you can’t understand what the code does after a quick look then it’s probably too complicated. A colleague uses what he has termed the ‘squinty eyes test’ – the code passes if you can squint at the screen and it still looks readable (this is as much to do with good formatting as concise code, but still applies.)
Another similarity between writing an essay and writing software is in the different ways you can slice up your problem and solution. When I was first taught how to write a history essay I was told to chronologically detail what happened. Thing A happened because of Thing B, which then caused Thing C. But history is rarely this simple. It is more likely that D, E and F also had an effect on C, and that A would never have happened without C. So then I was shown a more sophisticated writing style which involved breaking things up into different topics. Then I could analyse how each topic relates to another, in an approach that more represents object oriented programming. I’m not saying that an object oriented style is necessarily more sophisticated, but it is a style that makes more sense when looking at the bigger picture (although can be harder to think about when you first consider the problem).
Anyway it’s fair to say that if you’d told me when I was at school that I would now be a software developer, I would not in a million years have believed you. In fact it’s likely that I wouldn’t have known what a software developer even was. I studied IT at GCSE but I seem to remember my friend ‘helped’ with most of the practical work (which mainly consisted of doing crazy things in Excel) while I wrote it up. (And I got an A* while he got a B – shows how screwed the exam system is). I figured it could be useful to enlighten the next generation about IT jobs in the real world (not that I’m arrogant enough to think that they will actually care what I have to say!)
I guess the other reason I changed my mind (and why I started thinking about this at all) was that I’ve been to a bunch of talks lately where I feel that I haven’t really learnt anything new. I don’t mean this as a bad thing. I’ve been at talks where I’ve thought ‘I know that, I agree with that’. I’ve still enjoyed the talks, because they’ve given me the chance to think about things and because they’ve let me see that other people think the same way as me, and that’s really useful. So while I’m pretty nervous about having to get up in front of a bunch of sixteen year olds and talk about being a software developer, I’m actually pretty excited that I get the chance to share something I’m passionate about. If that makes me a geek then so be it.
After six months of calling myself a tester I am moving back into development for the forseeable future. However my time in testing has really opened my eyes to its importance in software development. The following ‘commandments’ are important lessons I have learnt about testing, in roughly the order that I learnt them.