Graduate Program KB

Domain Driven Design

Chapter 5 - A Model Expressed in Software

  • Simple to conceive associations between objects but difficult to implement
  • There are three patterns of model elements: entities, value objects and services

Associations

  • "For every traversable association in the model, there is a mechanism in the software with the same properties"
    • For example, an association between a customer and a sales representative reflects both a conceptual relationship and physical implementation, much like a reference between two objects in code
  • Implementation of relationships aren't always direct, the design must account how relationships are traversed in the system
  • Many models of relationships are many-to-many and bi-directional, which are complex, hard to maintain and don't convey much about the actual nature of the relationship
  • There are strategies to simplify relationships:
    • Impose a direction: Decide which side of the relationship is primary and make it uni-directional (ex. from country to president, not the reverse)
    • Add a qualifier: Reduce complexity by constraining the association (ex. only one president per country)
    • Eliminate unnecessary associations: Remove relationships that don't make sense
  • Adding constraints such as limiting the number of valid relationships can make associations easier to implement and understand
  • In some cases, bi-directional associations may be necessary but can often be constrained further to simplify the model

Entities

  • Many objects are defined by their identity rather than their attributes
    • For example, a person's identity persists even though their address or name may change
  • An entity like a user may exist across different systems, potentially with different attributes
    • The identity must remain consistent to avoid issues like duplication and mismatched data
  • Not all objects in a model have meaningful identities, if an object's identity is important then the model must prioritise it
  • The model must have a way to distinguish each entity, regardless of form and history
    • May involve attaching a unique identifier or symbol
  • It's important not to designate objects as entities if unnecessary
  • Modeling entities:
    • Keep it simple, only focusing on essential characteristics
      • Unique and immutable ID attached to the entity
      • Common attributes such as name and address which are common query attributes
    • Non-intrinsic attributse can be moved to an associated object (could be other entities or value objects)
    • In some domains, entities may use IDs from external sources such as the government but it may introduce complexity as it's not foolproof

Value objects

  • It's inefficient to assign an identity to all objects
    • Increases complexity, burdens system with unnecessary tracking and prevent performance optimisations
  • Value objects, unlike entities, describe attributes or aspects of the domain
    • Defined by what they are, not who they are
    • These objects are purely descriptive, representing information but don't need a unique identifier
  • Value objects are often transient, created for a specific operation then discarded
  • For example, a person is an entity but their name is a value object
    • Value objects are immutable, their state persists after creation which reduces complexity and ensures stability
  • Related attributes should be bundled together, forming a cohesive whole
    • Ex. Address value object should contain street, city, state, etc.
  • Designing value objects:
    • Should be made immutable
      • An Name object can be copied or shared between two people but if it's mutable, changing it for one person would affect the other
    • Trade-offs between sharing and copying value objects
      • Copying can overload system with too many objects, sharing can create bottlenecks in distributed systems especially. Flyweight patterns can be implemented to help make objects interchangeable and minimise memory usage
    • When to copy or share?
      • Copy when immutability is not guaranteed when passing between processes
      • Share if the object is strictly immutable and when space and overhead is a concern
    • Mutable objects are allowed if:
      • They change frequently
      • Creating or deleting them is resource-intensive
      • Replacing them could disturb object clustering (ex. in databases)
      • If an object is mutable, it must not be shared between different parts of the system

Services

  • Some operations span multiple domain objects and forcing these behaviours on a single object can increase model complexity
  • A service is used when certain operations don't naturally belong to any entity or value object
  • Services don't maintain state or represent a domain object, just exist to simply perform operations
    • Typically named after verbs to represent an action
  • Characteristics of a good service:
    • Service relates to the domain but not fit naturally as part of an entity or value object
    • Interface should be well definde using other domain model elements such as entities or value objects
    • Should not have its own state and should be reusable across different clients
  • Don't overuse services, some behaviour and operations still naturally belong within entities or value objects

Modules

  • Modules allow you to focus on the details within it and see relationships between modules without getting lost in internal details
  • Should represent meaningful concepts in the domain, not just an arbitrary divisions of code
  • Low coupling (limited dependencies) and high cohesion (related key elements) between modules
  • Modules tend to evolve alongside smaller elements within them
    • Harder to refactor modules than classes but allowing modules to reflect changes keeps the model relevant and adaptable
  • Module names become part of the ubiquitous language which reinforces the conceptual structure of the model

Modelling paradigms

  • Entities, value objects, services and modules are fundamental building blocks for an object model in DDD
  • Model driven design doesn't mean forcing everything in an object model, there are other paradigms such as rules engines though it often introduces complexity
  • The object-oriented paradigm dominates
    • Balances simplicity and sophistication
    • Widespread adoption, mature tools and infrastructure
    • Has developer support and established frameworks unlike other paradigms