Making them reusable isnt the main goal. But by making them thin its easier for them to be reusable, but of course also easier to re-implement them from scratch. It works both ways.
Well, as far as ZF is concerned. We write integration tests for everything, so spotting a regressing is easy.
I'd say, 70% of the logic comes in a controller plugin of some sort, so there's not too much boilerplate, unless you call a 'setup' (well, in ZF words: init()), boilerplate. The rest os older stuff which we haven't got around to refactoring yet.
The tests really help with refactoring or exchanging dependencies etc.. And at the same time, because the code is very explicit.
Missed half of what I wanted to add.
os = is
And the code is easy to understand because it's explicit. ;-)
Lukas has raised some advantages of using controller as a service.
Other than the bit of extra work involved, are there any drawbacks from a code design perspective, to defining the controller as a service?
When programming OOP i follow the rule: "When my IDE cannot help auto completing I'm using bad practice programming". In other words I fully agree with this blogpost. I am choosing Symfony because it claims to be using best practices, however the standpoint of fabian and Co. makes me a bit worried. I don't understand why using the approach of controllers as being services is even a discussion. For me having to adept to a framework not being able to use the a construct function as i would use is very inconvenient to say at least. Also, as a former framework developer of my own i intend to first walktrough the bundles i plan to use, the DIC, as it is currently implemented makes this too hard. Also, i hate requesting the container for every single action i Do. Why would anyone want to use get(container)->request when you could have a much cleaner this->request, cleaner, fully IDE compatible, giving much better overview and being much closer to the way people already programm using no framework. Again i cant believe this is even part of a discussion. The container fails, even to new people using symfony2 (as this seems to be the only reasoning).
Argh, i should leave this for now and should enjoy my holiday in Greece.
@keymaster: there are a couple of drawbacks to defining controllers as services:
1) you are forced to write boilerplate code to handle the injection as well as the configuration of the service itself
2) you cannot lazy load services
For 1) I actually don't think its an disadvantage. The configuration file helps be keep an overview of the dependencies. This is even cooler given the DebuggingBundle, have a look at this screenshot. This Bundle gives you livesearch across all defined services showing you a graph of the dependencies.
For 2) in 99.9% of the cases the need to lazy load services is a good indicator that your Controller does too much.
Another approach which basically tries to combine some advantages of the approaches mentioned here, is to use the DiExtraBundle. This will allow you to define your dependencies explicitly without defining your controllers as services.
Its a step up in some ways, but it doesn't let you adjust the dependencies from the outside.
Yes I want DIC with my controllers for two reasons: Consistency and Type safety.
If you use DIC throughout the code to configure your objects why not with your Controllers as well? Why should I teach my devs multiple ways how to deal with dependencies in my application? This seems to obviously wrong and error prone. Sure in many most cases you do not need to reconfigure a controller in a different context and since the controller layer is quite thin (actually should be) it probably makes no sense to test it. BUT you should test it anyway, it`s code, it`s in your project, it could break, so write a test for it, thus you need a DIC. Sure you could test the code above as well since the objects get pulled from the DIC but this is no good style.
Type safety is awesome. In the code above when you try to access the templating object by using $this->container->get('templating') you cannot be sure what you get in return. If you make sure that you have set-up type hinting for for constructor and setter methods, it will result in much cleaner and much easier to understand code. If I see that the Controller needs an instance of the Templating interface, I know what to search for. In the example above I do not have a clue what to search for. In fact I need to scan the code completely to locate the position where the templating-alike object was pushed into the registry to be able to see what kind of object we are dealing with.
And one more minor thing: In the first example above you do not get th benefit of code completion because your IDE does not know anything about the object was was accessed by the key "templating".
Just my ideas from my experiences with DICs, frameworks and applications and yes we could reuse controllers multiple times in the past, in most cases with add/edit forms where the basic control flow is the same but in some cases need to deal with minor differences.
One more thing that just came to my mind:
The thinner the controller the more likely is it to reuse that component. Think of a controller that is responsible to delete an object from an data store. The controller grabs the id of the record from the request and passes it to the delete method of the service. This logic is so abstract that it could be reused for user objects, order objects and most other objects from your application. So you need just one implementation and just by configuration you are able to use that code in different contexts.