Friday, November 2, 2018

FACTORIES | Domain Model | Domain Layer

When creation of an object, or an entire AGGREGATE, becomes complicated or reveals too much of the internal structure, FACTORIES provide encapsulation.

Shift the responsibility for creating instances of complex objects and AGGREGATES to a separate object.

Which may itself have no responsibility in the domain model but is still part of the domain design. 

Provide an interface that encapsulates all complex assembly of domain objects. 

Due to these objects, it does not require the client to reference the concrete classes of the objects being instantiated. 

Create entire AGGREGATES as a piece, enforcing their invariant.

All business rules related to the creations of Domain Objects or Aggregates are delegated to Factories.

Invariants == Things to should be always true.


What are Factories in Domain Driven Design 

Factory: methods for creating domain objects should delegate to a specialized Factory object such that alternative implementations may be easily interchanged.

  • A factory separates use from construction in the domain.
  • Knowledge of creating a complex domain object can be hidden from client code and domain objects by employing a factory class.
  • A factory can be used to create the appropriate instance of a domain object based on the needs of the caller.
  • Factory methods can encapsulate the internal state of an aggregate.
  • When you have multiple constructors for different purposes use a factory object to increase the expressiveness of the code.
  • If a domain object is simple and has no special rules for valid construction, favor a constructor method over a factory object.

Factory

Factory design pattern is rather popular and is more widely used than other design patterns.
Some aggregates and entities can be rather complex, and complex objects can create themselves using constructor. The situation can be even worse: when you pass a complex object creation process to the client side. Basically, it means that the client should know a project’s inner structure and dependencies. This disturbs encapsulation and bounds the clients to a specific realization, and you will have to modify the client part when introducing any changes to the object as well.
To make a long story short, it is a much better choice to create complex aggregates or other objects separately. This is when you should rely on factories. Factories are program’s elements that are responsible for creation of other objects.
As a rule, factories are designed as factory method in aggregate root. Factory methods are efficient because they can express ubiquitous language (which constructor can’t do).
When you create factory method in aggregate root, you need to follow all the rules of invariant aggregate and create it as a unified whole. This method must be one and undivided. All factory method creation data (value objects) should be passed within a single communications' operation. All the details are hidden.
Value objects and entities are created differently. As values are unmodifiable, all the attributes should be passed right after the creation. Meanwhile, you can add only specific attributes to entities (the ones that are important for this specific aggregate and its invariants).

Factories

Of all the tactical patterns used in DDD , the factories are probably one of the most known and used. Responsible for the creation of instances of objects that require certain construction logic that we want to hide, thus being a resource that allows us to encapsulate the complexity of object construction . Known as factory classes or factory methods .
Initially the logic of construction of an object is done in the constructor . When it begins to increase its complexity through various logics, the object itself should not be responsible for controlling them to create itself. We must extract them and encapsulate them in factories, allowing us to ensure a correct instantiation of the objects, avoiding inconsistencies or incorrectly initialized objects.
The business rules for the construction of instances in the factories must not be lodged , for that we have the domain services , although they can include invariants facilitated by the domain experts that assure us correct and consistent states.
Normally, patterns are used to adapt abstract factories . In which through implementations of interfaces we satisfy the creation of objects of our domain model:

The abstract factories are hosted in the Domain layer since they build instances of objects associated with the domain modeling (entities, value objects or aggregates) . They must be designed from the ubiquitous language of the organization.
The methods factory are very common in aggregates to encapsulate the logic construction that contains added. In the following graph we can see the examples of factory methods according to aggregate and context:

What are Factories in Domain Driven Design?
A commonly recognised term in object-orientated programming is Factory. A Factory is an object that has the sole responsibility to create other objects.

Factories are definitely not unique to Domain Driven Design, but they do hold an important role within a Domain Driven Design project.

In today’s article we are going to look at Factories, why are they important and how to use them within the context of a Domain Driven Design application.

What is a Factory?
A Factory is an object that has the single responsibility of creating other objects.

For example, we might have the following simple Factory class in PHP:

class Factory  
{  
public static function build($type)  
{  
if ($type == ‘iPhone’) {  
return new iPhone;  
}

if ($type == ‘Nexus’) {  
return new Nexus;  
}  
}  
}

$mobile = Factory::build(‘iPhone’);  
The Factory class has a single static method called build that has the responsibility to accept a type of mobile phone and return the correct new object instance. This Factory class should have no other responsibilities.

Factories can also be methods on an existing object. For example, we might have the following Order object that has the responsibility for creating a new Invoice:

class Order  
{  
// other methods

public function invoice()  
{  
return new Invoice(/** details */);  
}

// other methods  
}  
In either case, when something has the responsibility for creating another object, it’s called a Factory.

Factories are often used to create Aggregates. As we looked at in last week’s tutorial on Aggregates (What are Aggregates in Domain Driven Design?), Aggregates provide encapsulation and a consistent boundary around a group of objects.

Aggregates are important because they enforce the internal consistency of the object they are responsible for. A Factory can be useful when creating a new Aggregate because it will encapsulate the knowledge required to create an Aggregate in a consistent state and with all invariants enforced.

Why would you use a Factory?
There are a number of important reasons as to why you would want to use a Factory as part of your application. As applications grow in complexity, Factories become more common.

Standardises the instantiation of an object
Factories provide a consistent interface for creating complex objects within an application. As an application grows, the rules around object creation can get lost. Factories provide a standard way to instantiate objects so the creation of new objects is not lost in ambiguity.

