The process of software development is complicated. When we face problems, we usually try to tackle the complexity by turning it into more understandable and manageable pieces.
Domain-Driven Design is a software development methodology for tackling complex software projects to deliver an end-product that meets the goals of the organization. In fact, Domain-Driven Design promotes focusing the project on an evolving core model.
Domain-Driven Design was written by Eric Evans in 2003. It is a combination of widely accepted best practices along with Evans’s own insights and experiences. If you are new to the idea of Domain-Driven Design, there is a lot to learn in this book.
It will teach you how to effectively model the real world in your application and use OOP to encapsulate the business logic of the organization. This is how Martin Fowler [Biggest software Artisan Lecture] describes it:
In his excellent book Domain Driven Design, Eric Evans creates a classification of the different kinds of domain objects that you're likely to run into.
In my opinion, a
Domain Model is your perception of the context in which it applies. Let me describe it a bit more.
Domain itself means the world of the business you are working with and the problems they want to solve. For example, if you want to develop an app for online food delivery, your domain will be everything (problems, business rules, etc.) about online food delivery that needs to be done in your project.
Model means your solutions to the problems of Domain. Exactly, in fact, Model is in the brain of the business expert. Domain is not a chart, UML, code or a diagram; Model is the Idea of how to draw diagrams. The Model should be focused on knowledge around a specific problem that is simplified and structured to provide a solution.
The Domain Model is your structured solution to the problem. The Domain Model should represent the vocabulary and key concepts of the problems of domain.
Ubiquitous Language is the language that is used by business experts to describe the Domain Model. It means that the development team uses the language consistently in all communications, and also in the code. This language should be based on the Domain Model. Here's the definition of ubiquitous language by Eric Evans:
By using the model-based language pervasively and not being satisfied until it flows, we approach a model that is complete and comprehensible, made up of simple elements that combine to express complex ideas.
Let me give an example:
$product = new Entity/Product(); $product->setTitle( new Title('Mobile Phone')); $product->setPrice( new Price('1000')); $this->em->persist($product); $this->em->flush();
In the code above, I create a new product, but in the application the product must be added, not created:
//add is a static method in product class $product = Product::add( new Title('Mobile Phone'), new Price('1000') );
In a development team, if someone creates a product and someone else adds a product, this will violate ubiquitous language. In this case, if in the product
add method we have some extra actions such as sending email, they all will be missed, and also the definition of adding a product in the team will change. We would have two different definitions for one term.
In this article, I am not planning to talk about object-oriented design. But Domain-Driven Design proposes the fundamentals of a good design. Eric Evans believes:
Developing a good domain model is an art.
In order to develop a good domain model, you need to know about Model-Driven Design. The connection of the model and the implementation is called Model-Driven Design. The Layered Architecture is one of the Model-Driven Design blocks.
In order to tackle complexity, we need to separate concerns, i.e. isolate every part of the design to concentrate more on specific sections. The system must be able to interact between sections. Layered Architecture is the idea of isolation of each part based on years of experience and convention. The Layers are listed below:
Let's describe each layer with details.
User Interface is responsible for showing information to the user and interpreting the user’s commands. In Laravel, the view is the User Interface (presentation) Layer.
Application Layer is the way we communicate with the world outside (out of the application domain). This layer behaves as a public API for our application. It does not contain business rules or knowledge. Controllers in Laravel are located here.
Domain Layer is the heart of business software. This layer is responsible for representing the concepts of the business, information about the business situation, and business rules.
Infrastructure Layer provides generic technical capabilities that support the higher layers and also support the pattern of interactions between the four layers (that is why repositories are located in this layer).
Let me describe it a bit more. For example, if we are an email company (such as Gmail), the email would be in the model layer, but if we are a food delivery company, email would be in our infrastructure layer. Why? Because sending email for food delivery is not vital.
Connection between layers is mandatory, but without losing the benefit of the separation. The connection would be in one direction. As you see in the schema above, the upper layers can communicate with lower layers. If the lower layers need to connect with an upper layer, they must use patterns such as callbacks or observers.
If you are inspired to see how Domain-Driven Design could be applied to a project that is being built with Laravel 5 as the underlying framework, I will describe the folder structure in this article and come up with other definitions in follow-up articles. In order to create the folder structure, we need to create a folder structure in our
app folder of the root directory, as shown below:
├── Presentation ├── Application ├── Domain ├── Infrastructure
Presentation is the view, where we put our blade files.
Application is where we put our controllers. Laravel 5 lets us configure the namespace of our controller in
protected $namespace = 'App\Application\controllers';
And also you can configure the path of view in
//... 'paths' => [ realpath(base_path('App/Presentation')), //...
Now we have just configured the folder structure of Laravel. If you're wondering where Laravel's default model would be located, I should mention that a real repository in Domain-Driven Design must work with a simple PHP object as a database object, and Laravel Eloquent (Active Record) is a God object (big ball of mud). Also, to have good aggregates, we need to use Datamapper (Doctrine ORM) instead of Active Record.
This article is one of a series on Domain-Driven Design in Laravel. Laravel needs some extra packages and configuration to be adopted with Domain-Driven Design.
As you can see, I have presented the core concepts, but I believe it may be hard to grasp it alone. I will cover more in the next articles of this series.