styleguide - naiieandrade/2017.2-Desenho GitHub Wiki

  1. Header
  2. Indentation and Spacing
  3. Syntax
  4. Naming
  5. Comments
  6. Classes and Modules
  7. Exceptions
  8. Collections
  9. References

1. Header

The header must content the class name, file name and description of the class.

#############################################
# File name: comments_controller.rb
# Class name: CommentsController
# Description: Controller used to communicate with the view highways/show
#############################################

2. Indentation and Spacing

The indentation levels are defined with two spaces instead of a TAB. Each line must contain a maximum of 80 characters, and a single blank line must be used to separate methods from a class, or logical blocks within methods.

#wrong
def enterprise_group_ranking

  @quantity = params[:sanctions_count]
  @enterprises = Enterprise.where(sanctions_count: @quantity).paginate(:page => params[:page], :per_page => 10)

end
def payment_group_ranking

  @quantity = params[:payments_count]
  @enterprises = Enterprise.where(payments_count: @quantity).paginate(:page => params[:page], :per_page => 10)

end

#right
def enterprise_group_ranking
  @quantity = params[:sanctions_count]
  @enterprises = Enterprise.where(sanctions_count: @quantity).paginate(:page => params[:page], :per_page => 10)
end

def payment_group_ranking
  @quantity = params[:payments_count]
  @enterprises = Enterprise.where(payments_count: @quantity).paginate(:page => params[:page], :per_page => 10)
end
  • Classes with no body definitions are not defined in a single-line format.
#wrong
PaymentClass = Class.new(Payment)

#right
class Payment < ActiveRecord::Base
    #content starts here
end
  • Spaces are used after:
    • commas
    • colons
    • operators
    • semicolons
    • Spaces are also used before operators.
    • The exception regarding operators is the exponent operator.
    • No spaces are used after !.
#wrong
array = [ element1,element2,element3 ]

puts "( I'm a string )"
puts "[ I'm a string ]"
puts "{ I'm a string }"

range1 = (1 .. 10)

exponent_variable = 2**5

false_boolean = ! true

#right
array = [element1, element2, element3]

puts "(I'm a word)"
puts "[I'm a string]"
puts "{I'm a string}"

range1 = (1..10)

exponent_variable = 2 ** 5

false_boolean = !true
  • No spaces are used inside range operators.
  • The when statement is indented one level deeper than case statement.
#wrong
case
when variable.action == ''
  puts 'Case 1'
when variable.action == 'variable_action'
  puts 'Case 2'
when variable.action == 'wrong_variable_action'
  puts 'Case 3'
else
  variable.action
end

#right
case
  when variable.action == ''
    puts 'Case 1'
  when variable.action == 'variable_action'
    puts 'Case 2'
  when variable.action == 'wrong_variable.action'
    puts 'Case 3'
else
  variable.action
end
  • Parameters of method calls, when spamming more than one line, are indented.
#wrong
def a_simple_method ( argument_one, argument_two, argument_three, argument_four,argument_five, argument_six, argument_seven)
  #content starts here
end

#right
def a_simple_method ( argument_one,
                      argument_two,
                      argument_three,
                      argument_four,
                      argument_five,
                      argument_six,
                      argument_seven )
  #content starts here
end

3. Syntax

  • Every variable must be initialized.
#wrong
user_name
user_age

#right
user_name = ""
user_age = 0
  • :: is used only for constants and constructors. Not for regular method invocation.
#wrong
PaymentClass::payment_class_method

#right
PaymentClass.payment_class_method
EnterpriseModule::EnterpriseSomeClass::SOME_CONST
  • Optional parameters are defined at the end of the parameters list. Each must be used instead of for, unless it is unavoidable.
#wrong
def last_sanction
  sanctions = ["section1","section2","section3"]

  for sanction in sanctions
    puts sanction
  end
end

#right
def last_sanction
  sanctions = ["section1", "section2", "section3"]

  sanctions.each do |sanction|
    puts sanction
  end
end
  • Use if/else statement to express conditions. The condition of a if/else statement is written on the same line and between parenthesis.
#wrong
if 5 > 4
  puts "It's true"
end

#right
if (5 > 4)
  puts "It's true"
end
  • Every if statement must have an additional else statement.
#wrong
user_name = "Bob"

if(user_name != nil)
  puts user_name
end

#right
if( user_name != nil )
  puts user_name
else
  # nothing to do!
end
  • Only one expression per line is used in the body of a constructor, like if/else. comment: # (* The nested form if x;... must not be used.)
  • Ternary Operator ?: must not be used. if/then/else/end must be used instead.
  • The operator ! must be used instead of not.
  • The operators && and || must not be used. Instead, are used the keywords and and or.
#wrong
if (5 > 4 && 6 > 5)
  puts "It's true"
else
  # nothing to do!
end

if (5 > 4 || 6 > 5)
  puts "It's true"
else
  # nothing to do!
end

#right

if (5 > 4 and 6 > 5)
  puts "It's true"
else
  # nothing to do!
end

if (5 > 4 or 6 > 5)
  puts "It's true"
else
  # nothing to do!
end

unless must not be used with else. if must be used instead.

  • Parenthesis around parameters of methods that are part of an internal DSL, such as Rake, Rails or RSpec, methods that have a keyword status in Ruby, like attr_reader or puts, and attribute access methods, must be omitted. In any other methods, parenthesis must be used around parameters.
#wrong
class Payment
  attr_reader(:name, :date)
  # content starts here
end

#right
class Payment
  attr_reader :value, :date
  # content starts here
end
  • Logical operators and and or should replace && and || in logical expressions.
