Programming Patterns
Programming patterns are names given to frequently recurring design problems. Quite a few people argue that patterns are used as rote memorization and are therefore harmful, or that they were just a passing trend. However, the real advantage of programming patterns is that they reduce the cost of communication.
"Let's extract this into a Strategy Pattern,"
"Let's wrap the external SDK with an Adapter Pattern,"
"A Query Facade works better than a Repository for this query" — statements like these lower the cost of conversation.
This document is not a comprehensive explanation of every pattern; it is a pattern index for a personal wiki. The detailed content of each pattern is broken out into separate pages. When a pattern document grows too long, it becomes hard to search within a single page, and adding examples and counter-examples later becomes inconvenient.
When looking at a pattern, you should think about the following before focusing on its name.
What changes?
What should be hidden?
What needs to be replaceable?
Where is the boundary that meets the external system?
Does this abstraction actually reduce the cost of change?
Personal note: Patterns carry a slight air of pretension. But then again, so does every professional vocabulary.
The difference between patterns and idioms
A programming idiom is a small, natural expression specific to a particular language. A pattern is larger, typically addressing relationships among multiple objects, modules, or layers.
Category | Description | Example |
|---|---|---|
Principle | Criteria for judgment | SOLID, DRY, YAGNI |
Pattern | Solution structure for a recurring problem | Strategy, Adapter, Repository, Retry |
Idiom | Natural expression per language | Python |
Syntax | Forms permitted by the language |
|
- Category
Principle
- Description
Criteria for judgment
- Example
SOLID, DRY, YAGNI
- Category
Pattern
- Description
Solution structure for a recurring problem
- Example
Strategy, Adapter, Repository, Retry
- Category
Idiom
- Description
Natural expression per language
- Example
Python
with, C++ RAII, Rust?
- Category
Syntax
- Description
Forms permitted by the language
- Example
if,class,interface
Even the same Strategy Pattern looks different across languages.
In Java and C#, an interface is the natural fit; in Python, a callable or duck typing feels more natural. Even when the pattern name is the same, the implementation should conform to each language's idioms.
GoF Patterns
The GoF's Design Patterns is the book that gave names to solutions that had been recurring in object-oriented code.1 The GoF divides patterns into Creational, Structural, and Behavioral categories.
GoF Category | Representative Patterns | Rough Concern |
|---|---|---|
Creational Pattern | Factory Method, Abstract Factory, Builder, Prototype, Singleton | How to create objects |
Structural Pattern | Adapter, Decorator, Facade, Proxy, Bridge, Composite, Flyweight | How to assemble objects |
Behavioral Pattern | Strategy, State, Observer, Command, Template Method, Iterator, Visitor | How objects collaborate |
- GoF Category
Creational Pattern
- Representative Patterns
Factory Method, Abstract Factory, Builder, Prototype, Singleton
- Rough Concern
How to create objects
- GoF Category
Structural Pattern
- Representative Patterns
Adapter, Decorator, Facade, Proxy, Bridge, Composite, Flyweight
- Rough Concern
How to assemble objects
- GoF Category
Behavioral Pattern
- Representative Patterns
Strategy, State, Observer, Command, Template Method, Iterator, Visitor
- Rough Concern
How objects collaborate
GoF patterns remain useful, but in practice they are not sufficient on their own. In web, database, and operational contexts, patterns like Repository, DTO, Retry, Timeout, Circuit Breaker, and Cache-Aside appear far more frequently. Fowler's Patterns of Enterprise Application Architecture is the reference that organizes these enterprise application patterns.2
Quick glossary
These are terms that come up frequently in pattern documentation. Rather than lengthy explanations, only enough is written here to keep reading from stalling.
Term | Meaning |
|---|---|
Policy | A decision rule that changes depending on the situation. Discount policy, authorization policy, shipping fee policy — anything that answers "how should this be decided?" |
Strategy | A swappable algorithm or policy. In the Strategy Pattern, a policy is extracted into an object so it can be replaced. |
Logging | Recording what happened during execution. Used for incident analysis, auditing, and debugging. |
Caching | Temporarily storing frequently used values in a nearby storage location. It is fast, but introduces cache invalidation problems. |
Validation | Checking whether input values or state satisfy a set of rules. Comes up frequently in API requests, form inputs, and domain commands. |
Renderer | The role of transforming data into an output form such as a screen, image, HTML, or PDF. |
Storage | A place that holds data, such as a file system, database, or cache. Depending on context, it may refer to a physical storage medium or a storage abstraction. |
External SDK | Libraries provided by payment processors, SMS gateways, or cloud vendors. If they spread directly into internal code, replacing them becomes difficult. |
Legacy API | An API from an older system. It often has a mismatched interface with new code, making it a good candidate to wrap with an Adapter. |
Cross-Cutting Concern | A concern that cuts across multiple features. Examples include logging, authorization checks, caching, metrics, and retry. |
Domain | The business area the program addresses. For an online store, the domain includes orders, payments, shipping, and products. |
DDD Model | A domain-centric model as described in Domain-Driven Design. It prioritizes business concepts and rules over database tables. |
Entity | A domain object with an identifier and a lifecycle. Two objects with the same values are still different objects if their IDs differ. |
Value Object | An object whose meaning lies in its value rather than its identity. Examples include money, coordinates, time periods, and email addresses. |
DTO | Data Transfer Object. A data shape used for API responses or for crossing process boundaries. |
Aggregate | A grouping of related Entities and Value Objects into a single consistency boundary. It typically serves as the unit of persistence for a Repository. |
API Handler | An entry point that receives an HTTP request, validates it, and forwards it to the appropriate service or command. |
Command Handler | An object or function that processes commands that cause state changes, such as "create order" or "withdraw member." |
Middleware | A layer that intercepts requests and responses to handle common processing. Logging, authentication, CORS, and compression are common examples. |
ORM | Object-Relational Mapping. A tool that maps between objects and relational database tables. It does not, however, mean you can ignore SQL. |
RPC | Remote Procedure Call. A communication style in which a function across a network is called as if it were local. |
Lock | A mechanism that locks a resource that would be corrupted by concurrent access. Examples include DB row locks, mutexes, and distributed locks. |
Idempotency | The property of ensuring that sending the same request multiple times produces the same result as sending it once. Often seen alongside Retry. |
Backoff | A strategy of progressively increasing the interval between retries, used to avoid hammering a system that is already experiencing failures. |
Fallback | An alternative path used when the primary path fails. Examples include returning a cached value, sending a default response, or calling a backup server. |
TTL | Time To Live. The duration a cache entry or token remains valid. |
Stale data | Data that is no longer up to date. Caches often trade accepting stale data for improved speed. |
Execution plan | The plan a database generates for how it will execute a SQL query. This is where it decides whether to use an index or perform a full table scan. |
Transaction | Grouping multiple database operations within a single consistency boundary. It commits on success and rolls back on failure. |
- Term
Policy
- Meaning
A decision rule that changes depending on the situation. Discount policy, authorization policy, shipping fee policy — anything that answers "how should this be decided?"
- Term
Strategy
- Meaning
A swappable algorithm or policy. In the Strategy Pattern, a policy is extracted into an object so it can be replaced.
- Term
Logging
- Meaning
Recording what happened during execution. Used for incident analysis, auditing, and debugging.
- Term
Caching
- Meaning
Temporarily storing frequently used values in a nearby storage location. It is fast, but introduces cache invalidation problems.
- Term
Validation
- Meaning
Checking whether input values or state satisfy a set of rules. Comes up frequently in API requests, form inputs, and domain commands.
- Term
Renderer
- Meaning
The role of transforming data into an output form such as a screen, image, HTML, or PDF.
- Term
Storage
- Meaning
A place that holds data, such as a file system, database, or cache. Depending on context, it may refer to a physical storage medium or a storage abstraction.
- Term
External SDK
- Meaning
Libraries provided by payment processors, SMS gateways, or cloud vendors. If they spread directly into internal code, replacing them becomes difficult.
- Term
Legacy API
- Meaning
An API from an older system. It often has a mismatched interface with new code, making it a good candidate to wrap with an Adapter.
- Term
Cross-Cutting Concern
- Meaning
A concern that cuts across multiple features. Examples include logging, authorization checks, caching, metrics, and retry.
- Term
Domain
- Meaning
The business area the program addresses. For an online store, the domain includes orders, payments, shipping, and products.
- Term
DDD Model
- Meaning
A domain-centric model as described in Domain-Driven Design. It prioritizes business concepts and rules over database tables.
- Term
Entity
- Meaning
A domain object with an identifier and a lifecycle. Two objects with the same values are still different objects if their IDs differ.
- Term
Value Object
- Meaning
An object whose meaning lies in its value rather than its identity. Examples include money, coordinates, time periods, and email addresses.
- Term
DTO
- Meaning
Data Transfer Object. A data shape used for API responses or for crossing process boundaries.
- Term
Aggregate
- Meaning
A grouping of related Entities and Value Objects into a single consistency boundary. It typically serves as the unit of persistence for a Repository.
- Term
API Handler
- Meaning
An entry point that receives an HTTP request, validates it, and forwards it to the appropriate service or command.
- Term
Command Handler
- Meaning
An object or function that processes commands that cause state changes, such as "create order" or "withdraw member."
- Term
Middleware
- Meaning
A layer that intercepts requests and responses to handle common processing. Logging, authentication, CORS, and compression are common examples.
- Term
ORM
- Meaning
Object-Relational Mapping. A tool that maps between objects and relational database tables. It does not, however, mean you can ignore SQL.
- Term
RPC
- Meaning
Remote Procedure Call. A communication style in which a function across a network is called as if it were local.
- Term
Lock
- Meaning
A mechanism that locks a resource that would be corrupted by concurrent access. Examples include DB row locks, mutexes, and distributed locks.
- Term
Idempotency
- Meaning
The property of ensuring that sending the same request multiple times produces the same result as sending it once. Often seen alongside Retry.
- Term
Backoff
- Meaning
A strategy of progressively increasing the interval between retries, used to avoid hammering a system that is already experiencing failures.
- Term
Fallback
- Meaning
An alternative path used when the primary path fails. Examples include returning a cached value, sending a default response, or calling a backup server.
- Term
TTL
- Meaning
Time To Live. The duration a cache entry or token remains valid.
- Term
Stale data
- Meaning
Data that is no longer up to date. Caches often trade accepting stale data for improved speed.
- Term
Execution plan
- Meaning
The plan a database generates for how it will execute a SQL query. This is where it decides whether to use an index or perform a full table scan.
- Term
Transaction
- Meaning
Grouping multiple database operations within a single consistency boundary. It commits on success and rolls back on failure.
Structural Patterns
Pattern | Common use cases | One-line guidance |
|---|---|---|
Composition | Policies, renderers, storage, validators | Look here first when inheritance hierarchies grow too deep |
Strategy Pattern | Discounts, shipping fees, authorization, sorting, validation | When an algorithm or policy changes frequently |
Adapter Pattern | External SDKs, payment processors, file storage, legacy APIs | When preventing an external interface from leaking into internal code |
Facade Pattern | Order creation, member registration, payment completion processing | When a simple entry point is needed in front of a complex subsystem |
Decorator Pattern | Logging, caching, authorization checks, metrics | When adding extra behavior without modifying the original object |
- Pattern
Composition
- Common use cases
Policies, renderers, storage, validators
- One-line guidance
Look here first when inheritance hierarchies grow too deep
- Pattern
Strategy Pattern
- Common use cases
Discounts, shipping fees, authorization, sorting, validation
- One-line guidance
When an algorithm or policy changes frequently
- Pattern
Adapter Pattern
- Common use cases
External SDKs, payment processors, file storage, legacy APIs
- One-line guidance
When preventing an external interface from leaking into internal code
- Pattern
Facade Pattern
- Common use cases
Order creation, member registration, payment completion processing
- One-line guidance
When a simple entry point is needed in front of a complex subsystem
- Pattern
Decorator Pattern
- Common use cases
Logging, caching, authorization checks, metrics
- One-line guidance
When adding extra behavior without modifying the original object
Control Flow Patterns
Pattern | Common use cases | One-line guidance |
|---|---|---|
Guard Clause | API handlers, validation, command handlers | When reducing nested |
Result Pattern | Parsing, validation, domain commands | When failure is part of the normal business flow rather than an exception |
State Pattern | Order status, game state, approval workflows | When per-state behavior and transitions become complex |
- Pattern
Guard Clause
- Common use cases
API handlers, validation, command handlers
- One-line guidance
When reducing nested
ifblocks by handling failure conditions up front
- Pattern
Result Pattern
- Common use cases
Parsing, validation, domain commands
- One-line guidance
When failure is part of the normal business flow rather than an exception
- Pattern
State Pattern
- Common use cases
Order status, game state, approval workflows
- One-line guidance
When per-state behavior and transitions become complex
Data Access Patterns
Pattern | Common use cases | One-line guidance |
|---|---|---|
Repository Pattern | Aggregate storage for orders, members, products, etc. | When pushing DB details out of domain code |
Query Facade | Admin screens, dashboards, list APIs | When read-only queries are forced to drag along the domain model unnecessarily |
Model boundary separation: DTO / Entity / Value Object | Web APIs, external integrations, DDD models | When the rate of change differs among the database, domain, and API response |
- Pattern
Repository Pattern
- Common use cases
Aggregate storage for orders, members, products, etc.
- One-line guidance
When pushing DB details out of domain code
- Pattern
Query Facade
- Common use cases
Admin screens, dashboards, list APIs
- One-line guidance
When read-only queries are forced to drag along the domain model unnecessarily
- Pattern
Model boundary separation: DTO / Entity / Value Object
- Common use cases
Web APIs, external integrations, DDD models
- One-line guidance
When the rate of change differs among the database, domain, and API response
Operational Patterns
Pattern | Common use cases | One-line guidance |
|---|---|---|
Retry | HTTP clients, DB commands, message processing | When the failure is transient and retrying may succeed |
Timeout | External APIs, databases, RPCs, lock acquisition | When a slow dependency is holding up the entire system |
Circuit Breaker | Payment processor APIs, auth servers, remote services | When a failing external dependency threatens to bring down your own server |
Cache-Aside Pattern | Product detail pages, configuration values, authorization lists | When the same data is read repeatedly and slightly stale values are acceptable |
- Pattern
Retry
- Common use cases
HTTP clients, DB commands, message processing
- One-line guidance
When the failure is transient and retrying may succeed
- Pattern
Timeout
- Common use cases
External APIs, databases, RPCs, lock acquisition
- One-line guidance
When a slow dependency is holding up the entire system
- Pattern
Circuit Breaker
- Common use cases
Payment processor APIs, auth servers, remote services
- One-line guidance
When a failing external dependency threatens to bring down your own server
- Pattern
Cache-Aside Pattern
- Common use cases
Product detail pages, configuration values, authorization lists
- One-line guidance
When the same data is read repeatedly and slightly stale values are acceptable
Practical selection guide
When you see this problem | Start with this pattern |
|---|---|
Inheritance hierarchies grow too deep | Composition |
A policy or algorithm changes frequently | Strategy Pattern |
The shape of an external SDK spreads into internal code | Adapter Pattern |
Subsystem call sequences become complex | Facade Pattern |
You want to add extra behavior without modifying the original object | Decorator Pattern |
Nested | Guard Clause |
The caller must handle failures directly | Result Pattern |
Per-state behavior and transitions are complex | State Pattern |
DB details are leaking into domain code | Repository Pattern |
Screen queries are forced to drag along the domain model | Query Facade |
External calls fail occasionally | Retry + Timeout |
A failure in an external dependency is bringing down your system | Circuit Breaker |
The same data is read repeatedly | Cache-Aside |
- When you see this problem
Inheritance hierarchies grow too deep
- Start with this pattern
Composition
- When you see this problem
A policy or algorithm changes frequently
- Start with this pattern
Strategy Pattern
- When you see this problem
The shape of an external SDK spreads into internal code
- Start with this pattern
Adapter Pattern
- When you see this problem
Subsystem call sequences become complex
- Start with this pattern
Facade Pattern
- When you see this problem
You want to add extra behavior without modifying the original object
- Start with this pattern
Decorator Pattern
- When you see this problem
Nested
ifblocks grow too deep- Start with this pattern
Guard Clause
- When you see this problem
The caller must handle failures directly
- Start with this pattern
Result Pattern
- When you see this problem
Per-state behavior and transitions are complex
- Start with this pattern
State Pattern
- When you see this problem
DB details are leaking into domain code
- Start with this pattern
Repository Pattern
- When you see this problem
Screen queries are forced to drag along the domain model
- Start with this pattern
Query Facade
- When you see this problem
External calls fail occasionally
- Start with this pattern
Retry + Timeout
- When you see this problem
A failure in an external dependency is bringing down your system
- Start with this pattern
Circuit Breaker
- When you see this problem
The same data is read repeatedly
- Start with this pattern
Cache-Aside
Signs of pattern overuse
Creating a Strategy when there is only one variant.
Adding multiple layers of Adapter when there is only one external system.
Wrapping a simple function call in a Command object.
Creating a State Pattern when there are only two states.
Piling DDD, CQRS, and Event Sourcing onto a simple CRUD screen.
Something is named after a pattern but ends up being a massive object that hides responsibility.
To put it textbook-style, patterns are not decorations for showing off skill. They are only meaningful when they reduce the actual change pressure the code is experiencing right now.
Personal note: That said, when explaining code using pattern terminology, it tends to look impressive and clients are inclined to pay more. Even when it is nothing special, it can come across as expertise. The textbook answer is that patterns are not for showing off, but not everything goes by the textbook.
See also
Object-Oriented Programming
Programming Idioms
Composition
Data-Oriented Programming
SQL
Columnar Databases
[1] Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1994.
https://www.informit.com/store/design-patterns-elements-of-reusable-object-oriented-9780201633610
[2] Martin Fowler. Patterns of Enterprise Application Architecture. Addison-Wesley, 2002.
https://martinfowler.com/books/eaa.html
[3] Martin Fowler. Refactoring: Improving the Design of Existing Code. 2nd ed., Addison-Wesley, 2018.
https://martinfowler.com/books/refactoring.html
https://www.informit.com/store/refactoring-improving-the-design-of-existing-code-9780134757599
[4] Joshua Kerievsky. Refactoring to Patterns. Addison-Wesley, 2004.
https://www.informit.com/store/refactoring-to-patterns-9780321213358
[5] Eric Evans. Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley, 2003.
https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
[6] Vaughn Vernon. Implementing Domain-Driven Design. Addison-Wesley, 2013.
https://books.google.com/books/about/Implementing_Domain_Driven_Design.html?id=X7DpD5g3VP8C
[7] Gregor Hohpe, Bobby Woolf. Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions. Addison-Wesley, 2003.
https://www.enterpriseintegrationpatterns.com/
https://martinfowler.com/books/eip.html
[8] Michael T. Nygard. Release It!: Design and Deploy Production-Ready Software. 2nd ed., Pragmatic Bookshelf, 2018.
https://pragprog.com/titles/mnee2/release-it-second-edition/
[9] Brendan Burns. Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services. O’Reilly, 2018.
https://www.oreilly.com/library/view/designing-distributed-systems/9781491983638/
[10] Martin Kleppmann. Designing Data-Intensive Applications. O’Reilly, 2017.
https://www.oreilly.com/library/view/designing-data-intensive-applications/9781491903063/
[11] Chris Richardson. Microservices Patterns: With Examples in Java. Manning, 2018.
https://www.manning.com/books/microservices-patterns
https://microservices.io/patterns/
[12] Mark Seemann, Steven van Deursen. Dependency Injection Principles, Practices, and Patterns. Manning, 2019.
https://www.manning.com/books/dependency-injection-principles-practices-patterns
[13] Robert C. Martin. Clean Architecture: A Craftsman’s Guide to Software Structure and Design. Prentice Hall, 2017.
https://books.google.com/books/about/Clean_Architecture.html?id=fwvetAEACAAJ
[14] John Ousterhout. A Philosophy of Software Design. Yaknyam Press, 2018.
https://web.stanford.edu/~ouster/cgi-bin/aposd2ndEdExtract.pdf
[15] Christopher Alexander, Sara Ishikawa, Murray Silverstein. A Pattern Language: Towns, Buildings, Construction. Oxford University Press, 1977.
https://global.oup.com/academic/product/a-pattern-language-9780195019193
[16] Microsoft Azure Architecture Center. Cloud Design Patterns.
https://learn.microsoft.com/en-us/azure/architecture/patterns/
Category: Programming | Software Engineering | Design Patterns | WIKI
Footnotes
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 1994.https://www.informit.com/store/design-patterns-elements-of-reusable-object-oriented-9780201633610 ↩
- Martin Fowler. Patterns of Enterprise Application Architecture. Addison-Wesley, 2002.https://martinfowler.com/books/eaa.html ↩