How do entities, DTO, DOA work together and what’s their role within a system

domain-driven-designobject-oriented-designspring

Most of my work is written in Java using Spring Boot. In a recent project my entities contained no business logic, Spring Data was used to handle repositories and I have service classes that controllers would call to retrieve certain data or perform actions on an entity. For example, you might have a UserService with a resetPassword action which would handle resetting a users password.

I’ve read a lot about domain-driven design lately and I’m getting confused because the examples in one book show behaviour on what looks like an entity. For example, a changeStatus() action on an Order.

If applying the MVC pattern, I’m struggling to understand the relationships between controllers, services, DTOs, DAO and entities.

Let’s say your building a web service, your controller will return JSON to the client. Your entities would match the structure of your database, but you need another type of object to return the data to the client as the structure of that data could be different from your database, this is the DTO?

Would your controller talk to a service? And what would the service return? Entities or DTOs? If entities would you map those to DTOs using a mapper in the controller?

What about behaviour? Is that ok in a service class, or should entities be mapped to DAOs that contain behaviour?

I’m confused, when I research this, some appear to get entities, repositories and DAOs confused. Some say entities can contain behaviours, others say no.

Another example, say we want to know what permissions a user has in the system, we can find this by calling getUserPermissions(User user) which might return List. What would we call from inside a controller? Would we put this in a PermissionsService class and call that? Or would we have another object that represented an entity but which also had behaviour and could communicate with the repositories to gather additional data? We certainly couldn’t put it on the entity itself, as that would mean injecting a repository into an entity, which feels wrong.

Any guidance is appreciated.

Best Answer

Your primary starting points should be

  • Eric Evans: Domain Driven Design
  • Martin Fowler: Patterns of Enterprise Application Architecture

Evans offers the clear introduction to what it means to put the domain model first. Fowler summarizes the domain model pattern, along with several alternatives to it.

Here's the key idea - enterprises write custom software (rather than just buying something off of the shelf), because either the off-the-shelf-ware they need doesn't exist, or because being able to fine tune the details are important to the bottom line of the business.

If you are an enterprise with a JVM development team, you don't roll your own web server, or data access objects, or any of that truck that is the same that everybody else uses. You download Spring, or something else your development team likes, and invest your development capital in code that makes a difference.

So when Evans talks about "entities", he's not talking about rows in a database -- that's just plumbing. He is talking about concepts that are critical to the business model -- what does it mean to be a cargo shipment? If we get a message announcing that a container has been unloaded at the wrong port, or has missed a connection, what do we do about it?

And yes, absolutely, in the Evans/Fowler framing, the classes that represent domain entities do include methods that modify their own state. Tell, don't ask.

A repository class would be responsible for getting the OrderEntity from the db and returning it, but what class would be responsible for mapping it to an Order object on the domain?

Per Evans, chapter 6, that work would also happen within the repository -- more precisely, you would read the value (from hibernate), convert the value into an aggregate root using a Factory, and then return the root to the application.

(So the application code get to see the hibernate value at all, it is enclosed within the aggregate root).