- #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
#5: Force Clients to Break Fast When Interfaces Change
If you’ve implemented tips #1-4, then your house is effectively in order. You have the ability to quickly make a change to a database class’s design, test an instance of that class, use the outcome of that test to predict the behavior of a production database in the same class, and promote that change, all without the fear of destroying vital data in long-lived databases.
It’s a good place to be but, you’ll find, it uncovers other problems that also need to be solved. The biggest one is that you are going to be tempted to change your database’s public interface. In fact, in all but the most extreme cases, you are going to absolutely need to change the public interface of your database or risk corruption by way of misuse (Figure 8).
A little bit of effort allows you to concentrate the details of your database class’s public interface into the same document that defines how an individual database instance is constructed. Those details can then be used in the construction itself and run through easy-to-write code generators for each client language you need to support (Figure 9).
As a result, you end up having a single place to make changes in your databases’ designs. If you make a breaking change, the impact is projected out to all points of coupling nearly instantaneously.
When a change to a database design can cause a problem with a downstream system that may not be found for days, weeks, or even months, change is a dangerous thing (Figure 10). This is because the real cost of any defect stems from how long it’s been around rather than how hard it is to fix. In the database world, that goes double as certain problems that go uncaught can cause production databases to become polluted with toxic, invalid data.
Knowing that breaking changes will report immediately allows you to be more confident in modifying the public interface. After a change, if everything compiles and all the tests run, you know you’re good. If anything breaks or any tests fail, you know you either need to back out your change or fix it.
Having the ability to transform the public interface of any class is vital to any agile effort. In fact, it seems to me that any development effort at all would have a hard time succeeding if public interfaces could not adapt to changing requirements. Since you want to be successful and you cannot stop interfaces from flexing over time, you need a way to force downstream systems to tell you whenever such a change impacts them.