Domain-Driven Design - Laravel
Domain-Driven Design is a software development approach that tries to bring the business language and the code as close together as possible.
Introduction
In 2023 the term Domain-Driven Design gained more popularity in the developer's community. If you are from the Laravel development side you may hear this term more often in recent times. so, today we are going to discuss everything about Domain-Driven Design.
Domain-Driven Design
DDD (Domain-Driven Design) is a software development approach that tries to bring the business language and the code as close together as possible. This is the most critical attribute of this approach. But for some reason, DDD is one of the most misunderstood and overcomplicated topics in the developer community.
Why do we need DDD?
In software development, the hardest part is maintaining & building a new feature on existing software.DDD teaches us to structure our code in very expressive and logical. In the most simple Laravel application, you have models and controllers. What do you think when you see a project with 50 models and 50 controllers?
That seems reasonable but you have to dig deeper if you want to have a good understanding. Now, what about 300 models and 500 controllers? your project size may be grown up easily. Now it's a pain for a development team to maintain it in a native MVC or any other MV* architecture. That's where the approach comes into play as developers we prefer technical terms over business concepts.
Example :
Just see the code snippet below that I have written in one of my side projects a couple of months before (it's not Laravel).
public function get_view_container_new_user(Request $request)
{
if (!auth()->user()->canAccess('membership')) {
return response()->json([
'status' => 'error',
'message'=> "Permission denied"
]);
}
$validator = Validator::make($request->all(),[
'name' =>'required',
'tittle' => 'nullable|string',
'membership_id' => 'nullable',
'tags' => 'nullable|array',
'id' => "required_if:select_all,==,false|array",
"prefference" => 'nullable',
],$customMessages);
if($validator->fails()){
return response()->json([
'ststus'=>'error',
'message' =>implode(',',$validator->errors()->all())
]);
}
$to = $request->ip_address;
$transfer = [
'status' => false,
'lead_data' => []
];
$filter_info_test = $request->ids;
$filter_info = json_decode($filter_info_test, true);
if($request->filled('select_all')) {
$lead =Leads::where('id',$filter_info_test)->get();
return response()->json($lead,200);
}
Can you figure out what is it for or can you understand? After a couple of months do I have any clue what the heck is a get_view_container_new_user? No, I have no idea what it is. This project is about customer relationship management and leads but it does not reveal that intention.
And from a business point of view, the terms are not that much belong to technical like container get a view & I hope you ever hear a product manager saying wow, we got so much positive feedback on the get_view_container_new_user
feature?
You may think if I take a step back and look at the file structure, you may have a better idea. The file structure
Nope, I think still you have no idea what is happing even if we have a document on each feature it's very hard to transfer the knowledge to a new developer who gets into the team.
So strategic design is all about not building projects like this one. The code base should be closer to the business terms. The DDD and technical design give you some valuable support in maintaining applications. To achieve this DDD has some concepts. They are
Value Objects
Data Transfer Objects
Repositories
Custom Query Builders
Services
Actions
View Models
CQRS
States and Transitions
Domains and Applications
All these above concepts can be used to achieve a domain-driven design architecture but there are not any strict rules to follow these are the guideline you choose any of the following concepts that suit your project & your team.
Basic Structure
The main idea of the DDD is to organize all the code related to a single domain inside a domain name. In Laravel, we can achieve that by simply adding some lines of code to composer.json
the file . We are not building it as a package so, we don't need any new logic for scaffolding a default Laravel application and upgrading to a newer version is also easy.
Step 1 :
Add this line in a composer.json
file.
"autoload": {
"psr-4": {
"App\\": "app/",
"Domain\\": "src/Domain",
"Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/"
}
},
Step 2 :
Run composer dump-autoload
.
Step 3 :
Now create a new folder with a name src
at the root of your project.
Step 4 :
Then inside src
folder create a folder Domain
where all the folders can be created for each domain with the following namespace. And inside each domain folder, we can place our Actions & Models & Services.
Conclusion
This article is to just give a basic idea about Domain Driven Design. There are a ton more things to cover & this is an article inspired by Martin Joo - Domain-Driven Design with Laravel.
That is one of the best books to learn about DDD on Laravel. I am not affiliated with him or promoting this book this is my personal thought. Please share & like
Feel free to share your inputs in the comments for improvements.