You don’t need a service layer: Fat controllers are okay

May 22, 2011 – 5:51 pm Tags: ,

Here’s a counterpoint to the currently popular view of “fat controllers are bad”, and the current fad of everyone and their cousin implementing service layers:

You don’t need one. Fat controllers are okay too.

Why you don’t need a service layer

A service layer is an additional level of complexity in your application.

Remember the good ol’ KISS principle? Keep it simple, stupid.

There’s a lot of code in your controllers. Who cares? It’s easy to see what’s going on if you’ve structured them logically into actions and maybe a helper function or two if needed.

If you were to include a service layer, it would…

  • Cause a higher cognitive overload: It’s more difficult to see what’s going on and where, and to remember how things work without having to check
  • And add another layer of indirection – the only thing you can’t solve by adding more layers of indirection is having too many layers of indirection, so don’t add unnecessary ones.

You could say that having a service layer would make things easier to unit test. But you’re going to test your controllers anyway, right?

So go right ahead, start with fat controllers!

Start with fat controllers?

You may have noticed that I said “start with” fat controllers.

So what does this really mean?

It’s fine if you code your things in the controllers, but there comes a point when you should stop that.

The moment you realize you’re duplicating your code, stop and refactor.

This is one of the very basics of software engineering: Avoid duplication by creating functions and classes.

However, you don’t necessarily need to do this prematurely – Similar to prematurely optimizing, you should avoid creating classes or code that isn’t necessary.

This isn’t to say you should never start with a service layer – There are various reasons why you might want to start with it, such as when doing test-driven development or when you already know you need to use the functionality in more than one place in the future (for example if you also need a command-line script).

What I am saying is that you should not go and write a service layer just because you can or just because the internet says you should.

Also note that you can have other abstractions besides the service layer. For example if you use ORM, you can often utilize domain objects to avoid ending up with a huge mess even if you don’t have a service layer.

Conclusion

So it’s fine if you don’t have a service layer in your simple application.

Don’t put too many layers in place in an application that doesn’t need them – it just becomes more complex than it has to. You can always change it later if it grows beyond the point.

If you’re working on an application which is large, having a service layer is definitely advantageous for various reasons, like testability and reduced code duplication.

Always think “Do I really need this?” before doing something – Remember the YAGNI principle.

