rad
rad

Reputation: 1937

The best way to create Read Model (aggregate)

I have to create a complex "read model" (cart) with CartLine and some other informations. At the moment I have a ViewModel based on many other objects (Cart, Operation...), the logic to build this object is dispatched in a Respository and a Controller (not in Aggregate), and I want refactor this code, with the repository to return directly the "read model" (With formatted text, price...).

I am only allowed to use Stored Procedure (client's policy) with Dapper. I am looking for a better way to create this read model :

1.Call existing stored procedures, map the stored proc results on DTO and then map again the results on my read model

public class Cart
{
    public Cart(CartDb cartDb, IEnumerable<CartDetailDb> cartDetailsDb, 
                                                      OperationDB operationDb)
    {
        //Code
    }
}

-> Have two levels of objects, I think it's a mess

2.Create stored procedures that will map directly to my read model (to avoid the DTOs)

-> I don't like this method because I could end up putting some logic in the Stored Procedures

3.Use ViewModel

Other suggestions?

Upvotes: 0

Views: 1079

Answers (1)

mclark1129
mclark1129

Reputation: 7592

If I understand you correctly, your data model for this entity does not exactly line up with your domain model for this Read entity. You would also like your repository layer to return you the domain model version of Read directly without requiring some intermediary DTO layer.

In my opinion, option #1 makes the most sense. Because there is an impedance mismatch between your data model and domain model, mapping logic will be required somewhere to translate data between the two models. The most appropriate place for this logic to go would be inside of your repository layer, since the entire purpose of this layer is to map objects between the domain and their persistence.

This does not mean that you need to create a DTO layer to map from your stored procedure that you just then turn around and remap to a domain object. You could simply perform the translation logic directly on the result sets returned by your data access layer and turn it into a domain object in one step.

In the case of data access, the need for DTOs is largely determined by what technology you are using for data access. For example, if you are using the ADO.net libraries (SqlCommand, SqlConnection, etc) then a DTO is probably not required. However, if you're using an ORM like Entity Framework or NHibernate then it may make sense to use the objects generated by those tools strictly as a DTO and map to a full fledged domain object. Of course, since those objects are generated for you that pretty much eliminates any maintenance issues with having a DTO layer.

This also does not mean that you need to place the translation logic in your stored procedures in order to make the data layer return result sets that exactly match your domain model. I would avoid this at all costs as you said yourself, this puts domain logic in your database.

Finally, you mention that the domain object consists of "Formatted Text" such as price. I would point out that most times text formatting is actually part of the UI layer and not your domain model. That means that if you have a property on your model such as Price, it should be represented as a Double or Decimal and not a String formatted as currency. In other words, the value should be 5.00 and not "$5.00".

For handling formatting translations like these, it's appropriate to wrap your domain object with a ViewModel like you mentioned, to handle the translation from the domain to the UI layer. Using a strict separation concerns in situations like these helps to create a more robust system that is easier to maintain.

Upvotes: 1

Related Questions