21 Ağustos 2013 Çarşamba

domain driven design - domain layer in practice

I will try to put forward a step by step strategy for domain layer design. This article will be a practical approach to establish a philosophy while designing domain layer. You should already know the domain layer design to solid your knowledge with this article. First and the foremost; lets assume we are pretty sure about what our domain needs and a domain expert are ready to help us forward!

Bounded context is a logical space for a model with the same terminology, concepts, rules and one ubiquitous language. Lets say we are working on one bounded context. Also we can assume that we have numerous tables and relationships among these tables.[As we discussed previously; our first goal in domain layer will be implementing an understandable hierarchy inside.]. One bounded context might be too big to catch at the first sight or it might need a separation inside to clarify its inner workings. In that situation we divide our bounded context into modules. These modules are like database schemas where we simulate some certain parts of the database. If we still have difficulties on understanding; we could give an example of a payment module inside our CRM software's bounded context. Well, now we find ourselves inside a bounded context's module and curious about what is next..?

Now we aim to standardize relationships inside our domain layer module elements to reduce communication overhead. For our example; we are inside the payment module now and we will use aggregates to group highly cohesive entities and make sure they communicate each other through the root entity's interface.[We can communicate with aggregate's child entities through the root entity, and every aggregate element can hold the reference of other aggregate's root entity.]

