Introduce
This article is based on the technical principles of programming from Robert C. Martin’s book Clean Code , adapted for Ruby. This is not a mandatory writing guide. It is a guide to producing readable, reusable and refactable software in Ruby.
Not all guidelines in this document must be strictly adhered to, and disseminated globally. These are guidelines and nothing else, but they are drawn from the years of collective experience of Clean Code authors.
Our software engineering profession is just over 50 years old and we are still learning a lot. When software architecture is as old as real-life architecture, perhaps then we will have harder rules to follow. For now, let these tutorials serve as the foundation for evaluating the quality of Ruby code that you and your team generate.
One more thing: knowing these will not immediately help you become a better software developer and working with them for many years does not mean that you will not make mistakes. Each piece of code begins as a first draft, like a wet clay shaped into its final form. Finally, we eliminate imperfections when we consider it with our colleagues. Don’t satisfy yourself by the first drafts that need improvement. Instead, keep improving them.
Variables
Use meaningful and pronounced variable names.
Bad:
1 2 |
yyyymmdstr <span class="token operator">=</span> <span class="token builtin">Time</span> <span class="token punctuation">.</span> now <span class="token punctuation">.</span> <span class="token function">strftime</span> <span class="token punctuation">(</span> <span class="token string">'%Y/%m/%d'</span> <span class="token punctuation">)</span> |
Good:
1 2 |
current_date <span class="token operator">=</span> <span class="token builtin">Time</span> <span class="token punctuation">.</span> now <span class="token punctuation">.</span> <span class="token function">strftime</span> <span class="token punctuation">(</span> <span class="token string">'%Y/%m/%d'</span> <span class="token punctuation">)</span> |
Use the same vocabulary for the same variable type
Choose a word for the whole concept and just use it.
Bad:
1 2 3 4 5 6 7 8 |
user_info user_data user_record starts_at start_at start_time |
Good:
1 2 3 4 |
user starts_at |
Use searchable and constant names
We will read more code than we write. It is important that the code we write is readable and searchable. Without naming the last variables that make sense, we would hurt the reader of the code. So make your variable name searchable.
Also, instead of hard-coded values and using “magic numbers”, create constants.
Bad:
1 2 3 4 5 |
<span class="token comment"># What the heck is 86400 for?</span> status <span class="token operator">=</span> <span class="token constant">Timeout</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">timeout</span> <span class="token punctuation">(</span> <span class="token number">86</span> _400 <span class="token punctuation">)</span> <span class="token keyword">do</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> |
Good:
1 2 3 4 5 6 7 |
<span class="token comment"># Declare them as capitalized globals.</span> <span class="token constant">SECONDS_IN_A_DAY</span> <span class="token operator">=</span> <span class="token number">86</span> _400 status <span class="token operator">=</span> <span class="token constant">Timeout</span> <span class="token punctuation">:</span> <span class="token punctuation">:</span> <span class="token function">timeout</span> <span class="token punctuation">(</span> <span class="token constant">SECONDS_IN_A_DAY</span> <span class="token punctuation">)</span> <span class="token keyword">do</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> |
Use explanatory meaningful variables
Bad:
1 2 3 4 |
address <span class="token operator">=</span> <span class="token string">'One Infinite Loop, Cupertino 95014'</span> city_zip_code_regex <span class="token operator">=</span> <span class="token regex">/^[^,\]+[,\s]+(.+?)s*(d{5})?$/</span> <span class="token function">save_city_zip_code</span> <span class="token punctuation">(</span> city_zip_code_regex <span class="token punctuation">.</span> <span class="token function">match</span> <span class="token punctuation">(</span> address <span class="token punctuation">)</span> <span class="token punctuation">[</span> <span class="token number">1</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> city_zip_code_regex <span class="token punctuation">.</span> <span class="token function">match</span> <span class="token punctuation">(</span> address <span class="token punctuation">)</span> <span class="token punctuation">[</span> <span class="token number">2</span> <span class="token punctuation">]</span> <span class="token punctuation">)</span> |
Good:
1 2 3 4 5 |
address <span class="token operator">=</span> <span class="token string">'One Infinite Loop, Cupertino 95014'</span> city_zip_code_regex <span class="token operator">=</span> <span class="token regex">/^[^,\]+[,\s]+(.+?)s*(d{5})?$/</span> _ <span class="token punctuation">,</span> city <span class="token punctuation">,</span> zip_code <span class="token operator">=</span> city_zip_code_regex <span class="token punctuation">.</span> <span class="token function">match</span> <span class="token punctuation">(</span> address <span class="token punctuation">)</span> <span class="token punctuation">.</span> to_a <span class="token function">save_city_zip_code</span> <span class="token punctuation">(</span> city <span class="token punctuation">,</span> zip_code <span class="token punctuation">)</span> |
Avoid the use of meaningless mapping variables
Obviously better than the default.
Bad:
1 2 3 4 5 6 7 8 9 10 11 |
locations <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">'Austin'</span> <span class="token punctuation">,</span> <span class="token string">'New York'</span> <span class="token punctuation">,</span> <span class="token string">'San Francisco'</span> <span class="token punctuation">]</span> locations <span class="token punctuation">.</span> <span class="token keyword">each</span> <span class="token keyword">do</span> <span class="token operator">|</span> l <span class="token operator">|</span> do_stuff do_some_other_stuff <span class="token comment"># ...</span> <span class="token comment"># ...</span> <span class="token comment"># ...</span> <span class="token comment"># Wait, what is `l` for again?</span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> l <span class="token punctuation">)</span> <span class="token keyword">end</span> |
Good:
1 2 3 4 5 6 7 8 9 10 |
locations <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token string">'Austin'</span> <span class="token punctuation">,</span> <span class="token string">'New York'</span> <span class="token punctuation">,</span> <span class="token string">'San Francisco'</span> <span class="token punctuation">]</span> locations <span class="token punctuation">.</span> <span class="token keyword">each</span> <span class="token keyword">do</span> <span class="token operator">|</span> location <span class="token operator">|</span> do_stuff do_some_other_stuff <span class="token comment"># ...</span> <span class="token comment"># ...</span> <span class="token comment"># ...</span> <span class="token function">dispatch</span> <span class="token punctuation">(</span> location <span class="token punctuation">)</span> <span class="token keyword">end</span> |
Do not add unnecessary content
Do not repeat class / object names in variables.
Bad:
1 2 3 4 5 6 7 8 9 10 |
car <span class="token operator">=</span> <span class="token punctuation">{</span> car_make <span class="token punctuation">:</span> <span class="token string">'Honda'</span> <span class="token punctuation">,</span> car_model <span class="token punctuation">:</span> <span class="token string">'Accord'</span> <span class="token punctuation">,</span> car_color <span class="token punctuation">:</span> <span class="token string">'Blue'</span> <span class="token punctuation">}</span> <span class="token keyword">def</span> <span class="token function">paint_car</span> <span class="token punctuation">(</span> car <span class="token punctuation">)</span> car <span class="token punctuation">[</span> <span class="token symbol">:car_color</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'Red'</span> <span class="token keyword">end</span> |
Good:
1 2 3 4 5 6 7 8 9 10 |
car <span class="token operator">=</span> <span class="token punctuation">{</span> make <span class="token punctuation">:</span> <span class="token string">'Honda'</span> <span class="token punctuation">,</span> model <span class="token punctuation">:</span> <span class="token string">'Accord'</span> <span class="token punctuation">,</span> color <span class="token punctuation">:</span> <span class="token string">'Blue'</span> <span class="token punctuation">}</span> <span class="token keyword">def</span> <span class="token function">paint_car</span> <span class="token punctuation">(</span> car <span class="token punctuation">)</span> car <span class="token punctuation">[</span> <span class="token symbol">:color</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'Red'</span> <span class="token keyword">end</span> |
Use default arguments instead of conditions
The default argument is usually cleaner than the condition. Please note that if you use them, your method will only provide default values for unknown arguments. Other “falsy” values like false and nil will not be replaced with the default values. Bad:
1 2 3 4 5 |
<span class="token keyword">def</span> <span class="token function">create_micro_brewery</span> <span class="token punctuation">(</span> name <span class="token punctuation">)</span> brewery_name <span class="token operator">=</span> name <span class="token operator">||</span> <span class="token string">'Hipster Brew Co.'</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> |
Good:
1 2 3 4 |
<span class="token keyword">def</span> <span class="token function">create_micro_brewery</span> <span class="token punctuation">(</span> brewery_name <span class="token operator">=</span> <span class="token string">'Hipster Brew Co.'</span> <span class="token punctuation">)</span> <span class="token comment"># ...</span> <span class="token keyword">end</span> |
next
Clean Code Ruby – Methods (comming soon)