Laravel DDD application structures

Jeroen • May 17, 2022

This post will give a quick overview of different possible application setups to start with Domain Driven Design (DDD). If you want to learn more about DDD I would recommend the books and articles by Vaughn Vernon or Matthias Noback.

There are different ways to set up your application when you want to structure it by domain and separate the layers in your application.

In the following overviews I will only show the source's directories to keep it simple. The different methods will increase in the amount of setup that is necessary to get started. They (probably) don't all adhere to DDD in its purest form, but that was never the goal for me. I tried them all but I do not have a clear favorite; an important factor in my consideration would be the experience of the team and what they would feel comfortable with to use.

1. The Subfolder

The first structure has a low barrier to entry, it involves creating a Domain folder inside app. This does not seem like much, but it could come with additional guidelines your team might agree on, such as "all domain code should be covered by unit tests, all other code will use Laravel's feature tests."

Pro: suits well for a first attempt at DDD. Con: the domain might get muddy and 'disappear' within the application.

app/
    Console
    Domain
    Exceptions
    Http
    Models
    Providers
bootstrap
config
database
lang
public
resources
routes
storage
tests

2. The Other Folder

The next method places the domain outside the app folder, this requires a minimal setup in your composer.json to define the new namespace besides App\\. Of course the same thing applies to this method (and in fact, to all methods); your team may make additional guidelines and document them in the readme.

Pro: this is getting one step closer to the screaming architecture because a new developer will immediately spot the domain of the application. Con: you might experience some 'friction' as to where to find certain classes (do I open app or domain?).

app
bootstrap
config
domain
database
lang
public
resources
routes
storage
tests

3. The Package

This will likely use a package (shameless plug) to manage your domain as a package (sometimes also called a module).

Pro: useful approach to (strictly) separate domains from your application, and their development as well. Con: there will be extra overhead in registering, installing and controlling the packages.

app
bootstrap
config
database
lang
packages/
    DomainA
    DomainB
public
resources
routes
storage
tests

4. The Hexagon

This is when you want to go the extra mile and decouple your application, infrastructure and domain code. What I like about this approach is having the three layers separated, but still together and not in between the config, public and other folders.

Pro: it clearly 'screams' what your application is, does and has. Your domain code is decoupled from framework implementation and every layer can be fully tested with its own strategy (unit, feature, end-to-end, etc.). Con: A couple of hours extra setup, and less likely to be able to automatically be upgraded (because tools like Shift and Rector might not recognise what they need for their tools).

app/
    Application/
        Events
        Jobs
        Listeners
    Domain/
        DomainA
        DomainB
    Infrastructure/
        Console
        Exceptions
        Http
        Models
        Providers
bootstrap
config
domain
database
lang
public
resources
routes
storage
tests

Conclusion

In conclusion, it is possible to follow principles of Domain Driven Design as much with Laravel as it is with any other framework. Make sure to dive into the concepts and ideas behind it and let it spark your (and your teams) creativity!