After we start the implementation of our entity classes inside aggregates, we will also make sure putting necessary logic inside these classes. There are some design methods that forces developers to use classes without any logic inside[POJO], yet it falls short if we consider object oriented principles. All classes comes with necessary logic to resemble a real world element. [Please check out this article for further reading, http://www.martinfowler.com/bliki/AnemicDomainModel.html]

What would be inside an aggregate? 
  1. There might be a constructor. If there is a constructor, you explicitly force consumer of the class to set some variable for the class construction. If there is a constructor, there should also be a default constructor for the entity framework. There might not be any constructors inside it, that way you don't override the default constructor and you don't need to put any parameterless constructor inside your class.You could use a factory pattern for your root entity class' construction. For child entities you will use root entity for construction in order to be consistent on aggregate pattern.  
  2. There could be validation code inside your aggregate classes. You can check fields' values to be set to expected range. [You may implement IValidatableObject to deal with validation inside your entity]
  3. Author of the class will put 1 to 1, 1 to Many etc. relations inside the classes. You can mark them virtual if you want to enable lazy loading or go default with the eager loading.
  4. These entity classes are either be a subclass of Entity or Value Object. [For deeper explanation about value objects, please check out Martin Fowler's blog.]
  5. You will have rules in your domain. According to these rules you filter your data to present it inside a UI element. In that case you deal with conditions in your queries. This is where you should check out the specification pattern. [http://martinfowler.com/apsupp/spec.pdf] For example you have a bank account. It should be 14 characters long and also starts with certain letters. You can specify these conditions and use them together, in other words AND them, to filter a specific set from a pile of data.
  6. There will be repositories. Because your class shouldn't take care of persisting itself to the database. This is called separation of concerns principle. [Think of and engine that is responsible for giving momentum to a vehicle. Does it build itself? No.] So what we do in here is, we create a repository class for every root entity inside aggregates and escalate its crud operations to the infrastructure layer. That way, we are not aware of any underlying database persistence technology. You can ask now how to do such a separation and answer will be found in dependency injection pattern. 
Now we have every single element with also some extra features inside our aggregates and it is time to talk about domain services where we group simple operations to establish domain related complex operations. To begin with, we aren't holding any state information or transaction logic inside the domain service. Domain service only knows the operations about domain; if you put any infrastructure logic inside it, it won't confront the principles of domain layer design. Lets think of a situation where we assign a commodity or aspect of one entity to another. In this case, we create a service to check if the assignment could be made for the destination entity. Then we get the necessary data from one instance and assign it to another. Here we will have the origin and destination objects and transferable commodity as inputs. As you can see; our domain service aims to group module oriented operations to perform complex tasks. 

What else we can need inside our domain layer? Answer might be a unit testing module. I personally recommend unit testing strategy especially for domain layer ever since its operations are core concepts that should be verified. That way we can keep the boundaries and consistency inside the domain layer and prevent corruption in the future. 

In this article, I didn't go through every detail of the domain layer. Rather than that, I tried to tell core concepts of a domain layer. At the same time I tried to give a learning path to the user for further reading.
Hope it helps your first steps through the domain driven design.




19 Ağustos 2013 Pazartesi

domain driven design - domain layer in theory

Nowadays I am working on domain driven design concepts and I am gonna share my inspections and findings throughout my journey. So other developers may get benefits with less effort.


Domain Layer


It will be reasonable to start from this layer ever since Eric Evans mentions it as "The heart of the software". Starting from this layer would make you understand what you are developing. So later you can put technology aspects and further requirements on top of it. As soon as it is loosely coupled with other layers, you could easily understand its inner workings. Well I wanna quick start explaining with a summarized approach.


- Architecture


Domain model layer separates behavior of domain rules from infrastructure layers implementation details. All components of the domain model layer must completely ignore technologies that the data persistence infrastructure layer is based on [such as OR/M]. Also it isn't dependent on application and presentation layer. Domain entities should be allowed to hold references to DAO’s neither to OR/M. According to separation of concerns principle;  entities does not need to build & save itself. We shouldn't invoke repos from within entities (in the domain layer).  If we simply want to query data and get the state information, then we can call repositories but still all the transactions and uow should be in transaction services layer.
The logic we should include within the domain layer should be the logic that we could be speaking about with a domain expert.


What structures or definitions could we face with in Domain Layer;
  • POJO: POJO means plain old java object and resembles just the entity fields inside a class. Such class called anemic classes because they lack the necessary business logic. Many experts criticise this type of design approach as the opposite of object oriented programming methodology. Opposite of this type is called prescriptive and we will design further with this approach.
  • Aggregate Pattern: Conceptual group of association objects that are considered as a whole unit with regard to data changes will simplify relationships. We call this aggregate pattern and used to define ownership and boundaries of the domain model objects. Moreover it ensures consistency in changes of a model that has many complex relations and associations. There are inner workings and important details of this pattern. While using, stick in your mind that, there is always a root entity in this structure. We will try to communicate with other entities inside the aggregate through this root entity. Aggregates can hold references of other root entities for communication. Basically other entities and value objects are meaningful to aggregate.
    • Single point of entry to aggregate is the main point to ensure integrity.
    • Aggregates can be queried from repos, anything inside the aggregate; child entities, value objects must be accessed from its related aggregate repository
    • The internal objects of an aggregate, however should be allowed to have references to root entities of other aggregates (or simple entities that don’t being inside an aggregate).
    • Disposal of root entity will erase other entities inside aggregate.
    • If aggregates needs to be persisted to db, it needs to accessed through root entity
      You only need the aggregate roots to encapsulate complex interactions among a cohesive group of                classes. When aggregate roots, hold aggregate roots; we have to keep the concept of "bounded                    contexts" in mind to prevent coupling too big parts of the domain together and make the code hard to            change.
  • Factory Pattern: When creation of object or an entire aggregate becomes complicated or reveals too much of the internal structure then factories provide necessary encapsulation. Basically if class constructor has many checks and validations then it is better to use a factory method to deal with construction work. Factories have no responsibility in domain model but it is part of domain design.
    • Requirements for a good factory: Each creation method is atomic and enforces all invariants of the created object. This means the creation of the entire aggregate, with all invariants satisfied, with optional elements to be added.  
    • If an interior object to an aggregate needs factory, usually we should place the logic on root aggregate. This hides the implementation of the interior of the aggregate.
    • Value objects are immutable so factory creation is the only place for them.
  • Specification Pattern: Separating the decision as to which object types should be selected in a query from the object that makes the selection. Eg. you have a list of customers. You defined a specification for a gender and you also have specifications for age groups. You can then group them to filter the list of customers.
  • Repositories: They are responsible for the lifecyle of aggregates. To obtain a value object of an aggregate, client must request it from the root of the aggregate. There is a problem in this approach; in large apps we always make sure that client always has a reference to the object needed or to another which has a reference to it.
    • This will force holding too many references, later we can lose the track.
    • Brings coupling.
    • Unnecessary associations which aren't really needed.
    • Another problem is; clients direct access to db to use an object has negative impacts to consistency.
      • Eg. it is possible that it will restore an object internal to aggregate which will brake the encapsulation.
    • Therefore we use repository in order to encapsulate all logic needed to obtain object references.
    • Domain objects won't have to get the needed references to other objects of the domain. They will get them from repositories.
    • Repository acts as a global storage place for globally accessible objects.
    • Repository may also include a strategy; it may access one persistence storage or the other based on the specified strategy.
    • So with implementing repositories; we decoupled domain model from the need of storing objects or their references and accessing the underlying persistence infrastructure.
    • We prefer to to provide repositories for aggregate roots that actually need direct access.
While the factories are concerned with the creation of objects; repositories take care of already existing objects.


- Details


  1. There are several construction approaches happening in this layer.
    • There are classes without constructors. If you don't define any constructor to your class then you don't need to create a parameterless constructor too. So class and entity framework works fine without any constructors defined in the class.
    • If you decided to create a constructor to force user to set some variables upon creation (these variables also called invariants) then you need to create a constructor with parameters. From that point if you need your entity framework work properly you need to put a parameterless constructor in your class.
      • Now what is invariant and why entity framework complains about a parameterless constructor.
        • Deep understanding of your model will force you to create valid objects with specific rules. In object oriented modeling, you can assure validity of your class by implementing a contract by defining must-be-set rules to your constructor.
          • [Eg. you can put parameters to your class and check them to see if they have values to set otherwise you can throw an exception]
        • Why entity framework complains? Well, when you create a constructor with parameters you hide the default constructor which the entity framework uses. That is the main reason to create one parameterless constructor.
    • If you have classes with complex creation logic, domain driven design's best practices encourage to use factory pattern for creation. Basically you create a factory class for your complex class and you create the class (usually this is the root entity of your aggregate) and its child classes. In other words when creation of object or an entire aggregate, becomes complicated or reveals too much of the internal structure, factories provide encapsulation. As a matter of fact; using factory classes doesn't need extra constructor inside your complex class, so that you won't need an extra parameterless constructor too.
      • As you noticed, I mentioned factory pattern and aggregate pattern so far. Later I will try to explain them with their important usages and aspects for a consistent understanding.