MVC: The Most Vexing Conundrum
MVC, short for Model/View/Controller, is one of the hallmarks of Ruby on Rails’ design. But unless you know what that is, just saying so doesn’t do much for ya.
<span id="more-3346"></span>
Into JavaScript? Have I got good news for you!
If you’re interested in JavaScript-driven web apps, snazzy visual fx, and generally confusing people into thinking your site is Flashโbut oh-so-much betterโyou should buy our JavaScript Performance Rocks! book while it’s still in beta. Written by Thomas Fuchs, the creator of Scriptaculous, and yours truly, the maker of funny jokes and shiny graphics.
We cover everything from The Most Ridiculous Performance Fix Ever (and it is ridiculous), to serving strategies, DOM diets, loop unrolling (for those really extreme cases), how to play nice with the garbage collector, and everything in between. And it comes with our custom profiling tool, The DOM Monster, which analyzes your pages and suggests fixes. This package is only $24 right now but will be $29 as soon as it’s done, in mid-June 2009… but if you snag your copy today, you get the final version by email just as soon as it’s ready and save a noteworthy 5 bux! You can’t lose.
Patterns: Patently Perfect!
If you’re still reading this, I’m going to operate on the assumption that you don’t know what MVC is but are, perhaps, cautiously curious. Well, if you’re cautious, buck up! It’s not that difficult to understand once you find a good explanation, and curiosity may have killed the cat but you’re a human and a little sturdier than that, right? And anyway, it’s hard to get killed reading a blog unless you drown in someone else’s self-pity.
Design Patterns: Templates for Programmers
Design patterns are templates so that programmers don’t have to reinvent object-oriented software architecture. Design patterns come about when learned people sit down and figure out the best general way to design a program’s overall functional structure when using object-oriented programming. We’re not talking where you put files, or what your methods do, but how, in an abstract sense, all your programming pieces fit together. Think of them as basic blueprints for your applications—you have your foundation and your steel girders pre-ordained, but the color of the bathroom tile is up to you.
What Every Good Programmer Knows (and Sometimes Does)
If you program much, your code probably migrates towards a higher overall quality over time. In fact, if you’re a smart programmer, the way you design your overarching code structure probably evolves over time as you learn from your mistakes—or rather, from having to go back later and maintain your mistakes (or other peoples’).
So, the hard way, you probably learned that intermixing business logic (the nuts and bolts of your script) with display logic (“if they’re not logged in, show this”) is a Very Bad Idea. And you might have realized that it’s a Pretty Good Idea to cordone off sections of your basic web app so that they interoperate, but aren’t inseparable. You’ve probably even learned to write a number of little functions that each do just one simple thing and then have larger aggregator functions that call them in order.
If all of what I’ve said above is true, you’re utilizing a very rough and informal kind of design pattern, and you’re almost two thirds of the way to MVC.
That Most Vexing Conundrum
MVC is one of the most famous and popular design patterns for creating applications with user interfaces, and not particularly vexatious in and of itself. Again, MVC stands for Model/View/Controller, which was apparently assembled as an acronym in no particular order. (MCV or CMV might make more sense, but for some reason neither are as euphonious as MVC.) MVC has three distinctive components, and if you separate them appropriately you end up with a program that is much more portable, scalable, and maintainable than if you hadn’t.
The Bits & Pieces
Sometimes order is important. I’m describing these three components from the ground up. They’re all interdependent, certainly, but this is really the natural order of things:
Models are the foundation. Hooray for cinderblocks and cement! A model is commonly something that represents a table of data; in Rails, you have to create a model, one for each table, which describes the relationships (if any) to other models (tables). Without a model, you’re unable to actually do anything with any kind of data. Wouldn’t that be fun? A web app without data! It’d be almost like a movie without acting…
Controllers are the power tools. Controllers are the tools you use to manipulate data described in the models. When it comes to CRUD operations, manipulating data, and anything that’s considered “business,” controllers are where it’s at—literally. The controller is the one that does all the data validation, the data reading and writing with the help of the lovely model, and hands the finished product off to the view to display. (Full disclosure: in Rails, some data validation is in fact built into the model handling, but this isn’t really typical.)
Oh, crud! Don’t know CRUD from any other 4-letter c-word? See my previous article.
Views are the spackle and paint. Views let you actually put a face on the application. In the case of web sites, this is the point where your data goes out over the wire, be it in HTML or XML or what-have-you. You’re only allowed to have display logic in views—such as looping through content, and hiding or showing links based on who’s logged in.
But… er… Why?
It’s not a bad question. There are several answers:
- Separating business logic (controller) and display logic (view) let you easily change the appearance of your application at any time.
- It makes it easier to make changes behind the scene in the business logic department, too—your code will be oh-so-readable.
- One word: reusability. You write some cool stuff in Rails (or other MVC outfit). You want to use it again later. You have absolutely no problem, it’s almost as easy as drag and drop, because your code is sweetly compartmentalized.
- Having models separate from controllers gives ActiveRecord the ability to work its magic—which spares you from having to write queries all over the place.
So… Wasn’t This About Rails?
Right you are! This is about Rails. See the diagram above and follow along.
When you’re working on your Ruby on Rails app, you’re forced to do MVC to a large degree. The Model part of MVC is handled by ActiveRecord; you create a new model in /yoursite/app/models/
using script/generate model
and then you open it up and edit it to describe how that model relates with the others.
You have to build a controller, too, and you do that with script/generate controller
. Controllers are found in /yoursite/app/controllers/
and generally you have one controller per model, although you can have controllers without models, too—they can control other controllers (gasp!).
And lastly, views, which you will find in /yoursite/app/views
(noticing a trend here?). In Rails, you build views in .rhtml
template format—an intermixing of HTML and Ruby/Rails code in <% %>
tags. No business logic allowed! Ahh, it’s lovely.
Wrappin’ it Up
That’s it for today, folks. But I’ve found some time recently to play around more on the Rails code side of things, and so I’ll be writing about that too soon. Nobody’s popped up in the mean time to write any more really good tutorials so be sure to come back because I plan to be the one to fill that void.
I wish I read this when I was first starting out with Rails! The existing tutorials were a little lacking on explanation of MVC. Fortunately, the folks in #rubyonrails at freenode helped me out, but now we can also recommend this article to newcomers.
Well, actually someone really clever popped up recently to write really good Rails tutorials. It’s you.
Thanks ๐
Good stuff. I look forward to more articles from you.
An additional benefit of MVC in Rails at least is that it tends to encourage you to put your logic where it’s testable by unit tests.
I love your writing style! Its clear, lucid, and entertaining!
I want to have your babies… err… well… I’ll just keep reading your blog, then. ๐
BTW, ONLamp.com is publishing part 2 of my Rails tutorial next week, and I start off by mentioning your "Really Getting Started in Rails" article for those who want to know the "whys". Keep up the good work, Ruby and Rails can really use good press like this!
What I would like to read now is how to go beyond the basics of Rails. Scaffolding is nice, but could I customize it? How do I relation models work and how do I use them in practice? What about user authentication?
Thanks to everyone for the comments. Please do keep telling me what you want to read about!
I’m working on my first largeish Rails app and so I will be covering it in a set of tutorials. I will be doing at least one article on ActiveRecord and relationship models as the first bit. That’s actually next on my to-do list. As for user auth, I haven’t gotten that far yet… but hopefully will in not too long. ๐
You really don’t have to do your own authentication anymore. Tobias Luetke has written a login generator that adds authentication, users, and logins to your rails app. Check it out at: http://wiki.rubyonrails.org/rails/show/LoginGenerator
For more advanced discussions of some of these topics, you should also be reading Scott’s stuff at: http://scott.elitists.net/tags/show?tag=ruby%2Bon%2Brails He’s covered modelling a more complex domain and validation including custom validation so far.
Honestly, for people who are already programmers who might get interested in Rails, Scott’s stuff is more interesting than Amy’s work here. I would really be interested in seeing Amy explore introducing Rails for non-developers, which seems to be the approach she’s taken so far.
I know about the login generator, although I haven’t used it yet. I’m sure that there will be things to be changed or customized depending on what the person using it wants to get out of their login system. It can’t work entirely how you want out of the box. ๐
Andrew: I’m going to Rails as a fairly accomplished PHP developer. I’m writing the things I wish I could have read when I began Rails. It’s not just that I’m aiming for the non-developer (I haven’t gotten anywhere near that basic yet), but I’m aiming for those of us who think differently, or who have never used anything like Rails. I understood MVC, and true OOP, and knew some Python before I started, but I still felt pretty overwhelmed by Rails at first. I know I’m not the only one.
You’re definitely not the only one.
What’s been the most difficult for me, though, has been wrapping my head around the things that Rails does for me. Somehow, it just feels like I’m doing something terribly wrong when my model consists of just a few lines of code and a working controller isn’t that much longer.
The only other thing that’s hard for me is knowing just where to start when I code: starting with the controller seems more natural, but I don’t know if ActiveRecord has enough "expectations" to make it easier to develop the underlying model first.
Amy, there’s been plenty written for beginners so writing at the intermediate level (those who yearn for a deeper undertsanding) is excellent. Further, writing about area that frustrated or confused you also good because others are likely to have had the same experience (plus later on you’ll forget about it as everything becomes more natural).
Nathan, you can start with the controller if you like — Rails doesn’t care. On the other hand, Rails makes it so easy to to create and change your model that its nice to give you controller some data to play with. Do what what works for you.
Curt, thanks for the encouragement. I’d be doing it even if people didn’t agree, though. I’m stubborn ๐
That ‘kinda like my ex’ for ActionController made me laugh out-loud at work ๐
Tim
Hi Amy,
You have done some excellent work so far here. It’s interested to read about the experiences of somewhat looking at rails from a PHP/Html Developer perspective. Especially from someone in the Baltimore-DC area. (I’m out of Bethesda)
I’m doing a series myself on Ruby/Rails coming from the other direction, i.e. J2EE/Java web application development. If you are interested, check out my latest at http://www.patrickpeak.com.
Very nice article, I used some of the points in an intro to MVC for my university project.
Thanks for the article Amy. ‘ooh, pretty pictures!’ and ‘kinda like my ex’
Suddenly it all becomes clear for my designer brain!
More please.
I’m new to the i.t. game. fortunately my wise brother took my shaky hand and placed a rails book in it. next he opened this window and gave me a more confident step into your world. i appreciate that you are speaking in a way that is unintimidating and easy to read. thank you so much. the humor gave me a laugh and a reason to remember how everything works!!!! i’ll check back in.
Thankyou! The must frustrating thing I’ve found trying to learn rails is understanding the underlying MVC convepts, which seem to be assumed knowledge in every other tutorial. You’ve explained the concept clearly, without skipping over bits that ‘everyone should know’.
Again, thankyou!
The problem is my browser!
Excellent tutorial. I’ve been combing through mvc source code for what seems like days and making little progrss. This has put it all together for me, thx!
When I first needed to commit to OOD, it seemed that MVC was a useful concept, but not in the right order for me (as you said), and missing an object (or group of objects): VCPM
My app uses both a DB and it’s primary function is to display data in different graphical as well text formats, after often intensive processing.
It seemed logical to me to add a Processor which took the data from the Model, processed it, and then passed that through Controller to View.
This may or may not be helpful to those on rails. I’m not (or not, yet anyway).
Thanks Amy.
Sterling Stuff!
Love David
.. again, really nice job on that article. I think being forced to use MVC is going to change my life ๐
Nick
Hmmmm. Last I checked, validation and business logic were the Model’s job, not the Controller’s. Although, I admit I could be wrong considering I’m reading this 486 days later, and it appears nobody else has raised this issue. AND, I stumbled onto this blog while searching for a clearer understanding of Ruby’s interpretation of a Controller, which calls my knowledge of Controllers into question.
I found these two links which pretty much left me still asking, isn’t a Controller just a Mediator?
http://c2.com/cgi/wiki?WhatsaControllerAnyway http://www.phpwact.org/pattern/model_view_controller