In multi-tier architecture with a service layer, is it acceptable to have one service call another service?
Asked Answered
W

3

6

I have a multi-tiered app with a data layer containing repositories.

On top of this, I have a service layer. My understanding is that there should be a single service for each repository.

Is it ok to have Service A make a call to another method in ServiceB? This would, of course, create a dependency on Service B in Service A(I am using interfaces and DI).

In my example I have a User service which handles, adding users, authenticating users, finding a user by ID, etc. I also have a Book service which allows me to add book for a specific user.

Should the book service make a call to the user service to retrieve a User instance for which to add books to?

Worldwide answered 26/10, 2011 at 18:47 Comment(1)
Yes, it's acceptable. Would you rather make the booking service use the User repository?Islean
P
9

Short answer: yes

A bit less short:

Your alternatives are to either let the "book service" directly access the "user repository" or to extend the user service so it is able to add a book - neither a good option... so it is correct to do what you describe (Book Service accesses user service)... a more "pure option" would be to create a controller/aggregate/transaction/coordinator service that uses the book service and the user service to achieve what you describe, this way both "direct services" (book and user) stay "dependency-free"...

Prefecture answered 26/10, 2011 at 18:56 Comment(2)
Do you have a suggestion regarding how to avoid a circular dependency? As the app grows, it may be convenient to have the user service reference the book service. Does the "pure option" avoid this? If so, can you help me understand how? It seems like an additional logical layer may be needed. Perhaps that's what you're suggesting above? But if it is just another "service" it seems like it might be easy to inadvertently add a circular dependency in the future.Kilian
The "pure option" avoids this... and you can think of it as service over services, more like a "use-case-oriented service/facade". It shields any consumer from the details and avoids introducing a dependency between book and user service. It makes the relationship between the 2 services explicit and keeps it localized to the specific usecase.Prefecture
I
1

Yes this is acceptable, as long as it makes sense to do so.

If the book service requires logic to run from the user service, and the book service does not call on the user service, you will have to duplicate the user service logic in the book service. This means that if your business logic changes for what the service logic does, you have to make sure to update the book service with the logic, or else you will have bugs and inconsistent (and unexpected) behavior.

However, if you find this happening a lot, you might have to start looking at what functionality each service does, and possibly break them apart into smaller services.

Informer answered 26/10, 2011 at 18:58 Comment(0)
D
0

User mentioned he was using EF. In this case he can either pass the User Object to the Book Service or the User Id and create a User Object in the Book Repository before the save.

Denominator answered 26/10, 2011 at 18:54 Comment(3)
And where would you put this method?Ochre
This is what I intend, but what would I do with the userID? Since I am using EF I need a User object to to associate the Book with...meaning I have to call the user repository at some point Should I call the user repo directly from the book service? This does not seem the obvious option to me.Worldwide
Oh, you didn't mention you were using EF. In this case you can pass a User Object to the Book Service or you could still pass the User Id and create the User Object in the Book Repository for the Save.Denominator

© 2022 - 2024 — McMap. All rights reserved.