I’m currently developing an online game for a client using The Server Framework. I didn’t realise that it was an online game when they originally contracted me. It’s become a useful example of emergent requirements. Each time I think the project is complete they come back to me and say “and now we want you to quote for doing X”…
Almost a year ago I published a series of articles on a piece of code that allows you to write TCP/IP servers on Windows machines. The Server Framework is designed to suit 80% of people’s needs and provide something that they can extend without needing to worry about the actual details of a high performance TCP/IP communications server.
Several people contacted me to extend this software for them. One of these new clients wanted me to add support for Secure Sockets Layer using OpenSSL. This seemed like an interesting thing to do, so I jumped at the chance. I did the work and wrote about it in Windows Developer Journal.
Given that the client had contacted me asking for a pretty specific addition to The Server Framework and that they’d implied that they just required SSL support and that they would be writing the server itself I’d assumed that it would be a rather short engagement. However, that wasn’t to be the case…
Once the SSL support was complete I was sent a request for adding a ‘basic game framework’ to the server. They supplied a rough spec, I quoted them a price and got on with the work. The framework was, essentially, a chat system that incorporated the ability to have multiple rooms. They were focusing on the server side code, but wanted a simple client to exercise the server code.
At this point I made a couple of rather classic mistakes. I over generalised my solution by making assumptions about how the rough description of what they wanted might be used and I provided flexibility that they hadn’t really requested… Given that I was providing more than what they wanted and given that these things came for free because of how I’d designed the solution I didn’t feel too bad about it at the time… I was hoping to save time if I got later phases of the work.
The game framework was complete. They were happy. Now they wanted a little more… Each new phase has been relatively small, reasonably focused and quite discrete. The specs are pretty good, but limited to the exact requirements of each phase. As the project has progressed I’ve realised more and more that the XP folks have it right when they say that you should do the simplest thing that passes all the tests… In this case the most important tests are my client’s requirements. These are now pretty precise and unambiguous.
Having so many small iterations with such limited requirements at each stage has made it obvious to me that my initial solutions have proven to be over engineered. They did what was required, but the design allowed for things that just haven’t been needed. I anticipated requirements for flexibility that never materialised. I tried to do more than was required and mostly I guessed wrong. It didn’t take any longer for me to provide flexibility so it seemed like a good thing to do. However, eventually it has become obvious that maintaining the extra code does take time, and after several iterations where the flexibility was still unused we’ve eventually removed it…
The problem with adding in a little extra flexibility at each iteration is that the extra code can grow almost exponentially. If the next phase doesn’t make use of the flexibility built into the code then you can find that you’re maintaining a framework rather than an application. You may find that it’s a framework in which only a small percentage of the code is actually used by the project that you’re working on… As I’ve said before, code that doesn’t get to run will rot..
For the last few iterations each requirement has been addressed with the simplest possible solution. As the later requirements build on the earlier ones we redesign as required. The redesign is quick becuase the original code has a simple design that does just what it needs to do to fulfill the requirements and no more.
I don’t need to design in unspecified flexibility in advance because I’m confident that I can redesign to deal with new requirements as they arise and that means that all the code that’s being written is actually getting used right away.
Every line of code provides business value to the client in this iteration.