Share this:
  1. 40 Responses to “You don’t need a service layer: Fat controllers are okay”

  2. A rule of thumb I knew for deciding whether to introduce a Service Layer is “when you need to support more than one user interface”; in fact you make a good example with a CLI script, which is another interface. Other possible alternative UIs are web service/html with layour/ajax.

    By Giorgio Sironi on May 22, 2011

  3. … or you need to provide similar functionality within the user’s frontend and the admin panel at the same time which very likely means heaving two modules with a controller each. This is when it does make sense to add a Service Layer.

    By Michael on May 22, 2011

  4. Nice post. When I started reading I was worried about the duplicating code issue, but you addressed that nicely in the next paragraph. I think most “seasoned” developers include the service layer anyway, because they know most of the code will/should be duplicated otherwise, and then it makes sense to have all such logic in the same layer, and not distributed over multiple places.

    By Remi Woler on May 22, 2011

  5. I’m glad you wrote on the topic. I’ve seen some developers who feel that they are left out if they don’t implement the service layer. This is caused partly because the supposedly gurus recommend nothing other than service layer these days.

    By Sudheer on May 23, 2011

  6. Is this a joke?

    By umpirsky on May 23, 2011

  7. Thanks for the comments everyone.

    @Giorgio, that is a pretty good rule :)

    @Michael, also a good point.

    @Remi code duplication is one of my biggest annoyances, so yeah – I always recommend avoiding it.

    @Sudheer, indeed – I wanted to provide a different point of view on the discussion, since especially less experienced developers may get the idea that they always need to implement a service layer for their code to be “any good”.

    @umpirsky You may have misunderstood the post if that’s what you feel :) Feel free to explain why you think this is a joke

    By Jani Hartikainen on May 23, 2011

  8. I just must disagree. Since I don’t see any good reason to have anything fat, especially not controllers.

    By umpirsky on May 23, 2011

  9. I have to disagree as well, putting a lot of logic in your controllers means you’re probably going to have to do a lot of forwarding between actions or sully the process flow by making awkward calls to other controllers/actions.

    Like Giorgio said above, when you need to support multiple user interfaces having those services separated into their own layer helps a lot.

    By Cory Comer on May 23, 2011

  10. I think what Jani wanted to say is that if you need a Service Layer, go ahead and use it. But don’t use a Service Layer just because you can. The take-away here is to not over-engineer, never. Just build the stuff you need to get the job (properly) done. A well-skilled developer will realize later that it’s time to refactor business code and move it into a dedicated Service if there is a real, non-artifical need to do so. From this perspective, I do agree with this post.

    By Michael on May 23, 2011

  11. @Michael yep, that’s pretty much the idea – You should try to use your own judgement on whether you actually need something vs. just doing it ‘cos it’s cool or something.

    @Cory if your code starts to become like that, then you probably do need a service layer.

    By Jani Hartikainen on May 23, 2011

  12. @Jani How can @Cory make a fat controller then?

    By umpirsky on May 23, 2011

  13. I don’t know if there’s really a “how” to it… If your application doesn’t have logic that needs to happen in separate places, then it can work just fine with just a controller.

    This is similar to how you don’t always need an MVC framework in your applications, even though it might be nice to have one.

    It can be more straightforward or simply faster to not include extra things, although there is always a certain point after which not having those extras can become a problem (so you should stop and refactor when needed as mentioned in the post)

    By Jani Hartikainen on May 23, 2011

  14. As long as the fat controller is still testable, I don’t see any reasons to have a service layer. It is rarely the case however. I would say ‘Start with a test first’ and if you used TDD, you wouldn’t land on a fat controller in the first place.

    By Bulat Shakirzyanov on May 24, 2011

  15. The author of this post is obviously a extremely inexperienced developer. Regardless of whether you are going to support more than one UI, or if you have two places where you need common code, there are a number of other very real and inescapable reasons that you need a distinct service tier.

    The first is separating use-case from UI flow. By separating the two it keeps your session handling, redirect routing out of your representation of your business logic. Ideally, your controllers should be extremely thin, with only data transformational code and redirection as their purpose. In strongly typed languages, you can enforce better security by using data types in your service tier methods that physically can’t include some types of questionable input.

    Secondly, an important point of the service tier is that the publicly exposed methods of the service tier is where your unit of transaction atomicity begins and ends. By not having weird branching points due to presentation logic, you are sure that your transaction either happened, or it did not when the public service tier method exits back to its caller. By adhering to this approach the likelihood of inconsistent data in your persistence tier is mitigated.

    Third, with a distinct service tier your code becomes testable. You don’t have to simulate your presentation framework. The use-case tests become simplistic and don’t require the introduction of any additional concepts or dependencies. You are just testing for the single responsibility of the service tier method without all of the convolution.

    By Matthew Werny on May 24, 2011

  16. @Matthew Sorry, but I have close to 10 years in the industry, so I’m not sure if “extremely inexperienced” describes me very well ;)

    While you provide valid points, I think you may have slightly misunderstood the point of the post. You might want to read the rest of the comment discussion here.

    By Jani Hartikainen on May 24, 2011

  17. @Jani You just wanted to attract visitors to comment, didn’t you :) I saw many contraversal posts lately…

    By umpirsky on May 24, 2011

  18. I honestly didn’t think it would prove to get this much attention, but I had a feeling it might get a few comments :)

    I just wanted to put this on paper a bit better, since I had a thought that you didn’t necessarily need a service layer in every case. (Mentioned it shortly on twitter maybe a week or so ago :) )

    By Jani Hartikainen on May 24, 2011

  19. I have a problem with title of this article. I do feel that you don’t need service layer by all means but on the other hand you definitely don’t want fat controllers either. To put this in other words if you end up with fat controller then you probably do need another level of abstraction in your application (whether that should be a service layer or something else depends on specific situation).

    P.S. I have seen much talks about service layer this days and they often had nothing to do with service layer, so here is an interesting definition to show from which perspective I’m talking here

    By Gosa on May 24, 2011

  20. Nice counterpoint. I don’t disagree with you in general, but I’m concerned that the word “model” does not appear on this page at all, blog or comments.

    Have the CRUD MVC frameworks really convinced a generation that models are purely for automating database access, and that the only alternative to fat controllers is a Service Layer?

    By Simon on May 24, 2011

  21. @Simon
    Exactly, and I would add whole “domain layer” that should represent you application is somehow neglected when talking about OO design and principles in context of frameworks and MVC, somehow frameworks tend to occupy our minds more then it should, we should really be thinking about given domain problem and solve it best we can and think about its place in MVC (or what ever) framework afterwords, but this is easier sad then done especially in current “agile era” :)

    By Gosa on May 24, 2011

  22. @Simon database access isn’t mentioned on this either :) But yeah, when you talk about “model” or “models” a lot of people would automatically assume an active record object or such.

    I was personally mostly thinking this article from the point of view where you have domain objects and ORM.

    If you had no abstractions at all (eg. straight SQL or whatever in your controllers) it would indeed make having a “fat” controller a poorer choice than with at least some abstraction.

    By Jani Hartikainen on May 24, 2011

  23. Overall, I like this article and the discussion behind it. It brings to light the fact that there are several different scenarios at play.

    1 – I know re-use is paramount because I must support an admin, front-end, CLI, and likely a Web Service API. In this case, I must start with a service layer. Also, if I’ve solved this problem before (at another company, for another client, etc.), I know the use cases, I’m using TDD, and it is clear that I need to abstract from the start.

    2 – I know re-use is paramount (for all of the same reasons as #1); however, I’m not sure how to implement the features so I use TDD to add features incrementally — this could be directly to the controller, this could be small helpers. Once I start to integrate the functionality, I can start organizing into services (but I probably already have most of the services I need because I used TDD).

    3 – I am a beginner, I don’t know how to do TDD, so let me start with what I can grok. Add everything to the controller (if I am disciplined, I’ll re-factor to services, otherwise, the controller will stay fat).

    There are more scenarios — no two developers are exactly alike but I believe the above three captures most cases.

    By Wil Moore III on May 24, 2011

  24. I disagree with the post.
    First of all, you don’t have to chose between fat controllers and having a complex service layer in your application.
    As you said yourself, if your controller grows to complex, you can create a helper function and multiple actions.
    Which is true, but if you do that, why is that better than having those in their respective models/helpers at the first place?

    it’s not a coincidence that the current best practice is that your controllers should be skinny.
    http://www.youtube.com/watch?v=91C7ax0UAAc
    1, having skinny controllers can save you from code duplication
    2, having skinny controllers makes your code more testable (testing controllers usually require more complex bootstraps), because you can test your business logic through your models.
    3, having skinny controllers makes your code more readable, because you see the high level stuff there, and not the implementation details.

    so while I’m agree that one can save some time in some cases if he just throws together some prototype code in the short run, but he should be aware that it is technical debt, it will be harder and harder to maintain the code, if he isn’t willing to pay the interest.

    Tyrael

    By Tyrael on May 24, 2011

  25. @Tyrael:

    You make a really important point in your comment.

    “…one can save some time in some cases if he just throws together some prototype code in the short run, but he should be aware that it is technical debt…”

    For this reason, those that dislike this article, I can see your complaint. Developers looking for a _reason_ to cheat/cut-corners may see this article as ammunition. That being said, I personally take the article for what it is is (a different look at something). I don’t care about developers using this article as ammunition because those that design sub-par architectures will find a way to justify it no matter what. Let’s not blame the messenger :)

    By Wil Moore III on May 25, 2011

  26. @Jani – Just because you have been in industry for 10 years, doesn’t mean you learned how to avoid code debt by properly separating your concerns.

    Just because you put out your sign as a free lancer saying “Look everybody I’m a programmer” doesn’t mean that you know what you are talking about, or that you’ve had enough time working in systems that other people have left to you that were ill informed enough to do what you are promoting, as well as other hair brained ideas that rack up code debt.

    I think it’s great that you’ve set up a blog and are exploring new ideas, but as your resume indicates, you’ve really only be doing it for a little over 3 years and are just cutting your teeth. Be very careful how and what you say, because as a previous posted pointed out that developers that are looking for a way to half do things will go “Look see this guy said it was ok. I’ll go ahead and do it this way.” and completely make a mess because they were dumb enough to listen to your naiveté.

    By Matthew Werny on May 25, 2011

  27. @Tyrael I was speaking about not having a service layer, not about not having any sort of domain objects at all :)

    @Matthew If you want to sound smart, please stop judging people based on a single blogpost. None of what I said here racks up any code debt – maybe you missed the part where I said when you start getting such you need to stop and refactor?

    By Jani Hartikainen on May 25, 2011

  28. “@Tyrael I was speaking about not having a service layer, not about not having any sort of domain objects at all ”

    the title tells otherwise, this is why I think that this article is an intended flamebait.

    Tyrael

    By Tyrael on May 25, 2011

  29. I’m not quite sure what it is with the title but fair enough. Articles which are against the common opinion probably often seem bit flamebaity, but at least I try to give a balanced idea by providing example cases where what I’m saying here is not true etc. :)

    By Jani Hartikainen on May 25, 2011

  30. the problem with the title is that you suggest fat controllers.
    which is ~ equals to “not having any sort of domain objects at all”

    Tyrael

    By Tyrael on May 25, 2011

  31. It appears to me like the useful part of this post may have been lost on some of its readers!

    There is a phrase which sums this all up quite well. “Its as good as it is useful”.

    In some circumstances, a service layer is bound to be overkill. If you are working on a short lived promotional / marketing site, or a simple site that will receive very little maintenance, then why spend a not-insubstantial amount of the overall time needed to make the project working on a service layer, which in all honesty, your not going to take advantage of.

    While I strongly feel that a service layer is a very good idea, I also agree that some people are taking it to another level, and using it everywhere, instead of only where it is useful.

    Overall I think this is a great post by Jani, and he did sum up quite well, “it’s fine if you don’t have a service layer in your simple application” … “If you’re working on an application which is large, having a service layer is definitely advantageous”

    I hope that the flameing in the comments here doesn’t continue, and detract from what is essentially only a sanity check, and nothing more!

    By Ryan Mauger on May 25, 2011

  32. Way to go, Jani!

    I take the idea of the post to be more about learning, about encouraging an iterative refactoring process for non-experts.

    Sure, we all know about thin controllers, fat models and service layers. These offer real benefits to testability, DRY-ness, SRP, etc. These are all Good Things ™.

    But sometimes for beginners, getting one’s head around it all can be difficult. Sometimes, to get moving forward, it’s helpful to simply walk through what you need in a fat controller – evil as that may be – and then let the development process itself lead to the realization: “Man, this seems familiar. Didn’t I do nearly the same thing just a minute ago? Guess I should push this processing down into a model or into a service or some damn thing.”

    The goal is definitely best practices. But I think it can be helpful to allowing people – especially non-experts – to move in that direction in an iterative fashion.

    Now, off to write some aspirational code: models, mappers, and services. ;-)

    By David Weinraub on May 25, 2011

  33. @Tyrael I’ve added a sentence into the post to hopefully clarify the fact that you can have other things besides a service layer.

    Also thanks to everyone else for your comments. I think the comments may have become the best part of this post :)

    By Jani Hartikainen on May 25, 2011

  34. Well, nice one… I cannot say that I completely agree with the “fat controller” thing but unless you really need it I think every layer that you add to the software makes it more complex and costly too, so should be avoided…

    Every minute that the developers spend increases the cost and the overall time so adding lots of additional classes means more typing, more time spent on organizing the code and reduces the readability too which makes it relatively harder to adapt if some programmers get involved later…

    So if the software is not so big go ahead with the fat controller. Well, let me call it “plump” maybe, not fat. If it’s getting fat or it’s clearly obvious that it’ll get fat than a model class is enough, which handles the bussiness logic… Actually you may call it a “service layer” anyway to make it sound cool :) A service layer w/o any other layer beneath it :P

    I’m working on web projects for more than 15 years now and never needed mappers, DAO’s, service layers and other “cool named” stuff… I think it depends on WHAT you are programming. Unless you’re working on a really large project it’s trivial to go with lot’s of layers…

    By m.ozan hazer on May 25, 2011

  35. This is a personal view.. for small application it is fine to have fat controllers (very small applications :)). From medium to large applications, I prefer service layer. I consider service layer as the boundary for my application. Controllers and views should act like an external application which uses service layer as an interface to interact with my application.It helps me to expose my business logic as an API to out side world in many cases………

    By Vijay on Jul 9, 2011

  36. Remember the “old-days” when every page was presented with single PHP page/script that contained all the actions, formatting and logic and PHP hadn’t ever even heard of MVC. Fat controllers are approach towards that legacy. But as the software you’re making ain’t big, go ahead and make them fat. No need to make it bulk because you can, YAGNI :)

    When using Services with large libraries, it creates one more layer of complexity but also creates an uniform Gateway between namespaces, and we want support loose coupling between classes. Business object should not use another object from another namespace but ask a Service to do it.

    Using Services, making Controllers fat is really up to if you’re working with 1 month projects or developing ever lasting systems.

    By Niko Kivelä on Jul 17, 2011

  37. I’ve been reading a bit recently about IoC containers, Dependency Injection and service layers – pros and cons. It seems that quite a few people enjoy using the architectural patterns involved. Perhaps it becomes easier to grok the code when one always follows a set of popular patterns?

    I believe one should solve the problem at hand. Sometimes even a Stored Procedure in a proprietary language could be the solution, even though that completely trashes a bag full of best practices and patterns.

    In the end you will have to compromise, sometimes getting your way and sometimes not.

    By Arne Evertsson on Dec 30, 2011

  38. Do we not have enough obesity in the world nevermind passing it onto our controllers? I would advocate you have thin controllers and do create a service layer.

    Layering is an important role in software design and development as it separates responsibilities and allows for cleaner code – yes there is some more complexity however if you cannot handle that you shouldn’t be developing software should you?

    Trying to reduce complexity at any level will always have a knock on effect elsewhere such as quality so at the end of the day it’s the client who suffers.

    So shame on you for giving bad ill formed and thought out advice.

    By Les on May 24, 2012

  39. @Les, let’s say you’re creating a one-off quick app prototype. It isn’t going to be particularily useful to build a dozen of layers into it, now is it :)

    There is no one perfect way to build software. My advice is always quite thought through, perhaps you should also put some thought into your comments before posting them and you might find an actual flaw in it next time ;)

    By Jani Hartikainen on May 24, 2012

  40. Excellent post!

    I see everybody is saying “fat ugly controllers are evil!”, then I look at my controller: yes, it’s fat (let’s say 500 LOC), but the code is clear, nicely structured, there is no duplication and there are no other clients (methods external to the controller) who would need to use this code, these functions. Then what would become better if I just move these functions into some service class in the model?
    I doubt that it will give me any REAL PRACTICAL benefits.

    I thought that maybe I’m just too stupid to understand all the evilness of fat controllers, so I tried to google and immediately found this article :)

    I think that you need to move a method out of a controller when you also need to use this method in some other place. In this case – yes, move it to a model (or some service class in a service layer) and call it both from your controller and from that other place where you need it – that’s all, problem solved.

    The most important thing is:
    When someone says you must implement some pattern, or follow some principle (like “avoid fat controllers”) you should always think what real practical benefits you’ll get. Do you really have a problem and that principle will help eliminate it? Or maybe there is no real problem? When someone tells you to follow some principle (again, being it “avoid fat controllers”, or SRP, etc.) let that person PROVE that you have a REAL problem in your code and that his suggestion will make your code better ON PRACTICE. If he can’t prove it, then there is a big chance that your code is ok and that person just likes patterns and principles, without realizing whether they are necessary or not in a concrete situation.

    By Pavel on Jul 27, 2012

  41. Pavel, thanks :) I always try to advocate good programming styles, but I also try to keep things so that they are giving practical benefits and not only for sake of it being the “good thing to do” if it doesn’t help solve a problem.

    By Jani Hartikainen on Jul 29, 2012

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)