Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD using Doctrine

I am in the process or trying to re-model an existing application using an ORM and trying to adhere to DDD as much as possible.

Work order is the AR and has more than a dozen child entities. I intended on modeling this class like so:

class WorkOrder {

  private $number = 0;
  private $manual = '';

  ...

  // Sub-Entities

  private $consumables; // Collection (1:m)
  private $dimensions;  // Collection (1:m)
  private $sequences;   // Collection (1:m)

  ...

}

Now I would need a repository to load (and persist?) this aggregate root -- correct?

The repo would return one or more aggregates which when I access the sub-entities (through indirect getter/setters -- not dot-notation) will lazy load the information I am after???

I will have another class to act as a factory for creating work orders -- which is a detailed process and includes substantial business logic/validation rules...

But if the factory creates the work order aggregate does the repo just persist the AR?

This factory would have to query a third party service (through REST or otherwise) and basically build a snapshot of an approved document describing work scope.

So the repository encapsulates the ORM or which ever persistence layer I should choose?

Right now my file structure would look something like:

WorkOrder/
  /Factory.php
  /Aggregate.php
  /Repository.php

  /Entity/Header.php
  /Entity/Shipping.php
  /Entity/Warranty.php
  /Entity/Certification.php
  ...

The repository would have methods like:

FindOneByTrackingNumber()
FindAllByCriteria()

save($root);

My factory would have methods like:

createWorkOrderFromRpi()
createWorkOrderFromCsv()
...

I have read through several articles and countless posts on here:

http://williamdurand.fr/2013/08/07/ddd-with-symfony2-folder-structure-and-code-first/

While the detail is excellent I need a second opinion on my own interpretation, please. :)

Regards, Alex

like image 682
Alex.Barylski Avatar asked Sep 16 '13 18:09

Alex.Barylski


1 Answers

Doctrine does not fit DDD. It cannot handle deep domain objects relationships. I think there is no ORM outthere that actually maps the objects very well without writeing lots of annotations or mapping metadata. ORMs are useless if you build your domain model right.

You need to consider one the basic rules of DDD : one transaction per aggregate. Designing your domain model with that rule in mind will help you with the persistence also. You'll even realise you don't need relational database anymore. Even by using a RDBMS will help you with scalability.

Yes a repository in 99% of the cases is used to persist domain objects. The repository should handle the mappings not the ORM that will autmagically populate the domain objects by using reflections with data, methods that a domain object should not care about.

Making your own mappings in a repository (simple property db table columns mapping) is not hard when it comes to removing and saving an aggregate. The problem is with updating an aggregate, but the problem is not the mapping , but the tracking of state changes of the domain object. But again this is not a mapping concern but an unit of work concern.

Now I would need a repository to load (and persist?) this aggregate root -- correct?
Correct. The repository persist domain state changes, and reconstitutes the domain's state.

The repo would return one or more aggregates which when I access the sub-entities (through indirect getter/setters -- not dot-notation) will lazy load the information I am after???
Yes you could have getters (if you use the domain model to populate the UI, oposed to cqrs where you use the the domain model just to keep track of the state of the domain). You should never have setters, you should have just methods that change the state, these methods reflect the ubiquitous language (changeName, addItemToCart). Lazy loading is usefull just for saving some memory. If memory is not the problem, you can also make snapshots of the domain objects latest state. Yes lazy loading is the job of the ORM which is forcing you to have some kind of getters in your domain object, which is a big limitation for DDD.

But if the factory creates the work order aggregate does the repo just persist the AR?
The factory creates new state in your domain. Repository reconstitues the state that once was created by the factory.

So the repository encapsulates the ORM or which ever persistence layer I should choose?
Yes the repository should handle the reconstitution of the domain state. ORM is just a technical matter, it's just a library. Anyway , ORM is part of a common library/shared kernel layer and repository is part of the infrastructure layer.

Regarding your file structure, you should read more about DIP, IOC, DDD bounded contexts. This will help you build your application based on components, and will decouple the components towards a scalable application.

like image 71
Tudor Avatar answered Oct 21 '22 08:10

Tudor