Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 best practice, business logic and unit test

I'd like to create a highly maintainable code, with unit tests.

I have read the best practices so directories are organized as per best practice, with just one bundle named AppBundle, and I'm using annotations.

I have an issue with business logic. I've read that I should not put business logic inside controllers. As the vast majority of my code was not meant to be reused I put the logic inside the controllers. Yesterday I read here that "logic should live in the controller unless you’re going to unit test it or until you need to re-use it" and this made me faint: am I not going to unit test if I put my logic inside controllers?

I understand that "controllers should be as lean as possible, with few lines of code to glue stuff together". But what about forms? A form often has a logic like "display the form, if it's valid do something and display another page". Now if I'm going to put the form creation and logic inside a service (or a model?) I'd have to put the page render command inside that, so basically the controller would be 1 line, with all the rest inside the service, and the actual decision of which page to display would be done inside the service, not the controller itself...so what's the point of a controller, just the routing?

I really need to understand this before proceeding (i've already developed 3 months on this and I'd have to rework a lot, but better now than never)...

Thank you!

EDIT: some additional considerations to address some of the comments below.

I have a clear understanding of how forms work in Symfony, with the creation of the form and it's management with the "isValid()" in the same place.

Let's imagine the following controller which performs the following operations:

get the current customer from security context
queries the DB to get the field $user->getIsBillable()
if the user is not billable
    queries the DB to find if someone else is paying for him
else //the user is billable
    create and manage form1
if the user is not billable but there is someone who is paying for him
    check if the license is active (I have to call an external API)
    if the license is not ok
        redirect to a page to update credit card info
if the user is not billable
    create and manage form2
else
    create and manage form3
render the license management page with all the necessary forms created  

What would be supposed to do? Put all this stuff into a service which would return the forms (or null if a form is not created)? Consider that in the "is valid" of some of the forms I render the same page with simply updated info. Or should I create a service foreach of the forms creation and keep the logic in the controller?

like image 550
Sergio Negri Avatar asked Dec 25 '22 21:12

Sergio Negri


2 Answers

You should keep your logic outside the controllers in order for your code to be more reusable and to reduce code duplication.

The best practice is to have your business logic registered as a Symfony service instead. The controller should be as lean as possible as it only handles the view and accessing your services to run business logic functionality.

Using services will make your code more reusable and it will be easier to write unit tests for each part of your code.

Forms are handled in a different way in Symfony2 and you should read more about it: http://symfony.com/doc/current/book/forms.html

like image 94
D_R Avatar answered Dec 27 '22 21:12

D_R


Like most php frameworks, symfony2 has its problems.

Turns out symfony2 best practices are not always best practices. But in most cases symfony allows for loose coupling and proper dependency injection, it just doesn't tell you in the "book".

For example a very important topic: http://symfony.com/doc/current/cookbook/controller/service.html

I usually have my form types as services, my controllers as services and other services for the business logic. My controller actions are ideally around 3-5 lines of code. Sometimes when handling a file upload they will be slightly longer though.

You can unit test your business logic services, but for your controllers and forms you will need some sort of integration testing, or use heavy mocking.

I understand that "Selenium" is a good tool for testing such things, I haven't used it yet.

like image 28
Marcel Burkhard Avatar answered Dec 27 '22 19:12

Marcel Burkhard