Can someone explain the phrase "Fat model, skinny controller"? - ruby-on-rails

I'm learning Ruby on Rails. I noticed this phrase "Fat model, skinny controller". I'm not sure what that means. Does that mean I have to use more code in model and less code in controller? Can someone explain this?

You understand correctly. Main reason for this recommendation is that you only need process request parameters and initialize model layer in controllers. Business logic need to be implemented in model layer. This allows you to avoid code duplication and made testing easier using unit tests for models.
Also read this and go through whole site for best practices.

In short yes you have the idiom right, although if any piece of code with a defined role becomes bloated it can be a problem and may need some basic re-factoring.
Business logic used in models can be re-used in multiple different routes, or in web-service APIs, or a command-line script. It can also be unit tested without invoking the web server.
The same business logic in the controller can only be used via the web interface.

Related

Implementing application logic on model layer (MVC)

I keep reading that the biggest layer in the MVC pattern should be the model. I've also heard that we should avoid putting logic on the controller layer. However, as my ASP.Net MVC 5 application is getting larger, I see that I'm getting heavy views, heavy controllers, and... extremely tiny models (they're not more than references to my SQL tables).
Yes, I admit, I could never manage to put any logic on my model.
I like the MVC pattern, and my website is working good, but I keep on thinking that I'm surely not doing things right...
Can you show me some useful links about how to write MVC code properly? Rick Anderson's (Microsoft) MVC 5 tutorial is fine, but once again, his models are indeed very tiny...
In my applications I put as much logic as possible in the domain models. On top of that there is an application layer which interacts with the database and domain models to perform application specific operations. The controller actions have as little code as possible and just call methods in the application layer.
In addition I usually have a view model for each view. Any logic that you have making your views "heavy" would go there.
One of the main reasons I try to put as much logic as possible in the domain models is to make unit testing easier. Logic in the application layer usually involves the database, which you will need to mock in order to test. Moving logic to the domain models makes testing easier and makes you code more reusable.
This is a pretty complex issue. I have an in depth blog post on the question if you're interested.
This answer is also pretty close to what I would suggest.
You're missing a service/business layer which should be injected in your controllers though "Dependency Injection". These services do all the heavy lifting.
Having Models without any methods or operations in them is a good thing. You're only storing this info anyway. They basically just get; set; data.
Use extra layer between models and controllers (for example repositories as data access layer).
I strongly recommend using ViewModels-they make code much more organized.
You should Create Some Classes that purely doing business logic and emit ViewModels for MVC view. Controller should respond to actions and the action method delegate the responsibility of getting the model to this business classes.
After some research on this issue, and taking into account some of these answers and comments, I realized that a medium sized MVC project can't rely exclusively on the 3 layered model. As the controller actions become bigger, the developer starts feeling the need of creating a 4th layer: the service layer. Like Gunnar Peipman correctly suggests in the following blog post, "Controller communicates with service layer and gets information about how access code claiming succeeded": http://weblogs.asp.net/gunnarpeipman/archive/2011/06/20/asp-net-mvc-moving-code-from-controller-action-to-service-layer.aspx

Confused on MVC in rails

I am a bit confused on what to write where in Rails.
Ideally, I will be having a view, a controller, a model. Model should be having all the business logic. But in most of the Rails applications I've seen, I've seen most of the business logic written in the Controller files.
Should we call them as controller? And what about View-models. I am talking about the datamodels that are associated for a view. I am having JSF and Swing in my mind when I say this. There every view has a datamodel associated with it, usually a bean. But here, we don't have anything like that or I am ignorant? And what about service layers, How do I implement them in my Rails code.
To summarize my questions
Why are business logic being
written in Controllers in most of
Rails code? Is this a good practice?
How to incorporate the view-model in
rails, ie, data-models for view?
Where to put service layers in a Rails app?
Thanks
To summarize my answers:
The new standard for Ruby on Rails is to place business logic in the model. This is also known as fat model skinny controller.
Rails doesn't enforce this approach of one data model but you can implement it if you choose. The basic scaffolding does something similar.
The service layers will most likely be stored within rack middleware. This allows for general filtering of requests and responses.

Where does business logic go in rails?

I'm an ASP.NET MVC developer just starting with my first big project on rails however Im confused as where to put your business logic? on ASP.NET I create a library which contains services(Domain driven design) which handle business logic, I have heard that rails uses a concept of fat model skinny controller but I have some projects in ASP.NET which adding all the logic to the controller would create a big mess, is there any other way?
Go with the concept of FatModels and SkinnyControllers. Your models should know how they behave and what they should do.
When your models get too fat, extract them out into re-usuable modules and include them in your module.
Example of taking a fat controller (with logic) and moving to a model
Example of taking code from the views and moving into the model
You can easily test behavior of models using RSpec (or test/unit or shoulda). Then you can test that the application behaves correctly using Cucumber.
"Business Logic" or some might call it "Domain Logic" doesn't belong anywhere near Rails and/or your .NET MVC project. Rails and MVC should depend on your Domain not the other way around. I would recommend reading up on the Onion Architecture from Jeffery Palermo or watch "Architecture the Lost Years" by Robert Martin. (I think that's that talk anyway). There are probably more resources than that, but you'll thank yourself later for treating both Rails and .NET MVC like the 3rd party frameworks they are, and not the main house of your application.
I think this blog article provides a good overview of a strategy of incorporating domain driven design with in the rails framework: http://www.smashingboxes.com/domain-logic-in-rails/
TL;DR
Refactor your classic rails models into repositories, and use a facade layer in the controllers to interact with your domain model.
I'm struggling with this a little my self, and as much as the Fat Controller pattern seems to prevail, anything "fat" in software seems to be a smell, violating single responsibility.
You can put business logic anywhere you want (even in views! though that's a bad idea).
I'd say if the logic is tied to a real-world object, then put it on the model. Otherwise, use the controller. But it's up to you to determine how to do it for your app. Models are for modeling things, and Controllers are for controlling things.

ASP.NET MVC - when SRP and DRY appear to conflict

My simplest ASP.NET MVC 2 controllers make calls to my service layer and map view models to entities using AutoMapper. Everything looks fantastic and there is no repeated code.
However, when I get into scenarios where I have similar behavior I have trouble balancing Single Responsibility Principle (SRP) with Don't Repeat Yourself (DRY). An example of this might be the need to add/edit vehicles where some properties/behaviors are shared while others are unique to a specific vehicle.
If I strive for really thin controllers (thus honoring Single Responsibility Principle), I end up having repeated code in both the views and controllers with minor variations (title, field labels, field visibility, dropdown values, selection criteria, etc.).
If I strive for non-repeated code I end up bundling too much logic into a single controller/view and it gets bloated.
What are some ways of addressing repeated code in controllers / views? I'm not talking about database code that can be factored out to a repository. Nor am I talking about business logic that can be factored out to a service layer. I'm looking for tools and/or rules of thumb that will help me produce the best solution in the scenario described above.
You get:
partials
RenderAction
action filters
service layer and helper classes (not HtmlHelper)
model binders
base controllers
dependency injection
So your views can invoke shared partials/actions for similar parts, common data can be prepared by action filters, database access code can be hidden in smart model binder, or you can have parent controller that child controllers override with specific tweaks. And, of course, good old service layeres, where you just extract common code into helper/static methods, or, better, inject specific implementations.
That's nothing new, same old tricks.
Or, maybe, your controllers do too much works? This is where stuff above also helps. ASP.NET MVC has very good tools to hide infrastructure-layer code and move it away from controllers. And if it's not infrastructure - it probably belongs to domain layer. There you can use inheritance, composition and other OOP tricks.
Specific example. Suppose your controllers should set few properties in a different way.
You can have your views to do this, if it's mostly formatting or choosing what properties to show
You can have your entities to have virtual methods - i.e. refactor code to move decisions to domain layer instead of controllers
You can have helper ViewDetails classes that will take your entities and get the data based on for what you need it; this is a bit of a dirty trick but sometimes useful; you delegate decision to another "strategy" class
You can use action filters to add this data to ViewData, or to tweak specific ViewData.Model types (look for some interface of it).
You can have abstract controller, where children pass implementation details to the base constructor like (): base(repository => repository.GetSpecificData())
And so on. I actually use all of them in appropriate places.
You are worrying too much about SRP and DRY. They are principles only and are not always right. SRP and DRY are good if they make your code more maintainable, but if they are in the way then ignore them. MVC is similar. It is useful in simple small desktop applications but is not appropriate for web applications. Web Forms is much better for the internet world while MVC is something from the 1980s.
I recommend you to use SRP over DRY in those cases. I wrote here a detailed answer.
In short both are rules which help to keep your code maintainable. DRY is a low abstraction level mechanism, while SRP is a high abstraction level. By maintain an application the high abstraction level structure is more important than the low abstraction level.
In your case I don't think it is necessary to give up DRY.
An example of this might be the need to add/edit vehicles where some
properties/behaviors are shared while others are unique to a specific
vehicle.
Many design patterns can help in this case. You can use decorator, composition, and so on... combined with builders for the different types of vehicles.
I found that ApiEndpoints is very good for this. You create a class for each controller method. A little more code, but I think it's very clean.

MVC Models & Controllers where what to write

We have started using MVC framework and now we are bit confused where to write business-logic, in controllers or models?
For the project we are going to use WCF layer as DAL.
People have different views on Model & Controller, and think differently of writing business logic either in 'M' or 'C'.
What is the best practice?
I believe we will be accessing WCF (DAL) service in Model and applying all the business logic or filtering and then Controller accessing the data from Model.
These are my rules:
Controller
Mainly Pageflow . Determines what View is displayed next.
Has access to Services ( ie productService.GetProduct(Model.ProductID) )
Model
I have 2 of them.
POCO-Classes - used by all layers (BLL,DAL)
ViewModel - used by View and Controller for stronly typed views.
View
Hopefully mainly easy HTML
I try to have the layout in a way, that it is possible to have different kind of people work at the project: The frontend guy and the backend guy.
The backend guy will do the Service and Repository.
The Frontend guy will do Controller and Views. He also does ajax.
Try to keep -Business- logic and -Application flow- logic separate. Most people tend to mix those together as -business logic-
Most people keep their business logic in the model and this is considered best practice. Steve Sanderson who has written xVal endorses this method.
As I’ve discussed before, validation rules should go in your domain model, because the role of your model is to represent the workings of your business. It ensures that the rules will be enforced consistently, regardless of whether the UI coder remembers them or not.
Check out his post about xVal that talks about the problem you are discussing.
Do not think that model is supposed to be build from data access logic (wcf service in your case) only. I would recommend you to check out Domain Driven Design, it goes well with MVC. Controllers shouldn't contain any business logic. Controller action method should be ~20 or less lines. But that's just my opinion (made up from countless sources).

Resources