Skip to content
This repository
Newer
Older
100644 421 lines (335 sloc) 11.844 kb
3add7a87 »
2011-09-14 fixed heading
1 # Abstract
dc31232f »
2011-09-12 initial version
2
15e47f1f »
2011-09-14 improved the header a bit
3 ... nearly everybody is convinced that every style but their own is
4 ugly and unreadable. Leave out the "but their own" and they're
5 probably right...
6 --Jerry Coffin (on indentation)
7
e842c369 »
2011-09-12 minor change
8 This document was created when I, as the Technical Lead of the company
d8519e59 »
2011-09-15 fixed a grammar issue
9 which I work for, was asked by the CTO to create some internal documents
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
10 describing good style and best practices for Ruby programming. I started off
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
11 by building upon
dc31232f »
2011-09-12 initial version
12 [this existing style guide](https://github.com/chneukirchen/styleguide),
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
13 since I concurred with most of the points in it. I hope it will be useful to
14 other people as well and I hope that I'll get a lot of feedback and
15 suggestions on how to improve the guide for the benefit of the entire Ruby
16 community.
dc31232f »
2011-09-12 initial version
17
18 ## Formatting
19
20 * Use UTF-8 as the source file encoding.
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
21 * Use two space indent, no tabs. (Your editor/IDE should have a setting to
22 help you with that.)
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
23 * Use Unix-style line endings. (Linux/OSX users are covered by default,
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
24 Windows users have to be extra careful.)
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
25 * If you're using Git you might want to do `$ git config --global
26 core.autocrlf true` to protect your project from Windows line endings
27 creeping into your project.
28 * Use spaces around operators, after commas, colons and semicolons, around {
29 and before }.
dc31232f »
2011-09-12 initial version
30
e7998adb »
2011-09-13 another try
31 ```Ruby
32 sum = 1 + 2
33 a, b = 1, 2
34 1 > 2 ? true : false; puts "Hi"
35 [1, 2, 3].each { |e| puts e }
36 ```
dc31232f »
2011-09-12 initial version
37
4999e13e »
2011-09-14 Grammatical fix on line 28.
38 * No spaces after (, [ or before ], ).
dc31232f »
2011-09-12 initial version
39
2681d4b8 »
2011-09-13 added highlighting to all examples
40 ```Ruby
41 some(arg).other
42 [1, 2, 3].length
43 ```
dc31232f »
2011-09-12 initial version
44
7e83122a »
2011-09-16 improved formatting
45 * Indent `when` as deep as `case`. (As suggested in the Pickaxe.)
dc31232f »
2011-09-12 initial version
46
2681d4b8 »
2011-09-13 added highlighting to all examples
47 ```Ruby
48 case
49 when song.name == "Misty"
00032bf4 »
2011-09-16 Fix examples for "case"
50 puts "Not again!"
51 when song.duration > 120
52 puts "Too long!"
53 when Time.now.hour > 21
2681d4b8 »
2011-09-13 added highlighting to all examples
54 puts "It's too late"
55 else
56 song.play
57 end
58
59 kind = case year
60 when 1850..1889 then "Blues"
61 when 1890..1909 then "Ragtime"
1f379fc7 »
2011-09-15 fix typo
62 when 1910..1929 then "New Orleans Jazz"
63 when 1930..1939 then "Swing"
2681d4b8 »
2011-09-13 added highlighting to all examples
64 when 1940..1950 then "Bebop"
65 else "Jazz"
66 end
67 ```
dc31232f »
2011-09-12 initial version
68
69 * Use an empty line before the return value of a method (unless it
7e83122a »
2011-09-16 improved formatting
70 only has one line), and an empty line between `def`s.
dc31232f »
2011-09-12 initial version
71
2681d4b8 »
2011-09-13 added highlighting to all examples
72 ```Ruby
73 def some_method
74 do_something
75 do_something_else
dc31232f »
2011-09-12 initial version
76
2681d4b8 »
2011-09-13 added highlighting to all examples
77 result
78 end
dc31232f »
2011-09-12 initial version
79
2681d4b8 »
2011-09-13 added highlighting to all examples
80 def some_method
81 result
82 end
83 ```
84
dc31232f »
2011-09-12 initial version
85 * Use RDoc and its conventions for API documentation. Don't put an
7e83122a »
2011-09-16 improved formatting
86 empty line between the comment block and the `def`.
dc31232f »
2011-09-12 initial version
87 * Use empty lines to break up a method into logical paragraphs.
9872e4e3 »
2011-09-14 Moved Emacs stuff to parentheses.
88 * Keep lines fewer than 80 characters. (Emacs users should really have a look
89 at whitespace-mode.)
90 * Avoid trailing whitespace. (Emacs users: Whitespace-mode again comes to the
91 rescue.)
dc31232f »
2011-09-12 initial version
92
93 ## Syntax
94
7e83122a »
2011-09-16 improved formatting
95 * Use `def` with parentheses when there are arguments. Omit the
2681d4b8 »
2011-09-13 added highlighting to all examples
96 parentheses when the method doesn't accept any arguments.
97
98 ```Ruby
99 def some_method
100 # body omitted
101 end
dc31232f »
2011-09-12 initial version
102
2681d4b8 »
2011-09-13 added highlighting to all examples
103 def some_method_with_arguments(arg1, arg2)
104 # body omitted
105 end
106 ```
dc31232f »
2011-09-12 initial version
107
7e83122a »
2011-09-16 improved formatting
108 * Never use `for`, unless you know exactly why. Most of the time iterators
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
109 should be used instead.
2681d4b8 »
2011-09-13 added highlighting to all examples
110
111 ```Ruby
112 arr = [1, 2, 3]
da7a8446 »
2011-09-12 Minor formatting issue
113
2681d4b8 »
2011-09-13 added highlighting to all examples
114 # bad
115 for elem in arr do
116 puts elem
117 end
dc31232f »
2011-09-12 initial version
118
2681d4b8 »
2011-09-13 added highlighting to all examples
119 # good
120 arr.each { |elem| puts elem }
121 ```
122
7e83122a »
2011-09-16 improved formatting
123 * Never use `then` for multiline `if/unless`.
dc31232f »
2011-09-12 initial version
124
2681d4b8 »
2011-09-13 added highlighting to all examples
125 ```Ruby
126 # bad
127 if x.odd? then
128 puts "odd"
129 end
130
131 # good
132 if x.odd?
133 puts "odd"
134 end
135 ```
dc31232f »
2011-09-12 initial version
136
7e83122a »
2011-09-16 improved formatting
137 * Favor `if/then/else` over the ternary operator. *if* is an
5e0a7a01 »
2011-09-14 a few improvements
138 expression in Ruby and the resulting code is arguably easier to
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
139 read (albeit not as concise). Remember that _"Programs must be written for
140 people to read, and only incidentally for machines to execute."_ (Abelson
141 and Sussman)
5e0a7a01 »
2011-09-14 a few improvements
142
143 ```Ruby
144 # good
145 result = if some_condition then something else something_else end
146
147 # not so good
148 result = some_condition ? something : something_else
149 ```
150
ee895ddd »
2011-09-16 fixed the single line when rule and added a couple of new rules
151 * Never use `if x; ...` - it is deprecated in Ruby 1.9. Use
152 `if/then/else` instead.
153
154 ```Ruby
155 # bad
156 result = if some_condition; something else something_else end
157
158 # good
159 result = if some_condition then something else something_else end
160 ```
161
162 * Use `when x then ...` for one-line cases. The alternative syntax
163 `when x; ...` is deprecated in Ruby 1.9.
164
7e83122a »
2011-09-16 improved formatting
165 * Use `&&/||` for boolean expressions, `and/or` for control flow. (Rule
dc31232f »
2011-09-12 initial version
166 of thumb: If you have to use outer parentheses, you are using the
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
167 wrong operators.)
a5e10afb »
2011-09-14 added another example
168
169 ```Ruby
170 # boolean expression
171 if some_condition && some_other_condition
172 do_something
173 end
174
175 # control flow
176 document.saved? or document.save!
177 ```
178
7e83122a »
2011-09-16 improved formatting
179 * Avoid multiline ?: (the ternary operator), use `if/unless` instead.
180 * Favor modifier `if/unless` usage when you have a single-line
181 body. Another good alternative is the usage of control flow `and/or`.
dc31232f »
2011-09-12 initial version
182
2681d4b8 »
2011-09-13 added highlighting to all examples
183 ```Ruby
184 # bad
185 if some_condition
186 do_something
187 end
dc31232f »
2011-09-12 initial version
188
2681d4b8 »
2011-09-13 added highlighting to all examples
189 # good
190 do_something if some_condition
191
192 # another good option
45feb66b »
2011-09-14 minor improvement
193 some_condition and do_something
2681d4b8 »
2011-09-13 added highlighting to all examples
194 ```
dc31232f »
2011-09-12 initial version
195
7e83122a »
2011-09-16 improved formatting
196 * Favor `unless` over `if` for negative conditions (or control
197 flow `or`).
2681d4b8 »
2011-09-13 added highlighting to all examples
198
199 ```Ruby
200 # bad
201 do_something if !some_condition
dc31232f »
2011-09-12 initial version
202
2681d4b8 »
2011-09-13 added highlighting to all examples
203 # good
204 do_something unless some_condition
dc31232f »
2011-09-12 initial version
205
2681d4b8 »
2011-09-13 added highlighting to all examples
206 # another good option
a5e10afb »
2011-09-14 added another example
207 some_condition or do_something
2681d4b8 »
2011-09-13 added highlighting to all examples
208 ```
209
dc31232f »
2011-09-12 initial version
210 * Suppress superfluous parentheses when calling methods, but keep them
211 when calling "functions", i.e. when you use the return value in the
212 same line.
2681d4b8 »
2011-09-13 added highlighting to all examples
213
214 ```Ruby
215 x = Math.sin(y)
216 array.delete e
217 ```
218
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
219 * Prefer {...} over do...end for single-line blocks. Avoid using {...} for
220 multi-line blocks. Always use do...end for "control flow" and "method
221 definitions" (e.g. in Rakefiles and certain DSLs.) Avoid do...end when
222 chaining.
dc31232f »
2011-09-12 initial version
223
7e83122a »
2011-09-16 improved formatting
224 * Avoid `return` where not required.
dc31232f »
2011-09-12 initial version
225
2681d4b8 »
2011-09-13 added highlighting to all examples
226 ```Ruby
227 # bad
228 def some_method(some_arr)
229 return some_arr.size
230 end
231
232 # good
233 def some_method(some_arr)
234 some_arr.size
235 end
236 ```
dc31232f »
2011-09-12 initial version
237
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
238 * Avoid line continuation (\\) where not required. In practice, avoid using
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
239 line continuations at all.
dc31232f »
2011-09-12 initial version
240
2681d4b8 »
2011-09-13 added highlighting to all examples
241 ```Ruby
242 # bad
ee895ddd »
2011-09-16 fixed the single line when rule and added a couple of new rules
243 result = 1 - \
2681d4b8 »
2011-09-13 added highlighting to all examples
244 2
dc31232f »
2011-09-12 initial version
245
c20ef92d »
2011-09-13 minor fix
246 # good (but still ugly as hell)
2681d4b8 »
2011-09-13 added highlighting to all examples
247 result = 1 \
ee895ddd »
2011-09-16 fixed the single line when rule and added a couple of new rules
248 - 2
2681d4b8 »
2011-09-13 added highlighting to all examples
249 ```
dc31232f »
2011-09-12 initial version
250
861cf3b9 »
2011-09-14 Made argument naming convention consistent.
251 * Using the return value of = is ok.
dc31232f »
2011-09-12 initial version
252
2681d4b8 »
2011-09-13 added highlighting to all examples
253 ```Ruby
254 if v = array.grep(/foo/) ...
255 ```
dc31232f »
2011-09-12 initial version
256
257 * Use ||= freely.
258
2681d4b8 »
2011-09-13 added highlighting to all examples
259 ```Ruby
260 # set name to Bozhidar, only if it's nil or false
261 name ||= "Bozhidar"
262 ```
dc31232f »
2011-09-12 initial version
263
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
264 * Avoid using Perl-style global variables (like $0-9, $`, ...).
dc31232f »
2011-09-12 initial version
265
266 ## Naming
267
7e83122a »
2011-09-16 improved formatting
268 * Use `snake_case` for methods and variables.
269 * Use `CamelCase` for classes and modules. (Keep acronyms like HTTP,
dc31232f »
2011-09-12 initial version
270 RFC, XML uppercase.)
7e83122a »
2011-09-16 improved formatting
271 * Use `SCREAMING_SNAKE_CASE` for other constants.
ee895ddd »
2011-09-16 fixed the single line when rule and added a couple of new rules
272 * The names of predicate methods (methods that return a boolean value)
273 should end in question mark.
274 (i.e. `Array#empty`).
275 * The names of potentially "dangerous" methods (i.e. methods that modify `self` or the
276 arguments, `exit!`, etc.) should end with exclamation marks.
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
277 * The length of an identifier determines its scope. Use one-letter variables
278 for short block/method parameters, according to this scheme:
dc31232f »
2011-09-12 initial version
279
9259e8cb »
2011-09-12 more indentation fixes
280 a,b,c: any object
281 d: directory names
282 e: elements of an Enumerable
283 ex: rescued exceptions
284 f: files and file names
285 i,j: indexes
286 k: the key part of a hash entry
287 m: methods
288 o: any object
289 r: return values of short methods
290 s: strings
291 v: any value
292 v: the value part of a hash entry
293 x,y,z: numbers
dc31232f »
2011-09-12 initial version
294
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
295 And in general, the first letter of the class name if all objects are of
296 that type.
dc31232f »
2011-09-12 initial version
297
7e83122a »
2011-09-16 improved formatting
298 * When using `inject` with short blocks, name the arguments `|a, e|`
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
299 (accumulator, element).
7e83122a »
2011-09-16 improved formatting
300 * When defining binary operators, name the argument `other`.
2681d4b8 »
2011-09-13 added highlighting to all examples
301
302 ```Ruby
303 def +(other)
304 # body omitted
305 end
306 ```
307
7e83122a »
2011-09-16 improved formatting
308 * Prefer `map` over *collect*, `find` over *detect*, `select` over
309 *find_all*, `size` over *length*. This is not a hard requirement; if the
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
310 use of the alias enhances readability, it's ok to use it.
dc31232f »
2011-09-12 initial version
311
312 ## Comments
313
5de71f67 »
2011-09-14 Combined Steve McConell quote with its parent bullet
314 * Write self documenting code and ignore the rest of this section. _"Good
315 code is its own best documentation. As you're about to add a comment, ask
316 yourself, ‘How can I improve the code so that this comment isn't needed?’
317 Improve the code and then document it to make it even clearer."_ (Steve
318 McConnell)
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
319 * Comments longer than a word are capitalized and use punctuation. Use two
320 spaces after periods.
dc31232f »
2011-09-12 initial version
321 * Avoid superfluous comments.
5e0a7a01 »
2011-09-14 a few improvements
322
323 ```Ruby
324 # bad
325 counter += 1 # increments counter by one
326 ```
327
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
328 * Keep existing comments up-to-date. No comment is better than an outdated
329 comment.
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
330 * Avoid writing comments to explain bad code. Try to refactor the code to
331 make it self-explanatory.
dc31232f »
2011-09-12 initial version
332
c7d87682 »
2011-09-14 started sections on classes and exceptions
333 ## Classes
334
7e83122a »
2011-09-16 improved formatting
335 * Always supply a proper `to_s` method.
336 * Use the `attr` family of functions to define trivial accessors or
c7d87682 »
2011-09-14 started sections on classes and exceptions
337 mutators.
338 * Consider adding factory methods to provide additional sensible ways
339 to create instances of a particular class.
340 * Prefer duck-typing over inheritance.
341 * Avoid the usage of class (@@) variables due to their "nasty" behavior
342 in inheritance.
7e83122a »
2011-09-16 improved formatting
343 * Assign methods proper visibility levels (`private`, `protected`)
c7d87682 »
2011-09-14 started sections on classes and exceptions
344 in accordance with their intended usage. Don't go off leaving
7e83122a »
2011-09-16 improved formatting
345 everything `public` (which is the default). After all we're coding
c7d87682 »
2011-09-14 started sections on classes and exceptions
346 in *Ruby* now, not in *Python*.
347
348 ## Exceptions
349
350 * Don't suppress exceptions.
351 * Don't use exceptions for flow of control.
7e83122a »
2011-09-16 improved formatting
352 * Avoid rescuing the `Exception` class.
c7d87682 »
2011-09-14 started sections on classes and exceptions
353
dc31232f »
2011-09-12 initial version
354 ## Misc
355
7e83122a »
2011-09-16 improved formatting
356 * Write `ruby -w` safe code.
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
357 * Avoid hashes as optional parameters. Does the method do too much?
c7d87682 »
2011-09-14 started sections on classes and exceptions
358 * Avoid methods longer than 10 LOC (lines of code). Ideally most methods will be shorter than
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
359 5 LOC. Empty lines do not contribute to the relevant LOC.
360 * Avoid parameter lists longer than three or four parameters.
7e83122a »
2011-09-16 improved formatting
361 * Use `def self.method` to define singleton methods. This makes the methods
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
362 more resistant to refactoring changes.
dc31232f »
2011-09-12 initial version
363
2681d4b8 »
2011-09-13 added highlighting to all examples
364 ```Ruby
365 class TestClass
366 # bad
367 def TestClass.some_method
368 # body omitted
369 end
370
371 # good
372 def self.some_other_method
373 # body omitted
374 end
375 end
376 ```
dc31232f »
2011-09-12 initial version
377
378 * Add "global" methods to Kernel (if you have to) and make them private.
7e83122a »
2011-09-16 improved formatting
379 * Avoid `alias` when `alias_method` will do.
380 * Use `OptionParser` for parsing complex command line options and
381 `ruby -s` for trivial command line options.
2289a479 »
2011-09-12 fixed a typo
382 * Write for Ruby 1.9. Don't use legacy Ruby 1.8 constructs.
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
383 * Use the new JavaScript literal hash syntax.
384 * Use the new lambda syntax.
7e83122a »
2011-09-16 improved formatting
385 * Methods like `inject` now accept methods names as arguments.
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
386
387 ```Ruby
388 [1, 2, 3].inject(:+)
389 ```
8d46362d »
2011-09-14 formatting fix
390
dc31232f »
2011-09-12 initial version
391 * Avoid needless metaprogramming.
392
393 ## Design
394
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
395 * Code in a functional way, avoiding mutation when it makes sense.
dc31232f »
2011-09-12 initial version
396 * Do not mutate arguments unless that is the purpose of the method.
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
397 * Do not mess around in core classes when writing libraries. (Do not monkey
398 patch them.)
399 * [Do not program
400 defensively.](http://www.erlang.se/doc/programming_rules.shtml#HDR11)
401 * Keep the code simple and subjective. Each method should have a single,
402 well-defined responsibility.
403 * Avoid more than three levels of block nesting.
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
404 * Don't overdesign. Overly complex solutions tend to be brittle and hard to
405 maintain.
406 * Don't underdesign. A solution to a problem should be as simple as
03cbfba6 »
2011-09-14 Edited for grammar and formatting.
407 possible, but no simpler than that. Poor initial design can lead to a lot
408 of problems in the future.
409 * Be consistent. In an ideal world, be consistent with these guidelines.
dc31232f »
2011-09-12 initial version
410 * Use common sense.
5e0a7a01 »
2011-09-14 a few improvements
411
412 # Contributing
413
414 Nothing written in this guide is set in stone. It's my desire to work
415 together with everyone interested in Ruby coding style, so that we could
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
416 ultimately create a resource that will be beneficial to the entire Ruby
417 community.
5e0a7a01 »
2011-09-14 a few improvements
418
9f8ab7b8 »
2011-09-14 Reset lines to 80 characters
419 Feel free to open tickets or send pull requests with improvements. Thanks in
420 advance for your help!
Something went wrong with that request. Please try again.