Model – View – Controller (MVC). Where do you put your business logic?

When I first started doing Rails development over a year ago, I often found other developers suggesting that I refactor my code to move the business logic out of the controller, and into the model.  After this happened several times, I wondered why this seemed so obvious to them, and why that wasn’t the way I was naturally doing things.  It wasn’t just me and another developer approaching problems in different ways.  It was multiple people approaching problems in a similar way — and then me.  I wondered why there was this general difference in thought processes and solutions?

I began to passively wonder if my background in Java was contributing in some way to my way of thinking here.  Since then, I have also heard other Rails developers who are working with former Java developers say things like

"these are good developers but they keep putting business logic in their controllers!"

That made me think more seriously about what a person’s Java background might have to do with this.

VIEW 

In earlier days of PHP, classic ASP, and early JSP, it was OK to put business logic in the view.  Back in the day, it was common to find <% %> tags in JSPs with all kinds of logic in the Java code.  I think we all now agree that business logic does not belong here. 

let the view deal only with DISPLAYING what it has.

MODEL 

It seems like I’ve spent a lot of time seeing a model as simply a data-holder class.  Something like a Struct in C.  Something like a Bean in Java, with private attributes, and with get/set methods for each attribute.  It’s just a data transfer object, nothing more.  But why?  Perhaps it comes from my EJB days.  That might explain why so many other former Java developers do the same thing.  To us,

the model carries data but is dumb. 

CONTROLLER 

I always thought of the controller as being the one smacking around the model objects to get them to do what the controller wants – and

what the controller wants the model to do, is the business logic. 

A RAILS WAY OF THINKING 

Give the model more credit.

The model isn’t so dumb after all.  It doesn’t just hold state.  It contains the business logic behind the behavior of that model.  A model knows better than any other code how itself behaves, what it does or does not do, and how it interacts with the outside world.  I can try to predict how my brother will behave in a given situation; I can take a guess based on what I know about him.  But only he knows for sure, and the only way I can know for sure is to interact directly with him and find out.

Let the controller control the flow of information.

This leaves the controller with only the responsibility of collecting information and routing it to the right place.  It’s the electronic curator that finds and obtains art, and hands it off to the decorators to display.  He decides what pieces go in which rooms.  However, the decorators (analogous to the view) are the ones that decide how to arrange the art within that room for all to see.

I still need to be reminded sometimes to not put so much logic in my controller.  It is starting to come more naturally to me, but old habits die hard I suppose.  This way of thinking makes more sense to me now that I understand where my past way of thinking comes from.  I like this new way because it really makes sense now, and also because

I find that code re-use comes much easier when needed business logic is already available in the model.

.

Advertisements
Posted in code. Tags: , . 7 Comments »

7 Responses to “Model – View – Controller (MVC). Where do you put your business logic?”

  1. Dean Says:

    One of my rules-of-thumb that I have come up with relatively recently, is: make it a model method if it’s something you might want to call from script/console. In a way, that encapsulates the use case: if it’s a discrete thing that I want to do with the model, then it should be a single method. Likewise, each controller action should be nothing more than a thin wrapper around what I want to do in script/console.

  2. driftwood Says:

    I was running into this exact same issue in the asp.net development. It made sense to me to put business logic into the controller and have the model just be a state controller. However, everything I read said that I was wrong.

  3. Steven Rock Says:

    Hi, I’m still a Java programmer, never tried Ruby. I have been perfectly fine with the Java lightweight Model in MVC. However this blog has peaked my interest. Why are people starting to put controller logic back in the Model? Why is it better than keeping everything in the controller? Just curious what the motivation is. I am always open to new ideas. Thanks.

    • Jonothan Farr Says:

      It’s just good object-oriented design: encapsulate your data along with the behavior that operates on that data. If your data is in the model and the behavior is in the controller then you’re building a procedural program, not an OO program.

      Here’s an excellent article by Martin Fowler that talks about this:
      http://martinfowler.com/bliki/AnemicDomainModel.html

  4. Quora Says:

    What are some best practices for designing ruby on rails models?…

    Rails Model is the place where you should care about: – Relationship Associations: relations with other models (one to one, one to many, many to many, polymorphic…) – Validations: validates your model attributes – Accessible attributes: define which …

  5. Keith Says:

    I’m write there with you Gayle. It almost seems like we need a new acronym! How about BMVC? Business Logic – Model – View – Controller. That way, the model can stay dumb, and the controller can worry only about wiring.

  6. Michael Chang Says:

    I guess I came to the Java party late because I’ve never, ever put business logic into a controller class. Controllers route requests (in the case of Front Controllers), delegate to services (the Service layer), and assemble/package data for the View layer. Business logic goes into the Service layer, which may or may not invoke one or more business delegates to do work, depending upon the complexity of the logic. The service layer exposes a coarse-grained API. Finally you have your Model layer, and it can get tricky here because there are no hard and fast rules. Personally, my model layer is composed of 2 parts, typically: domain model objects and data-access objects (DAOs). The service layer calls into DAOs which accept and return domain model objects (be they thick or thin). That’s the long and short of it. Things can change a bit depending upon the specific application, however.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: