17

If a controller gets too fat and model instantiation starts to add up, a service layer could be used.

  • If I just wrap the logic inside a service class, I will get a bunch of Services with one/two methods. This feels like a code smell. Any best practices regarding this?

  • Can a service instantiate models?

  • If a service instantiates models, the services can't be unit tested. They can only be covered by integration tests?

4 Answers 4

27

In 'SOLID' the 'I' stands for Interface Segregation. The whole idea of this principle is to split large interfaces into smaller ones, more modular. In MVC service would normally have an interface that controller would rely upon. You don't want your controllers to know about concrete implementation of that service. Therefore, a bunch of services with one or two methods is a good thing to have.

Services normally return DTOs in large applications or domain models directly in smaller applications. DTOs normally means more work, but better separation of concerns. The typical flow is:

  • Controller calls service
  • Service returns an object (be it a DTO, domain model or something else)
  • Controller maps DTO/domain model to a view model

Mapping can be done manually, but most developers prefer to use auto mapping framework such as Automapper because we don't like writing plumbing code and we can be quite lazy :-)

http://en.wikipedia.org/wiki/Interface_segregation_principle

https://github.com/AutoMapper/AutoMapper

One of many discussions on stackoverflow regarding use of DTOs and domain models: https://stackoverflow.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer

4
  • 1
    I would be careful using an auto mapper here uglybugger.org/software/post/… Sep 24, 2014 at 1:05
  • AutoMapper comes with a built-in unit testing functionality which allows you to verify all your mapping routines with one line. Author of this post did not mention that.
    – CodeART
    Oct 22, 2014 at 15:54
  • But he does know about it, and has used it. The comments go into this a bit. Oct 23, 2014 at 0:20
  • 3
    Lots of classes with only one or two methods usually means they are not cohesive. A service layer, if it exists, should be thin with the bulk of the logic being in the models. It seems rather pointless to bind a view to a dumb object which is nothing more than a property bag. The model in MVC should be the rich domain model, not an anemic one martinfowler.com/bliki/AnemicDomainModel.html
    – Andy
    Nov 10, 2014 at 1:18
3

In MVC the Model, is not just a DTO or set of Managers/Services it is meant to represent the concepts your application is modelling. You can think of this as the entire domain or the business logic including state and behaviours. Now given that we know that the purpose of the controller becomes a bit clearer. It's job is simply to translate commands onto the Model and the result back onto the views. This is usually done in the form of ViewModels which are different but often confused with the Model in MVC.

If you don't have a well defined Model then you may have gotten to the point where most of that logic now resides in the Controllers themselves. At this point in order to start reducing the size of your controllers you can start to pull this logic back into manager or service objects. These services typically return and operate on DTO/Entity like objects. Then the controller becomes the mapping layer between these services and the View Models. For a few good tips on mapping have a look at this article Friends don't let friends use AutoMapper.

As for your questions, the first one depends a lot on your applications. You'll need to do refactoring along the way which should become more apparent once you've removed the logic from your controllers. As for testing there is no problem instantiate models inside services however if you find it testing difficult it's probably just a sign you need to break up the service into smaller parts each with a single responsibility.

3

Controllers should only contain calls to the model (where the business logic happens) and based on those calls assign data for the view (objects of information or error messages) therefore controllers will be quite small even for a very complex page, if the controller still gets very big you should think that maybe that page should be expanded into more pages.

Still the model can be quite big... the solution I found was having a variable inside the controller that tells what model to load and for specific tasks I load the specific model.

Try to obey the model-view-controller model clean like this:

  • view: displays data
  • controller: collects userinput, asks model for the requested data and sends it back to the view
  • model: interacts with database and performs logical actions to prepare information
-1

I find services really helpful to perform logic that may need to perform by more than one controller or that is just not specific enough to be part of the controller, besides the fact that it stops my controllers of getting too big and hard to read...

I personally disagree with 'aaa' when he says that "model (where the bussiness logic happends)" since thats the whole reason you have controllers, in my opinion models need to be simple data abstractors so controller can perform the needed task; again services should not get involved into data abstraction task...

just saying yo....

1

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.