Author: Mark Guernsey
Publisher: Addison-Wesley, 2013
Aimed at: developers working with databases
Reviewed by: Kay Ewbank
Test Driven Development (TDD) is a well-known and accepted technique for mainstream programming, but is less well known in the database world. Mark Guernsey aims to change that in this book where he applies the technique to database development.
The book is written in a relaxed style with lots of insights that are obviously gained from actually designing databases, and on the whole I felt Guernsey explained his points well.
One important point to note is that Guernsey uses object-oriented terms in the book rather than the more conventional database terms. I follow his reasoning – standard databases don’t work in terms of classes and objects, so in order to use TDD in databases, you have somehow to make databases fit the model. Guernsey does this by using the database schema as the class, then works within that so a database instance is an object. It works so long as you’re flexible, but can be unsettling if you’re a pure database developer. On the whole I personally found this didn’t obscure the information; if you prefer pure database-speak, you may feel differently.
Guernsey obviously has a deep understanding of database design and development, and of TDD. Some of what he suggests does seem to go away – or perhaps beyond - the classical teaching on the subject, but this seems to be done in order to improve or make the techniques more relevant to database use.
The first two chapters explain the problems of applying TDD techniques to database development, and how to create a database ‘class’ and manage it. One criticism that can be levelled against this early material is that the author doesn’t discuss how this fits with Data Definition Language scripts, which could be used to achieve some of his aims; instead, he uses XML for the definition files. Chapter three introduces classical TDD and how it can be used against databases.
By chapter four Guernsey has moved on to how to use TDD, in this case to make changes safely. There’s good coverage of how to test your changes on the structure, and how to ensure your data is safe and correct after upgrading a production database. He then moves on to how to prevent duplication, with an interesting idea of using code to return errors if changes are made that would affect the database design. The use of stored procedures as a preferred method of working with your database is the main subject of the next two chapters, with a focus on defining behaviors and building for maintainability.
Handling errors, or rather ‘unplanned changes that might find their way into your database design’ is considered next. This isn’t about the type of errors that cause an actual ‘error’ and that you can use a debugger to handle; instead, it’s about design problems – some data appearing formatted incorrectly, for example.
The idea of designing a database for ‘maximum testability’ is the subject of the next chapter. Guernsey’s point is that for TDD to work, you have to always work in terms of objects and encapsulation, and he gives examples throughout this chapter (and the rest of the book) showing this in action. Next comes a chapter on mocking – the use of simulated objects that mimic the behavior of the real objects you’re designing. The explanations are well made, though applying them to databases does look tricky. Like the rest of the book, you have to throw yourself into the mindset of believing that TDD *can* work for databases in order to get the most from the material.
There’s a small chapter introducing the idea of refactoring, the concept of changing design without changing behavior. The concepts is good, though I remain to be convinced that it works with structures as complex as databases. I was equally skeptical on the topic of being able to rework a legacy database into one that conforms to TDD, but the chapter on it made interesting reading, with some good ideas on how to create a modern interface that works. The technique of using a façade for the front interface, and gradually transferring behavior across as you test it also gets a chapter.
The book concludes with two catch-all chapters, one of which looks at alternative variations other practitioners have used, and one of which looks at alternative data storage such as file systems and XML.
I have mixed feelings about this book. I liked the writing style. Guernsey obviously understands databases and TDD well, and I thought his explanations were as understandable as they could be. He says at the start of the book that test-driven development hasn’t gained traction in the database world, and I think he’s probably correct. I’m just not sure that database developers want to add another layer of abstraction to their database models.
Despite my reservations, this is a book worth reading if you’re a database developer. Some of the ideas work regardless of your development model, and you’ll know more about what TDD means and how you can use it – whether or not you fully embrace it.