ph-fritsche / pitch-demo

1 stars 1 forks source link

Directory structure best practices #1

Open tacman opened 2 years ago

tacman commented 2 years ago

In the article at https://medium.com/swlh/implementing-action-domain-responder-pattern-with-symfony-606539eea3a7, the directory structure is

src/
   Action/
         Input/
         Output/
   Domain/
   Infrastructure/
                 Responder/
                 ParamConverter/

But here, the directory structure is

├── Controller │   └── TodoController.php ├── Entity │   ├── TodoCollection.php │   └── Todo.php ├── Form │   └── TodoType.php ├── Kernel.php ├── Repository │   └── TodoRepository.php └── Responder ├── FormHandler.php ├── ItemHandler.php └── ListHandler.php

Where do Input/Output fit into this structure?

ph-fritsche commented 2 years ago

I followed Symfony's directory structure convention.

The src/Controller directory is repurposed to contain the actions. (It might also contain ordinary MVC-like controllers. Just return a Response and you automatically bail out of the Responder because there will be no kernel.view event.) Instead of one (invokable) class per action, I prefer to group multiple actions e.g. along the REST structure.

src/Responder is added because the response handlers have no place in Symfony's directory structure convention.

src/Entity contains the entities used as response payload beside those used by ORM. You could also have your ORM entities in src/Domain, your reponse payload in src/Action/Output and your request payload in src/Action/Input, but often enough you would end up with three identical entity classes describing the same data in different context which is more code to write, read and comprehend.

You can structure the code as you see fit. There is no technical barrier or benefit either way.

tacman commented 2 years ago

Thanks. The Input/Output being separated from the ORM entity also shows up in API-Platform's documentation: https://api-platform.com/docs/core/dto/

There, too, it seems like a lot of extra code for describing the same data, overkill for CRUD, but best practices are often overkill for tiny, demo projects. Still, it's the only way to learn. API Platform also recommends ADR when creating Custom Controllers (https://api-platform.com/docs/core/controllers/), but also recommends not to create custom controllers and use Extension Points instead. Sigh.

ph-fritsche commented 2 years ago

API Platform has a good reason for this I think. They have to provide a standardized interface for converting data into payload entities and vice versa.

For your action the function signature already declares the input and output of the action. That's why if the action e.g. returns a Todo object, this is non-ambiguous. When editing the Todo entity is (part of) the request payload in the context of the function parameters, the response payload in the context of the function return, and the domain entity in the context of the repository method. When listing the Todo[] there is no way to describe this in PHP without an additional class (TodoCollection). Here this only exists in the context of function return as response payload.