Search code examples
architecturecqrscommand-query-separation

Vertical Slice Architecture - What should go in the Controller, Command/Query, Response, CommandHandler?


After some thought and consideration, I have decided to restructure my existing directory structure of an app I have which is currently sliced Horizontally (in layers), into a Vertical Sliced approach.

To match the desired structure I changed my project files in this question to match the below linked example and make things clear.

- Controllers [Based on Request Method, GET, POST, PUT, calls appropriate service method]
  - ProductsController.php
- Data
  - DAL [Data Access Layer - Specific Read / Write Queries]
      - Products
  - Mapper [Maps parameter array to object]
      - ProductsMapper.php
  - Model [Contains classes matching table structure]
      - Product.php
  - Service [Business Logic]
      - ProductsService.php
  - Provider [Database Connection Class]
      - Database.php

So, after some research, I came to conclude that it would make things easier if I model my application structure using Vertical Slices and found a clarifying example.

Out with the Onion, in With The Vertical Slices

- Features
  - Products
    - AddFavoriteProduct
      - AddFavoriteProductController.php
      - AddFavoriteProductCommand.php
      - AddFavoriteProductResponse.php
      - AddFavoriteProductCommandHandler.php
      - AddFavoriteProductContainer.js
      - AddFavoriteProduct.js
      - AddFavoriteProduct.css
    - GetProductList
      - GetProductListController.php
      - GetProductListQuery.php
      - GetProductListResponse.php
      - GetProductListCommandHandler.php
      - GetProductListContainer.js
      - GetProductList.js
      - GetProductList.css

The problem I face is what do I delegate to each of these four files.

My general understanding is as follows.

Controller - Handles the request and calls command/query, or is this CommandHandler?

Command/Query - This has insert/update commands, or database queries which in my case will be facilitated through an Object Relational Mapping framework like Doctrine

Response - Returns to the user the desired information, or command status result as a JSON

CommandHandler - Unclear what goes in here...

Looking for some example snippet, or some clarification to start. Description of the function of each of the four components would be helpful.


Solution

  • The problem I face is what do I delegate to each of these four files.

    I recommend trying to find a balance between two tensions

    • You want things that regularly change together to be close together (ie: two ideas are in the same source file because they are logically and temporally coupled).
    • You want things that have different dependencies to be in different files.

    The important paper to review is Parnas 1971

    We propose instead that one begins with a list of difficult design decisions or design decisions which are likely to change. Each module is then designed to hide such a decision from the others.

    So for example, your Controller probably knows everything there is to know about HTTP, and the web framework you are using. But it probably doesn't know about your domain model, your database connections or your transaction boundaries.

    (As far as I know, there's nothing particularly magical about "four" files; it could easily be more than that, depending on how you cluster the design, what other kinds of interfaces you want to support, and so on.)