phpdomain-driven-designsolid-principlesvalue-objects

How far to push the SOLID principles in an app following DDD philosophy


I'm working on a domain-driven design PHP application that will last for years and that will have many modifications and new features. This is the first time I am developing trying to follow the different concepts of DDD, and I am also using CLEAN architecture as an architectural methodology to apply the DDD philosophy.

However, I find myself wondering how far to push the SOLID principles (and also some questions about DDD), let me explain.

I have a Value Object that represents credentials.

final class Credential
{
    public function __construct(
        private readonly EmailAddress $emailAddress,
        private readonly Password     $password
    )
    {
    }

    /* ... */
}

As you can see, my Credential class requires an e-mail address and a password (which are also Value Objects) to be instantiated.

This case raises several questions for me :

Also, as you might guess, a user will contain credentials, but if Credential is an aggregate, is this a good practice ?

I am really at the beginning of all these concepts, I am aware that everything may not be perfect and that is why I am turning to you. I read a lot of articles about this but sometimes a real feedback can be more beneficial than dozens of articles.

Thanks in advance for those who will take the time to answer my questions, and perhaps redirect me to resources to better understand the concepts.


Solution

  • Is Credential an aggregate ?

    No. It might be an aggregate root, which is to say the root object in the graph of objects that make up an aggregate. More likely it is a Value Object; an in memory representation of some fact/information that you are tracking with your domain model.

    Value objects that enclose other value objects are common.

    (Note: aggregates are not a modeling pattern, they are a lifecycle management pattern. Review chapters 5 and 6 of the "blue book" for clarification on this difference.)

    What about the Dependency Inversion Principle from SOLID ? Should I create an interface for each Value Object

    Probably not? Introducing an interface increases the accidental complexity of your solution; that only makes sense if there is some compensating benefit.

    Is it really a bad practice that a Value Object (or aggregate according to your answers) of my domain is dependent on another Value Object ?

    As noted above, having value objects that depend on other value objects is fine and normal.

    Value objects are primarily about information - they are a domain abstraction (EmailAddress, Password, Credential) that hide some data structure (String, Property Bag). Having class gives you a single data structure that is used "everywhere"; changes to that data structure are local to the class.

    Introducing interfaces as an abstraction for your value object gives you a way to have multiple data structures that express the same domain abstraction.

    Bluntly, introducing interfaces for values is not going to produce wonderful goodness unless you are in a context where you benefit from having multiple classes that represent the same domain abstraction.

    There is no magic; just trade-offs.