Thoughts on @RonJeffries “But We Need a Database… Don’t We?”
Ron Jeffries wrote a post a couple days ago with a title indicating its about databases, but then he proceeds into a test-driven development (TDD) coding exercise. Halfway through, an ostensible reader interrupts:
Hey! I thought this was supposed to be about databases???
Hey, yourself. Try to pay closer attention. This is totally about databases.
Why is this even remotely about databases???
Well, here’s why:
We have just defined a core element of our member database record, namely the purchase count, and made sure that it works. Now when we read a member record in from our database, we can instantiate it into our class MemberRecord and send it messages to decide what to do. This is OO here, my young padawan, and that’s how we do it.
Yeah, sure, old man, but what about the membership number? That’s the key, according to the story, and you don’t even have it. And isn’t there just a small matter of actually storing and retrieving these babies?
Patience, youngling. Each thing comes in its time. Let’s see what the next tests bring us.
His post is a good illustration of the revelation I had when first learning Agile coding practices: they let you start in the middle, with the business logic. A common traditional approach is to instead define a database schema first, and then deal with the UI and business logic. There are 2 problems with this traditional approach 1. the database is the hardest layer to change, and your design is likely most volatile in its early stages, and 2. it makes it that much easier to end up tightly coupling the components of your application together.
By starting with the business logic and no supporting infrastructure other than your tests, you have no choice but to fully decouple the application logic from the UI and the database. Then when your boss says, “we need to make a mobile version of this app by Friday!” you can work on the new mobile UI design without having to cut through a tangled thicket of blended UI and business logic.
Having said that, there are challenges with mimicking complex interactions with the database and UI layers through unit tests. I consider myself a novice with Agile techniques, but I’ll share what I’ve learned so far:
- For my Shashin project, which pulls data from Picasa json feeds, I simply saved copies of some feeds to local files, and my tests can talk to those files. This allowed me to keep developing while offline (on a flight to Hawaii!) which is very cool.
- There are the object mother and test data builder patterns but both can entail a fairly heavy degree of typing when dealing with large or complex data sets.
- My team at Penn is currently trying out FitNesse, which lets you specify your inputs and expected outputs through simple wiki tables (which you can paste from a spreadsheet). This seems about as lightweight as you can get. Although it’s an acceptance testing tool (not a unit testing tool), it can still help drive your design. If you follow specification by example practices, and write your code so that it can take inputs and send outputs to a FitNesse test fixture OR a database and a form, then congratulations, you’ve decoupled your code from the database and UI!