1

I am building an app that uses a client and a project entity.

The clients can extend their profile over various screens in their account, like status, settings, etc. These data sets are saved in seperate database tables by a WordPress plugin.

Now I need a way to display these user related data sets in the frontend.

So I was thinking of creating a client aggregate root (which is the client entity basically) and a bunch of entity objects:

/* Aggregate root */ 

class user {

        private $fullname;

        public function __construct( string $fullname, string $email ){

            $this->fullname = $fullname;

            ...

        }

        public function getFullname() {

            return $this->fullname;

        }

}


/* Settings entity */

class UserSettings{

    private $address;

    public function __construct( string $address ) {}

    public function getAddress() {}

}

Question 1: Does this approach make sense?

Question 2: How are aggregates actually assembled? Does this happen in the UserRepository? I couldn't find any PHP code examples.

Question 3: Since there's quite a lot of data in ie. Settings apart from just the address, my entity and repository object would grow accordingly, since I would need a method for each data set like address, company name etc. as far as I can see. This feels a bit weird since most of my objects contain 1-2 methods, not more. Is there anything I need to watch out for?

1 Answer 1

2

The clients can extend their profile over various screens in their account, like status, settings, etc.

Why not follow the ubiquitous/business language and have a client aggregate? This aggregate can be composed of an AccountSettingsList value object, a Person value object (that holds full name , address or other person related info), a Status value object. Why should they be value objects? Because there seems to be no reason generally for them to have identity within the aggregate, they are simply identified by their properties/descriptors.

These data sets are saved in seperate database tables by a WordPress plugin

From a domain driven design perspective, when building your domain objects/model you should try and keep any persistence related design out of it. But if the Wordpress plugin dictates the contracts/design of your objects then maybe domain modeling is not the best approach and you should simply follow the design that the Wordpress plugin expects (design by contracts in a way and in this case maybe the Wordpress plugin dictates what kind of objects/data strctures it expects).
But if the Wordpress plugin just takes care of persistence logic, then maybe you should just use it as a database abstraction layer.

Now I need a way to display these user related data sets in the frontend.

You could use your domain model objects directly to in your views (html templates or json objects), or you could have dedicated view models and services that build these view models from the database when they are needed (this way you just encode the view models in json and pass them to the client if its a REST type of API). But the simplest way is to somehow use the domain models directly in your views (put some getters in your domain models to make any data in your aggregates available for the views).

So I was thinking of creating a client aggregate root (which is the client entity basically) and a bunch of entity objects:

It does nto really matter how you name your entities/value objects as long as you understand what the domain needs. I think you are on the right track. The entities/value objects I enumerated above are similar.

Question 1: Does this approach make sense?

Yes, I think you are on the right track.

Question 2: How are aggregates actually assembled? Does this happen in the UserRepository? I couldn't find any PHP code examples.

Yes, they should be reconstituted by a repostiory. In order to not clutter your domain model layer with database logic, you can have a a contract in your domain layer (an interface) where you define your methods to retrieve and save your aggretate and in another layer (like let's say persistence or infrastructure layer) have the actual implementation of these interfaces. And use dependency injection/inversion of control to inject these repository implementations in your application services.

Question 3: Since there's quite a lot of data in ie. Settings apar...

I supose your settings data is static, like you and not your users decide what these settings are. If this is true, then I don't see any issues here. Not that much data at all. In your repositories you just have methods likes : findById, findByEmail (all returning one or more Client aggregates), a save method (that would save a new or a modified aggreagate), and maybe a remove/delete method (that would delete an aggregate). The repostiories are simple objects, they just retrieve and save aggreagates as a whole. You don't need separate methods for every entity/value object in an aggreagate. Again you should find/save aggreagtes in your repositories as a whole.

Sample repository :

ClientRepository implements IClientRepository {  
    public function findById(ClientId $id) : Client;  
    public function findByEmail(Email $anEmail) : Client;  
    public function save(Client $aClient) : void;
}

Now when it comes to saving modifications of an aggreagte you will have to monitor somehow the changes that happen in your aggreagates,t eh changes to their properties. You either take advantage of an ORM like doctrine that will make things easier, or somehow track your changes and compare the old aggreagate with the new one in your repositories and save the changes. You can also have 2 separate methods like saveNew and saveModifications if you decide to track changes yourself.

9
  • Thanks. I'm still unsure about my aggregates though - if I have 100 data sets for each client (address, company, phone, etc), I would have to write 100 getters in my client domain object to access this data in my view, something that I don't want to do. So I thought about using the __get() magic method, but then I would have to reference each data set (ie. ClientAddress) by it's database column name, and therefore my persistence logic would creep into the presentation or application layer. What's the usual approach in this case?
    – Hans
    Aug 14, 2018 at 16:49
  • If you need to have like 100 descriptors for a client (address, company, phone, ... 97 more descriptors) , you can bend the rules if it feels more natural to you. Nobody sais you should follow strict rules when modeling your domain. You can have one aggreagate named User that holds descriptors like email , username, password, creation date. Another aggregate named Person with descriptors like full name, address and other personal info. Employee aggregate with the company name where he works at, position in the company etc. I think you get the point. And you will have repostiory for each.
    – Geo C.
    Aug 14, 2018 at 18:42
  • But all those aggreagets will basically have 1 to 1 relationship probably since they all refer to the same client/person. Maybe User-Employee can be one to many, depends what is required in your project. But the main idea is that rules can be bent and model it the way it makes your project easier to understand and manage. Domain modeling is not easy. You will get the hang of it as you exercise more. Remember, nothing is set in stone with domain modeling.
    – Geo C.
    Aug 14, 2018 at 18:46
  • I gave the app owner the possibility to manage profile fields himself, through the WP plugin - and the took advantage of the feature. But even having multiple aggregates still implies that I would have to write all these getters, which will be a bit nasty. But currently I don't see any way around it. As you suggest, I'll try to stay close to the domain structure and client demands as I continue to create those objects.
    – Hans
    Aug 14, 2018 at 19:18
  • If the user can manage profile fields himself (like create new ones). Then why not have a value object named ProfileField, which will have 2 properties : fieldName and fieldValue. And the Client aggreagate will have a property named : profileFields which will be an array or ProfileField value objects. This is how I usually deal with dynamic fields which users can create
    – Geo C.
    Aug 14, 2018 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.