hattom
hattom

Reputation: 1

Domain Driven Design - Services should know about other services ? Or should know multiple repositories?

I'm creating a backend application and I'm trying to implement the Domain Driven Design. However, I had a question regarding my data structure that I intend to clarify.

Database Structure

Users
Id (PK 🔑)
First Name
Last Name
Email
Password
Customers Profile
User Id (PK / FK 🔑)
Height
Weight
Personal Trainers Profile
User Id (PK / FK 🔑)
Specialties

Taking into account the database represented above, I have some doubts on how to structure the Controllers, Services and Repositories of my application.

Let's imagine, that I want to update a Customer Profile and their User:

And to update their respective User on Users table? Should the Customer Service call an update method from the User Service? Or should the Customer Service call the User Repository directly?

I'm very confused, not knowing if it's correct, services know about other services, or services know repositories that theoretically belong to other services.

I will be very gratefully if someone could help me clarifying my doubts 🙂

Upvotes: 0

Views: 440

Answers (3)

Ajit Kumar
Ajit Kumar

Reputation: 181

I think the Database structure can be improved.

Rather than naming the table as Customer Profile and Personal Trainer Profile, name it as Customers and Personal Trainers.

As A Customer is a User & A Personal Trainer is a user

Updated Database Structure

Users
Id (PK 🔑)
First Name
Last Name
Email
Password
Customers
Id (PK 🔑)
User Id (FK 🔑)
Height
Weight
Personal Trainers
Id (PK 🔑)
User Id (FK 🔑)
Specialties

The Aggregate Roots are Customers & PersonalTrainers.

Now the Controllers and Services will be for Customers & personal trainers.

And any update to fields for users table for customers will be done via Customer Controller.

The class definition public class Customers extends Users & public class PersonalTrainers extends Users

Upvotes: 2

Eben Roux
Eben Roux

Reputation: 13246

Aggregates are independent objects that ensure consistency within the aggregate. A User represents a specific concept and a CustomerProfile another. The CustomerProfile should rather have its own Id (not necessarily UserId). Nothing stops you from modelling it as you have but keeping state changes on the two aggregate separate is going to make your life a lot easier.

That being said, whenever I do find that I have application services that make use of one another in some way I apply the good old "All problems in computer science can be solved by another level of indirection". I take the common bits and make a Task of sorts and use that in each.

Upvotes: 0

Luca Masera
Luca Masera

Reputation: 732

Sorry if I'll be a bit 'crude', but in your approach there's no real clue about DDD. I mean: Controllers, Services and Repositories are the 'the facto' way to develop an application with Spring. But this is not really DDD. To implement it with DDD you have to forget the database, focus on the entities of the domain, identify their functionalities and start to think how to translate this into code.

With this preface, I can say you that also within this 'the facto' approach is possible to adopt a DDD, at the price to rethink all the process that produces the code.

Hence, in your model, I would do something like this:

  • identify the entities of the domain that you want to model (here you have to find the root entities, aggregates and value objects -link 1, link 2);
  • given that the DDD is an object oriented approach, once you've identified your entities (and this is not so simple as it looks, believe me), you need to identify the functions that each entity offers. So, for example, for the PersonalTrainer entity, one possible function could be acceptTrainee(Course course, Person trainee), that add a new Person to a Course (remember, it's a sample, I have no idea about your domain).

Once you know your entities, or at least you start to identify them and some functions, you can think about the code. Here you can choose between several architectures: clean, ports & adapters, onion, 3-Layers architecture (the default and classic approach with Spring: controllers, services and repositories with entities). My personal approach is more or less what is described here.

I would suggest you to search and read a lot about how to do the things. There's no silver bullet, unfortunately: sometimes the domain is really simple and the extra overhead of a DDD and an 'unsual' architecture are totally useless; sometimes the domain is complex and big, hence a DDD approach with a more refined architecture are a much better choice.

Finally, to give you a concrete answer to work on your case, after identifying the entities and their functions I would put the model that you have produced into a domain package. Here I would also define the Repository interfaces, that you use to persist the entities (but you'll implement later). Once you have this, you can develop the services, where you put all the things together using what you have into the domain. I would put this code into an application package (but, remember, it's not a law: if you think is better, place them in a different place, or with a different name - take a look here, I really like this approach). Finally, I would start to implement the code of the infrastructure layer, where all the interfaces defined into the domain and the application layers will be implemented. Here I would put also the Controllers.

Remember: this approach allows only connections in one direction (domain -> application -> infrastructure), but never the opposite.

Finally, if you think about how to manage the domain entities with some ORM frameworks, I would suggest you to read this links: domain vs persistence model; stackoverflow question about this; domain and persistence separated.

Upvotes: 0

Related Questions