Way back when in the 1600′s, astronomy was all the rage in Europe, due for the most part to the invention and production of telescopes.
As a result, kinds of people were able to learn more and teach society more about stars and such, and it all progressed wonderfully. But, astronomy isn’t just looking at pretty lights; there are a lot of calculations. Also, these aren’t the hundred and fourteen plus twenty six type calculations that you do in your head; they’re heavy duty, with large numbers and frightening chains of arithmetic.
Presumably, the “graduate students” of astronomy at the time were assigned the task of sitting around and crunching numbers for the more experienced astronomers.
Then, a man named John Napier changed everything. By reducing the accuracy of the calculations slightly, he developed (or, at least, introduced in Europe) the system of “logarithms”, which make arithmetic much easier (they’re the basic idea behind the slide rule).
This is what Rails has done to web applications. By making small assumptions about how you write your code and how your app serves its users, it has made the process of developing and deploying high quality web applications a much less painful process.
But, this seems to start to change as you finish your first seven or eight months with your web application. The templates are scattered, the controllers are bloated and the models are sitting around doing nothing. Slowly but surely, your development time slows down, features are delivered slower and slower, and, worst of all, the fun leaks away from developing web applications.
You definitely don’t want this to happen to you.
If you are willing to put in little bits of time from the start, you might be able to prevent this from happening.
So, let’s get started with some things you should keep in mind when crunching out the code for that awesome new application that’s going to change the world.
No Business Logic in Templates
Templates are not meant to do the “crunch work” of your application! Stop pushing all of your code out to the templates!
Specifically, business logic is anything you’re doing with the data. So, if you’re computing a person’s age, that’s business logic.
The appeal of doing this is present; you only have to deal with one file at a time. If you need to fix something on /user/signup, you know that the problem is in the view, because the controller and model are pretty much empty!
But, there are other issues that kill your productivity. First off, code readability suffers greatly, because you’re expressing everything in terms of HTML output.
Secondly, it ruins the point of MVC, which is modularity. A lot of the productivity of Rails comes from the MVC
structure, so, do your best to preserve and follow it.
Also, putting all your logic in the view makes it very difficult to abstract away operations. As an example, if I wanted to compute a person’s age several times over in my application, I could write a method to abstract that calculation. However, when you’re stuffing everything in the views, that doesn’t work and you’ll be repeating the heck out of yourself.
Consider this template:
<% ps = Post.where(:author => "Dhaivat Pandya", :blog => "Something",:language => "English", :market => "developers") %><% if ps.time_posted.nil? %>Oops, using old system please revert.<% end %><div id="times"><span class="age"><%= Date.today - ps.time_posted %></span><span class="age_edited"><%= Date.today - ps.time_edited %></span></div><div id="post-<%= ps.id %>" data-id="<%= ps.post_id %>"><div id="author">ps.author</div></div>
That’s so convoluted, I can barely tell what is being produced here. I can’t imagine how I would debug this when the time came.
Let’s try to simplify this madness.
First of all, why in the world would you do a database query INSIDE THE VIEW?! We should make view variables for all the computations we’re doing inside the view. Here’s our final view:
<% if no_time_included %>Oops, using old system please revert.<% end %><div id="times"><span class="age"><%= @age %></span><span class="age_edited"><%= @age_edited %></span></div><div id="post-<%= @id %>" data-id="<%= @p_id %>"><div id="author">@author</div></div>
All we’ve done is just set a few variables and move our logic to the controller (or, model, which might be better) and, it makes the code much cleaner.
As you can see, by putting in a little bit of work, you’ll make your life much easier in the future when you have to sort through your application to fix that one annoying bug.
Logging is Important!
What do you do when your server goes down? Panic? Scream? All of the above?
When your server goes down, you’re scrambling to figure out why it happened and fix it as fast as possible. If you’re doing logging well, you’ll have a much better time.
You need to log all of the following:
- Big database changes
- User logins – logouts
- Server connections
- Subprocess spawning
- AJAX requests and the response
Note that that’s very far from an exhaustive list! Think about what you’ll want when you have a rainy day.
Also, understand that you don’t want to log so much that you’re spending more time on logging than on database queries (unless, of course, you’re not doing any database queries)!
Learning about syslog is an excellent investment; logging is awesome, but, you can’t have it hurting user experience.
Skinny Controller, Fat Model
This philosophy has recently been under attack, but, it has worked well for me, and I encourage you to try it out as well.
The idea is that you don’t put all of your business logic in the controller and, instead, you put in the model which is supposed to be a better place.
For example, if you want to find out, from the database, what users had logged in at a specific time, add that method to the model and call it from the controller.
This would be the model:
class User < ActiveRecord::Base...def self.find_logins_at_time(time)#method implementationend...end
That really keeps your code modular, because all controllers that use the model User are able to access that method (if you want them to).
It just doesn’t seem “right” to stuff all your code into the controller, which is actually meant to answer HTTP requests.
Rails Still Uses Regular Old Ruby
Ruby on Rails. That’s what its called. Its not just Rails.
That means that you can use the good old ruby with which we’re all familiar. Classes, methods, static variables, etc. work basically the same way, except Rails steps in sometimes and makes magic happen. For example, Rails makes class variables available to the view from the controller.
What does that mean? Well, that means don’t be blinded by all of the “Rails” around you, you can still use your Ruby knowledge.
Use methods and static variables where you should, because ruby is an incredibly powerful language which you can use to your advantage to improve productivity and make maintenance easier.
It’s worth your time to learn more about ruby and its advantages and disadvantages with other languages.
As an example, I was recently developing a financial web application in which there were a ton of configuration options which weren’t expressed very well in YAML. I was able to use Ruby to develop a DSL (domain specific language) so that configuration proceeded ten to twenty times faster.
This isn’t a complete list of things you should do, but, you should definitely do the things that are on the list.
I hope you enjoyed reading it, and, hopefully, your next bug will be easier to fix.