2

I have a web application implementing the MVC pattern where I have controller classes whose methods each map to an HTTP request.

I also have a service layer with a bunch of service classes, with each service class typically containing operations specific to a particular domain entity.

For simple logic (like CRUD), one controller method typically uses at most one service class and usually only one method on that service class.

My question is how to handle logic that involves two (or more) entities.

The options I see are:

  1. Let one of the existing service classes handle the entire logic.
  2. Create a new service class dedicated to handling logic like this.
  3. Still use the existing service classes but put the orchestration logic in the controller. The controller still delegates the "meat" of the logic to separate services, but it would take care of things like sequencing and deciding at what point(s) to commit changes.

I'm currently favoring option 3 but I would like to know if there is a better way. Please feel free to add any option that I have not yet listed.

5
  • 1
    In my view, M/V/C are elements of the user interface. The actual business logic needs to be outside of these. Oct 7, 2016 at 8:50
  • I agree. All the options I listed put the business logic outside the controller. (Well, it depends whether you count orchestration as business logic or not.) Do you think orchestration should be considered as business logic? Oct 7, 2016 at 8:55
  • 1
    If several business logic components or models are being orchestrated to the end of properly updating persistence, that is also likely business logic, and particularly so if the update has a transactional or atomic requirement.
    – Erik Eidt
    Oct 7, 2016 at 15:31
  • 1
    Option 2, unless option 1 makes more sense. Option 3 and your controller starts losing its "single responsibility".
    – Spivonious
    Oct 7, 2016 at 20:55
  • Are you creating a brand new abstraction that uses your existing ones (option 2) or is it very closely related to an existing one, but a bit more complicated to involve several other services as well (option 1). Just because it's doing some orchestration that does not mean it needs its own business layer.
    – c_maker
    Oct 9, 2016 at 9:40

2 Answers 2

3

An important guideline in deciding where to place code is to keep all code in a single class at the same level of abstraction. In your case, in a typical MVC application the controller operates at a level of abstraction where it makes connections between components and transfers data between them. If an existing service class has a similar level of abstraction then it may be a good fit there, but by your description ("orchestration" sounds like it manages the existing services rather than doing similar things to what they're already doing) it doesn't. So I would suggest creating a new class for it.

1
  • Thanks for the input. Yes it does seem that the controller is at an abstraction level that is too high and my existing entity-specific services are at an abstraction level that is too low. A new class at a "medium" abstraction level (that is what you are suggesting, correct?) could be what's needed. Oct 7, 2016 at 9:18
2

I would not recommend you putting the orchestration logic in a controller,
reason being the controller should just delegate calls to a service and send the appropriate view to be rendered.
Also when you have the logic in a service, you could have other controllers using that service as well
and you thereby gain reusability.
However it is difficult to say if you need a separate service just for orchestration without looking at the code.
In most cases a single service would need to use/orchestrate with multiple other services to serve a request.

4
  • Thanks for the input. Do you think that a controller method should call at most one service? Oct 7, 2016 at 7:57
  • again it depends, say you have a logger service that's logs requests, then first controller might invoke the log methods and then pass on to the business service.
    – Vignesh.N
    Oct 7, 2016 at 8:04
  • Okay. The way I understand your answer is, if there's logic that's not directly related (such as logging), then it's okay for one controller to invoke multiple services (equivalent to option 3). Otherwise, choose either option 1 or 2. Is that correct? Oct 7, 2016 at 8:13
  • yes, as long as there aren't any business logic in controller. even things like logging could be handled by middlewares in the request pipeline, but In some cases you might want to invoke some services which is not really a business service.
    – Vignesh.N
    Oct 7, 2016 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.