📖 Business
Domain Logic Patterns
Fowler identifies three fundamental patterns for organizing domain logic, each suited to different levels of business complexity. Transaction Script organizes logic as a single procedure per business operation — simple, direct, and appropriate when business rules are straightforward. Domain Model distributes behavior across a rich network of interconnected objects that mirror the business domain — powerful for complex, evolving rules but demanding to build and map to a database. Table Module sits between them, organizing one class per database table with instance methods operating on record sets — a pragmatic middle ground common in .NET environments. The choice among these three patterns is the most consequential architectural decision in an enterprise application, and getting it wrong creates pain that compounds with every new feature.
2
Minutes
2
Concepts
+45
XP
1
How It Works
  1. Transaction Script — One procedure per business transaction. A "place order" operation is a single method that validates the order, calculates totals, applies discounts, checks inventory, and writes to the database. All logic is in the script; data structures are dumb containers.
  • Strengths: Easy to understand, straightforward mapping to use cases, simple data source interaction
  • Weaknesses: Logic duplication across scripts, no reuse of business rules, becomes unwieldy as complexity grows
  • Best for: Simple CRUD applications, reporting tools, internal admin tools
  1. Domain Model — Business logic lives in objects that represent domain concepts (Order, Customer, Product) with both data and behavior. An Order object knows how to calculate its total, a Customer object enforces credit limits, and these objects collaborate to implement business rules.
  • Strengths: Handles complex business rules elegantly, promotes reuse, aligns code with business language
  • Weaknesses: Requires sophisticated ORM mapping, harder to understand for simple operations, steeper learning curve
  • Best for: Complex, rule-heavy domains — insurance, finance, supply chain, anything with intricate business logic
  1. Table Module — One class per database table, with methods operating on a RecordSet (result set) rather than individual domain objects. An OrderModule class has methods like CalculateTotal(DataSet orders, int orderId) that operate on tabular data.
  • Strengths: Natural fit for record-set-oriented environments (.NET DataSets), simpler than Domain Model, avoids ORM complexity
  • Weaknesses: Logic organization tied to database structure, less expressive than Domain Model for complex rules
  • Best for: .NET applications using DataSets, moderate complexity with strong database-centric thinking
  1. The complexity threshold — Fowler's decision heuristic: start with Transaction Script. When scripts begin duplicating logic and becoming hard to maintain (typically when business rules interact across multiple entities), migrate to Domain Model. The transition cost is high, so if you anticipate complex business rules from the start, begin with Domain Model. Table Module is the pragmatic choice when your platform provides strong record-set support.
  1. Mixing patterns — In practice, applications often combine patterns. Simple CRUD areas use Transaction Script while complex core domains use Domain Model. The key is being intentional about which pattern applies where, rather than accidentally ending up with Transaction Scripts that should be a Domain Model.