Presentation Logic vs Application Logic vs Domain Logic
ฝัง
- เผยแพร่เมื่อ 5 ก.พ. 2025
- All videos in this playlist: • ASP.NET 8 REST API Tut...
In today's video we'll talk about Presentation Logic vs Application Logic vs Domain Logic.
We'll present and define each, talk about their relationship with one another and see where the code should sit within our project.
Join us on discord: / amantinband
Get the source code: / amantinband
Support the channel: / amantinband
Connect with me on 'em socials:
Twitter: / amantinband
LinkedIn: / amantinband
GitHub: github.com/ama...
Check out all my courses on DomeTrain:
dometrain.com/...
Support the channel and get the source code:
/ amantinband
Thanks for watching, don't forget to like & comment & subscribe! ❤️ 💻
Thank you Amichai, I am learnig so much with you. Keep teaching us that way.
Thanks Amichai! I missunderstood this subject, your explanation is pretty clear.👍
Related to this, if we work with anemic domain objects, should we move domain logic from domain entities to domain services?
Thanks a lot, u are the best to explain this topics.
Hi Amichai, thank you for the video. My question is where should I put the checking unique username, while managing user creation request? As we assume, I need to call representation layer here, but this is a business rule.
Validation is usually one of the following 2:
1. Input validation
2. Business rule validation
Input validations (usually) fall under presentation logic. Meaning that invalid input isn't supposed to reach application logic.
Business rule validations should be enforced as part of the domain.
Unique username is usually considered a business rule validation. If you want to put this validation in the domain, you have the following 2 options:
1. Creating a domain service (similar to an application service - but is logically part of the domain since it participates in decision making)
2. Encapsulating the logic within a domain object.
For number 2, there are also 2 options:
1. Accepting the list of usernames as a parameter (or, more generally, the data needed to make the business decision and trusting the caller will invoke the method with the correct values)
2. Accepting an interface that allows fetching the usernames/validating uniqueness of a username. This interface is logically part of the domain and uses the language of the domain. (or, more generally, interacting with an interface that is part of the domain, where the underlying implementation doesn't matter or can be mocked)
That said, you can always be pragmatic and simply add a query as part of your validation logic to make sure the username is unique, and in inner parts of your application trust/assume that this is being enforced earlier upstream.
Hope that makes sense is isn't too abstract.
Checking limits should always be at the domain layer.
As a real-world example, my point of sale for work has multiple sections where a stock-on-hand check needs to be performed.
There are 2 checkouts, 1 for the stores, 1 for the trade customers, and a system to convert trade customer orders which were put through to the local store by the customer into an invoice or to a warehouse order.
I /could/ put the SOH check into the presentation layer, but that means if the logic changes for checking stock levels, I have to update all 3 presentation layers.
I could put it into the application logic, but I basically end up with the same problem.
The only valid place for it, is in the domain logic area, it means all 3 things just say 'convert order to invoice', and that 1 thing does the check, if it fails, it returns error codes and messages up the stack for the presentation layer to do what it needs to do.
Similarly for your example, the domain layer is the one that should be checking if the user is at their product limit, that way if you have multiple services that could interact with that user domain, you don't have to put the check in all the application layers.
This is what I like about the architecture of the ABP framework. They additionally have the concept of DomainServices, where you e.g. do duplicate checks when creating an item (as the domain objects should not have external dependencies, they cannot know there are duplicates) or to check for global limits...
Edit: for global limits it could be debatable where they belong. I could think of features where they belong to the application
😅 . the reason most trend not suitable for me . For front end like android or swift maybe yes because you deal with one place
How often does things like this really change in reality or is swapped out?
I tend to start to dislike clean code more and more and everything is put in different places. Needs a LSP for doing code review because you find nothing without intelligence.
I like to keep things together per feature so I find what I look for without jumping all over
@@EMWMIKEI'd still consider it clean as long as there is a pattern to follow for the next feature or the next maintainer. Derek Comartin from codeopinion e.g. likes to put everything from command over handler to specific service all in one file.
@@EMWMIKE clean code is a joke trend same as when mvc code trend started. Not all companies have 20 people working on certain things . The smaller codebase and some call as mono much suitable and easy to maintain but if code clean with multi team and multi service , nobody knows how integrity's data between all the services . Keep small and profitable first then expand whatever needed .
Hi Amichai, could you make a video talking more about your .editorconfig settings?
Hi, great video!
The validation should be done in controller or in repository?
I'd say neither. If the validation is about the request format that's a presentation concern and it should be there, but not inside the controller, a validation class or the request class itself is a better option.
If the validation involves more business logic then that would be in the domain layer (or maybe in application layer) while repository is in the persistence
@@junior.santana Sorry, my mistake, i mean that I would use fluentvalidation and inject in service layer , Is that correct?
@@alfonsdeda8912 Let's see his response, but IMO this kind of validation done with fluent validation usually refers to presentation concern. But if you're doing some more domain logic with it then the service later would be fine. In any case it's good to have the validation separated from the actual processing, either in a method or in a separate class just for doing that
Thank you, Amichiai, for this video.
The controller action starts with mapping to internal representation. The line of code looks like:
var product = request.ToDomain();
I'm wondering where the ToDomain method belongs, and in relation to this question, I'm wondering where the CreateProductRequest class belongs.
I think this is a more complex question than it may appear at first glance. I love the idea of encapsulating this mapping into a single method call, but I'd love for more explanations.
Imho the request belongs to the presentation logic because it is specific to endpoint the controller provides. With it comes the ToDomain function.
Though it could be an extension method or you could be using a mapper library.
If you have another presentation layer, say a REST API, you would probably have another set of requests because e.g. the API requires other fields or because the API is public and you don't want to introduce breaking changes if you change the endpoints for the web frontend.
Edit: Given the request is specific to the controller (=presentation), the mapping to the domain model must also reside in the presentation layer because otherwise you would violate clean architecture constraint that the direction of access is always outside to inside
The mapping to internal representation and from external representations are presentation concerns.
Since we are working within a single assembly, the requests and responses can own their conversion to and from the domain objects.
As the application grows, this may change, but the conversion logic still falls under presentation logic. Once the requests and responses cannot reference the domain objects, I like mapping the objects either via extension methods or via a mapper (Mapster, AutoMapper etc')
Hi Amichai, do you have any tutorials on microservices and best practices. I think it would be very popular. Thanks again.
Thank you Amichai. In multiple videos it is suggested that DTOs should not have behaviours. Here we added mapping? Is leaking the domain model to the presentation layer a good idea, given nothing is preventing us to use its behaviours in the presentation layer?
If there is a 3rd party dependency where we send over some of the request data to then use it in the domain would we still map to domain in the presentation layer or that would then be an application concern?
Thank you
Great lesson!!
What is the name of this tool that you use to generate these arrows and blocks?
DemoPro
One question suppose you have list of Product that i want to show at datatable (5 or more fields), so there will method in Core say GetProducts and then if you want to show same Products in the DropDown where just Name and Id fields are required. Then should we use same method to GetProducts and then transform it DropDown or there should be a separate method that will return List which will also reduce overfetching. But then we will be exposing "Core" class to the outside world or We have 2 classes dropdown at presentation DropDownPresentation and dropdown at DropDownCore, and we do extra extra conversion just to follow the rule.
I thought the presentation is not suppose to know about the domain layer following clean architecture. It should only know the application layer. Then why can we convert the product to response and also convert request to product from the presentation layer.
Great video are we going to use Mediatr and CQRS in this project?
I hope not. Overengineering
What about the persistence, does it fall under application logic or presentation logic as we can later on try to swap our way to access the DB, and you didn't explain why we used Records as we could have used Domain objects to achieve that and why the records didn't have their separation from the controllers.
And as always thank you for your awesome content.
Persistence goes into the application because if you had it at the presentation layer, 1. the application could not access it by it's own (e.g. you would have to do duplicate checks within the presentation layer) and 2. you would have to duplicate the persistence for each layer outside the application layer (i.e. multiple presentation layer e.g. endpoints for web UI, REST API, CLI and also integration tests)
Edit: See Amichai's response regarding the persistence as a separate concern. Of course he is right and I tried to answer it under the assumption that there are only these two layer as candidates.
1. Persistence doesn't fall under any of them (it's its own). Once you have your application, presentation, and domain logic separated, persistence will naturally be isolated (at least from those 3).
2. Records are a good choice for DTOs. The requests & responses are presentation concerns and should be separated from the domain objects.
3. As the project grows, the requests and responses will likely move to their own folder or project. For now, they are placed in the controller for convenience.