tags:

views:

282

answers:

9

In MVC architecture lets consider django:

I have a method to calculate best employee of the year (1000 lines of code with a complex logic), where should I define it and who will call it?

Thanks

+3  A: 
  1. putting logic in View will not allow you to write unit tests easily and can't reuse effectively.This says that you should never put the complex logic in a view you should separate it from the view.
  2. If logic is closely tied to a (class/objects of a class) putting that logic in the model makes sense.
  3. In case the logic is closely tied multiple objects/classes you can use one of the model to put logic or you can create a service object (or when the code is too huge) which will handle this logic.
Rama Vadakattu
A: 

In a MVC architecture, the business logic must be implemented in the controller.

This might be a bit confusing with Django, because the controller is called the view and the view is the template. In fact, django is sometimes called a MTV architecture (Model-Template-View) rather than a MVC (Model-View-Controller)

See the django FAQ and the django book

So your logic, should be placed in the views.py file (not as a view itself) or in an external module. For a huge amount of code, a dedicated file is certainly a good idea. A view will be in charge to call your code. Of course unit-testing of the code must be taken into account in the design, that's why your code should'nt be a view itself (the http stuff makes it more difficult to test).

In my opinion, if you put in the model it breaks the MVC rules especially if your code is pure logic with low dependency with the model. Personnaly, I prefer to keep only database related code in the model.

luc
+8  A: 

As for django, the best place to put business logic is inside models. The view should be clean from business logic and should only be used to get the data to be displayed/presented on template or in other words let the view be used for view logic only.

From django FAQ:

In our interpretation of MVC, the “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it. It’s a subtle distinction.

By putting your business logic under models, it will lead you to unit test easier because models is not coupled with HTTP methods or processing.

jpartogi
A: 

With regards to your specific example "a method to calculate best employee of the year (1000 lines of code with a complex logic) ... where should I define it and who will call it?"

For that much code, I would probably make a new module (perhaps ranking.py) and put it there. Who will call it depends on how you use it, but I would guess that it would be called from one of your views.

Wogan
+4  A: 

I concur with those who think that such logic should be placed within the models.py files. However, something as big as what you have, with over 1k lines of code, would start to clutter the models.py files [for me]. I would be inclined to move such code in a separate file within a given application. No harm in doing that.

ayaz
+9  A: 

From the Django docs

Adding extra Manager methods is the preferred way to add "table-level" functionality to your models.

  1. Create a module with that logic (year_employee.py)
  2. Lets say you have a model Employee than add a manager for it :

    class EmployeeManager(models.Manager)
       def of_the_year(self):
            from year_employee import my_calc_func
            return my_calc_func()

than add this manager to you model


class Employee(models.Model):
   [...]
   objects = EmployeeManager()

than you can simply do that:


chosen_employee = Employee.objects.of_the_year()
Pydev UA
+1  A: 

Is this a custom application? If yes extracting the business logic away from the view is not really going to be at all possible. Sometimes you have to put it in there for a myriad of reasons, one of which would be maintainability.

Beyond that a calculation should be outside of the UI, in 99.9 % of the cases.

Woot4Moo
A: 

From your inputs:

Defining a separate module "services.py" for holding methods / classes with complicated algorithm and logic.

As we know eventually the call will be made from views (who knows what it wants) so the best we can do is to call a method in models which internally calls the logic from services module, uses models data to do the processing and return the result to be written on to the response.

Thanks for your responses.

Vishal
A: 

I try to follow the "skinny controller, fat model" concept (link is specific to Rails, but the concept still applies). Your controller should not have much code in it at all, except to deal with sessions, cookies, forms, etc. All of the actual logic of your app should reside in your model, making it easier to test and refactor later.

Kyle Slattery