DDD: Domain model namespaces convention
Asked Answered
V

1

11

I'm writing an application with a domain model in PHP, and am wondering which naming convention I should adopt.

Let's say I have a Customer, having an Address within its aggregate root.
I also have a Product, having an Option within its aggregate root.

I have two alternatives:

  1. Keep aggregate roots at the root of the domain model:

    Customer
    Customer\Address
    Product
    Product\Option
    

    Pro: I can use both Customer and Product in the same namespace
    Con: Customer has to reference its own Address as Customer\Address

  2. Group all aggregate classes in the same namespace, including the aggregate root:

    Customer\Customer
    Customer\Address
    Product\Product
    Product\Option
    

    Pro: Customer can reference its address as Address
    Con: from my root domain namespace, I have to reference:

    • Customer as Customer\Customer
    • Product as Product\Product
Vehemence answered 9/8, 2011 at 19:42 Comment(4)
It's an interesting questions. Would be nice to hear how other people have solved it. Hopefully we'll see some answers soon, Benjamin :-)Rabelais
Starting a bounty, hoping to get more resources on the subject! :-)Vehemence
One thing that crossed my mind (perhaps off-topic): namespaces are specially usefull when projects are big in dimension, and / or when there's a lot of people involved in their development / maintenance. The basic principle of DDD is to keep everything simple and to the point, wich means that there will hardly exist any type of colisions inside the appliction. So .. are namespaces real necessary in this case?Discount
@yoda: that's a good question, however the app we're working on currently consists of several dozen classes, so yes, we're really happy to have namespaces to organize the code!Vehemence
C
5

I wrote a little framework a while ago and i choose to use the first solution you propose.

Keep aggregate roots at the root of the domain model:

Why?

Actually I asked myself the same question you're asking today and after a bit of discussion with my team mates we agreed that it felt more logical not to repeat the class name in the namespace.


Let's see how to instanciate your classes with solution n°2

Customer\Customer
Customer\Address

You will have to write :

$customer = new Customer\Customer();
$address = new Customer\Address();

You can see the repetition right? It kind of doesn't feel right to me. In my opinion it's like writing

$customer->getCustomerId();

Why repeat Customer in the method name? We know it's the customer's id since we're using a Customer object.

Another "bad thing" with this model is the impossibility to use reserved keyword as class name.

For exemple, using the pear convention you could have had the class

Customer_Abstract

Located at Customer/Abstract.php which is ok to me but if you try to translate it using namespace you will have

namespace Customer;

class Abstract {}

which results in a fatal error. So again you will have to repeat the domain in the class name :

namespace Customer;

class AbstractCustomer {}

$customer = new Customer\AbstractCustomer();

Now let's see how to instanciate your classes with solution n°1

Customer
Customer\Address

You will write :

$customer = new Customer();
$address = new Customer\Address();

We don't have to repeat Customer twice anymore to instanciate the Customer class. However it is still clear that Address is related to Customer.

That's why I choose to use this model.

EDIT : Zend Framework 2 use this convention too

Chiseler answered 29/8, 2011 at 13:9 Comment(3)
Thanks for your answer. However, it looks like ZF2 actually uses the exact opposite approach: Zend\Form\Form, Zend\Mail\Mail, etc. They aim to pack each component in a single directory.Vehemence
You're right. I didn't look at all the code. I saw Zend\Controller\Router, Zend\Controller\Router\Route and I didn't look further. My bad.Chiseler
Ok, I thought we would have more reading on this question, but that probably means that it's just a matter of personal preference, not "best practices". What we'll end up with, will be to put only the aggregate roots at the root of the domain model namespace, and all their child entities in a namespace with the corresponding name. If the aggregate root is an abstract class, concrete classes subclassing it will be in the subnamespace as well.Vehemence

© 2022 - 2024 — McMap. All rights reserved.