Sonntag, 19. April 2015

Follow the Ruby styleguide entirely! pt. 2

Programming styleguides are less a matter of taste. They are way more a matter of optimizing code readability. And following styleguides reveals own perception that others will read the code.
Code is communication. So programming styleguides are important!

1. Ternary Operator

Favor the ternary operator(?:) over if/then/else/end constructs for one liners. It is more common and obviously more concise.
# bad
result = if language.dynamic? then 'Awesome!' else 'Huh.' end

# good
result = language.dynamic? ? 'Awesome!' : 'Huh.'

2. Preprocess variables

Use &&= to preprocess variables that may or may not exist. Using &&= will change the value only if it exists, removing the need to check its existence with if.
# bad
if name
  name = name.downcase
end

# bad (even worse)
name = name ? name.downcase : nil

# ok
name = name.downcase if name

# good
name = name && name.downcase

# better
name &&= name.downcase

3. Indent case whens

Indent when as deep as case. It is the style established in the "Programming Ruby" (aka the Pickaxe book).
# bad
case language
  when 'Ruby'
    puts 'Awesome!'
  when 'Java'
    puts 'Huh.'
  else
    puts 'Let me see.'
end

# good
case language
when 'Ruby'
  puts 'Awesome!'
when 'Java'
  puts 'Huh.'
else
  puts 'Let me see.'
end

4. Constant references

Use :: only to reference constants (this includes classes and modules) and constructors (like Array() or Nokogiri::HTML()). Do not use :: for regular method invocation.
# bad
ActiveRecord::Base::reflections
Hash::new::keys

# good
ActiveRecord::Base.reflections
Hash.new.keys
ActiveRecord::Reflection::AssociationReflection::VALID_AUTOMATIC_INVERSE_MACROS
Nokogiri::HTML()

5. Procs

Prefer proc over Proc.new.
# bad
Proc.new { |n| puts n }

# good
proc { |n| puts n }

6. Array check

Use [*var] or Array() instead of explicit Array check, when dealing with a variable you want to treat as an Array, but you are not certain it is an array. [link]
# bad
paths = [paths] unless paths.is_a? Array
paths.each { |path| do_something(path) }

# good
[*paths].each { |path| do_something(path) }

# good (and a bit more readable)
Array(paths).each { |path| do_something(path) }

7. Parameter whitespaces

Use spaces around the = operator when assigning default values to method parameters: [link]
# bad
def do_something(arg1=:default, arg2=nil, arg3=[])
  # do something...
end

# good
def do_something(arg1 = :default, arg2 = nil, arg3 = [])
  # do something...
end
While several Ruby books suggest the first style, the second is much more prominent in practice (and arguably a bit more readable).

8. Multi line method chaning

Adopt a consistent multi-line method chaining style. Use trailing chaining.
When continuing a chained method invocation on another line, include the . on the first line to indicate that the expression continues:
# bad - need to read ahead to the second line to know that 
# the chain continues
one.two.three
  .four

# good - it's immediately clear that the expression continues 
# beyond the first line
one.two.three.
  four

9. Multi line Array literals

Align the elements of array literals spanning multiple lines.
# bad - single indent
languages = ['Ruby', 'Python', 'Java', 'C#', 'Scala',
  'CSS3', 'HTML5', 'XML', 'Javascript']

# good
languages = [
  'Ruby', 'Java', 'C#', 'Scala',
  'CSS3', 'HTML5', 'XML', 'Javascript'
]

# good
languages = 
  ['Ruby', 'Python', 'Java', 'C#', 'Scala',
   'CSS3', 'HTML5', 'XML', 'Javascript']

10. Use && and ||

The and and or keywords are banned. It is just not worth it. Always use && and || instead.
# bad
# boolean expression
if language.dynamic? and language.awesome?
  puts "It must be Ruby"
end

# control flow
language.dynamic? or language.awesome?

# good
# boolean expression
if language.dynamic? && language.awesome?
  puts "It must be Ruby"
end

# control flow
language.dynamic? || language.awesome?

Further articles of interest:

Supported by Ruby 2.2.1 and Ruby on Rails 4.2.0