Folder and namespace structure with DDD

Published 2 years ago by NoorDeen

what is the best way to organize my application structure when Develop using Domain Driven Design and Laravel 4 or 5 ?

Best Answer (As Selected By NoorDeen)
thepsion5

I usually divide large apps into 4-5 namespaces, all starting with an app-wide namespace. For this example, I'm going to create a ToDo List app, so the base namespace will be ToDo.

Then I have 3 namespaces grouped under that one:

  • App - Laravel specific functionality - validator classes, service providers base models, etc

  • Domain - All of my business logic, such as entities, repository interfaces, and domain services

  • Infrastructure - All of the persistence logic. That includes repository implementations, cache decorators, etc

And in addition to those, I have at least one "port" namespace. For a typical web app it would be Http, for a REST API it would be Api, for artisan commands it would be Cli. So the total directory structure might look something like this:

app/
----ToDo/
--------App/
------------Providers/
----------------ToDoServiceProvider.php
----------------ConfigServiceProvider.php
------------Validators/
----------------LaravelValidator.php
------------ValueObject.php
------------BaseModel.php
--------Domain/
------------List/
----------------EloquentList.php
----------------ListRepository.php
----------------ListService.php
----------------ListValidator.php
----------------Priority.php
------------Task/
----------------EloquentTask.php
----------------TaskRepository.php
----------------TaskService.php
----------------TaskValidator.php
--------Http/
------------Lists/
----------------ListController.php
----------------ListPresenter.php
----------------ListViewComposer.php
------------Tasks/
----------------TaskController.php
--------Infrastructure/
------------Lists/
----------------ListRepositoryCacheDecorator.php
----------------EloquentListRepository.php
------------EloquentTaskRepository.php

EDIT: Updated to reflect some additional classes I've outlined in subsequent posts

nrivero

I don't know if its the best but the way I do it is. AppName\Solution\Layer... For instance, if I have a repository for a budgeting app I would do something like this..

Budget\Core\Infrastructure\Data\UserRepositoryInterface

the reason I add a "solution" to the namespace is in case I want to add different functionality or section to my web app. Like if my app is a e-commerce store but I wanted to add blogging functionality.

I add the "layer" to the namespace so I can quickly keep track of what layers of my application are being interacted on by the current class. I usually have a "User Interface", "Application", "Domain" and "Infrastructure" layer.

I'm curious how other people approach it.

jekinney
jekinney
2 years ago (225,385 XP)

I prefer to keep my namspaces short. I'll use different main folders as for each main area similar to nrivieo but not as deep. My namespaces generally don't go over 3 words, 4 at the most.

thepsion5

I usually divide large apps into 4-5 namespaces, all starting with an app-wide namespace. For this example, I'm going to create a ToDo List app, so the base namespace will be ToDo.

Then I have 3 namespaces grouped under that one:

  • App - Laravel specific functionality - validator classes, service providers base models, etc

  • Domain - All of my business logic, such as entities, repository interfaces, and domain services

  • Infrastructure - All of the persistence logic. That includes repository implementations, cache decorators, etc

And in addition to those, I have at least one "port" namespace. For a typical web app it would be Http, for a REST API it would be Api, for artisan commands it would be Cli. So the total directory structure might look something like this:

app/
----ToDo/
--------App/
------------Providers/
----------------ToDoServiceProvider.php
----------------ConfigServiceProvider.php
------------Validators/
----------------LaravelValidator.php
------------ValueObject.php
------------BaseModel.php
--------Domain/
------------List/
----------------EloquentList.php
----------------ListRepository.php
----------------ListService.php
----------------ListValidator.php
----------------Priority.php
------------Task/
----------------EloquentTask.php
----------------TaskRepository.php
----------------TaskService.php
----------------TaskValidator.php
--------Http/
------------Lists/
----------------ListController.php
----------------ListPresenter.php
----------------ListViewComposer.php
------------Tasks/
----------------TaskController.php
--------Infrastructure/
------------Lists/
----------------ListRepositoryCacheDecorator.php
----------------EloquentListRepository.php
------------EloquentTaskRepository.php

EDIT: Updated to reflect some additional classes I've outlined in subsequent posts

NoorDeen

thank you @nrivero for reply . your name space structure makes me think about my application subsections .

@jekinney thank you for replay . for short namespaces it is good to right less code when use the classes , right ?

thank you @thepsion5 . this is very good and organized structure . can you tell me more details about each group responsibilities ?

maytham

@thepsion5 I like it, but would like to know what is the reason to not keeping the default structure?

NoorDeen

@thepsion5 you are using psr-0 autoloading , right ?

thepsion5

Sure. I'll break this into a few different posts so each one isn't massive.

App Namespace

This is what I would consider the primary point of integration between my business logic, infrastructure logic, application ports (web, REST API, CLI), and Laravel. This is where I configure all of my dependency injection and store classes that are extended by the domain code without having any domain logic themselves. As a general rule, most of these classes will be abstract

  • Binding TaskRepository to EloquentTaskRepository via a service provider
  • Binding configuration data from one of Laravel's config files to a class that requires it as part of its constructor[1]
  • Creating an abstract LaravelValidator class that fulfills an interface without containing the actual rules for business logic validation
  • Creating a BaseModel class that provides shared functionality to my entities
  • Creating specific application-level services (not domain services) that rely on Laravel, such as utilities for moving files[2]
  • Creating abstract classes used by the various ports, for example an ApiController that has helper methods to transform responses, return API-specific error codes, embed meta information, etc