Factories provide encapsulation
When the creation of an object becomes complicated, or it reveals too much of the internal structure, Factories provide encapsulation.

A Factory encapsulates the knowledge needed to create a complex object or Aggregate. The Factory needs to know a lot about the internal structure and dependencies of the object, but the Factory will shield this complexity from the outside world by providing an interface that reflects the goals of the client and an abstract view of the created object.

The consumer of an object should not be required to understand the internals of an object and so a Factory provides this encapsulation for complex objects.

Objects should not be responsible for their own creation
The real power behind object-oriented programming is the encapsulation of an object’s internal logic. A client should be able to use an object without ever being concerned about the internal implementation of that object.

Objects should have a single responsibility, and so complexity of an object should be distilled until nothing remains that does not relate to its meaning.

However, it’s easy to overload an object with complexity when it becomes responsible for it’s own creation. Certain objects will require a complex process of instantiation that can muddy the water of the object’s single responsibility.

When this situation occurs, it’s time to abstract that creation process to a Factory. There is no inherent value in having an object take responsibility for it’s own creation.

An important layer of abstraction
Factories can also provide an important layer of abstraction that protects the client from being dependent on a particular concrete class.

For example, we might have a payment gateway Factory that should provide a class for accepting payments from customers to any one of many payment gateways.

The Factory should protect the client by providing a class that implements a particular interface. It is up to the Factory to instantiate and return a particular class based upon a given type. This shields the dependency inside of the Factory.

Factories in Domain Driven Design
In object-oriented programming the use of Factories is extremely common across many different languages. The use of Factories long predates Domain Driven Design. Domain Driven Design is largely built on good object-oriented programming patterns.

Domain Driven Design is all about modelling the domain of an application. Factories have nothing to do with the domain of an organisation, but they do form an important part of the domain of an application.

It is the domain of the application that is responsible for creating and working with Domain Objects. The Ubiquitous Language of a Domain Driven Design project will not directly refer to the process of creating objects. However it is our responsibility to devise the appropriate technical solution for working with the Domain Objects of an applications.

This means that despite the fact that the Ubiquitous Language of a project does not directly refer to Factories, they still form an important part of the Domain layer of the application.

Designing the interface of a Factory
The interface of a Factory is important as it should reflect the goals of the client and an abstract view of the created object.

Each operation of a Factory should accept everything that is required to create the new object in a single interaction. This means that the Factory should require that you pass in everything needed to create the object or Aggregate so that it’s internal invariants are satisfied.

It’s also important to decide how problems should be handled if the invariants of the created object are not satisfied. Typically this would be handled by throwing an Exception (When should you use an Exception?), but sometimes it makes sense to simply return null.

And finally you should use abstract types, rather than concrete classes. This means instead of relying on any particular concrete implementation of a class, instead you should rely on a generic interface of that type of object.

Should a Factory contain logic?
Factories provide an encapsulation around the instantiation of a particular object. This means the Factory will know about the internals of the object, but it will act as an abstraction from the outside world.

Therefore, the internals of an object will often leak out into the Factory. This is an inevitable situation when the complexity of object creation increases.

Often the complexity of creating a new object will mean that the Factory itself will become responsible for protecting the invariants of the object. As I mentioned earlier, the object should have a single responsibility and anything that does not enhance that meaning should be distilled.

Due to the coupled nature of the Factory and the object, it is usually fine to allow the Factory to protect the invariants of the object.

Entity Factories Vs Value Object Factories
Two of the most important types of objects are Entities and Value Objects (What is the difference between Entities and Value Objects?).

Entities have identity within the application and so exist as part of a lifecycle. Value Objects on the other hand are immutable and are easily destroyed and replaced.

When using a Factory to create Value Objects, the Factory should create the Value Object as a complete whole.

Entities on the other hand often have a minimum set of requirements, and then further optional properties that can be set during the lifecycle of the object. An Entity Factory should be able to create an Entity with the minimum requirements for that Entity to be valid.

An important part of an Entity is its identity. When using a Factory to create an Entity you can either pass in the identity as an argument to the method, or alternatively allow the Factory to create the new identity as part of the object creation process.

Reconstituting Stored Objects
Objects are usually moved around during the processing of an application. It is very rare that all objects will live entirely in memory. Instead objects are usually persisted to a database or transferred across a network.

Factories can be used to reconstitute objects as well as create new objects, however there are a couple of important differences.

Firstly, an Entity Factory should not assign a new id to an existing Entity. This means you will need to maintain two different Factories for creating or reconstituting Entities.

Secondly, the Factory needs a way to deal with broken invariants when an object already exists. This could be due to any number of reasons, but the internal consistency of the object is extremely important and so this problem should be handled with the appropriate response. Typically this would be an Exception because it is signally that something has seriously went wrong during the processing of that object.

Conclusion
Factories are a very important tool to have in your developer tool belt. At first it can be difficult to fully appreciate when and where you should use Factories in your code. But over time and through experience you will find that using Factories can really clarify and distill your code.

Factories are by no means exclusive to Domain Driven Design or PHP. You will likely encounter Factories in one form or another in just about every object oriented programming language.

So if you are struggling to deal with the complexity of instantiating certain objects, try thinking about using a Factory to distil that complexity and bring order to your code.


No comments:

Post a Comment