I have a book, which talks about design patterns and the use of layers in particular i.e. presentation layer, business logic layer and data access layer.
I now understand the concept of a utility class and a data transfer object. However, all of the examples and information in the book talk about how they apply to the business logic layer.
I assume that they also apply to the data logic layer as well or is there another design pattern that I am unaware of?
This question follows on from a question I asked yesterday, here: VB.NET - Creating objects on every loop.
I will post some code to clarify what I am asking if required, though this is more of a conceptual question.
Utility classes and DTOs are equally at home in the data and presentation layers. I often use DTOs defined in the data layer to pass data "up" to the business layer.
Related
I'm currently following an IT study, and we're asked to use interfaces and DTO's in a multi-layered ASP.Net Core MVC consisting of Presentation, Logic/Business, and Data Access, using dependency inversion so that both the presentation and DAL have references to the logic layer. In between the Logic and DAL, we have to use DTO's and Interfaces. I understand the concepts of both, and I know how to use them. However, we can decide for ourselves whether we want to create seperate layers for our DTO's and Interfaces, or to stick them in the logic layer. We are also asked to explain why we chose one option over the other. However, I cannot find any sources for why you would pick one over the other anywhere. So that's why I'm asking here.
So my question is: What are the advantages and disadvantages of putting your DTO's and Interfaces in a seperate layer, and what are the advantages and disadvantages of just keeping them in the logic layer?
Thanks in advance.
What are the advantages and disadvantages of putting your DTO's and Interfaces in a separate layer
I imagine separate layer like this:
Core
|
------------
| | |
DAL BLL PresentationLayer
Advantages are:
can be used in any other layers. So each layer can expose own dto by its API,
but internally it uses own classes. E.g. data layer can use internally own model clases Person,
however data layer returns PersonDto to Business Layer
you can easily reference this separate layer into other layers without forcing to introduce unnecessary
dependencies. E.g., if application is using just one model from data layer, then you will have to reference
this layer into presentation layer.
Disadvantages:
recompiling? If you edit your dto, then you need to recompile your layer and recompile all layers that
depepnds on this layer
what are the advantages and disadvantages of just keeping them in the logic layer?
Advantages:
I do not think that this approach has any advantages
Disadvantages:
wheneever you want to use dto or interface in any other layer, you have to reference the whole
this logic layer. This logic layer can expose unnecessary API for this layer.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have read the PPP book and clean code, coder and architecture books.
I know that:
Clean architecture is a layered architecture
What is it like being open layered or close layered architecture
Clean architecture books suggests that each layer can access it`s inner layers, and not only the very next inner layer
So I assume that clean architecture does not force being close layered and it allows being open layered, meaning that for example UI which is in the frameworks layer can directly access Entity, jumping 2 layers in the way.
And I understand that if clean architecture forced being close layered, we could not implement repository interface directly from Frameworks layer and we should implement it in the terms of next layer and this next layer should have implemented it in the terms of its next layer and so on.
Now my question is, why we can't introduce Entity as the parameter type of the usecase or controller directly and why do we have to define data structures or DTOs in the middle layers and bother converting entity to data structures and return it as response, while we are allowed to use and see Entity in the controller layer because the access rule is not violated?
Consider this example, suppose we have:
JobView
JobController
JobUseCase(RequestModel) : ResponseModel
JobEntity
Now if JobView wants to call JobController, it should pass RequestModel. Now could we simply introduce JobEntity as the RequestModel like so:
JobView
JobController
JobUseCase(JobEntity)
JobEntity
I know that doing like so will increase the fragility of code, because that way if we change JobEntity, then JobView has to change. But does clean architecture force SOLID principles being fragile or rigid as a rule?!
Why not using entity as request model of usecase?
You have answered this question yourself: Even as you do not break the dependency rule, it will increase the fragility of the code.
why we cant introduce Entity as the Parameter type of usecase or controller directly and why we have to define data structures or DTOs in the middle layers and bother converting entity to data structures and return it as response , while we are allowed to use and see Entity in the Controller layer because the access rule is not violated?
The (Critical business) Entities and the DTOs are in the application of very different reasons. Entities should encompass the critical business rules and have nothing to do with communication between adapters and interactors. DTOs should be implemented in the most convenient way to enhance this communication, and don't have any immediate reason to depend on business entities.
Even as an entity might have the exact same code as a DTO, this should be considered coincidence, as their reason to change are completely different (Single responsibility principle). This might seems to collide with the popular DRY principle (Dont repeat yourself), but DRY states that knowledge should not be duplicated, code might still look the same in different parts of the application as long as they are changed by different reasons.
Not sure I understand the reasoning behind your question:
Does clean architecture forces SOLID principles or not being fragile or rigid as a rule?
How could Clean Architecture possibly force rigidity and fragility? Defining an architecture is all about: how to take care widely of fundamental OOP principles such as SOLID and others…
On the other hand, your following example would definitely denature Clean Architecture:
JobView > JobController > JobUseCase(JobEntity) > JobEntity
This implicitly tells us that you've retrieved your entity most likely from the controller, which completely misses the point of the Interactor (or use case) and so of the Clean Architecture.
Interactors encapsulate application business rules such as interactions with entities and CRUD on entities done via the Entity Gateway which in turn encapsulate the infrastructure layer.
Furthermore, in Clean Architecture context, your entities which are parts of your model layer should have nothing to do with your controller which is part of your delivery mechanism, or more exactly, which is the evaluator of the HTTP request message. Denaturing this way the lower level component that is the controller would affect negatively the SRP (=> fragility increase) and the degree of decoupling between your components (=> rigidity increase).
You say:
And I understand that if clean architecture forced being close layered, we could not implement repository interface directly from Frameworks layer and we should implement it in the terms of next layer and this next layer should have implemented it in the terms of its next layer and so on.
Your entity framework's RepositoryInterface and its implementations belong to the infrastructure layer and they should be wrapped, adapted by the entity gateway. Law of Demeter might be important to respect here as we are talking about the business model's closed layer's port (EntityGatewayInterface)'s implementation.
Finally, for the reasons above, I suspect the following assumption being wrong and so would be all the further assumptions based on that one, leading yourself to total confusion:
So I assume that clean architecture does not force being close layered and it allows being open layered, meaning that for example UI which is in the frameworks layer can directly access Entity, jumping 2 layers in the way.
But whether it forces being closed layered or not, Clean Architecture explicitly and concretely defines itself (relation between components) such as on the UML class diagram below:
I can see only a close layered architecture from that diagram…
It seems to me that an open layer is an oxymore, that it does not constrain what a layer is supposed to constrain by nature, because by definition, a layer is an isolation, an abstraction of a group of components reduced to its port, meant to reduce technical debt such as fragility etc...
Additional Resources
Conference given by Uncle Bob resuming well enough why and how to implement Clean Architecture: https://www.youtube.com/watch?v=o_TH-Y78tt4
The above answers are accurate, but I'd like to point out why this creates confusion as I've seen it before: because from a dependency perspective, there is nothing wrong with passing entities across the boundaries. What you cannot pass is any type that has a dependency on an outer layer, that's a no-no for reasons obvious. Much of the book talks about dependency issues, so that creates confusion - why aren't the entities ok?
As stated above, entities need to observe SRP just like any other code. If you use entities for data transfer purposes, you have introduced an unnecessary coupling. When the entity needs to change for a business reason, at the very least the mapping code and maybe more in the outer layer need to change in response.
I'm designing a layered application where 90% of the business and data access entities have the same properties. Basically it doesn't make sense to create one set of classes for each layer (and map) with the same properties for the sake of separation of concerns. I'm completely aware of automappers but I'd rather not use one in this case as I think it's unecessary. Is it ok to share share the business entities between the business and data access layer in this scenario? We will manage the remaining 10% of the classes by creating adhoc/transformed classes within the same namespace.
Any other design approach?
I think sharing between layers is the whole point of having model classes backed by a data store. I would avoid adding unnecessary architecture unless the code really needs it. If you get to a point where you need to be agnostic of the data store or some other similar situation, I would you might look into the Repository pattern. Simple code = maintainable code.
I have some business objects and some very similar corresponding data contract objects for getting data across the wire via WCF service.
What mechanism should I use to get populated data contract objects from business objects?
In an ideal world, should the data contract layer know about the business layer?
or
Should the business layer know about the data contract layer?
or
Should there be another mapping layer that has static methods like GetDataContractFromBusinessObject?
I am a big fan of the "mapping layer with static methods" technique you mention. Then, your business objects and data contracts don't depend on each other either way.
I often will add a derived class to handle data consumption from a specific backing store in my business layer.
Another option is to an interface data layer representation that the business class understands. And then have your data layer implement that interface. I prefer this method as it is much simpler to have you business layer interact with an abstracted version of your data layer then having your data layer understand your business objects.
In Domain Layer or Data access layer?
The primary motivation for DTOs is to present an interface tailored to another layer (typically, the presentation layer). For example, a data entry screen may need some bits of data from a User object in addition to some bits from an Order, etc. In that case, the Domain to DTO should happen at the layer which the presentation layer invokes, i.e., typically a "service" layer.
There are libraries like Dozer out there which automate the grunt work of converting between domain models and DTOs.
The key take away is DTOs are meant to abstract the data (not business logic) out of richer domain model objects - hence, DTOs should be converted back to domain objects as early as possible (at service layer) so the rest of your application layers may work with richer domain objects (data and business logic)
I'm not much of a fan of DTOs, but I say don't do it in the data layer. The data layer deals with model objects and their persistence. Why couple it with other layers by bringing DTOs into it? I'd map them somewhere else, probably between the service and ui tiers, just at the point where they cross the boundary between where they're created and where they're used.
Putting this in MVC context, if you have both controllers and services layer you should put it in the controller. This would make a DTO closer to the view layer and allow the service layer to play with domain objects only, avoiding possible confusion with other models.
The DTO itself is actually the MVC model (Explained here: https://stackoverflow.com/a/1058186).
Below is a recommended tutorial that mashes the controller, service layer and DTO concepts together (In java using Spring framework, but the concept is clear for other platforms as well):
https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application