120 lines in one action. Order confirmation: load the order, charge the card, send the email, render the page. It ran fine for a year. Then a console script needed the same operation, and the action turned out to be glued to SMTP, to the database and to the HTTP request. All at once.
Symfony people talk about dependency injection so much it sounds like religion. It is one simple idea: a class receives its dependencies and does not create them.
In Kohana we usually do the opposite. new Mailer() right in the action. ORM::factory('Order') wherever we need it. It works. Until the day you want the logic somewhere without a request.
So I took that action apart, one piece at a time.
The mailer goes behind an interface and comes in through the constructor. Order loading goes into a repository class. The business operation itself, confirm, charge, notify, becomes one service class with one public method. The controller keeps maybe ten lines: read input, call the service, render.
Nothing here needs Symfony. The container only removes the boring wiring code. You can do the same wiring by hand in any framework, in one factory file. I did it in Kohana, by hand, in an afternoon.
One thing I disagree with in most DI articles. They sell testability as the main goal. For me testability is a side effect. The real goal is that dependencies are visible: you open the constructor and you see what this class touches. No surprise on line 87.
Explicit is better than convenient. Most days.