#wrong
incorrect_logic = is_fuit and (is_red or is_orange)

#right
correct_logic = is_fuit && (is_red || is_orange)

4. Naming

  • Names are defined in english.

  • Class names are PascalCase.

  • snake_case is used for:

    • symbols
    • methods
    • variables
    • naming files
    • naming directories
#wrong
def LastPayment
  puts paymentVariable
end

#right
def last_payment
  puts payment_variable
end
#wrong
sanctioType.rb
#right
sanction_type.rb
#wrong
App/allModels/sanction_type.rb

#right
app/all_models/sanction_type.rb
#wrong
class User_controller < ActiveRecord::Base
  #class content
end

#right
class UserController < ActiveRecord::Base
  # class content
end
  • SCREAMING_SNAKE_CASE is used for constants and global variables.
#wrong
constant_sanction = "I'm a constant"

#right
CONSTANT_SANCTION = "I'm a constant"

5. Comments

  • Use block comments instead of single line comments.
#wrong
=begin
comment line
another comment line
=end

#right
# good
# Comment line.
# Another comment line.
  • Comments are written in english.
  • Comments longer than one word are Capitalized, and end with a period. A space is used after a period.
#wrong

# i'm a long comment, you should've notice that my lenght is being
# greater quickly

#right

# I'm a long comment, you should've notice that my lenght is being
# Greater quickly.
  • Comments of each method must have description,parameters and its return.
# Description: Searchs for a enterprise according the params sent by user,
# once did it, return a set of enterprises with pagination.
# Parameters: none.
# Return: @enterprises.

6. Classes and Modules

  • Classes must have a consistent structure. The class definition is followed by, in this order: extendand include, inner classes, constants, attribute macros, other macros (if any), public class methods, initializations, public instance methods, and, near the end, protected and private methods.
class Payment
  # 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
  # content starts here
end

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

  # followed by other public instance methods
  def some_method
    # content starts here
  end

  # protected and private methods are grouped near the end
  protected

  def some_protected_method
     # content starts here
  end

  private

  def some_private_method
     # content starts here
  end

end
  • Multi-line classes must not be nested. Instead, each class must have its own file.
#wrong
# foo.rb
class User
  class Payment
    # 30 methods inside
end

class State
  # 20 methods inside
    end
  # 30 methods inside
end

#right
# foo.rb
class User
  # 30 methods inside
end

# foo/bar.rb
class User
    class Payment
        # 30 methods inside
    end
end

# foo/car.rb
class User
  class State
    # 20 methods inside
  end
end
  • Modules should be preferred instead of classes, if they only have class methods. A class should only be created if it makes sense to do so.
#wrong
class UserClass
  def self.some_method
    # content starts here
  end

  def self.some_other_method
    # content starts here
  end
end

#right
module SomeModule
  module_function

  def some_method
    # content starts here
  end

  def some_other_method
    # content starts here
  end
end
  • The attr functions must be used to define trivial accessors or mutators.
#wrong
class OneClass
  def initialize(value, date)
    @date = date
    @date = date
  end

  def value
    @value
  end

  def date
    @date
  end

end

#right
class OneClass
  attr_reader :value, :date

  def initialize(value, date)
    @value = value
    @date = date
  end

end
  • attr_reader and attr_accessor must be used instead of attr.
# wrong
attr :value, true
attr :one, :two, :three

# right
attr_accessor :value
attr_reader :one, :two, :three
  • Class variables @@ must not be used.

  • Visibility levels to methods, like public, protected, private, must be used properly, depending on the method and its functionality and objective.

  • The visibility method must be indented on the same level as the method they apply to. One blank line must be used above and below the visibility level.

class Payment
  def public_method
    # content starts here
  end

  private

  def another_private_method
    # content starts here
    end

end

self.method must be used to define class methods.

class User
  self.user_self_method
    # content starts here
  end

end

7. Exceptions

  • Exceptions are signaled with the fail method. The raise method must be used only when purposely raising the exception.

  • RuntimeError must not be explicitly specified in fail/raise.

  • fail/raise must not be used with an exception instance, instead being used with an exception and a message as arguments.

#wrong
fail PaymentException.new('message')
# Note that there is no way to do `fail SomeException.new('message'), backtrace`.

#right
fail PaymentException, 'message'
# Consistent with `fail SomeException, 'message', ba´cktrace`.

8. Collections

  • Array and hash creation notation must be used in its literal form.
#wrong
array = %w(here have an array)

#right
array = ['here',  'have',  'an', 'array']
  • Comma after the last item of an array or hash must not be used.
#wrong
array = ['here',  'have',  'an', 'array
', ]

#right
array = ['here',  'have',  'an', 'array']
  • first and last must be used accessing the first or last item of an array or hash, instead of [0] or [-1].
#wrong
First_element = array[0]

#right
First_element = array.first
  • Symbols must be used instead of strings as hash keys, unless for some reason unavoidable.
#wrong
hash = {'key1' => 1, 'key2' => 2, 'key3' => 3}

#right
hash = {key1: 1, key2: 2, key3: 3}
  • Hash keys must follow the Ruby 1.9 hash literal syntax , being composed of the symbol name, followed by a colon and the key value.
#wrong
hash = {:key1 => 1, :key2 => 2, :key3 => 3}

#right
hash = {key1: 1, key2: 2, key3: 3}
  • If there is a key that is not a symbol in a hash, the hash rocket syntax must be used for all keys instead of the Ruby 1.9 hash literal syntax.
#wrong
{key_a: 1, 'key_b': 2}

#right
{:key_a => 1, 'key_b' => 2}