Thursday, February 20, 2014

Domain Driven Design in Laravel 4 - Part 1

After reading the a couple of books recently on Domain Driven Development (DDD) I was inspired to see how it could be applied to a project I am currently working on that is being built with Laravel 4 as the underlying framework.

I won't go into any detail up front about DDD, as a quick google will provide plenty of introductory material. If you want an in-depth look at the subject the two books I read are:
If you are just writing a simple php CRUD based application then it probably isn't worth worrying about the concepts of DDD. If all you are doing is adding some posts, attaching comments, and maybe a few tags, then the out of the box Laravel 4 architecture will suit just fine. 

I am however currently working an corporate information tracking and dashboard system, and although starting out reasonably simple, is going to extend beyond simple CRUD tasks and include some complex business logic. While DDD may be overkill even for this particular application, it does encourage some good programming techniques. For instance:
  • The separation of concerns, with the domain specific logic/functionality contained within the domain model, and separate from the both the application/UI and the infrastructure/persistance layer
  • A focus on a true 'Model' in the MVC architecture, with the Model being a representation of the domain in question, rather than just an ORM layer
  • A more 'Object' oriented approach to design and development. While php is now much closer to other OO languages in terms of functionality, many php apps just use objects to encapsulate procedural code - taking what the DDD people might refer to as a 'Transaction script' approach to the entire application.
In relation to the last point above, DDD makes you think about the domain entities as real objects that encapsulate both data and functionality. This is in contrast to what is often seen in php apps, with objects/entities being wrappers for getter/setter methods and all business logic put in a service layer - something that the likes of Fowler call an Anemic Domain Model.

Anyway, enough already, I am boring you! - if you have ended up here you probably already know all this ... so how can a DDD architecture be applied in Laravel 4 application?

First up - there is no one 'right' way to implement DDD in any language/technology stack. These are just my initial thoughts and ramblings, and this is going to be a case of constant refactoring over the next few months, hence the 'Part 1' in the title. I am by no means an expert in this, so happy to take feedback from anyone about other/better approaches.

Initial Project Structure

After some messing around I have come to the following initial project structure. 

The application is currently called Tracman, and this folder sits within the default Laravel 'app' folder. The default Laravel controller, model and view folders are not used and can be deleted. 

The structure is based on a simple layered approach, with the key layers being the Model, the Application and Infrastructure. 
  • Model - where all the entities and business logic specific to the domain sit
  • Application - at this stage this houses the Web user interface controllers and views, and also the API layer
  • Infrastructure - the persistence layer in the form repositories, along with any other technical components
In order to point Laravel to the new view folders within the Application/Web folders I have added some mappings to a boot section in the TracmanServiceProvider.php file:

    public function boot() {
        

        \View::addLocation(app('path') . '/Tracman/Application/Web/Views');

        \View::addNamespace('admin', app('path') . '/Tracman/Application/Web/Admin/Views');

        \View::addNamespace('user', app('path') . '/Tracman/Application/Web/User/Views');

    }

Under Models, the Projects folder represents a bounded context, and as the application grows other folders will be added to represent the other bounded contexts within Model.

Ok, now I have the structure planned out I am working on how best to link the entity objects in the Model layer with the repositories in the infrastructure layer.

Questions I still have at this stage are:
  • Is the Eloquent ORM still useful in this context, or is it an unnecessary overhead to hydrate eloquent objects which are then used to hydrate the domain entities?
  • What is the best way to create and hydrate the domain entities within the repositories? Currently I am using App::make within the repository to create each new entity, but not sure if this is the best/most efficient method.
  • Would an hexagonal architecture be better than a straight layered approach, or would adding a ports and adaptors layer really be overkill?
Would love to hear thoughts from anyone else that is using a DDD approach with Laravel. Time permitting, if I get some of the repository -> entity wiring sorted I will put a copy of the basic structure up in github.

No comments:

Post a Comment