DDD - Modelling the Domain - Factories

In Object-Oriented programming there are many design patterns to create objects that were mainly popularised by Gamma et al (1995). It should be stressed out that “favouring object composition over class inheritance” (Gamma et al, 1995) is central to Domain-Driven Design which raises the importance of the creational patterns, hereafter referred to as Factories (Evans, 2003). In short, Factories are objects that have a single responsibility i.e. to encapsulate the logic of creating other objects (Evans, 2003).

Often the construction of domain objects is too complex and this is especially true for aggregates (Evans, 2003). For example, consider a Computer aggregate with one or more CPUs, RAM chips, hard disks etc. Should the Computer know how to create its own CPUs and RAM? Calling the constructors of CPU and RAM inside the Computer's constructor is a sign that an independent Factory needs to be employed to shift the responsibility of assembling complicated objects (Evans, 2003).

According to Evans (2003), there are 2 main ways of employing factories when designing the domain model: as a Factory Method and as a standalone Abstract Factory object (Gamma et al, 1995). An aggregate could provide a Factory Method to instantiate an object that is not part of the aggregate after it is created (Evans, 2003, Vernon 2013). As a case in point, consider a ShoppingCart aggregate that contains a list of products. To create a PurchaseOrder we need the contents of the cart. Instead of fetching and processing the contained products directly, we could employ the method ShoppingCart.create_order_for(customer) that instantiates and returns a PurchaseOrder object for a particular customer and enforces any invariants (Vernon, 2013). Furthermore, factory methods on aggregates could be used to hide implementation details from the client e.g. the method PurchaseOrder.add(product, quantity) could instantiate an OrderItem enforcing any aggregate integrity rules (Evans, 2003). A standalone Abstract Factory object is generally used to provide "an interface for creating families of related or dependent objects without specifying their concrete classes" (Gamma et al, 1995). In this case, the Factory object should create and return a reference to the whole aggregate (e.g. a Computer) including any depending objects (e.g. CPU, RAM) and enforcing any business logic (Evans, 2003). Moreover, a Factory object could be used in reconstituting domain objects from the data store (Evans, 2003). At the same time, Factories should not be overused, especially when an object's construction is not complex.

References

  • Evans, E. (2003) Domain-Driven Design: Tacking Complexity In the Heart of Software. Boston: Addison-Wesley.
  • Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1995) Design Patterns: Elements of Reusable Object-Oriented Software. New York: Addison-Wesley.
  • Vernon, V. (2013) Implementing Domain-Driven Design. Boston: Addison-Wesley.

This post is an excerpt of my MSc Thesis titled "Applying Domain-Driven Design in Python - designing a self-hosted Read-it-Later service" (January 2014).

This article was updated on

Related post

DDD - Modelling the Domain - Services

When designing a Domain Model the prominent modelling paradigm is objects and as a result we are mapping concepts i.e. nouns to DDD building blocks such as Entities and Value Objects. The behaviour associated to those concepts is mapped to methods using verbs. However, there are domain specific functions that we would like to define in the model but cannot be attached into an existing Entity or Value Object (Evans, 2003). Instead of forcing foreign operations into domain objects, Evans (2003) introduced the concept of Domain Services.

DDD - Modelling the Domain - Value Objects

There are elements of the Domain Model without any conceptual identity which are typically used to characterise Entities (Evans, 2003). Those elements are called Value Objects and their significance is often neglected (Vernon, 2013). Examples of Value Objects are: Zip Code, Order Number, Phone Number, Money, Currency, Date, Date Range, E-mail Address, URL etc. Value Objects express domain concepts and are part of the Ubiquitous Language (Evans 2003; Vernon, 2013).