Loading content...
You now have frameworks for identifying problems, evaluating pattern fit, and considering alternatives. This final page synthesizes everything into a practical decision checklist—a tool you can reference whenever you're considering whether to apply a design pattern.
The checklist is not meant to be followed rigidly. It's a thinking aid that ensures you consider important factors before committing to a design decision. Over time, many of these checks will become intuitive. But especially when you're developing pattern selection skills, working through the checklist prevents common mistakes.
How to Use This Checklist
Work through the sections in order. Each section has a go/no-go assessment. Continuing past a failed section means you're accumulating risk. If you find yourself skipping or rationalizing past failures, that's a signal to stop and reconsider.
Each section contains verification questions. For each question, honestly assess whether your situation passes. A 'No' doesn't always mean stop—but multiple 'No' answers in a section suggest reconsidering your direction.
Before selecting any pattern, verify that you've properly identified the problem.
| Check | Question | Red Flag if No |
|---|---|---|
| □ | Can you state the observable symptom in one sentence? | Vague problem understanding; likely to solve wrong problem |
| □ | Have you traced the symptom to a root cause (not just another symptom)? | May address symptoms rather than causes |
| □ | Can you identify at least two competing forces creating the design tension? | May apply pattern where no real design problem exists |
| □ | Can you state the desired outcome without mentioning any solution? | Solution contamination; outcome confusion with approach |
| □ | Have you identified what must remain unchanged (constraints)? | Pattern may violate existing invariants |
| □ | Can you categorize this into a problem family (creation, behavior variation, composition, etc.)? | Problem not yet well enough understood for pattern selection |
If you cannot check at least 4 of these 6 boxes, stop pattern selection. Return to problem analysis. Selecting a pattern with unclear problem understanding leads to misapplication.
Sample Problem Statement for Reference
Before proceeding, write a problem statement. It should look like:
Observable: Adding new export formats (PDF, CSV, JSON) requires modifying the ReportGenerator class.
Root Cause: ReportGenerator handles both data assembly and format-specific rendering. Export logic is coupled to generation.
Forces: (1) New formats will continue to be added, (2) Generator logic must remain stable, (3) Each format has unique rendering requirements.
Desired Outcome: Add new export formats without modifying ReportGenerator. Generator produces format-agnostic data; formatters render.
Constraints: Existing reports must continue working. Current PDF output quality must be maintained.
Problem Family: Algorithm/behavior variation (different rendering algorithms for same data).
If you can write a statement like this, proceed to pattern evaluation.
Before diving into pattern selection, verify that a pattern is actually warranted.
| Check | Question | If No, Consider... |
|---|---|---|
| □ | Is the variation/complexity unlikely to be addressed by a simple if/else or switch? | Simple conditional may be the right solution |
| □ | Will more than 2-3 variants exist? | Small variant count often doesn't warrant pattern abstraction |
| □ | Does the problem span more than one module/class? | Local problems often have simpler local solutions |
| □ | Is the area likely to change after initial implementation? | Stable code benefits less from pattern flexibility |
| □ | Would the team benefit from a shared design vocabulary here? | Patterns add communication value in collaborative contexts |
| □ | Does the problem recur in multiple places? | One-off problems may not justify pattern infrastructure |
If you're applying a pattern based on anticipated future needs rather than current proven needs, challenge yourself: Is this speculation? Can you start simple and refactor to the pattern when specific need materializes?
For each candidate pattern, verify fit across all dimensions.
| Dimension | Verification Question | Pass/Fail |
|---|---|---|
| Intent | Does the pattern's stated intent directly address your identified problem? | □ Pass / □ Fail |
| Intent | Can you explain why this intent applies without philosophical gymnastics? | □ Pass / □ Fail |
| Applicability | Does your context match at least 3 of the pattern's stated applicability conditions? | □ Pass / □ Fail |
| Applicability | Are there any applicability conditions you're ignoring? If so, can you justify ignoring them? | □ Pass / □ Fail |
| Participants | Can you assign a domain element to each pattern participant without stretching? | □ Pass / □ Fail |
| Participants | Do your elements' responsibilities align with what the pattern expects of those roles? | □ Pass / □ Fail |
| Consequences | Have you reviewed all stated pattern consequences (benefits AND costs)? | □ Pass / □ Fail |
| Consequences | Are all cost consequences acceptable in your specific context? | □ Pass / □ Fail |
Scoring Your Fit Evaluation
Comparative Evaluation (When Multiple Candidates Exist)
Complete the fit checklist for each candidate pattern. Compare:
If the Intent dimension fails, stop evaluating that pattern. Intent is the foundation—a pattern whose purpose doesn't match your problem cannot be made to fit through good applicability or participant mapping.
Consequences deserve deeper analysis. For your leading candidate pattern, work through this consequence checklist.
| Category | Question | Your Assessment |
|---|---|---|
| Complexity | How many new classes/interfaces does this pattern introduce? | Count: ___ |
| Complexity | Can your team understand this pattern without training? | □ Yes / □ Needs explanation |
| Performance | Does the pattern add indirection in a hot path? | □ Yes, acceptable / □ Yes, concerning / □ No |
| Performance | Will pattern infrastructure impact memory or startup time significantly? | □ Yes, acceptable / □ Yes, concerning / □ No |
| Testability | Does the pattern improve or complicate unit testing? | □ Improves / □ Neutral / □ Complicates |
| Testability | Can pattern components be tested in isolation? | □ Easily / □ With effort / □ Difficult |
| Maintainability | When requirements change, will the pattern localize changes? | □ Yes / □ Partially / □ No |
| Maintainability | Will new team members understand why the pattern was used? | □ Yes / □ With documentation / □ Unlikely |
| Evolution | Can the pattern accommodate anticipated changes (roadmap items)? | □ Well / □ Partially / □ Poorly |
| Evolution | Is the pattern reversible if needs change unexpectedly? | □ Easily / □ With effort / □ Major refactor |
How to Interpret Consequence Assessment
Common Pattern Consequence Trade-offs
| Pattern | Typical Benefit | Typical Cost | Mitigation |
|---|---|---|---|
| Strategy | Algorithm flexibility, eliminates conditionals | More classes, client must select strategy | Factory for selection; documentation for clarity |
| Observer | Decoupled notification, extensible listeners | Can be hard to trace cause/effect | Good logging; limit chain depth |
| Decorator | Composable behavior modifications | Many small classes, stack depth | Limit decorator chains; clear naming |
| Factory Method | Decoupled instantiation | Parallel class hierarchies | Keep hierarchies shallow |
| State | Localized state-specific behavior | More classes than switch statements | One file per state; clear transitions |
Every pattern has costs. The question isn't whether costs exist but whether benefits outweigh costs in your specific context. A pattern is right when its consequences are acceptable and its benefits address your actual needs.
Before finalizing a catalog pattern, verify you've considered alternatives.
| Check | Question | Notes |
|---|---|---|
| □ | Have you considered a simple solution (function, if/else, switch)? | Simple is better when sufficient |
| □ | Would a modified/simplified version of the pattern work? | Full canonical form may be overkill |
| □ | Does your language/framework provide an idiomatic solution? | Built-in solutions often cleaner |
| □ | Are there relevant patterns from non-GoF catalogs (EIP, DDD, etc.)? | GoF isn't the only pattern source |
| □ | Could pattern combination address your problem better than a single pattern? | Complex problems may need multiple patterns |
| □ | Is a custom design more appropriate for your unique constraints? | Not every problem maps to catalog patterns |
Alternative Quick-Compare
If multiple alternatives remain viable, do a quick comparison:
| Criterion | Catalog Pattern | Pattern Variant | Simple Solution | Custom Design |
|---|---|---|---|---|
| Addresses problem fully | □ | □ | □ | □ |
| Acceptable complexity | □ | □ | □ | □ |
| Team can implement well | □ | □ | □ | □ |
| Maintainable over time | □ | □ | □ | □ |
| Fits time/effort budget | □ | □ | □ | □ |
| Total ✓ | __/5 | __/5 | __/5 | __/5 |
When alternatives score similarly, choose the simpler one. Simplicity is itself a design virtue. You can always evolve toward more sophisticated solutions if needs grow; removing premature sophistication is harder.
Before implementing, verify you're ready to proceed.
| Check | Question | If No... |
|---|---|---|
| □ | Can you draw the pattern structure with your domain elements mapped? | You may not fully understand the pattern or the mapping |
| □ | Can you explain to a colleague why this pattern (and not alternatives)? | Your reasoning may not be sound; get feedback |
| □ | Do you know which tests you'll write to verify the pattern works? | Consider TDD; tests clarify design intent |
| □ | Have you identified the first concrete use case you'll implement? | Start with a specific case, not the abstract structure |
| □ | Is there documented/sample code for this pattern you can reference? | First-time implementation without references is risky |
| □ | Do you have a rollback plan if the pattern doesn't work out? | Know how to revert if reality invalidates assumptions |
Pre-Implementation Sketch
Before coding, create a quick sketch of your pattern implementation:
Example Sketch for Strategy:
Interface:
ExportFormatterwithformat(report: Report): stringImplementations:
PDFFormatter,CSVFormatter,JSONFormatterContext:
ReportService.export(report, formatType)— uses Factory to get formatterFirst test:
CSVFormatter.format(sampleReport)returns valid CSV string
If you can write this sketch, you're ready to implement.
Don't implement the pattern abstractly first. Implement one concrete case, then the second, then extract the pattern. This ensures the abstraction serves real needs rather than imagined ones.
After implementing a pattern, document your decision for future maintainers.
| Check | Documentation Item | Purpose |
|---|---|---|
| □ | Problem statement: What problem did this pattern solve? | Future readers understand the 'why' |
| □ | Alternatives considered: What else did you evaluate? Why not those? | Prevents re-evaluation; records reasoning |
| □ | Pattern choice rationale: Why this pattern specifically? | Makes decision auditable and teachable |
| □ | Participant mapping: Which classes play which pattern roles? | Helps readers map code to pattern |
| □ | Extension points: How should future developers add new variants? | Enables proper pattern usage by others |
| □ | Known limitations: What doesn't this pattern solve? What was out of scope? | Prevents inappropriate pattern expansion |
Documentation Template
# Design Decision: [Pattern Name] for [Feature/Component]
## Problem Statement
[What observable symptom triggered this design? What's the root cause?]
## Forces
- [Force 1]: [Description]
- [Force 2]: [Description]
## Solution: [Pattern Name]
[Brief description of how the pattern applies]
### Participant Mapping
| Pattern Role | Our Implementation |
|--------------|--------------------|
| Strategy | `ExportFormatter` |
| ConcreteStrategy | `PDFFormatter`, `CSVFormatter` |
| Context | `ReportService` |
### Extension Guide
To add a new export format:
1. Create new class implementing `ExportFormatter`
2. Register in `FormatterFactory`
3. Add format option to API enum
## Alternatives Considered
- **Simple switch statement**: Rejected because 6 formats already, 4 more planned
- **Template Method**: Rejected because formats don't share algorithm structure
## Limitations
- This pattern addresses format variation only, not report structure variation
- Performance-critical bulk exports may need different approach
Keep pattern documentation close to the code (e.g., README in the pattern's directory). Centralized design docs often go stale. Colocated docs are more likely to be updated when the pattern evolves.
For quick reference, here's the complete pattern selection process distilled into decision checkpoints:
You may cycle through these stops multiple times. Discovering that consequences are unacceptable might send you back to considering alternatives. Realizing during mapping that participants don't fit might send you back to different patterns. This is normal and healthy.
You now have a complete framework for selecting design patterns systematically rather than intuitively or haphazardly.
Pattern Selection Mastery
With practice, the checklist thinking becomes internalized. You'll naturally consider alternatives, evaluate fit, and analyze consequences without explicitly working through each item. But when facing a particularly complex or consequential design decision, returning to the explicit checklist ensures rigor.
Remember: The goal is effective design, not pattern application. Patterns are tools in service of building maintainable, extensible, understandable software. Select patterns that serve that goal; reject patterns that don't—no matter how elegant they might be.
You now have the framework to select patterns like an experienced software architect.
Congratulations! You've completed the Pattern Selection Framework module. You can now identify problems precisely, evaluate pattern fit systematically, consider alternatives thoroughly, and make defensible pattern decisions. This capability distinguishes engineers who apply patterns effectively from those who apply them ceremonially.