The funny thing about programmers is that we spend years of our professional lives believing that our job is to tell computers what to do.
Reality is that computers do what they were told to do just fine. No matter whether you write "Hello World" or kill someone with a drone. Computers do precisely what they were told to.
Your job, your real job is to tell programmers, and you yourself in the first place, what you told computers to do. The idea of modern software development is in structuring and cleanly describing task that a computer will perform.
The truth is that #computers don't read what you wrote in your programs, people do. Computers compile your code down to bits and bites and the only ones who see what you actually wrote are other #humans.
If you start to look at your job and code you produce this way, it becomes immediately apparent that #programming is much like story telling.
Now think of it. How do you know that a guy can't tell stories for squad? It's really simple, when a story teller deviates from the story line all the time, get stuck with unimportant details, constantly jumps back and fourth between the points, etc. you immediately know that the story is gonna suck.
In the end you can understand what happened in the story, you even can retell it, but did you enjoy the story? did you get inspired to retell and maybe extend it?
Same exact thing happens in software. When you write cryptic, full of noise piece of code, no one is going to enjoy it. No one will think of it twice. And you're the first to suffer.
Well, you're here for a simple secret sauce don't you? So here it is
The less noise your code has the better
Note that I'm not talking about explicit vs. implicit code, convention over configuration, meta-programming evils or any other things of this sort.
The trick to good software is to write in your code exactly what makes sense for the story your code tells. If it's good for the story to be explicit, do it. If the stuff you write has nothing to do with the story, kick it out. Kick it out for good. If it's vaguely coupled, use meta-programming and conventions.
Some classical examples to prove the point. Say a post has an author.
class Post < ActiveRecord::Base belongs_to :author, class_name: 'User', foreign_key: :authored_by end
See? All this noise about class name and foreign keys. Get it out
class Post < ActiveRecord::Base belongs_to :user end
The second version doesn't have the nice author naming in it, but it is much better because it goes straight to the point and in a short sentence tells you everything you need to know.
Another example, say a class needs to set a reference to users who created/edited its records
class Setting < ActiveRecord::Base belongs_to :creator belongs_to :editor attr_accessor :editing_user before_create :set_creator before_update :set_editor private def set_creator self.creator = @editing_user end def set_editor self.editor = @editing_user end end
Noise, all those callbacks and attr_acessors it's just rubbish that doesn't have much to do with what you're trying to accomplish. Much more explicit and nice way to do it would be say like so.
class Setting < ActiveRecord::Base belongs_to :creator belongs_to :editor def editing_user=(user) if new_record? self.creator = user else self.editor = user end end end
See how it now tells exactly what's going on? This code says, we have a creator and an editor and we assign them from the editing user. No middle noise about callbacks. No extra noise from having two methods in private namespace.
One more classical example. Massaging your data in a controller
class PostsController < ApplicationController def create if params[:post][:text].present? if params[:post][:text] =~ /fuck|cock|shit/ flash[:error] = "Be nice" @achtung = true end end if !@achtung @post = Post.new(params[:post]) if @post.save flash[:success] = "Yoo hoo!" redirect_to :index else render :new end else redirect_to :index end end end
All those conditions have nothing really to do with your controller. To be precise all this logic does not belongs to the controller level at all. Yeah, you can do that and it will work, but it's not good software.
class PostsController < ApplicationController def create @post = Post.new(params[:post]) if @post.save flash[:success] = "Yoo hoo!" redirect_to :index else render :new end end end class Post < ActiveRecord::Base validate :bad_language_check private def bad_language_check if text =~ /fuck|shit|cock/ errors.add(:text, "has some pretty bad language") end end end
Now your controller clearly says what's going on. And you can easily see what happens in both cases when it can and cannot create a record. Same of the Post class, you can clearly see that it validates the text for bad language. And the checker itself is in the private section, just to hint you that its implementation is not that important for the post itself.
It's really simple. Want to write good software? Stop writing it for the computers and start writing it for humans.
It is that simple.