What should 'Service Layer' do? (MVC; layered architecture)

- I'm working on an MVC project, and from the controllers I'm using different services. As you can see in the screenshot, this services are Operation, Admin and Account, and they all are in the same layer. Models, controllers and views are inside the Web layer/project. - What I've learned so far while reading here and there, is that service layer contains CRUD business operations, using repositories (Repository Pattern and Unit of Work in my case). And the business rules are contained inside those operations (though I may be wrong on this new learning). - On some other place I've read that business rules belong to the 'Business Layer', and the BL may or may not be implicitly contained in the 'Service Layer'. Moreover, may the BL be a DLL (for example) outside of the SL. Hence, my questions: - What is your experience regarding the implementation of Service Layer? How do you implement it (the best)? - What do you think are best practices regarding this topic? - Is it the same 'Business rules' than 'Business logic'? - My main problem with most of the information I've found is the lack of actual and simple real work examples (like this line I read in some answer at SO: "For example, a book library lending a Book to a Client (with corresponding Inventory changes) might do so from a domain service." This is just one of the (not completely helpful) readings I made: https://stackoverflow.com/questions/2268699/domain-driven-design-domain-service-application-service Probably there's some (or a lot) on non-sense in this post. Keep in mind I'm barely starting, and there's a lot of information out there, even contradictory. At least that seems to be the landscape for me in a somewhat shallow research in the internet.
Stack Overflow
Domain Driven Design: Domain Service, Application Service
Can someone explain the difference between domain and application services by providing some examples? And, if a service is a domain service, would I put the actual implementation of this service w...
16 Replies
Becquerel
Becquerel2y ago
you won't find simple examples of this kind of architecture because it's not meant for simple projects - it adds too much complexity to be worth it which is why I always suggest seriously asking if your project is going to be complex enough to support this kind of involved architecture up front (you can always refactor later!) I would personally separate CRUD and other forms of data access from your business logic - if that separation takes the form of different projects or 'layers' is up to you
BlueJayBird
BlueJayBird2y ago
In that case, were would you place the business logic and why?
Becquerel
Becquerel2y ago
in its own section, with as few dependencies as possible
Esa
Esa2y ago
I usually work with 3 layers, where the CRUD is in the data/integration layer. This is not directly contained in the business layer, but the business layer calls it. So we have a distinct separation between service layer and data/integration layer. This is to create an abstraction between the what (the operations / service / what you want to do) and the how (sql / soap / rest / graphql etc). The service layer holds the method calls needed to execute business flows. If one service layer flow is to ActivateProducts(customerId), then that layer may call Integration.CustomersService.GetCustomer(customerId), Integration.AccountService.GetCustomerProducts(customerId), Integration.AccountService.ActivateProducts(productIds). All these integration services can be considered data layer as they're the final point of contact for us before entering into a different system. The reason is mostly separation of concerns.
BlueJayBird
BlueJayBird2y ago
@Fyren Ok. Thanks for all that information. I have some additional questions for you. 1) The third layer you not mention is the Presentation Layer. Right? Should I expect to have an MVC project there? 2) ActivateProducts(customerId) could call from the controller? The call would be made like this: Controller → Service layer → Data layer 3) I don't get the Integration. part from your example. I thought it was the actual Data layer, but it looks like something else since it is using the Services.
Esa
Esa2y ago
1) - I haven't used that term myself. Mostly in my work I've had Controller, Service, DataAccess and/or Integration. Keep in mind I work only with backend, not full stack. 2) - This is exactly right. But make sure your dependencies dont flow through. I.e. your controller layer should not have any using directives that belong in the data layer. If you mean to return an object through your controller, it must not be an object from deep inside your project (don't return a data object directly or a service object - it should be one from the Controllers/Models folder preferrably). Edit: this means you will need to map objects, which can be a hassle but separates responsibilities. 3) - These layers do not have to be called exactly the same things as you read in examples / best practises /books, but they essentially mean the same. In my example Integration represents an external system I've integrated into my project. It doesn't matter if it's a web api, SOAP service or database, it's something I've just named Integration. Because it is an external system, I need to treat it similarily to how you treat a database.
BlueJayBird
BlueJayBird2y ago
Ok. Thanks for that, @Fyren. One last question, about the naming of my services (I didn't name them).
BlueJayBird
BlueJayBird2y ago
I understand that account services are provided for users when dealing with their accounts. But...
BlueJayBird
BlueJayBird2y ago
What's the exact difference between Admin and Operations? Honestly I'm pretty clueless about what they are supposed to do, and I can't way clearly from the actual methods that can be seem in the code of those files. My best guess is that I need to dive into DDD concepts on services, but I'm barely learning about them.
Esa
Esa2y ago
Depends. Maybe your API exposes some functions that requires elevated user rights, such as an endpoint for modifying accounts. That sounds like something an admin should be able to do. OperationsService could mean anything, it's hard to say. In development "operations" usually pertains to the life cycle of something, but it could also mean "the operations you can perform with an account" etc, that requires a bit more context. Could really be anything, but these two are my bets at least (which is generic enough as it is). Theres a book named Domain Driven Design which is really good, I do recommend that one. It gets a bit dry by the end, but it's still very good.
BlueJayBird
BlueJayBird2y ago
I'm reading right now "Implementing Domain-Driven Design" by Vaughn Vernon. The one you mention is from the same author I think.
BlueJayBird
BlueJayBird2y ago
This is from the book. Probably this should lead me in the right direction.
Esa
Esa2y ago
Yes, this is exactly right Allright, let's go back to my original examples.
OrderManager
Service
OrderService
Integration
IntegratedCustomerService
OrderManager
Service
OrderService
Integration
IntegratedCustomerService
So in this example, I am hosting my business logic of OrderManager inside OrderService. With these terms I mean to imply a service that does order business flows. CreateOrder, CancelOrder, AuthorizeOrder etc. strictly speaking business stuff. It is as such a bit more high level - it does not care about how these orders are carried out. So OrderService calls IntegratedCustomerService which is where you see the implementation details of carrying out those requests. This is an Application Service from your example text. It contains the necessary methods to interact with the application (or integratedCustomerService) to carry out the business flows as written in OrderService. So it is
Controller
Domain Service (business)
Application Service (data/integration)
Controller
Domain Service (business)
Application Service (data/integration)
I realize this can get confusing, but thinking in terms of "what do I want to do" and separating it from "how do I want to do it" may help
Mayor McCheese
model service classes can be the start of a trip to god-classes; I tend to avoid using them in favor of purpose driven classes; you end up with a lot more classes that way, but they're smaller and have minimal mixed responsibilities.
Esa
Esa2y ago
@M11e I've thought about this too. Does that mean stuff like CreateCustomerProcess.cs and CancelCustomerProcess.cs instead of CustomersService.cs? I've usually opted for the model service classes for unrelated reasons, but I'm at a point now in some projects where they start to surpass 800+ lines of code. The purpose/process driven classes could be contained at 2-300 tops I suppose.
Mayor McCheese
I’d say just CreateCustomer But yes