Naming Conventions in Ruby

From Logic Wiki
Jump to: navigation, search


Source Codes Layout

  • 2 space indent no tabs
  • Use Unix-style line endings
  • Don't use ; to separate statements and expressions. As a corollary - use one expression per line
  • Prefer a single-line format for class definitions with no body
  • Avoid single-line methods. (exception : empty-body methods.)
  • Use spaces around operators, after commas, colons and semicolons, around { and before }.
  • No spaces after (, [ or before ], )
  • No space after !
  • No space inside range literals.
  • Indent when as deep as case.
case
when song.name == 'Misty'
  puts 'Not again!'
when song.duration > 120
  puts 'Too long!'
when Time.now.hour > 21
  puts "It's too late"
else
  song.play
end
  • Use empty lines between method definitions and also to break up methods into logical paragraphs internally
  • Avoid comma after the last parameter in a method call, especially when the parameters are not on separate lines
  • Use spaces around the = operator when assigning default values to method parameters
  • Avoid line continuation \ where not required.
  • Align the parameters of a method call if they span more than one line. When aligning parameters is not appropriate due to line-length constraints, single indent for the lines after the first is also acceptable
# bad (double indent)
def send_mail(source)
  Mailer.deliver(
      to: 'bob@example.com',
      from: 'us@example.com',
      subject: 'Important message',
      body: source.text)
end

# good
def send_mail(source)
  Mailer.deliver(to: 'bob@example.com',
                 from: 'us@example.com',
                 subject: 'Important message',
                 body: source.text)
end

# good (normal indent)
def send_mail(source)
  Mailer.deliver(
    to: 'bob@example.com',
    from: 'us@example.com',
    subject: 'Important message',
    body: source.text
  )
end
  • Add underscores to large numeric literals to improve their readability
num = 1_000_000
  • Limit lines to 80 characters

Syntax

  • Use def with parentheses when there are parameters. Omit the parentheses when the method doesn't accept any parameters
  • Do not use for, unless you know exactly why. Most of the time iterators should be used instead. for is implemented in terms of each (so you're adding a level of indirection), but with a twist - for doesn't introduce a new scope (unlike each) and variables defined in its block will be visible outside it
  • Do not use then for multi-line if/unless
  • Favor the ternary operator(?:) over if/then/else/end constructs.
  • Use one expression per branch in a ternary operator. This also means that ternary operators must not be nested
  • Leverage the fact that if and case are expressions which return a result.
# bad
if condition
  result = x
else
  result = y
end

# good
result =
  if condition
    x
  else
    y
  end
  • Use ! instead of not
  • The and and or keywords are banned. It's just not worth it. Always use && and || instead
  • Favor modifier if/unless usage when you have a single-line body. Another good alternative is the usage of control flow &&/||
# bad
if some_condition
  do_something
end

# good
do_something if some_condition

# another good option
some_condition && do_something
  • Do not use unless with else. Rewrite these with the positive case first.
  • Don't use parentheses around the condition of an if/unless/while/until
  • Avoid return where not required for flow of control.
  • Avoid self where not required. (It is only required when calling a self write accessor.)
  • Use ||= to initialize variables only if they're not already initialized
# bad
name = name ? name : 'Bozhidar'

# bad
name = 'Bozhidar' unless name

# good - set name to Bozhidar, only if it's nil or false
name ||= 'Bozhidar'
  • Use the new lambda literal syntax for single line body blocks. Use the lambda method for multi-line blocks
# bad
l = lambda { |a, b| a + b }
l.call(1, 2)

# correct, but looks extremely awkward
l = ->(a, b) do
  tmp = a * 7
  tmp * b / 50
end

# good
l = ->(a, b) { a + b }
l.call(1, 2)

l = lambda do |a, b|
  tmp = a * 7
  tmp * b / 50
end
  • Don't omit the parameter parentheses when defining a stabby lambda with parameters.
# bad
l = ->x, y { something(x, y) }

# good
l = ->(x, y) { something(x, y) }
  • Prefer proc over Proc.new
# bad
p = Proc.new { |n| puts n }

# good
p = proc { |n| puts n }
  • Don't use count as a substitute for size.

Naming

  • Name identifiers in English
  • Use snake_case for symbols, methods and variables.
  • Use CamelCase for classes and modules. (Keep acronyms like HTTP, RFC, XML uppercase.)
  • Use snake_case for naming files, e.g. hello_world.rb
  • Use snake_case for naming directories, e.g. lib/hello_world/hello_world.rb
  • Aim to have just a single class/module per source file. Name the file name as the class/module, but replacing CamelCase with snake_case.
  • Use SCREAMING_SNAKE_CASE for other constants.

Comments

  • If multiple lines are required to describe the problem, subsequent lines should be indented three spaces after the # (one general plus two for indentation purpose
  • Use TODO to note missing features or functionality that should be added at a later date.
  • Use FIXME to note broken code that needs to be fixed.
  • Use OPTIMIZE to note slow or inefficient code that may cause performance problems.
  • Use HACK to note code smells where questionable coding practices were used and should be refactored away.
  • Use REVIEW to note anything that should be looked at to confirm it is working as intended. For example: REVIEW: Are we sure this is how the client does X currently?
  • Use other custom annotation keywords if it feels appropriate, but be sure to document them in your project's README or similar.

Classes & Modules

  • Use a consistent structure in your class definitions
class Person
  # extend and include go first
  extend SomeModule
  include AnotherModule

  # inner classes
  CustomErrorKlass = Class.new(StandardError)

  # constants are next
  SOME_CONSTANT = 20

  # afterwards we have attribute macros
  attr_reader :name

  # followed by other macros (if any)
  validates :name

  # public class methods are next in line
  def self.some_method
  end

  # initialization goes between class methods and other instance methods
  def initialize
  end

  # followed by other public instance methods
  def some_method
  end

  # protected and private methods are grouped near the end
  protected

  def some_protected_method
  end

  private

  def some_private_method
  end
end
  • Don't nest multi line classes within classes. Try to have such nested classes each in their own file in a folder named like the containing class
# bad

# foo.rb
class Foo
  class Bar
    # 30 methods inside
  end

  class Car
    # 20 methods inside
  end

  # 30 methods inside
end

# good

# foo.rb
class Foo
  # 30 methods inside
end

# foo/bar.rb
class Foo
  class Bar
    # 30 methods inside
  end
end

# foo/car.rb
class Foo
  class Car
    # 20 methods inside
  end
end
  • Prefer modules to classes with only class methods. Classes should be used only when it makes sense to create instances out of them