- #1: Build Classes, Not Individual Databases
- #2: Don't Ignore History
- #3: Automate All Changes to Every Database Instance
- #4: Test Every Change to Database Design
- #5: Force Clients to Break Fast When Interfaces Change
- #6: Encapsulate Database Behavior
- #7: Drive Behavior from Information
- #8: Keep a Complete Unit Test Suite
- #9: Build Only What You Need
- #10: DON'T PANIC
#7: Drive Behavior from Information
It can be hard to figure out exactly what a “behavior” is in database terms. That’s partly because we’ve conditioned ourselves to think of most database design elements as passive things; things to be acted upon but that themselves do nothing.
Tables, for instance, are anything but passive. They are tightly-wound balls of highly interconnected behaviors. Whenever I say something like that, the things that jump into most people’s minds are the classic CRUD behaviors: create, read, update, and delete. Those are some of a table’s behaviors, but there are often several more.
To really understand what a behavior means in the database world, I find it useful to imagine every database has three layers of design. The innermost layer is knowledge, which is all the stuff that a database has learned over its life. The outermost layer is information, which consists of all the data transmitted that could potentially increase their recipient’s knowledge. The stuff in between is behavior. This way of considering database design is exemplified in Figure 13.
Typically, information lives in the parameters and results sets of stored procedures or views. Behavior then lives in the definition of those same stored procedures and views. Finally, knowledge tends to be stored in tables and indexes.
A principle of test-driven development is to drive design from the outside of a thing inward, rather than building “up and out.” If you imagine database design as being divided into knowledge, information, and behavior, then it’s easy to see how design should be driven into a database from the outside.
Start by defining the information your databases send to and receive from their clients. Use that understanding to create empty stored procedures or dummy views. Once that is done, add behaviors to said stored procedures or views. Finally, use the behaviors you’ve just designed to drive alterations to your underlying database structures.
Driving design from the outside in by starting with information, proceeding through behavior, and coming to rest on knowledge containers enables you to keep your database design natural to the problems it addresses. Natural designs are easier to work with and, therefore, support agility by giving a lower resistance to change.