Reputation: 191
In Clean Architecture design, Do we need to create a separate "Project" for each layer? Or Can we define the layer with the Folders and Namespaces on the same project?
I am working on designing a new application in MicroServices architecture using Net Core. I'm planning to use Clean architecture principles in my design.
I am planning to use the below project structure for my every individual service. Is this the right way? I'm trying to reduce the number of projects.
Upvotes: 2
Views: 4125
Reputation: 27904
I would strongly suggest you really embrace
SEPARATION OF CONCERNs
software design principal.
As my comment says "folder separation" for a new project is basically begging for a "big ball of mud" software project.
It is so simple to add the layers (csprojs) on a new project. And would be very very short-sighted not to.
In general, when in doubt, go with "over separation" over under. Why? Trivial to "combine" later. HUGE headache and effort to "separate later".
My typical setup.
./src/BusinessServices/Optum.Flex.MyProject.BusinessServices.csproj
WebApi Layer. (and top layer for IoC "Compositon Root"). References everything below, except unit tests.
./src/BusinessLogic/Optum.Flex.MyProject.BusinessLogic.csproj
Business Logic. References Optum.Flex.MyProject.DomainDataLayer.Interfaces.csproj. and Domain.csproj. DOES NOT REFERENCE concrete EntityFramework.csproj.
./src/DomainDataLayer.EntityFramework/Optum.Flex.MyProject.DomainDataLayer.EntityFramework.csproj
Concrete DomainDataLayer. References Optum.Flex.MyProject.DomainDataLayer.Interfaces.csproj. and Domain.csproj.
Will also contain Orm-Entites, Orm-Maps.
Can also contain the "converters" from Orm-Entities to DTOS(pocos) and vice versa. (Use mapster or automapper or hand map)
./src/DomainDataLayer.Interfaces/Optum.Flex.MyProject.DomainDataLayer.Interfaces.csproj
Interfaces for DomainDataLayer.
The interfaces accept and return Domain objects, the DTOS/POCOS.
./src/Domain/Optum.Flex.MyProject.Domain.csproj
DTOS (or POCOS). Has ZERO REFERENCES TO ANY OTHER LIBRARY. Simple Pocos/Dtos.
./src/UnitTestProjects/UnitTests.EntityFramework/UnitTests.EntityFramework.csproj
./src/UnitTestProjects/UnitTests.BusinessLogic/UnitTests.BusinessLogic.csproj
./src/UnitTestProjects/UnitTests.Domain/UnitTests.Domain.csproj
I go even further.
CQSP (Command Query Separation Principal)
https://martinfowler.com/bliki/CQRS.html
and
Do not pass ORM entities "across the wire" from rest services.
https://thorben-janssen.com/dont-expose-entities-in-api/
There are two main reasons for these questions and all the discussions that arise from them: Entities are POJOs. It often seems like they can get easily serialized and deserialized to JSON documents. If it really works that easily, the implementation of your REST endpoints would become pretty simple. Exposing your entities creates a strong coupling between your API and your persistence model. Any difference between the 2 models introduces extra complexity, and you need to find a way to bridge the gap between them. Unfortunately, there are always differences between your API and your persistence model. The most obvious ones are the handling of associations between your entities.
https://jacquessmuts.github.io/post/modularization_room/
Don't do this. Please. It breaks the core concept of Information Hiding as would be required by a project that implements a proper Separation of Concerns. Map Your Entity Instead, you should have two distinct objects. You should one object that represents the database Entity (Orm-Entity) (Java this is the JPA Annotated Object and C# this is the Orm-Attributed object (less preferred) or the FluentMapped Orm-Entity), and one object ("Dto" or "Poco") for passing around the pure data. Your database module should be literally the only module which imports the Room library. If any other module imports those implementation details of the database module, then you are not Information Hiding as you should.
and this breadcrumb to "composition root"
https://blog.ploeh.dk/2011/07/28/CompositionRoot/
Upvotes: 0
Reputation: 2286
It would seem in the beginning of development that holding everything together in one place is better, but when the project grows you will experience more and more dificulty maintaining an overview of the seperate components.
You can decide to move the code when this happens, but this can be more of an hassle then separating the code at the start.
Especially once you start thinking about the use of nuget packages and such, this can help you in figuring out which code is using what components.
Upvotes: 7