design-patternsarchitecturecqrsmediatr

Vertical Slice Architecture big number of models


I am playing with VSA and I encounter something that seams wrong. I want to build a Web Api using MediatR and CQRS. Now, let's say I want to implement some CRUD operation on an entity called User, that have a list of Cars and the Car have a list of Policies (Just a random example).

If for example I want to do the create flow I need the following models (I am considering sharing MediatR and Api Request, but I got some other problems in that case):

For Search/Get Endpoint I will need again 3 (almost identical - On create I don't have an Id) with the one from create) different classes for responses (If I share MediatR response with the Api Response).

Now let's say I want to add a "Add Car to storage" endpoint. I will need to duplicate the CarDto.cs, PolicyDto.cs and UserRequest.cs, CarRequest.cs classes in order to not use the same models in 2 different features.

In addition to all this I will need a mapper for all of them (UserRequest -> UserDto->User, CarRequest->CarDto->Car etc.).

Is that normal? I feel like I can share some of the classes (e.g. CarDto for both add User and add Car to storage flow), but I would like to have a rule and a consistency across the features.


Solution

  • Vertical Slice Architecture (VSA) is about organizing code and components around functional concepts. For example in a Financial Management Information System you might have: chart of accounts, invoicing, accounts payable, transactions, and so on.

    Importantly, you can also have slices that provide features and functionality that are "cross cutting" such as identity and access management (IDAM). Although these cut "horizontally" across other logical feature slices, they are technically implemented as a just another "vertical" slice in the code-base. Typically you would expect to see these concepts in the code-base - for example as folders and modules holding code that addressed the given concept (slice).

    FMIS Solution/
    FMIS Solution/Chart of Accounts
    FMIS Solution/Invoicing
    FMIS Solution/Accounts Payable
    FMIS Solution/Transactions
    FMIS Solution/IDAM
    FMIS Solution/Technical Logging
    FMIS Solution/Audit
    

    VSA is useful when you want to have a feature-centric approach. In addition, each vertical slice can decide for itself how to best fulfill requests.

    Command Query Responsibility Segregation (CQRS) is about keeping reads and writes on separate interfaces.

    Compared to VSA, CQRS this is a more low-level technique. VSA is the high-level architectural style that guides the overall architecture, and within that CQRS just looks at the detail of how the system will handle services and exchange data with them.

    Now let's say I want to add a "Add Car to storage" endpoint. I will need to duplicate the CarDto.cs, PolicyDto.cs and UserRequest.cs, CarRequest.cs classes in order to not use the same models in 2 different features.

    ...

    Is that normal? I feel like I can share some of the classes (e.g. CarDto for both add User and add Car to storage flow), but I would like to have a rule and a consistency across the features.

    Sharing concepts (realized as DTOs, etc) across models is not new. The Clean, Onion and Hexagonal (aka Ports & Adaptors) architectural styles all share a "central" (shared) layer for low-level domain entities, with the intent of making them reusable by the higher layers.

    VSA is an architectural style which means they provide guidance that prioritizes certain system qualities in response to common problems; "guidance" implies you still get to decide the details. It's up to you (or whomever is leading the architecture in your project) to decide what rules make sense for your project and how that should be implemented. For example, you might decide that: