1
votes

Initially my DDD repositories looked like this example:

class PersonRepository {
    Person findByID(id)
    List<Entity> findAll()
    List<Entity> findWithRegex(String)
}

Internally a Service provided the GUI transforming the Entity objects into DTO objects

Now I am trying to get into CQRS. After looking other examples, it seems that my repo should be like this:

class PersonReadModel {
    Person findByID(id)
    List<DTO> findAll()
    List<Entity> findWithRegex(String)
}

With just DDD my repos returned only Entity and List objects. With CQRS since many reads are used only for the UI, there are many read operations that return straight DTOs, therefore PersonReadModel looks like something not quite the traditional DDD repo.

Is this assumption right? Should I have PersonReadModel to return only List and preserve PersonRepository returning Entity and List objects? Should PersonReadModel be a Service that contains a link to the internal repository of a root aggregate?

I can relate a DTO with its Entity since both of them have an identity field. However I am concerned about the displayed DTO being of different revision than the Entity present in my domain model. All CQRS examples I have seen have DTO and Entities with an identity field, but not a revision.

Is the revision something I should be concerned about?

My guess is that the GUI code in the Application Layer will build a message with a DTO and a revision and that the Domain Layer will use to make sure that the requested command was built with the latest version.

1
what does the "revision" mean? - Yugang Zhou

1 Answers

1
votes

ReadModel is on the query side. You don't have to build this part in a DDD way, build it in an easily-query way. Once in a project, I even use public fields read model since they're just data holders.

@Entity
@Table(name="t_order_detail")
public class OrderDetailReadModel {
    @Id
    public String tracking_id;
    public String booking_contact_name;
    //other fields
}

public class OrderDetailReadModelQueryObject {
    OrderDetailReadModel findBy(String id);

    List<OrderDetailReadModel> findByReg(string regex);
}

On the command side, aggregate repository is simplified, most of the time just findById() and store() is needed:

class PersonRepository {
    Person findByID(id)
    void store(Person person);
}