Application service parameters / return types

domain-driven-design

Solution

+1

I prefer a mixed solution.

1) I use domain objects as arguments, but limited to ValueObject s. I believe the lifecycle of Entity s should be managed carefully, and most of the time the view doesn't have enough value to populate the whole Entity except very simple CRUD applications. I saw many times that some developers init Entity by constructor carelessly and populate them with only part of the fields they required for a particular function, this makes it very easy to introduce bugs for NullPointerException and the poor guy who is assigned to fix the issue has to search across tens of methods to find where the Entity given was created. Entity s are retrieved from Repository or created by Factory in my projects.

Sometimes I use some form objects as parameter for simplicity.

2) I use a mvc Controller to convert domain objects returned by application service to ViewAdapter(a componenet decouples domain models from ui), sometimes dettach work need to be done here.

3) I use a Facade only when the application service need to be exposed via remote procedure call like web-service. Dto s are used as arguments and return types in this case and the Facade is responsible for converting DTO and Domain Model.

4) Validation is awkward if the application service need to be exposed to both web view and remote procedure call. This causes duplicate validation implemented on both form objects and Dtos. I validate simple constraints only(Not null, length to name a few, business rules are validated by domain objects programmatically) because I haven't found a perfect solution yet.

Hope this helps and if there are better solutions do let me know please.

Update1:

1) I have to confess that I'm not a guru in this area and I'm trying to find a good solution as well. So sometimes there is some inconsistency in my current solution such as the form bean you mentioned in comment. Sometimes we take some form bean as Command and place some domain logic in it, so these command belong to Domain Layer in this case.

2) Transaction boundary is on the application service. Technically, The domain object could be modified out of the boundary inadvertently. We cover this by team discipline and code review.

Problem

I work on standard web application with domain organized around DDD concepts. I'm wondering what kind of objects my application services should accept and return. Let's say that I have an application service for `User` aggregate. 1) DTOs / simple types (string, int etc) ``` public interface UserApplicationService { void registerUser(UserDTO userDTO); List<UserDTO> getUsersForOrganization(String organizationId); } ``` In this case, application service is responsible for calling assembler transforming DTOs to domain objects and the other way round. Advantage of this approach is that my application service is a clear boundary for my domain objects. Another one is that application service is a clear transaction boundary. Domain objects that are managed by persistence context do not leak somewhere outside of the transaction. Disadvantage is that in case of forms, validation must be based on DTO. So my validation rules are duplicated between domain (object is responsible for its state) and DTO validation rules. (As in case of Spring MVC sample application). Also, if some parts of view requires another form of model (let's say that UserDTO has not enough information for view to be rendered), I'll need to create another DTO and basis on couple of DTOs returned from application service, compose another one, used by view. 2) Domain types ``` public interface UserApplicationService { void registerUser(User user); List<User> getUsersForOrganization(OrganizationId organizationId); } ``` In this case, controller / presenter is responsible for transformation. Big disadvantage is that my domain objects leak from application service - no clear separation. Also, where are our transaction boundaries? Domain objects that may be attached to, for example Hibernate session, leaks outside of application services layer. (However, I noticed that this is how many sample applications are written.) Advantage may be that the controller / presenter is responsible for preparation of model for view, so it can compose DTOs basis on the view requirements. For instance, view may require some additional information that is not returned in DTO from #getUsersForOrganizationMethod. Also, validation may be based on domain objects, so it's not duplicated between DTOs and domain objects. 3) Domain objects + facade This is third option used in DDDsample application. Application services return domain types, but there is some facade that is responsible for transformation. So in my case, controller / presenter talks to facade with DTOs, facade does the transformation and it talks with application services using domain objects. However, in my humble opinion it seems a little bit overwhelming - too many layers, too many boilerplate code. For one application service it may sound great, but if we had tens of them, we need to have the same number of facade methods - pure duplication. Additionally, where are transaction boundaries?

Original source

Related problems