[1] For example, I may have a Validator that relies on being supplied an array of valid Task Categories defined in a configuration file. The constructor accepts that array of categories and I use a service provider to bind them:

//ToDo/App/Providers/ConfigServiceProvider.php
public function register()
{
    $categories = $this->app['config']->get('todo.categories');
    $this->app->bind('ToDo\Domain\Tasks\TaskValidator.php', function($app) 
    {
        $categories = $this->app['config']->get('todo.categories');
        $factory = $this->app->make('Illuminate\Validation\Factory');
        return new TaskValidator($factory, $categories);
}

[2] There's probably disagreement on this, but I believe that my domain logic shouldn't care what directory a file is in as long as it's capable of accessing said file. Therefore, the service for locating files is an infrastructure or application concern

thepsion5

Domain Namespace

Put simply, this is where all of my business logic lives. Entities, Value Objects, Validators, Specifications, all the functionality that actually delivers value to the client will go here. Ideally, my entities would be POPO's (Plain Old PHP Objects) and not rely on Eloquent, but so far that's been difficult to make work well so I tend to use Eloquent for my entities - this is the one area where I egregiously violate SRP. But the ToDo\Domain\List namespace would have the following:

  • EloquentList - A List entity, I'd typically have mutators for Value Objects . If we want to consider the List entity an Aggregate Root, it would automatically have all of it's tasks loaded

  • Priority - A self-validating Value Object containing the List's priority. It might accept a numeric range from 1-10 or something simpler like "Low", "Normal", or "High"

  • ListRepository - A Repository interface with methods like findById($id), store($list), setPerPage($perPage = 0), sortBy($field, $direction = 'DESC'), existsByName($name) things of that nature.

  • ListService - This is the primary class my ports will be interacting with. If this functionality is complex enough, I'll break it from one class into several, others, maybe even individual Use Case classes[3], but for a small app a single service class is fine.

  • ListValidator - This is a validator responsible for performing validation that requires external data, which we can't do with the entity or value object. An example might be ensuring an List's name is unique among saved lists (which requires the repository as a dependency and as such can't be done as part of the entity).

All these things should only change based on what my client tells me. Any technical changes should go into abstract classes that the domain classes extend from or go into implementations of interfaces in the domain namespace.

thepsion5

Http Namespace

This is where all the logic that connects my application to someone's web browser should go. If it's involved in responding to HTTP requests, it should live here. This might include the following:

  • ListController - Fairly self-explanatory. This might extend from an abstract controller class in the App namespace if necessary, and would have the ListService class injected into it. It would be responsible for catching validation exceptions thrown from the ListService class and handle them by redirecting and sending errors to the view.

  • ListPresenter - If we wanted to add html-specific formatting to lists, like formatting dates or turning the priority number into a more readable label, this functionality would go here. The controller would be responsible for creating instances of this class and wrapping the EloquentList entity in it before passing it to the view

  • ListViewComposer - If there is additional data we need to attach to one or more list-specific views, it would live here. This can be just about anything and can even have various application/domain services injected into it

This is just one "port" of my application. If I had Artisan Commands, or a REST API there'd be another namespace for it containing all the relevant classes.

thepsion5

Infrastructure Namespace

Anything related to persistance will be in this namespace. The most obvious thing to go here would be repository implementations. In this particular example:

  • EloquentListRepository - This is the eloquent-specific implementation of the ListRepository interface in the domain namespace.

  • ListRepositoryCacheDecorator - This implements the same interface as the repository and acts as a decorator that adds caching functionality.

Other things that might go in this namespace: a ListDatabaseMapper class, if I was using the Data Mapper pattern instead of Eloquent. Usually this namespace is relatively sparse.

thepsion5

@maytham If we're talking about Laravel 4, I use a different structure because it just doesn't fit my needs. Any moderately-large application is going to be vastly underserved by just having model and controller directories. IIRC, Laravel 5's structure is actually pretty close to what I use.

@alnour_altegani PSR-4 actually, but I think I could use either in this case and they'd behave identically.

jekinney
jekinney
2 years ago (225,385 XP)

@alnour altegani Not really less code, but if you do need to dig into something 6 months later, trying to remember is a bear. so having a namespace (for me) only a few files deep helps while some people who document their structure better may not have this issue....

DarkRoast

@thepsion5 I was wondering if the app structure you demonstrated was related to the hexagonal architecture?

Great posts by the way!

thepsion5

@WookieMonster - Yep, it's inspired by Hexagonal Architecture, though Domain Driven Development has similar concepts. I think the biggest difference may be that the code supporting my adapters (abstract controllers etc, etc) lives in the App namespace.

I'm not 100% set on that, but my thinking is it reduces the mental workload to see what each port is actually doing. I see Http\Tasks\TaskController, Http\Tasks\TaskPresenter, Http\Tasks\CreateTaskForm without having to mentally filter out AbstractController, AbstractHttpForm, etc.

uxweb
uxweb
2 years ago (70,300 XP)

@thepsion5 Woooow man, this is a great information about structure, you should write an article or a book about this. I appreciate your time and effort to write your knowledge. Thank you so much!!.

Please sign in or create an account to participate in this conversation.