As I understand, when following the Low Coupling High Cohesion Principle, I should keep together the code that is related to same theme, splitting the code into modules/submodules by its "domain" or, in other words by what "topic" it is about, not by its "type".
E.g. it can be considered a bad idea to keep all interfaces together just because they're interfaces and keep all classes in other place. Or to keep all controllers in one place just because they're controllers, and all adapters in other. Etc.
A better option is to keep all code relating to shopping cart in one place, and all code related to goods in other. - So as they're are kinda modules. The Shopping cart folder will contain all code related to it: all controllers, adapters, entities, repositories etc - because they're all about the same thing.
On the other hand, a good clean architecture implies a clear division onto separate "layers", so that upper layers know nothing about lower ones.
- first of all, there is a separate 'library' level - like web server, input-output, or data structures (e.g. map or deque) - they should "know" nothing about other layers.
- then, at the top level there are some domain classes modelling domain entities and their relations, e.g. shopping cart and goods, maybe some business rules - they also "know" nothing about other layers,
- next, there is some application logic, that describes the way in which your application allows to use those domain objects
- and there is an infrastructure layer - the classes that use system layer and implement some interfaces required by upper layers.
- finally, "on top of that all" (actually, at the bottom) - there is also a composition root level, which wires everything together, it may be familiar with every class and their dependencies and supplies them, maybe DI container,
main()
function etc.
It'd be cool if there'd be a way to highlight that e.g. all objects from one layer are somehow related and should use one layer but not use another.
- How to organize the code? What are best practices?
As a very simplified example - should it be like
- bookstore
- customers
- customer entity
- customers repository interface
- customers repository implementation
- books
- book entity
- books repository interface
- books repository implementation
- book list view
- book details view
- amazon book adapter
or like
- domain
- customers
- customer entity
- customer repository interface
- books
- book entity
- books repository interface
- infrastructure
- repositories
- books repository implementation
- customers repository implementation
- views
- book list view
- book details view
- adapters
- amazon book adapter
But I'm not sure if this example illustrates the question well.