Archive for August, 2009
Coding Dojo #21: TDD as if you meant it revisited
In this weeks dojo we decided to revisit the “TDD as if you meant it’ exercise originally invented by Keith Braithwaite for the Software Craftsmanship Conference but recently tried out at the Alt.NET UK Conference in London.
The idea was to write code for ‘tic tac toe’ or ‘naughts and crosses’ and we were following these requirements:
- a game is over when all fields are taken
- a game is over when all fields in a column are taken by a player
- a game is over when all fields in a row are taken by a player
- a game is over when all fields in a diagonal are taken by a player
- a player can take a field if not already taken
- players take turns taking fields until the game is over
The code from Alt.NET UK is available on Google Code and what I found quite interesting is that the solutions are really quite different to each other.
Our code is up on bitbucket and again it is quite different to the other approaches.
The Format
For most of this week’s dojo Dave and I just worked together on the problem although a colleague did come and join us for the last half an hour or so. We were just pairing on a Mac.
What We Learnt
- We coded in Java in eclipse which I haven’t used for about a year and I was really surprised at how rapid the feedback cycle was. We seemed to be able to write a test and have it failing within seconds which is brilliant and just the way it should be whereas I’ve got used to a much slower feedback loop when using Visual Studio.
- We noticed as we did the previous times when we did this exercise that you notice objects in the code that you wouldn’t normally have noticed if we hadn’t been writing all the implementation details in the test first.
The ‘Square’ object was one which neither I nor Dave had expected to exist. We had imagined that code would end up on the ‘Game’ object and interestingly just before our colleague joined us we had drifted from the rules of the exercise and actually written the outline of a method on the game object to satisfy the 5th acceptance criteria ‘a player can take a field if not already taken’.
Luckily we undid that and it became obvious that the new code should be on an object of its own so that’s what we did.
- The code we have at the moment has everything implemented just using booleans which felt really weird when we were writing the code but seemed to be the simplest thing to do to meet the acceptance criteria.
We discussed this at the time and it seemed that any alternative approach where we didn’t do this would end up with us writing a really big test (perhaps with players making moves), therefore meaning the feedback cycle would be really slow.
For next time
- I think it would probably be quite interesting to try out this type of exercise and commit to either Git or Mercurial after each of the small steps so that we could see the story of the code more clearly afterwards.
- During our discussion on Continuous Integration a few weeks ago it was suggested that we could some sessions on parallelising tests and writing impersonators during one of our coding dojos so we might look at doing that next time around.
Book Club: Object Role Stereotypes (Jeremy Miller)
In last week’s book club we discussed an article written by Jeremy Miller for MSDN Magazine titled ‘Object Role Stereotypes‘ which discusses part of Rebecca Wirfs Brock’s book ‘Object Design‘.
I’ve been trying to read Object Design for about a year since coming across the book while reading through the slides from JAOO Sydney 2008 but I’ve often found the reading to be quite abstract and have struggled to work out how to apply the ideas to the coding I do day to day.
This therefore seemed to be like a good opportunity to get some more opinions and discussion on at least part of the book.
There are some of my thoughts and our discussion of the article:
- Liz pointed out that at ThoughtWorks University (which we both attended) we were shown the idea of writing the ‘job’ of an object just above the class definition, the point of this being that we would describe the responsibility of the object and ensure that objects only had one responsibility.
Neither Liz nor I have ever seen this done on any of the projects that we’ve worked on but it seems quite related to the idea of responsibility driven development which is encouraged in the book. The different role stereotypes would form part of the responsibilities that an object might have.
Matt Dunn suggested that perhaps the tests we write fulfill this role instead in a more indirect way although I think we would probably need to be writing tests with the quality Jimmy Bogard describes in his post on getting value our of your unit tests, instead of the pale imitations we often end up writing, to achieve this goal.
- I find each of the individual stereotypes quite difficult to remember on their own but Jeremy pointed out that they fit into 3 categories:
- Knowing (Information Holder, Structurer)
- Doing (Service Provider, Interfacer)
- Deciding (Controller, Coordinator)
I think the object role stereotypes mix quite nicely with some of the ideas from Domain Driven Design – for example a value object would probably be an information holder; an entity might be a structurer and an information holder; a factory could be a service provider; a repository is possibly an interfacer although I think that may be more the case if we are using a repository as a DAO instead of a true DDD repository.
- I think it might actually be easier when looking at existing code to question whether or not a particular object is actually only doing one thing or not before analysing which of the stereotypes it is fulfilling. We discussed although didn’t come to a conclusion whether there are certain stereotypes that should not be mixed together in one object. For example maybe an object which acts as an interfacer wouldn’t store state and therefore might not be an information holder as well.
- We briefly discussed some other articles which cover similar ideas including Isaiah Perumalla’s article on role based objects and Udi Dahan’s idea of the roles being described more specifically in the interface name. Both of these articles have some good ideas and I find the latter particularly intriguing although I haven’t tried it out on any code I’ve written as yet.
- The article also has some great ideas around coding in general which I think make a lot of sense:
Don’t be afraid to create small objects instead of wallowing in the mud of primitive variables
Designing software is often an exercise in managing complexity…you can take steps to limit the complexity of any given class by only assigning it a discrete set of responsibilities
Bear Shaving
I recently came across a blog post by Seth Godin where he coins the term ‘bear shaving’ which is where we address the symptoms of a problem instead of addressing the problem.
The main example he gives is the idea of shaving a bear so that it can deal with the increased temperature caused by global warming instead of addressing the underlying problem which has led to this happening in the first place.
As with yak shaving which is certainly rife in software development projects, I think we are guilty of bear shaving as well.
Although similar to yak shaving, bear shaving seems to be much more intentional – noone ever means to end up shaving a yak but they sometimes do whereas we might deliberately choose to shave a bear because of one of the following reasons from what I’ve noticed:
- We don’t want to work out what the root cause of our problem is, perhaps because we don’t have the time to do so or it’s just easier to find a work around.
- We know what the root cause of the problem is but it’s too difficult to do anything about it.
- We know what the root cause of the problem is but we can’t do much about it because it’s out of our control (perhaps a bottle neck in another team for example)
An example of this that we have been juggling on our project is working out the best thing to do when the continuous integration build is red due to a failure related to an integration end point that is known to be flaky.
We’ve massively reduced the impact that this has on the early part of our build pipeline by introducing a self initialising fake but there are still some calls through to the service layer since we aren’t storing the result of every single call.
When those service calls that do go through each time are having problems we can often end up with several hours where we can’t checkin.
Even when this flakiness goes away we haven’t quite managed to reduce the random build failures down to zero which means that the feedback loop is not as quick as it could be.
As a result of this we have come up with two different ways of allowing people to continue working locally without needing to check into the main repository:
- Using Git as a local patch management tool and keeping different changes on different branches.
- Making multiple copies of the Subversion repository locally with different changes on different copies
The problem with both of these solutions is that people now have versions of the code sitting on their machines which the rest of the team hasn’t yet been able to integrate with.
We are having more individual productivity to a degree but we are also creating more work in progress which the rest of the team will later need to integrate against.
We haven’t only spent time coming up with bear shaving solutions though.
One of the problems we had was that often when a new version of services was pushed into the integration environment that was the first time that we actually integrated against it. We now spend some time integrating against services in a pre-integration environment which has helped reduce the number of surprises that we get later on.
Another potential solution to part of the problem would be to make use of a distributed source control system such as Git or Mercurial as the main repository that everyone uses and then push every change into our Subversion repository.
We’ve tried some of the Git to Subversion and Mercurial to Subversion bridges available at the moment and none of them have quite worked for us so we haven’t been able to pursue this option.
Given that we often have constraints that we have to work under perhaps it would therefore seem inevitable that there will be some amount of bear shaving on any project?
Think a little, code a little
I recently came across an interesting post by Frans Bauma entitled ‘Think first, doing is for later‘ which was linked to from Jeremy Miller’s blog entry about incremental delivery and continuous design.
Right now I find myself in favour of Jeremy’s approach which is more about writing some code and then getting some feedback on it and then writing some more code instead of spending a lot of time thinking before we write any code.
My colleague Brian Guthrie referred to this approach on twitter as ‘think a little code a little‘ which I think sums it up pretty well.
The example that Frans gives is centred around algorithms so I wonder whether a bit of up front design to work out that we understand the algorithm is necessary before trying to code a solution.
On the other hand something that we’ve noticed in particular at coding dojos is that putting an idea into code helps to generate a rhythm of progress which we’ve struggled to create just by talking about the way that we think we can solve a problem.
Even with algorithms I find that I understand them more easily once they are written in code rather than just spoken about conceptually or drawn out in pseudocode.
My current thinking is therefore that I’d prefer to spend a little time thinking and then get the idea into the code more quickly even if that means we make more mistakes and have to do a few iterations of the code to end up where we want to be.
The alternative is to spend much more time thinking up front and then maybe getting to the solution more quickly but maybe realising that our idea doesn’t work once we get into the code which means we haven’t got that feedback as quickly as we might have been able to.
A similar idea is discussed in Domain Driven Design where Eric Evans points out that while a model that we come up with on the whiteboard may seem perfect that doesn’t actually matter if we find out that the idea doesn’t quite work when we try and put it into the code.
Uncle Bob has also written about the difference between no design up front and spending some time thinking about what we want to do and while some of the activities that we would do while thinking through an approach would be similar to those Frans’ identifies, I don’t feel the planning would go into quite that depth.
There is definitely a need for some thought in the process, however – what I refer to as lazy coding is the extreme of what happens when we don’t think at all about what we’re doing and that leads to code which is completely unmaintainable and very difficult for both ourselves and our colleagues to understand.
Often when we do this type of thing we like to refer to it as ‘technical debt‘ but I quite like the distinction Uncle Bob has been making on twitter between technical debt and just creating a mess.
I find the former is done as a result of us thinking about what we’re doing and realising that we need to take on a bit of debt with a shortcut now and then fix it up later. The latter on the other hand seems to occur when we don’t think about what we’re doing and just do the easiest thing possible.
An idea which I do like from the post is the idea of documenting why we made a certain decision.
From my experience quite often that information just remains in the heads of the people who made the decision and then we are relying on their memory when we come across a bit of code in the future and want to know why it was written in a certain way. In Dan North’s language this would seem to be the job of the project sharman although I guess it wouldn’t hurt to have some of that information written up on the project wiki as well.
I would still probably do that bit of documentation after we’d proved that the code actually worked rather than before writing any code which is what seems to be the approach.
I guess this approach does work for Frans so there is certainly some value in it from that perspective but from the projects I’ve worked on working in smaller increments has worked more effectively for us.
Strong opinions, weakly held
I find one of the most applicable mantras in software development is Bob Sutton’s idea that we should have strong opinions weakly held.
The idea as I understand it is that we shouldn’t sit on the fence but instead have an opinion that we research thoroughly and are prepared to back up. However, we shouldn’t become too attached to those opinions but instead be prepared to listen to alternative points of view and take those on where they prove more useful than our previous opinions.
I think there are a couple of reasons why it applies quite nicely to software development.
The first is that it doesn’t really matter if you’re ‘wrong’ and it’s quite rare that something you do is completely wrong – normally there might just be a way of doing something that you didn’t think of previously or a technique that you didn’t know about.
For example, it’s fine to throw away code if someone shows you a better way to do something.
In this case you are expressing your opinion (through code) about the way that you think a problem should be solved and if someone shows a different way then we can at least allow them to show us their way and then decide whether or not we like it better rather than becoming defensive that there could be another way to solve the same problem.
This seems quite closely linked to the idea of beginner’s mind and the ‘one true solution’ anti pattern.
The former is about having an open mind when studying a subject much like you do when you are studying something for the first time. This was an idea I came across when reading the ‘Wear the White Belt‘ entry of Apprenticeship Patterns.
The latter seems to manifest itself when we don’t explicitly consider the trade offs that always rear their head when making decisions in the world of software development and remain convinced that our solution to a problem is the only one that could possibly work.
I also read another interesting post which described a situation where a team threw away working code because it no longer made sense to keep it around since it didn’t add value.
I can’t remember working on a project where we threw away functional code in that way but it is true that having code which doesn’t add value is a burden so I can certainly see how this would have been a good decision.
The other reason I think strong opinions weakly held makes sense is that so often an approach only really makes sense within a given context and then in another context we might do something completely different.
I came across a great example of this recently on my project when we came to the realisation that creating a completely separate domain model to that defined in the service layer we interact with was probably not such a good idea and that we would probably be better off just conforming to the service layer’s model of the system.
I was fairly convinced for a long time that this wasn’t the right thing to do but in this situation we don’t have access to the business to drive out a more accurate model and the piece of the system that we are working on probably wouldn’t derive a great deal of value from doing this anyway.
Therefore my opinion, which perhaps would hold in another context, didn’t really make sense here so I’ve adapted it and in the process made it more useful to me.
With both of these examples I had reasons for why I thought the approach I was taking was the best one and I was able to discuss these before realising that there was a better way and therefore changed my opinion to adopt this new knowledge.
These are just a couple of examples of me changing opinions based on being shown a different/better way and I’m sure there will be many more occasions when this happens in the future, it’s just the nature of software development.