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?