Wednesday, 21 November 2007
Miranda was born last Thursday, a healthy little girl 53cm long and weighing 3.77kg. Her big sister Karina, (now three and a half) and Geoff and I are all doing well.
I hope to be at home with Miranda for about 6 months, so I don't expect to write much here for a while.
Monday, 5 November 2007
About TDD with TextTest
I begain using xUnit in 2000 and have been improving my skill at TDD ever since. Recently though I have been working less and less with xUnit tests, and more and more with using TextTest tests to drive development. This approach seems to preserve the original spirit of TDD, ie the tests are still driving development, but there are some differences and advantages.
When you use TextTest to drive development, your tests all end up being written in a representation that is separate from your code, ie a kind of Domain Specific Language (DSL). Your tests can be read and understood by anybody who understands the domain of the system under test, that is, they don't have to be able to read or write program code. You typically don't write new code when you write a new test, you just specify new desired program behaviour using this DSL. This makes it quick to add new tests, and easy to refactor your code later, since the test doesn't place any demands on the internal structure of your program (its classes and methods).
With xUnit tests, each test is only working with a small section of code, whereas a TextTest typically drives a path through a whole system or subsystem. This means that you need to use another technique to get fine grained visibility of what your code is doing. Instead of turning to a debugger, the approach with TextTest is to include log statements as you code. Having your application write a log is not a new idea and there are a number of excellent logging frameworks out there. TextTest allows you to not only specify the behaviour of your application in terms your customer will understand, but also control the application logging behaviour. When you make a code change, and your program no longer behaves the way the customer wants, (you introduce a bug), you can turn to the recorded application log to pinpoint exactly where program behaviour deviates from that previously recorded. So a test case consists basically of program input, expected user-readable output, and an application log.
TDD with xUnit is also generally accepted to be a design technique as well as a testing technique. I think there are two reasons for this. Firstly, just the fact of having these tests in some sense forces you to make good low level design decisions. Your code must exhibit loose coupling and high cohesion before you can extract units of code to test. This is desirable, and TextTest does not force you to do it, since it tests at a higher level of granularity. (On the other hand, if you are starting with poorly structured legacy code, where easily extractable units are hard to come by, you can get going with TextTest more or less immediately just by adding some (hopefully) harmless log statements. But I am not talking about legacy code in this article).
The second way in which TDD affects your design is that it forces you to think about the interface to your class before you define the implementation. This is low level design - choice of class and method names, and what arguments you give them. This is useful because thinking about the interface before the implementation should lead to a better, cleaner interface that is easier to use. TextTest doesn't help much with this either. It will force you to start by defining the interface to your whole program or subsystem, but it won't help on the class level. So when developing with TextTest we suggest something called “usage first” design. Start with the external interface to your program, and write code as if the classes and methods you want are already there. Then fill in the implementations, always working top down, and defining the usage of a class or method before your implement it. This takes some discipline, but leads to a similar effect to using xUnit.
About Code Katas
A code Kata is an idea introduced by Dave (Pragmatic) Thomas. He points out that specialists in other disciplines do a lot more practicing than programmers do, in order to improve their skills. Others have further developed this concept into the idea of a “Coding dojo”, or a place where programmers meet to practice code Kata together. The website www.codingdojo.org is a resource for these communities, and amongst other things has a catalogue of various code Kata exercises various individuals and groups have worked on.
About the KataMinesweeper screencast
So that is all the theory, how does it work in practice? In this screencast, I demonstrate a PreparedKata of KataMinesweeper, using TextTest to drive development, in python. During development, I aim to work in a Test Driven manner, and I want to develop top down, usage first, in small steps. The idea is that although in real life you may not be so strictly test driven, or exclusively top down, or use such small steps, that it is important to know how to do these things, and they are worth practicing on a toy problem like this.
My aim is to demonstrate what it is like to do TDD with TextTest, and how you might solve this code Kata using the python programming language. If you would like to comment and give me constructive feedback on this screencast, I would love to hear from you.
The screencast is in four parts, and I estimate each part will take you about 10 – 15 minutes to view.
Thursday, 25 October 2007
At the XP2007 conference, Geoff and I presented a workshop entitled “The coder's dojo: Acceptance Test Driven Development in python”. (Geoff also presented the same workshop at agile2007). We had three aims with this workshop, the first was to use the meeting format of a coders dojo, the second was to do some coding in python and the third was to demonstrate how you can do Acceptance Test Driven Development using TextTest. We felt the workshop went well, we had around 30 participants and we were able to do a little of everything we had set out to do.
Perhaps the most important thing was what we learnt from the experience. The workshop participants gave us some very useful feedback. One thing people said was that there were too many new ideas presented to expect as much audience participation as we did, and that instead of trying to do a Randori style kata, we should have done it as a Prepared kata. There also seemed to be a view that the Kata we had chosen (KataTexasHoldEm) was quite a difficult one. Another very valuable piece of feedback was that we were doing Test Driven Development (TDD) with much larger steps than people were used to.
What I have done is to create a screencast in an attempt to address this feedback, and open up our workshop material to a larger audience. In it, I perform a Prepared Kata of KataMinesweeper, doing TDD with TextTest and python. Geoff and I have been developing this approach to testing for a few years now, and we think it deserves consideration by the wider agile testing community. There are important advantages and disadvantages compared to classic TDD with xUnit.
I will write an article about this approach and provide links to the screencast in my next post on this blog.
Friday, 19 October 2007
Bob clearly doesn't plan his interviews or think in advance about what questions to ask. He just seems to sit down and chat with people as if he were in a bar somewhere and happened to have a microphone on the table. He often assumes his listeners know the background of the person and what is being discussed, and doesn't ask people to elaborate. Bob also tends to interrupt the person he interviews and presents his own opinions rather than getting them to elaborate on their views.
It's a far cry from the other podcasts I like to listen to, where the interviewers are really professional, for example Bob McDonald on Quirks and Quarks, or Greg Galant on Venture Voice.
Anyway, as I said, Bob Payne does interview some interesting people. I listened to this podcast today, where he was talking to Dave (Smalltalk) Thomas. They rambled on at some length about different programming languages and platforms, and Dave started talking about what he called "boutique" languages, APL being a case in point. What he said about this community totally corroborated what I discovered when I met a couple of APL programmers recently. There aren't that many of them, they mostly work for financial institutions, and they collaborate very heavily with their business users/domain experts. This article by Stephen Taylor gives a flavour of how this community works, and talks about a kind of pair programming between an APL expert and an end user. It sounds really cool, actually, and highly productive.
Bob Payne is clearly a Ruby community member, and Dave (Smalltalk) Thomas is in the Smalltalk community. I mostly count myself part of the Python community these days. Each programming language community seems to have its quirks and personalities. Of the communities I've hung out with to any extent, I've noticed that the Ruby community seems to be really friendly and welcoming to newcomers, whereas the python community can often seem very aloof and somehow intimidating. The Java community is so enormous it doesn't seem to notice other communities exist, or have anything useful to offer, although it's a few years now since I've hung out with them, and they may be moving on.
I think these "community personalities" arise partly because people move between language communities slowly and infrequently. Once you get good at a particular language it is always easier to stick to it than learn a new one. In their first book the Pragmatic Programmers advise you learn a new language every year, but I'm sure only a vanishingly small proportion of programmers manage this, and even fewer go on to get involved in more than one language community.
I am really interested to see what will happen with all this talk of Polyglot programming that (amongst others) Neal Ford has been talking about - they predict that in future your average system will be built from a number of parts written in different languages, each suited to the task in hand, running on one of the major Virtual Machines - .Net or the JVM.
If this does indeed happen, I think it should result in a major shakeup of the way programming language communities operate and interact, and I believe this will be really positive for the industry. At the moment I feel like their are pearls of wisdom hidden in each separate community, and not enough people are moving around to pick up the pearls and distribute them to the others. Dave Thomas must be one of the few who has insight into more than just one. Maybe one day more programmers will be pairing with end users just like the APL guys have been doing for years.
Thursday, 4 October 2007
I had never really seen RSpec or Behaviour Driven Development (BDD) before and I was quite fascinated by it. It's basically Test Driven Development but with different words for everything, and much more human readable tests, or "examples" as they are known.
One of the other challenges we faced at this meeting was that we were developing on a Mac, which is an unfamiliar environment for most of us. There was one participant, Håkan, who was particularly fased by this. He obviously usually touch types on Windows and is very familiar with that keyboard layout. He persistently kept hitting what his fingers thought was the "home" key, that on this Mac had the effect of making all the code disappear from the screen. He must have done it a dozen times in five minutes, which was very frustrating for both him and us.
I thought it was a good analogy for how I felt faced with RSpec, when I have been working with xUnit for so many years. I must have said "let's run the tests now" or "that test is failing because..." a dozen times. In BDD they are not tests they are examples! By about the 5th time I said it people just got fed up with correcting me.
So it seems to me that if Håkan wants to start writing code on a Mac regularly, he's in for a frustrating time while he teaches his subconcious new habits. Likewise if I am going to learn BDD. The question is, is it worth the effort?
For Håkan, my immediate reaction is that learning a Mac keyboard wouldn't be worth it for him. I don't see the Mac keyboard as giving any great leap in productivity over a Windows keyboard, so the cost of switching would be prohibitive.
The potential benefit for me to switch from TDD to BDD is less clear to me. Would this change in language actually significantly improve the way I do software development? For the moment I plan to keep an open mind on the subject.
I have found out that he used a piece of software called wink to create the screencast, so I am currently working on one of my own. Watch this space!
Sunday, 23 September 2007
"One view, to paraphrase Kent Beck, is that manipulation is when you wouldn't getSomeone pointed out that they recently went on a training course where during one of the exercises, the course leader was not up front about its purpose. Afterwards he felt that this manipulation had led to a new insight that he was thankful for.
the same effect if you were upfront about the intervention."
(This quote is attributed to Michael Feathers)
This reminded me of an experience I had many years ago on a similar training course, which was long before I or anyone else had ever heard of agile. As software consultants we were supposed to be learning about the social aspects of our profession, and it was about the third day. The instructors had been interleaving lectures with little games and activities designed to illustrate what we had been learning. The exercise that sticks in my mind went like this.
We were instructed to divide into two groups, and each group was given a datasheet of information and a description of a problem to solve. We were put in separate rooms and given a suitable time limit. We were encouraged to examine the problem, the related data, and report back a suitable solution to the problem to the instructor within the time limit.
In our group we carefully read through the problem and datasheet, and using a whiteboard made connections between the various pieces of information. We quickly discovered that there were large gaps in the information we had and that it was rather difficult to solve the problem. We questioned our instructor about this but she said she had no further information for us. We used our initiative, we thought laterally and came up with what we thought was a reasonable solution. Towards the end of the allotted time we reported back to our instructor our best guess at a solution. She told us that it was wrong.
The other team had not managed to solve their problem either, and when we joined together to discuss what had happened, it turned out that both teams had actually been given the same problem to solve, but each had only half of the needed data. So the only way to successfully complete the exercise would have been for the two teams to pool their knowledge and come up with a joint solution.
I have to say that after 3 days of these kind of exercises I was pretty fed up and I wasn't the only one. There was a general feeling of being cheated and misled and that we had been set up to fail. In most of the other exercises we had done, talking to the other team would have been considered cheating, since in several of them had been set up as competitions.
The instructor explained that what she wished us to learn from this exercise was that in real life, if your team doesn't have enough information to be able to write the software, go and talk to the customer. This is a good thing to learn. However, it is not the insight I took away from the exercise. For a start, in real life you know who the customer is and if you don't have enough information, you know it is not against the rules to go and ask.
In general, I think that this kind of teaching technique can work really well and be a good antidote to endless lectures. However I think it can be done badly, as in this case. If your students come away feeling angry, cheated and misled, they are not going to be very receptive to your lesson, however well intentioned.
Wednesday, 19 September 2007
Let me tell you a story about a young developer called “Sue”.
Sue has just learnt all about eXtreme Programming. She has worked on an XP team with lots of pair programming, unit testing, refactoring, simple design etc and is totally converted. The world should be doing XP!
Sue hears about another application at her company which is in trouble. Let's call the application “Squirrel”. Squirrel has been in production for a few years now, the codebase is rather large and the internal design is somewhat confused. The Squirrel team is having increasing difficulty adding the features the customer wants in a timely manner. Sue is convinced what they need to do is to refactor the codebase and add lots of automated tests.
Sue manages to persuade her manager “Paul” to let her work on refactoring Squirrel. She gets a copy of the code out of the version control system and sets about writing unit tests and refactoring. A few weeks go by and Sue reports to Paul that everything is going really well. She has solved some significant technical challenges in order to put in place some unit tests and has a small suite that she runs regularly. She proudly shows Paul the test scores and some UML diagrams of how the code looked before her refactoring, and after. Paul is pleased at how much better the UML looks and when Sue asks for more time to improve the code further, he grants her request.
A few more weeks pass and Sue is starting to attempt quite ambitious refactorings. She really feels the Squirrel team is going to be delighted when they see how much better their code looks and how many tests it has.
Meanwhile the Squirrel team has been continuing to add features and fix bugs and are actually quite proud of the progress they have made with the small team available to them. The users of the Squirrel application have complimented them on how much more stable and usable the application is becoming.
After a few months, Sue, Paul and the Squirel team agree that the next release of Squirrel should include Sue's refactorings. The approach chosen is for the Squirrel team to take Sue's copy of the codebase, and integrate all the recent bug fixes and new features into it. Everyone thinks this will be straightforward using the advanced diff&merge tools provided with the version control system. Sue persuades Paul that this would be better than applying all of Sue's refactorings to the Squirrel team's version of the codebase, since she had made so many sweeping changes and her codebase had extensive unit tests.
It was a total disaster. Sue had introduced a huge number of bugs when refactoring. Sue didn't understand what the code was really doing, having never actually worked on the application before and having only the documentation to go on. She had hardly spoken to the Squirrel team in all the months she had been working on their code, even though their project room was a short walk from her desk. The unit tests she had written covered only a fraction of the codebase and often reflected her poor understanding of what the code ought to be doing.
The diff between the two branches of the codebase was huge and the integration work was difficult, time consuming and error prone. After a week or so the work was stopped, Sue was in the doghouse, “Refactoring” was a dirty word, and the Squirrel team went back to their old codebase.
So what went wrong? Sue clearly did not have enough understanding of the codebase in question and was not skillful enough to pull off the refactorings she attempted. She had too much faith in the few unit tests she had written and lent on them too much. Sue didn't think about the integration cost rising exponentially the longer she worked apart from the Squirrel team.
However, I think it is Paul who really carries the blame for what happened. As the manager responsible for both Sue and the Squirrel team, he should not have allowed Sue to continue working alone for weeks on end producing only UML diagrams and unit test reports. Paul should have anticipated the integration problems even if Sue didn't. He should have asked to see working code – if he had sat down and manually tested Sue's copy of Squirrel, he would have found serious bugs within minutes.
Well, thankfully Sue wasn't sacked immediately and was given a chance to redeem herself. Sue joined the Squirrel team and started working on bug fixes and customer features. She quickly gained more understanding of the code than she had ever got working alone. Sue did put in place a few unit tests and do some refactoring, but it was always in the context of whatever bugfix or feature she was working on at the time. Most of the big sweeping refactorings that Sue thought would make a difference were never implemented.
The customer was happy for a while but the pace of new feature addition was still a bit slow for them. The customer also discovered that they could get a much better product from a competitor. So a couple of years later they dropped Squirrel. Happily for Sue, by then she had found a better job with a more competent manager.
Tuesday, 18 September 2007
At the SaoPauloDojo meeting they clearly decided to start with the most interesting part of the problem, ie counting mines, and didn't get to the part that deals with input and output strings. I think this is a shame because they have jumped straight to writing tests that assume the minefield data will be a list of lists. I am not convinced this is the best data structure, and all the tests they have written are very coupled to this design decision. For example:
campoMinado = CampoMinado([[0,0,0],[0,0,0],[0,0,0]])
campoMinado = CampoMinado([[0,0,0],[0,0,0],[0,0,0]])
campoMinado = CampoMinado([[0,0,0],[0,0,0]])
I think that tests at the acceptance test level should be as independent as possible of these kinds of design decisions. Not only that, the acceptance tests should be readable to a non-coding domain expert. I would prefer to see tests that look more like this
input = """\
expected = """\
But then of course one of the first problems you have to tackle is how to handle the I/O rather than the perhaps more interesting problem of how to count the mines.
In the problem description the acceptance tests are already set up as plain text input and output, so for me it would be very natural to tackle the problem using the tool TextTest to drive development instead of unit tests. This is a technique that Geoff and I have been working on recently, we presented a workshop together at XP2007 and Geoff by himself at agile2007 exploring this idea. By using this technique you isolate your acceptance tests from the current implementation of the code and I think this makes you more agile. You can refactor your code as much as you like so long as the external acceptance tests still pass. I'm working on an article which will showcase this technique that hopefully I will get around to finishing soon.
I'm also planning to tackle this Kata together with my local dojo group - the Gothenburg Ruby User Group (GRUG) tomorrow evening. We are planning to use Ruby, RSpec and BDD, so it should be interesting to see what we come up with and how decoupled our tests are from the internal design of the code.
Friday, 14 September 2007
I'm a bit nervous actually. I haven't had a blog before. I'm hoping that it will turn into a place for me to write interesting articles about coding, which is an activity I enjoy. (I enjoy cooking too but I don't expect I will be writing about that so much.)
I hope I might comment on stuff other people write on the web. I also hope my writing skills might improve by doing so. So we'll see. I think someone wrote that the average blogger gives up after about 3 months so that might happen too. I am expecting a baby in about 8 weeks time so I may not even last that long. Anyway, my next post should be more interesting than this one.