Laravel and Domain Driven Development, File Structure Part 1

This article was originally written by one of the best minds who've worked in Zid, Bartosz Stecko

Photo by Ross Sneddon on Unsplash

In one of our previous posts, we mentioned that we've re-written our Backend codebase from OpenCart to Laravel, our next plan was to explore the world of Domain Driven Development and to re-implement "some" of our complicated components using this majestic pattern, considering one important point:

We will only use DDD when it's needed, it's an overkill to adapt it in some small components with basic business logics.
Do you want to learn more about DDD?

We're not going to introduce DDD in this article since there are better avaialbe resources for that, if you're completely new to this concept, you can check the following articles before proceed with this one:

In this series, we will talk about our journey in Zid with DDD, considering that our approach is connected to Laravel framework a little bit, and we will start from the file structure.

First of all, our application has the given structure, we will discuss each directory separately.

~/app
~/src/Application
~/src/Domain
~/src/Infrastructure*

~/app

So, this is the catalog, that is shipped by default with Laravel. Therefore, nothing fancy is expected to be in here. But, just for the sake of consistency - here you'd expect, that framework's infrastructure is located in here. You'd have your app kernels (either Console, HTTP, or something else, maybe), your Controllers, Service Providers, Middleware, all that Laravel-awesome-things. In the end, the purpose of this catalog is to provide communication with your Domain and end-user via some sort of interface (like an API). On this level, you should not know anything about business rules, entities, or whatsoever.

Before we get to the ~/src..
Yes, there is one more thing we need to mention here. That is the bounded context. Long story short, this states, that a given name can have a different meaning, depending on in which context you are.

For example, the word cart - in ecommerce world, it probably means the shopping cart, hence the place, you put your stuff in. However, go deep into the *Mines of Moria*, and whoever says cart, they refer to the mine cart. See? Those are bounded contexts in a nutshell. Want some *code-ish* example? Sure. Whenever you'll see a XYZCommand class inside the ~src/Application, we are not talking about the Laravel-ish command. We are talking more about the Command in terms of CQS - a recipe, for a Command Handler to perform some action.

~/src

This is the time, where we go into the ~/src world. I'll go "upside-down", so starting from the bottom. Just to be on the same page, the call stack goes as follows:

Communication between Layers is made using Interfaces. So, for example, if you want to use Repository on Domain layer, you'd declare Repository interface in given Domain, and the implementation would exist in Infrastructure layer (because infrastructure talks with Framework, hence can use it's persistence capabilities). Same applies to the Application. If you want to use something from the Laravel, for example, dispatch an Event, you'd declare EventDispatcher interface in Application and then implement it in Infrastructure layer.

Just a side note about the figure - Infrastructure is not part of the Framework.

You may think now, that this is an issue. You've to write a lot of code, so that in the end you can use your dispatch() function.

However, don't forget, that this gives you an opportunity to expand / exchange drivers whenever you want, and the change would apply only in one place, which is Service Provider, that binds interfaces to its implementations. Long story short, in a git diff you'd expect to see one change and additions only.


In the next part we will dig deeper in ~/src to talk about each directory inside it.