| |
| |
Foreword | |
| |
| |
Introduction | |
| |
| |
Acknowledgments | |
| |
| |
About the Author | |
| |
| |
| |
Object-Oriented Design | |
| |
| |
In Praise of Design | |
| |
| |
The Problems Design Solves | |
| |
| |
Why Change is Hard | |
| |
| |
A Practical Definition of Design | |
| |
| |
The Tools of Design | |
| |
| |
Design Principles | |
| |
| |
Design Patterns | |
| |
| |
The Act of Design | |
| |
| |
How Design Fails | |
| |
| |
When to Design | |
| |
| |
Judging Design | |
| |
| |
A Brief Introduction to Object-Oriented Programming | |
| |
| |
Procedural Languages | |
| |
| |
Object-Oriented Languages | |
| |
| |
Summary | |
| |
| |
| |
Designing Classes with a Single Responsibility | |
| |
| |
Deciding What Belongs in a Class | |
| |
| |
Grouping Methods into Classes | |
| |
| |
Organizing Code to Allow for Easy Changes | |
| |
| |
Creating Classes that have a Single Responsibility | |
| |
| |
An Example Application: Bicycles and Gears | |
| |
| |
Why Single Responsibility Matters | |
| |
| |
Determining if a Class has a Single Responsibility | |
| |
| |
Determining When to Make Design Decisions | |
| |
| |
Writing Code that Embraces Change | |
| |
| |
Depend on Behavior, Not Data | |
| |
| |
Enforce Single Responsibility Everywhere | |
| |
| |
Finally, the Real Wheel | |
| |
| |
Summary | |
| |
| |
| |
Managing Dependencies | |
| |
| |
Understanding Dependencies | |
| |
| |
Recognizing Dependencies | |
| |
| |
Coupling Between Objects (CBO) | |
| |
| |
Other Dependencies | |
| |
| |
Writing Loosely Coupled Code | |
| |
| |
Inject Dependencies | |
| |
| |
Isolare Dependencies | |
| |
| |
Remove Argument-Order Dependencies | |
| |
| |
Managing Dependency Direction | |
| |
| |
Reversing Dependencies | |
| |
| |
Choosing Dependency Direction | |
| |
| |
Summary | |
| |
| |
| |
Creating Flexible Interfaces | |
| |
| |
Understanding Interfaces | |
| |
| |
Defining Interfaces | |
| |
| |
Public Interfaces | |
| |
| |
Private Interfaces | |
| |
| |
Responsibilities, Dependencies, and Interfaces | |
| |
| |
Finding the Public Interface | |
| |
| |
An Example Application: Bicycle Touring Company | |
| |
| |
Constructing an Intention | |
| |
| |
Using Sequence Diagrams | |
| |
| |
Asking for "What" Instead of Telling "How" | |
| |
| |
Seeking Context Independence | |
| |
| |
Trusting Other Objects | |
| |
| |
Using Messages to Discover Objects | |
| |
| |
Creating a Message-Based Application | |
| |
| |
Writing Code that puts its best (Inter)Face Forward | |
| |
| |
Create Explicit Interfaces | |
| |
| |
Honor the Public Interfaces of Others | |
| |
| |
Exercise Caution When Depending on Private Interfaces | |
| |
| |
Minimize Context | |
| |
| |
The Law of Demeter | |
| |
| |
Defining Demeter | |
| |
| |
Consequences of Violations | |
| |
| |
Avoiding Violations | |
| |
| |
Listening to Demeter | |
| |
| |
Summary | |
| |
| |
| |
Reducing Costs with Duck Typing | |
| |
| |
Understanding Duck Typing | |
| |
| |
Overlooking the Duck | |
| |
| |
Compounding the Problem | |
| |
| |
Finding the Duck | |
| |
| |
Consequences of Duck Typing | |
| |
| |
Writing Code that Relies on Ducks | |
| |
| |
Recognizing Hidden Ducks | |
| |
| |
Placing Trust in your Ducks | |
| |
| |
Documenting Duck Types | |
| |
| |
Sharing Code Between Ducks | |
| |
| |
Choosing your Ducks Wisely | |
| |
| |
Conquering a Fear of Duck Typing | |
| |
| |
Subverting Duck Types with Static Typing | |
| |
| |
Static versus Dynamic Typing | |
| |
| |
Embracing Dynamic Typing | |
| |
| |
Summary | |
| |
| |
| |
Acquiring Behavior Through Inheritance | |
| |
| |
Understanding Classical Inheritance | |
| |
| |
Recognizing Where to use Inheritance | |
| |
| |
Starting with a Concrete Class | |
| |
| |
Embedding Multiple Types | |
| |
| |
Finding the Embedded Types | |
| |
| |
Choosing Inheritance | |
| |
| |
Drawing Inheritance Relationships | |
| |
| |
Misapplying Inheritance | |
| |
| |
Finding the Abstraction | |
| |
| |
Creating an Abstract Superclass | |
| |
| |
Promoting Abstract Behavior | |
| |
| |
Separating Abstract from Concrete | |
| |
| |
Using the Template Method Pattern | |
| |
| |
Implementing every Template Method | |
| |
| |
Managing Coupling Between Superclasses and Subclasses | |
| |
| |
Understanding Coupling | |
| |
| |
Decoupling Subclasses Using Hook Messages | |
| |
| |
Summary | |
| |
| |
| |
Sharing Role Behavior with Modules | |
| |
| |
Understanding Roles | |
| |
| |
Finding Roles | |
| |
| |
Organizing Responsibilities | |
| |
| |
Removing Unnecessary Dependencies | |
| |
| |
Writing the Concrete Code | |
| |
| |
Extracting the Abstraction | |
| |
| |
Looking up Methods | |
| |
| |
Inheriting Role Behavior | |
| |
| |
Writing Inheritable Code | |
| |
| |
Recognize the Antipatterns | |
| |
| |
Insist on the Abstraction | |
| |
| |
Honor the Contract | |
| |
| |
Use the Template Method Pattern | |
| |
| |
Preemptively Decouple Classes | |
| |
| |
Create Shallow Hierarchies | |
| |
| |
Summary | |
| |
| |
| |
Combining Objects with Composition | |
| |
| |
Composing a Bicycle of Parts | |
| |
| |
Updating the Bicycle Class | |
| |
| |
Creating a Parts Hierarchy | |
| |
| |
Composing the Parts Objects | |
| |
| |
Creating a Part | |
| |
| |
Making the Parts Object More Like an Array | |
| |
| |
Manufacturing Parts | |
| |
| |
Creating the PartsFactory | |
| |
| |
Leveraging the PartsFactory | |
| |
| |
The Composed Bicycle | |
| |
| |
Deciding Between Inheritance and Composition | |
| |
| |
Accepting the Consequences of Inheritance | |
| |
| |
Accepting the Consequences of Composition | |
| |
| |
Choosing Relationships | |
| |
| |
Summary | |
| |
| |
| |
Designing Cost-Effective Tests | |
| |
| |
Intentional Testing | |
| |
| |
Knowing your Intentions | |
| |
| |
Knowing What to Test | |
| |
| |
Knowing When to Test | |
| |
| |
Knowing How to Test | |
| |
| |
Testing Incoming Messages | |
| |
| |
Deleting Unused Interfaces | |
| |
| |
Proving the Public Interface | |
| |
| |
Isolating the Object Under Test | |
| |
| |
Injecting Dependencies Using Classes | |
| |
| |
Injecting Dependencies as Roles | |
| |
| |
Testing Private Methods | |
| |
| |
Ignoring Private Methods During Tests | |
| |
| |
Removing Private Methods from the Class Under Test | |
| |
| |
Choosing to Test a Private Method | |
| |
| |
Testing Outgoing Messages | |
| |
| |
Ignoring Query Messages | |
| |
| |
Proving Command Messages | |
| |
| |
Testing Duck Types | |
| |
| |
Testing Roles | |
| |
| |
Using Role Tests to Validate Doubles | |
| |
| |
Testing Inherited Code | |
| |
| |
Specifying the Inherited Interface | |
| |
| |
Specifying Subclass Responsibilities | |
| |
| |
Testing Unique Behavior | |
| |
| |
Summary | |
| |
| |
Afterword | |
| |
| |
Index | |