Preface....6
Why I Wrote This Book....6
What This Book Is About....7
Software Design....8
Modern C++....8
Design Patterns....9
Who This Book Is For....10
How This Book Is Structured....11
Conventions Used in This Book....12
Using Code Examples....13
O’Reilly Online Learning....14
How to Contact Us....14
Acknowledgments....15
1. The Art of Software Design....17
Guideline 1: Understand the Importance of Software Design....18
Features Are Not Software Design....18
Software Design: The Art of Managing Dependencies and Abstractions....19
The Three Levels of Software Development....22
The Focus on Features....27
The Focus on Software Design and Design Principles....29
Guideline 2: Design for Change....30
Separation of Concerns....30
An Example of Artificial Coupling....32
Logical Versus Physical Coupling....36
Don’t Repeat Yourself....41
Avoid Premature Separation of Concerns....46
Guideline 3: Separate Interfaces to Avoid Artificial Coupling....48
Segregate Interfaces to Separate Concerns....48
Minimizing Requirements of Template Arguments....51
Guideline 4: Design for Testability....53
How to Test a Private Member Function....54
The True Solution: Separate Concerns....59
Guideline 5: Design for Extension....63
The Open-Closed Principle....63
Compile-Time Extensibility....70
Avoid Premature Design for Extension....73
2. The Art of Building Abstractions....78
Guideline 6: Adhere to the Expected Behavior of Abstractions....79
An Example of Violating Expectations....79
The Liskov Substitution Principle....83
Criticism of the Liskov Substitution Principle....88
The Need for Good and Meaningful Abstractions....89
Guideline 7: Understand the Similarities Between Base Classes and Concepts....90
Guideline 8: Understand the Semantic Requirements of Overload Sets....95
The Power of Free Functions: A Compile-Time Abstraction Mechanism....96
The Problem of Free Functions: Expectations on the Behavior....99
Guideline 9: Pay Attention to the Ownership of Abstractions....103
The Dependency Inversion Principle....104
Dependency Inversion in a Plug-In Architecture....113
Dependency Inversion via Templates....118
Dependency Inversion via Overload Sets....119
Dependency Inversion Principle Versus Single-Responsibility Principle....122
Guideline 10: Consider Creating an Architectural Document....122
3. The Purpose of Design Patterns....130
Guideline 11: Understand the Purpose of Design Patterns....131
A Design Pattern Has a Name....131
A Design Pattern Carries an Intent....133
A Design Pattern Introduces an Abstraction....133
A Design Pattern Has Been Proven....137
Guideline 12: Beware of Design Pattern Misconceptions....138
Design Patterns Are Not a Goal....139
Design Patterns Are Not About Implementation Details....140
Design Patterns Are Not Limited to Object-Oriented Programming or Dynamic Polymorphism....144
Guideline 13: Design Patterns Are Everywhere....148
Guideline 14: Use a Design Pattern’s Name to Communicate Intent....154
4. The Visitor Design Pattern....160
Guideline 15: Design for the Addition of Types or Operations....161
A Procedural Solution....161
An Object-Oriented Solution....169
Be Aware of the Design Choice in Dynamic Polymorphism....172
Guideline 16: Use Visitor to Extend Operations....174
Analyzing the Design Issues....175
The Visitor Design Pattern Explained....177
Analyzing the Shortcomings of the Visitor Design Pattern....182
Guideline 17: Consider std::variant for Implementing Visitor....189
Introduction to std::variant....189
Refactoring the Drawing of Shapes as a Value-Based, Nonintrusive Solution....193
Performance Benchmarks....201
Analyzing the Shortcomings of the std::variant Solution....203
Guideline 18: Beware the Performance of Acyclic Visitor....205
5. The Strategy and Command Design Patterns....216
Guideline 19: Use Strategy to Isolate How Things Are Done....217
Analyzing the Design Issues....220
The Strategy Design Pattern Explained....227
Analyzing the Shortcomings of the Naive Solution....231
Comparison Between Visitor and Strategy....240
Analyzing the Shortcomings of the Strategy Design Pattern....241
Policy-Based Design....245
Guideline 20: Favor Composition over Inheritance....248
Guideline 21: Use Command to Isolate What Things Are Done....252
The Command Design Pattern Explained....252
The Command Design Pattern Versus the Strategy Design Pattern....262
Analyzing the Shortcomings of the Command Design Pattern....266
Guideline 22: Prefer Value Semantics over Reference Semantics....267
The Shortcomings of the GoF Style: Reference Semantics....268
Reference Semantics: A Second Example....272
The Modern C++ Philosophy: Value Semantics....275
Value Semantics: A Second Example....278
Prefer to Use Value Semantics to Implement Design Patterns....280
Guideline 23: Prefer a Value-Based Implementation of Strategy and Command....281
Introduction to std::function....281
Refactoring the Drawing of Shapes....284
Performance Benchmarks....292
Analyzing the Shortcomings of the std::function Solution....293
6. The Adapter, Observer, and CRTP Design Patterns....299
Guideline 24: Use Adapters to Standardize Interfaces....300
The Adapter Design Pattern Explained....301
Object Adapters Versus Class Adapters....304
Examples from the Standard Library....306
Comparison Between Adapter and Strategy....308
Function Adapters....309
Analyzing the Shortcomings of the Adapter Design Pattern....311
Guideline 25: Apply Observers as an Abstract Notification Mechanism....315
The Observer Design Pattern Explained....316
A Classic Observer Implementation....318
An Observer Implementation Based on Value Semantics....331
Analyzing the Shortcomings of the Observer Design Pattern....334
Guideline 26: Use CRTP to Introduce Static Type Categories....336
A Motivation for CRTP....337
The CRTP Design Pattern Explained....343
Analyzing the Shortcomings of the CRTP Design Pattern....351
The Future of CRTP: A Comparison Between CRTP and C++20 Concepts....355
Guideline 27: Use CRTP for Static Mixin Classes....358
A Strong Type Motivation....359
Using CRTP as an Implementation Pattern....362
7. The Bridge, Prototype, and External Polymorphism Design Patterns....370
Guideline 28: Build Bridges to Remove Physical Dependencies....371
A Motivating Example....371
The Bridge Design Pattern Explained....377
The Pimpl Idiom....382
Comparison Between Bridge and Strategy....387
Analyzing the Shortcomings of the Bridge Design Pattern....391
Guideline 29: Be Aware of Bridge Performance Gains and Losses....393
The Performance Impact of Bridges....394
Improving Performance with Partial Bridges....397
Guideline 30: Apply Prototype for Abstract Copy Operations....401
A Sheep-ish Example: Copying Animals....402
The Prototype Design Pattern Explained....404
Comparison Between Prototype and std::variant....410
Analyzing the Shortcomings of the Prototype Design Pattern....411
Guideline 31: Use External Polymorphism for Nonintrusive Runtime Polymorphism....412
The External Polymorphism Design Pattern Explained....413
Drawing of Shapes Revisited....417
Comparison Between External Polymorphism and Adapter....428
Analyzing the Shortcomings of the External Polymorphism Design Pattern....429
8. The Type Erasure Design Pattern....436
Guideline 32: Consider Replacing Inheritance Hierarchies with Type Erasure....437
The History of Type Erasure....438
The Type Erasure Design Pattern Explained....441
An Owning Type Erasure Implementation....445
Analyzing the Shortcomings of the Type Erasure Design Pattern....455
Comparing Two Type Erasure Wrappers....456
Interface Segregation of Type Erasure Wrappers....460
Performance Benchmarks....461
A Word About Terminology....463
Guideline 33: Be Aware of the Optimization Potential of Type Erasure....465
Small Buffer Optimization....465
Manual Implementation of Function Dispatch....477
Guideline 34: Be Aware of the Setup Costs of Owning Type Erasure Wrappers....484
The Setup Costs of an Owning Type Erasure Wrapper....485
A Simple Nonowning Type Erasure Implementation....488
A More Powerful Nonowning Type Erasure Implementation....491
9. The Decorator Design Pattern....505
Guideline 35: Use Decorators to Add Customization Hierarchically....506
Your Coworkers’ Design Issue....506
The Decorator Design Pattern Explained....515
A Classic Implementation of the Decorator Design Pattern....520
A Second Decorator Example....525
Comparison Between Decorator, Adapter, and Strategy....529
Analyzing the Shortcomings of the Decorator Design Pattern....531
Guideline 36: Understand the Trade-off Between Runtime and Compile Time Abstraction....534
A Value-Based Compile Time Decorator....535
A Value-Based Runtime Decorator....543
10. The Singleton Pattern....551
Guideline 37: Treat Singleton as an Implementation Pattern, Not a Design Pattern....552
The Singleton Pattern Explained....552
Singleton Does Not Manage or Reduce Dependencies....556
Guideline 38: Design Singletons for Change and Testability....558
Singletons Represent Global State....559
Singletons Impede Changeability and Testability....560
Inverting the Dependencies on a Singleton....567
Applying the Strategy Design Pattern....573
Moving Toward Local Dependency Injection....580
11. The Last Guideline....586
Guideline 39: Continue to Learn About Design Patterns....586
Index....591
Good software design is essential for the success of your project, but designing software is hard to do. You need to have a deep understanding of the consequences of design decisions and a good overview of available design alternatives. With this book, experienced C++ developers will get a thorough, practical, and unparalleled overview of software design with this modern language.
C++ trainer and consultant Klaus Iglberger explains how you can manage dependencies and abstractions, improve changeability and extensibility of software entities, and apply and implement modern design patterns to help you take advantage of today's possibilities. Software design is the most essential aspect of a software project because it impacts the software's most important properties: maintainability, changeability, and extensibility.