SKIP THE SHIPPING
Use code NOSHIP during checkout to save 40% on eligible eBooks, now through January 5. Shop now.
Register your product to gain access to bonus material or receive a coupon.
The practice of Test-Driven Development (TDD) has helped thousands of software developers improve quality, agility, productivity, and speed. In Test-Driven Database Development, Max Guernsey, III shows how to adapt TDD to achieve the same powerful benefits in database design and development.
Guernsey first explains why TDD offers so much potential to database practitioners, and how to overcome obstacles such as the lack of conventional “testable classes.” You’ll learn how to use “classes of databases” to manage change more effectively; how to define testable database behaviors; how to maximize long-term maintainability by limiting a database’s current scope; and how to use “emergent design” to simplify future expansion.
Building on this foundation, the author guides you through implementing modern TDD processes and database refactoring. He presents practical techniques for improving legacy databases; for deviating from strict TDD when necessary; and for adapting TDD to applications that persist data in file systems, XML, or serialized objects. Guernsey shows how to
• Build a simple infrastructure to track and standardize scripts and databases
• Define a sustainable TDD process for database design
• Safely change a design without losing data
• Design new databases that are lighter, leaner, simpler, more testable, and easier to change
• Reduce design costs by eliminating duplication
• Gradually bring the benefits of TDD, agility, and modern design to legacy databases
• Remediate errors that find their way into database designs
• Isolate behaviors and avoid unwanted dependencies that cause tests to fail
With this book as a guide, you will learn how to apply the proven practice of TDD to your database needs, and organize and optimize your organization’s data for a significant competitive advantage.
Test-Driven Database Development is the newest title in the highly respected NetObjectives Lean-Agile Series.
Applying Test-Driven Development to Architecture to Keep Your Team on Target
Five Ways to Optimize Encapsulation in Your Software Architecture
How Value-Stream-Oriented Architecture Can Help You Create Better Software
Ten Tips for Constructing an Agile Database Development Environment that Works
A Crash Course in Test-Driven Development
Download the sample pages (includes Chapter 3 and Index)
Foreword xvii
Preface xix
Acknowledgments xxv
About the Authors xxvii
Chapter 1 Why, Who, and What 1
Why 1
Agility Progressively Invades Domains Every Day 2
Agility Cannot Work Without TDD 2
TDD in the Database World Is a Challenge 3
Who 3
TDD and OOP 4
Applications and Databases 4
What 4
Databases Are Objects 5
TDD Works on Classes, Not Objects 5
We Need Classes of Databases 6
Summary 7
Chapter 2 Establishing a Class of Databases 9
The Class’s Role in TDD 9
A Reliable Instantiation Process 10
Tests Check Objects 10
Classes in Object-Oriented Programming Languages 11
Making Classes Is Easy: Just Make New Objects 11
One Path: Destroy If Necessary 11
Classes of Databases 12
Two Paths: Create or Change 12
The Hard Part: Unifying the Two Paths 13
Real Database Growth 13
How About Making Every Database Build Like Production Databases? 14
All DBs Would Follow the Exact Same Path 15
Incremental Build 15
Document Each Database Change 15
Identify Current Version 16
Apply Changes in Order as Needed 16
Implementation 16
Requirements 16
Pseudocode Database Instantiation Mechanism 17
Pseudocode Input 17
Summary 18
Chapter 3 A Little TDD 19
The Test-First Technique 19
Write the Test 20
Stub Out Enough to See a Failure 22
See the Test Pass 22
Repeat 23
Tests as Specifications 24
“Tests Aren’t Tests, They Are Specifications” 24
“Tests Aren’t Specifications, They Are Tests” 25
Tests Are Executable Specifications 26
Incremental Design 27
Building Good Specifications 28
Specify Behavior, Not Structure 28
Drive Design In from Without, Not the Other Way Around 29
Defining the Design Inside Out 30
Defining the Design Outside In 32
Summary 34
Chapter 4 Safely Changing Design 37
What Is Safe? 38
Breaking a Contract Is a Little Bad 38
Losing Data Will Probably Get You Fired 39
Not Changing Design Is Also Dangerous 40
Solution: Transition Testing 44
Test-Driving Instantiation 44
Transition Testing Creation 44
Transition Testing Addition 47
Transition Testing Metamorphosis 51
Why Not Use the Public Interface? 56
Transition Safeguards 56
Read/Read Transition Tests 56
Run by the Class of Databases on Every Upgrade 60
Backup and Rollback on Fail 60
Making Transition Tests Leverage Transition Safeguards 60
Summary 61
Chapter 5 Enforcing Interface 63
Interface Strength 64
Stronger Coupling Languages 64
Weaker Coupling Languages 65
The Common Thread 66
Coupling to Database Classes 66
The Problem Is Duplication 66
Client-Object-Like Enforcement 67
Creating Demand for a DatabaseDesign Class 67
Specifying the DatabaseDesign Class 68
Getting Rid of Duplication with Multiple Client Platforms 70
What Happens When Coupling Goes Bad? 71
Eliminating Duplication Between Database Build and Client Code 71
Decoupling Implementation from Design 72
Sticking Point: Change 73
Designs Change Over Time 74
Document All Versions of Design 75
Couple to the Correct Version of the Design 77
Sticking Point: Coupling 78
Various Clients Couple to Various Versions 78
Having to Change Everything All the Time Is Duplication, Too 79
Introducing the Lens Concept 83
Virtual Lenses 85
The “Current” Lens 89
The “New” Lens 89
Summary 93
Chapter 6 Defining Behaviors 95
A New Group of Problems 96
No Encapsulation 96
Hide Everything 97
Business Logic in the Database 97
Knowledge, Information, and Behavior 98
Information 99
Knowledge 102
Behavior 102
Outside-In Development 106
Defining the Test 106
Growing Interface 108
Growing Behavior and Structures 109
Justification by Specification 111
Work Against Present Requirements, Not Future 111
Build in Increments 112
Limit Access to What Is Specified 112
Summary 113
Chapter 7 Building for Maintainability 115
Never Worry About the Future 116
Look for Opportunities in the Now 116
Design to Information 117
Translate Info and Knowledge with Behavior 121
Guard Knowledge with Fervor and Zeal 124
Not Changing Is the Most Dangerous Choice 124
Keep Your Design Natural 126
Deal with the Future When It Happens 127
Define New Design 128
Introduce Minimal Changes 129
Get Tests Passing 131
Stop, Think, Refactor 133
Summary 136
Chapter 8 Error and Remediation 137
Kinds of Errors 137
Axis: Is the Error Good or Bad? 138
Axis: Is the Error Released or Not? 140
Dealing with Good Errors 142
Just Fix It 142
Document Behavior Now 143
Trace Feature Back to Its Genesis 145
Dealing with Bad Errors 146
Unreleased Errors 147
Released Errors 150
Catastrophic Errors 156
Summary 157
Chapter 9 Design 159
Structures Versus Design 160
Structures: Execution Details 160
Tests and Class Information 162
What Is Design? 163
Buckets of Concepts 163
Mandatory Part of True TDD 166
Composition and Aggregation 167
Composition: One Thing with Multiple Parts 168
Aggregation: Connecting Distinct Things 172
Reuse 175
Avoid Developing the Same Thing Twice 175
Reuse by Composition or Aggregation 177
Abstraction 178
Identifying Opportunities for Abstraction 178
Encapsulating Behaviors 179
Finding Ways to Allow Variation in Dependencies 185
Dealing with the Time Problem 186
Summary 190
Chapter 10 Mocking 191
Testing Individual Behaviors 191
Why Encapsulate 192
Tests Test Everything Not Under Their Control 193
Controlling Irrelevant Behaviors from Tests 194
Mocking Controls Behaviors 194
Mocking in Object-Oriented Programming 195
Setup 195
Decoupling 199
Isolation 202
Integration 202
Mocking in Database Design 203
Example Problem 204
Example Solution 205
Composition 208
Aggregation 210
Designing for Testability 210
Summary 210
Chapter 11 Refactoring 213
What Refactoring Is 214
Changing Design Without Changing Behavior 214
In the Context of Passing Tests 215
Lower and Higher Risk Design Changes 222
Lower Risk: Changing Class-Level Design 222
Medium Risk: Rearranging Behavior Logic 223
Higher Risk: Altering Knowledge Containers 225
This Is Not an Invitation to Skip Testing 226
Summary 226
Chapter 12 Legacy Databases 227
Promoting to a Class 228
Deducing Initial Version 228
Pinning the Transition Behavior with Tests 231
Controlling Coupling 231
Identifying and Locking Down to Existing Uses 232
Encapsulating on Demand 234
Controlling Change 235
Test-Driving New Behaviors 235
Pinning Construction on Demand 237
Pinning Behavior on Demand 238
Implementing New Behavior 239
Finding Seams and Components 240
Finding Seams 240
Encapsulating Components 243
Summary 247
Chapter 13 The Façade Pattern 249
Encapsulation with a Façade 249
Explanation of Façade Pattern 250
New Test-Driven Façade Database 254
Compositional Alternative 261
To Encapsulate or Not 261
Strangling the Old Interface 262
Transferring Changing Behaviors to Façade 262
Removing Access and Features When No Longer Needed 263
Test-Driving Behaviors in the Façade Database 264
Exposing Legacy Behaviors 265
Another Way to Do It 265
New Behaviors 266
Summary 266
Chapter 14 Variations 269
Having a Class Is Important—Implementation Is Not 270
Scenario: Skipping Steps 270
Problem 271
Solution 272
The Right Amount of Work 273
Scenario: Deviations 274
Problem 274
Solution 275
Solution Applied 277
Common Solution 281
Summary 281
Chapter 15 Other Applications 283
XML 284
Encapsulation 284
XSD Schemas 284
XSLT Transitions 286
Transition Test XSLT Changes 287
File Systems and Other Object Directories 288
Transition Test File System Manipulations 289
Shell Script Transitions 291
Data Objects 292
Class Definitions Are Schemas 292
Transition Test the Ugrader Class 294
Code Transitions 296
Summary and Send Off 300
Index 301