Enterprise Architecture Pattern Stack Selector
by @quochungto
Select the right enterprise application architecture patterns for every layer of your system using Fowler's PEAA decision framework. Use this skill when desi...
clawhub install bookforge-enterprise-architecture-pattern-stack-selectorπ About This Skill
name: enterprise-architecture-pattern-stack-selector description: "Select the right enterprise application architecture patterns for every layer of your system using Fowler's PEAA decision framework. Use this skill when designing or refactoring an enterprise app and asking: which domain-logic pattern should I use (Transaction Script, Domain Model, Table Module)? Which persistence pattern fits my stack (Active Record, Data Mapper, Table Data Gateway, Row Data Gateway)? Which web-presentation pattern applies (Front Controller, Page Controller, Template View)? How do I combine these into a coherent full-stack architecture? Triggers include: 'help me choose architecture patterns', 'which Fowler pattern for my app', 'enterprise application architecture', 'PEAA pattern selection', 'layer pattern selection', 'domain logic pattern vs persistence pattern', 'refactor enterprise app to patterns', 'how to structure a Spring/Django/Rails/ASP.NET app', 'what persistence pattern should I use', 'enterprise architecture decision', 'full-stack pattern stack', 'patterns of enterprise application architecture'. This is the hub skill β it maps your subsystem context to per-layer family selector skills and produces a consolidated Pattern Stack Decision Record." version: 1.0.0 homepage: https://github.com/bookforge-ai/bookforge-skills/tree/main/books/patterns-of-enterprise-application-architecture/skills/enterprise-architecture-pattern-stack-selector metadata: {"openclaw":{"emoji":"π","homepage":"https://github.com/bookforge-ai/bookforge-skills"}} status: draft source-books: - id: patterns-of-enterprise-application-architecture title: "Patterns of Enterprise Application Architecture" authors: ["Martin Fowler", "David Rice", "Matthew Foemmel", "Edward Hieatt", "Robert Mee", "Randy Stafford"] chapters: [introduction, 1, 8] domain: software-architecture tags: ["enterprise-architecture", "software-architecture", "design-patterns", "persistence", "web-application", "domain-logic", "layered-architecture", "pattern-selection"] depends-on: [] execution: tier: 2 mode: hybrid inputs: - type: codebase description: "The enterprise application codebase (domain, persistence, web layers) or a description of the subsystem under discussion." - type: user-description description: "Stack (language, ORM, web framework), subsystem scope, pain points, and any existing architectural commitments." tools-required: [Read, Grep, Glob, Write] tools-optional: [] mcps-required: [] environment: "An enterprise application codebase (OO language + SQL database + web layer), or a description of one. Works offline from description alone. Output: a Pattern Stack Decision Record markdown document." discovery: goal: "Produce a per-layer pattern stack recommendation for an enterprise application subsystem, routing each architectural layer to the right pattern family and documenting the rationale." tasks: - "Gather stack, subsystem scope, domain complexity, and existing commitments from the user or codebase" - "Route the domain-logic layer to the appropriate pattern family (Transaction Script / Domain Model / Table Module)" - "Route the data-source layer based on the domain-logic choice" - "Route the web-presentation layer to controller and view patterns" - "Apply the First Law of Distributed Object Design and route session-state and concurrency concerns" - "Produce a consolidated Pattern Stack Decision Record with per-layer rationale" audience: roles: ["software-architect", "senior-backend-engineer", "tech-lead", "staff-engineer"] experience: "intermediate" when_to_use: triggers: - "Starting greenfield enterprise application design" - "Evaluating architectural patterns for a new subsystem in an existing app" - "Refactoring a legacy enterprise app and needing a pattern vocabulary" - "Team alignment: getting everyone to agree on which patterns apply to each layer" - "Architecture review: auditing whether the current pattern stack is appropriate for the domain complexity" prerequisites: [] not_for: - "Micro-service topology decisions (this skill addresses in-process layering, not service decomposition)" - "Pure front-end or mobile applications with no server-side persistence" - "Implementation details of a single pattern (use the family selector skill for that)" environment: codebase_required: false codebase_helpful: true works_offline: true quality: scores: with_skill: null baseline: null delta: null tested_at: null eval_count: null assertion_count: 13 iterations_needed: null
Enterprise Architecture Pattern Stack Selector
When to Use
Use this skill at the start of enterprise application design or major refactoring, when a team needs to select consistent patterns across the domain-logic, data-source, web-presentation, concurrency, and session-state layers of an OO enterprise application backed by a relational database.
This is a router skill: it collects your context, routes each architectural layer to the appropriate pattern family, and produces a consolidated Pattern Stack Decision Record. If you have a specific layer question (e.g., only data-source patterns), use the targeted family selector skill instead.
Prerequisite check before starting:
Context and Input Gathering
Required Context
Observable Context (if codebase is present)
Scan the codebase for:
pom.xml, Gemfile, requirements.txt, package.json, *.csproj β detect stack and ORM.src/domain/ or src/models/ β are there rich entity classes with behavior, or thin data-holder classes?src/persistence/ or src/repositories/ β hand-rolled SQL vs ORM-mapped classes.src/web/ or src/controllers/ β one class per route vs a single dispatcher.schema.sql, migrations/) β how closely does the schema match the domain model?Sufficiency Gate
If domain-logic complexity is unclear, ask: "If I describe two business rules β are they mostly independent procedural steps, or do they interact through shared domain objects with their own behavior?" This distinguishes Transaction Script from Domain Model territory.
Process
Step 1 β Identify the layers in scope
List which layers the user's question touches: domain logic, data source (persistence), web presentation, concurrency, session state, distribution. If the user said "full stack" or "design my enterprise app", all layers are in scope.
WHY: The hub-and-spoke routing only produces value if it's scoped correctly. Selecting data-source patterns without knowing the domain-logic pattern already chosen leads to mismatched recommendations.
Step 2 β Start with the domain-logic layer (the central decision)
Fowler's "Putting It All Together" (Ch 8) is explicit: the domain-logic choice shapes every downstream layer decision. The three candidates are:
| Pattern | When to choose | |---|---| | Transaction Script (procedural service per use-case) | Simple domain logic; team comfortable with procedural style; scripts don't grow complex; low rule-variation count | | Domain Model (rich OO entity graph / DDD-style) | Complex business logic; many domain variations; team has OO modeling skill; willing to invest in O/R mapping | | Table Module (one class per table, record-set oriented) | Moderate complexity; environment with strong record-set tooling (e.g., .NET DataSet, COM+); good middle ground for .NET stacks |
Signals pointing toward Domain Model: duplicate logic spreading across Transaction Scripts; rules that depend on object state (not just database state); complex inheritance in the domain.
If the user's question covers domain logic in detail β invoke domain-logic-pattern-selector for deeper decision analysis. If unavailable β ask: "Are your business rules mostly independent per-use-case scripts, or do they involve domain objects with shared state and behavior?"
WHY: Getting the domain-logic choice wrong is the most expensive mistake. Choosing Transaction Script when domain complexity demands Domain Model leads to exponential duplication. Choosing Domain Model prematurely for CRUD-only systems adds O/R mapping overhead with no benefit.
Step 3 β Route the data-source layer based on the domain-logic choice
The data-source pattern is not an independent choice; it follows from Step 2:
If Transaction Script was chosen:
If Table Module was chosen:
If Domain Model was chosen:
If the user's question is primarily about persistence pattern selection β invoke data-source-pattern-selector for full analysis including structural mapping (inheritance, associations). If unavailable β ask: "What is the domain-logic pattern already chosen, and how closely does your class model match your database schema?"
WHY: Pairing incompatible domain-logic and data-source patterns is the most common enterprise architecture mistake. Using Data Mapper overhead on a Transaction Script system wastes complexity. Using Active Record on a complex Domain Model creates tight coupling between the domain and the schema.
Step 4 β Route the web-presentation layer
Web-presentation pattern selection is relatively independent of domain-logic and data-source choices, but depends on UI complexity and tooling.
Controller pattern:
View pattern:
Recommendation for most stacks: Front Controller + Template View is the safe default (and what most modern web frameworks implement by default).
If the user's question is primarily about web-presentation β invoke web-presentation-pattern-selector for deeper analysis. If unavailable β ask about navigation complexity and whether the application is document-oriented or workflow-oriented.
WHY: Choosing Page Controller for a complex, workflow-heavy application creates duplicated pre/post-processing logic across every controller. Choosing Transform View for a team with no XSLT experience creates a skills mismatch.
Step 5 β Apply the First Law of Distributed Object Design
First Law: Do not distribute. Run everything in a single process unless you have a hard requirement to separate processes (different security boundary, different deployment cadence, separate team ownership, hardware constraint).
If distribution is required:
For session state across requests:
If the user's question focuses on distribution or session state β invoke distribution-boundary-designer or session-state-location-selector respectively.
WHY: Premature distribution is Fowler's most-cited enterprise architecture anti-pattern. Distributing by domain object class (one process per entity type) makes every business operation a cascade of slow remote calls. The First Law exists because this mistake is pervasive and expensive.
Step 6 β Handle concurrency across requests
For long business transactions that span multiple HTTP requests:
If the user's question focuses on concurrency β invoke offline-concurrency-strategy-selector.
WHY: Skipping offline concurrency design leads to lost updates β a persistent source of data corruption in enterprise applications that is hard to diagnose retrospectively.
Step 7 β Produce the Pattern Stack Decision Record
Write a markdown artifact with: 1. Subsystem: name and scope. 2. Stack: language, framework, ORM. 3. Domain Logic Layer: chosen pattern + rationale + forces considered + alternatives rejected. 4. Data Source Layer: chosen pattern(s) + rationale + behavioral patterns needed (Unit of Work, Identity Map, Lazy Load). 5. Web Presentation Layer: controller pattern + view pattern + rationale. 6. Concurrency Strategy: chosen pattern + trigger condition. 7. Session State Strategy: chosen pattern + scalability implication. 8. Distribution: in-process or Remote Facade + DTO; rationale. 9. Known Risks: what to watch for as the system grows (e.g., Transaction Script growing into complex domain logic β upgrade to Domain Model). 10. Next Steps: which family selector skills to invoke for detailed implementation guidance.
WHY: Without a documented decision record, architectural decisions are re-litigated in every code review. The artifact creates shared vocabulary and makes the forces-and-resolution reasoning visible to the whole team.
Inputs
src/, schema.sql, build files to infer stack and patterns in use.Outputs
Output template:
# Pattern Stack Decision Record β [Subsystem Name]Stack
Language / Framework: [e.g., Java 21 / Spring Boot 3]
ORM / Persistence: [e.g., Hibernate 6 / JPA]
Web Layer: [e.g., Spring MVC / Thymeleaf] Domain Logic Layer
Pattern: [Transaction Script | Domain Model | Table Module]
Rationale: [forces that drove the choice]
Alternatives rejected: [why the others were ruled out] Data Source Layer
Pattern: [Table Data Gateway | Row Data Gateway | Active Record | Data Mapper]
Behavioral patterns: [Unit of Work | Identity Map | Lazy Load β as needed]
Rationale: [follows from domain-logic choice + schema complexity] Web Presentation Layer
Controller: [Page Controller | Front Controller + Application Controller]
View: [Template View | Transform View | Two Step View]
Rationale: [navigation complexity + team tooling] Concurrency Strategy
Pattern: [Optimistic Offline Lock | Pessimistic Offline Lock | Coarse-Grained Lock | Implicit Lock]
Trigger: [when this applies] Session State
Strategy: [Client | Server | Database Session State]
Scalability implication: [stateless vs server-affinity vs DB load] Distribution
[Single process β preferred] OR [Remote Facade + DTO β required because: ...] Known Risks
[Growth risks: when to re-evaluate the domain-logic choice] Next Steps
[ ] Invoke domain-logic-pattern-selector for implementation depth on domain layer
[ ] Invoke data-source-pattern-selector for persistence pattern detail
[ ] Invoke inheritance-mapping-selector if the schema has inheritance hierarchies
Key Principles
1. Domain-logic choice is the central decision β make it first. Every other layer decision is shaped by whether you chose Transaction Script, Domain Model, or Table Module. Reversing this decision later is expensive. Invest time here before designing the persistence or web layers.
2. The First Law of Distributed Object Design: minimize distribution. Every process boundary is a performance tax. Run as much as possible in a single process. Introduce Remote Facade + DTO only where a hard requirement forces a boundary. Do not distribute for the sake of perceived scalability β measure first.
3. Active Record fits simple Domain Models; Data Mapper fits complex ones. Choosing Data Mapper when Active Record would suffice adds unnecessary mapping complexity. Choosing Active Record for a complex Domain Model creates tight coupling that constrains future refactoring. The tipping point is when the schema and the object model begin to diverge significantly.
4. O/R mapping tools over hand-rolled mappers. When Data Mapper is required, use an established mapping tool (Hibernate, SQLAlchemy, EF Core, TypeORM). Hand-rolling a Data Mapper is a significant engineering undertaking β only justified if the tooling is truly unavailable or inappropriate.
5. Web-presentation patterns are platform defaults β work with them. Most modern frameworks have already made the controller choice for you (Spring DispatcherServlet = Front Controller; Rails Router = Front Controller; classic ASP.NET Web Forms β Page Controller). Override the default only when you have a specific reason; fighting the framework's grain is rarely worth the cost.
6. Optimistic Offline Lock is the right default for multi-request editing. Pessimistic locking is harder to implement correctly, creates hanging-lock failure modes, and adds server-affinity pressure. Default to Optimistic Offline Lock (version column) and move to Pessimistic only when you have measured high conflict rates and confirmed that late-failure is unacceptable to users.
7. Document the pattern stack and keep it visible. Architecture decisions fade from team memory. The Pattern Stack Decision Record is a living document β update it when the system grows and a layer's pattern needs to change (e.g., Transaction Scripts outgrowing into Domain Model).
Examples
Scenario A β Java/Spring Boot + Hibernate enterprise ordering system
Trigger: "We're building an order-management system for a B2B wholesaler. Complex pricing rules (tiered discounts, contract pricing, surcharges), multi-step order-approval workflow, 30 developers on multiple teams, Spring Boot + Hibernate stack."
Process:
@Version).Output: Pattern Stack Decision Record with Domain Model + Data Mapper (Hibernate) + Front Controller + Template View + Optimistic Offline Lock + Server Session State for workflow.
Scenario B β Ruby on Rails / Django application (framework defaults)
Trigger: "We're building a SaaS project-management tool. Standard CRUD with some business rules. Small team (5 engineers). Rails (or Django)."
Process:
lock_version column convention; Django provides select_for_update or F object compare-and-set.Output: Accept framework defaults (Active Record + Front Controller + Template View + Optimistic Offline Lock + Client Session State). Revisit domain-logic pattern if complexity grows.
Scenario C β ASP.NET Core enterprise application (.NET stack)
Trigger: "We're migrating a legacy ASP.NET WebForms app to ASP.NET Core + EF Core. Complex lease-calculation logic, 15-person team, SQL Server."
Process:
[Timestamp] / rowversion) β Optimistic Offline Lock by default.Output: Domain Model (or Table Module) + Data Mapper (EF Core) + Front Controller (ASP.NET Core MVC) + Template View (Razor) + Optimistic Offline Lock + Database Session State for durable workflow.
References
references/pattern-stack-decision-table.md β quick-reference routing table: domain-logic pattern β data-source patterns β behavioral patterns needed.references/layer-anti-patterns.md β common mis-pairings and how to recognize them in a codebase.License
This skill is licensed under CC-BY-SA-4.0. Source: BookForge β *Patterns of Enterprise Application Architecture* by Martin Fowler, David Rice, Matthew Foemmel, Edward Hieatt, Robert Mee, Randy Stafford.
Related BookForge Skills
Install related skills from ClawhHub:
clawhub install bookforge-domain-logic-pattern-selectorclawhub install bookforge-data-source-pattern-selectorclawhub install bookforge-inheritance-mapping-selectorclawhub install bookforge-object-relational-structural-mapping-guideclawhub install bookforge-web-presentation-pattern-selectorclawhub install bookforge-offline-concurrency-strategy-selectorclawhub install bookforge-session-state-location-selectorclawhub install bookforge-distribution-boundary-designerclawhub install bookforge-enterprise-base-pattern-catalogOr install the full book set from GitHub: bookforge-skills
β‘ When to Use
π‘ Examples
Scenario A β Java/Spring Boot + Hibernate enterprise ordering system
Trigger: "We're building an order-management system for a B2B wholesaler. Complex pricing rules (tiered discounts, contract pricing, surcharges), multi-step order-approval workflow, 30 developers on multiple teams, Spring Boot + Hibernate stack."
Process:
@Version).Output: Pattern Stack Decision Record with Domain Model + Data Mapper (Hibernate) + Front Controller + Template View + Optimistic Offline Lock + Server Session State for workflow.
Scenario B β Ruby on Rails / Django application (framework defaults)
Trigger: "We're building a SaaS project-management tool. Standard CRUD with some business rules. Small team (5 engineers). Rails (or Django)."
Process:
lock_version column convention; Django provides select_for_update or F object compare-and-set.Output: Accept framework defaults (Active Record + Front Controller + Template View + Optimistic Offline Lock + Client Session State). Revisit domain-logic pattern if complexity grows.
Scenario C β ASP.NET Core enterprise application (.NET stack)
Trigger: "We're migrating a legacy ASP.NET WebForms app to ASP.NET Core + EF Core. Complex lease-calculation logic, 15-person team, SQL Server."
Process:
[Timestamp] / rowversion) β Optimistic Offline Lock by default.Output: Domain Model (or Table Module) + Data Mapper (EF Core) + Front Controller (ASP.NET Core MVC) + Template View (Razor) + Optimistic Offline Lock + Database Session State for durable workflow.