How to name and implement Result set rows in DDD?

461 views Asked by At

In DDD you have an entity with an unique identifier (ID or UUID). Usually a entity represents a storable row in a database table. My repository can load a single entity (findById) or all Entities at once (findAll).

But now a have to write a special and very complex query with joins to other tables. The result set is not a special (User) entity anymore because I have selected different fields from multiple tables with aliases and so on. Depending on the query, the result may not contain an id.

I've hydrated this rows successfully into into an new collection of objects but struggling with the name (and type) of that thing.

My question is:

How to name and categorize such kind of rows coming from a custom query in DDD?

2

There are 2 answers

2
Sylvain Lecoy On BEST ANSWER

It seems you need a query service here.

DDD fits really nicely with CQRS, and I believe the results you want are read-only.

In this case you create a special object for your need: UserData, if the user contains some other relations like a collection of roles, or right, you can call it UserRightsData for instance, and fetch it from a UserQueryService.

Query services are typically in the application layer.

If you want non read-only results, and instead plain entities that you can manipulate and persist, then you need to give us more details. In particular, you should be able to load this entity from a repository, call a domain operation, and persist it, via an application service.

Query services are well suited for views, tables, and data display, with sorting, filtering and so on...

Edit: plalx nailed it in a response of Eben Roux's post.

ProjectName/
    IdentityAndAccess/
        Application/
            Command/
                AuthenticateUserCommand.php
                ChangeEmailAddressCommand.php
                ChangeUserPasswordCommand.php
                ChangeUserPersonalNameCommand.php
                ...
            Data/
                UserData.php
                UserRightsData.php (POPO containing User infos and a list of rights)
                RightData.php (Single comment infos)
            UserApplicationService.php
            UserQueryService.php
        Domain/
            Model/
6
Eben Roux On

Firstly, you should avoid querying your domain model unless you are truly after a specific aggregate. Even then, and depending on your design, you may not be able to get the required data.

The typical recommendation is to use a specialized query layer along with, possibly, a read model that represents the required data. That read model may be as typed or loose as you need. For instance, if a list of name/value pairs will do the trick perhaps you may opt for that.

These queries are not really part of the domain and, as such, fall outside of the domain-driven design in terms of modelling. They are, however, important as part of your overall architecture/approach.

update:

In response to @Luca Masera's comment:

I typically use something like this (C#) for, say, a Product:

public interface IProductQuery
{
    int ActiveCount();
    DataRow Details(Guid id);
    Query.Product Get(Guid id);
    IEnumerable<Query.Product> Matching(ProductSpecification specification);
}

The Query namespacing is so that the read model Product does not interfere with my actual domain Product.

Depending on my requirement I will use the appropriate return object/structure/type.