Sonntag, 29. März 2015

Create concise Ruby methods!

In the available Ruby method name space there are also method names, which are known from collection classes like Array or Hash. Since they are quite common it is easy to understand the intention of such methods, especially when used in a similar context.
For example a Person class dealing with a bunch of forenames:
class BankAccount
  attr_accessor :attributes
  def initialize attributes={}
    @attributes = attributes.assert_valid_keys :name, :amount
  end

  def add_money money
    @attributes[:amount] += money
  end

  def attribute attribute_name
    @attributes[attribute_name]
  end

  def attribute= attribute_name, value
    @attributes[attribute_name] = value
  end
end
and:
bank_account = BankAccount.new name: 'John', amount: 1000
bank_account.add_money 200
bank_account.attribute :amount
=> 1200
bank_account.attribute :amount, 2000
bank_account.attribute :amount
=> 2000
can be refactored to:
class BankAccount
  attr_accessor :attributes
  def initialize attributes={}
    @attributes = attributes.assert_valid_keys :name, :amount
  end

  def << money
    @attributes[:amount] += money
  end

  def [] attribute_name
    @attributes[attribute_name]
  end

  def []= attribute_name, value
    @attributes[attribute_name] = value
  end
end
Sending the messages is not only less typing but more important it is way more clear what happens:
bank_account = BankAccount.new name: 'John', amount: 1000
bank_account << 200
bank_account[:amount]
=> 1200
bank_account[:amount] = 2000
bank_account[:amount]
=> 2000

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8

Sonntag, 22. März 2015

Mark dangerous Ruby methods!

Methods that perform a permanent change to the object itself are potentially dangerous. That is why those methods should be marked with an exclamation mark at the end.
For example:
class BankAccount
  attr_accessor :amount
  def initialize amount
    @amount = amount
  end

  def withdraw_money amount
    @amount -= amount
  end
end
should be refactored to:
class BankAccount
  attr_accessor :amount
  def initialize amount
    @amount = amount
  end

  def withdraw_money! amount
    @amount -= amount
  end
end
and using it makes definitely clear, that the money is withdrawn permanently:
bank_account = BankAccount.new 1000
bank_account.withdraw_money! 200
=> 800
person.amount
=> 800

Supported by Ruby 2.1.1

Sonntag, 15. März 2015

Mark boolean methods in Ruby!

Some methods are special. They return a boolean value. Ruby has a convention for them: a question mark at the end.
The code:
class Person
  attr_accessor :age
  def intialize attributes={}
    @age = attributes[:age]
  end

  def is_adult
    @age > 18
  end
end
person = Person.new age: 20
person.is_adult
=> true
What does it express? Does it mean "The person is an adult" or does it ask "Is the person an adult"?
To make things clear the Ruby way is putting a question mark at the methods end:
class Person
  attr_accessor :age
  def intialize attributes={}
    @age = attributes[:age]
  end

  def adult?
    @age > 18
  end
end
person = Person.new age: 20
person.adult?
=> true
Using a question mark for boolean methods leaves no question.

Supported by Ruby 2.1.1

Sonntag, 8. März 2015

Avoid get or set prefixes in Ruby method names!

Getter and setter methods marked with get or set as prefix are from Java land, because it is an inflexible language.
Ruby is flexible and therefore provides a more concise way. A Javaish looking:
class Person
  def get_age
    @age
  end

  def set_age age
    @age = age
  end
end
should be refactored to:
class Person
  def age
    @age
  end

  def age= age
    @age = age
  end
end
Apart from using attr_accessor in those simple cases, it allows to send a more meaningful message:
person = Person.new
person.age = 30
person.age

Supported by Ruby 2.1.1

Sonntag, 1. März 2015

Prevent negations in Ruby!

Programming is about the communication between human being and the machine. So it is all about readable codes. That said, there are still some basic coding techniques widely used, which are less readable. Negation is one of them.
For example, it is common in Ruby to:
![1, 2, 3].empty?
=> true
in comparison to:
[1, 2, 3].any?
=> true
Asking for values is more straight forward than asking for not being empty. It removes the baggage of negation. Another example:
!"Ruby".blank?
=> true
can be refactored to:
"Ruby".present?
=> true
Object#present? is a monkey patch in Ruby on Rails, which is exactly the negation Object#blank? behind the scenes. But it is way more intentional.
Furthermore never do something like:
!11.even?
=> true
but instead:
11.odd?
=> true
The last negation example is not that awkward apparently:
puts "Non zero" unless 1.zero?
=> "Non zero"
but also can be refactored to the more optimistic:
puts "Non zero" if 1.nonzero?
=> "Non zero"
Please note that the Numeric#nonzero? returns self if the number is not zero (which is truish), nil (equated with false) otherwise.
Preventing negations is also about the own API. Hiding negations behind the API is absolutely reasonable.
Stay positive!
Further articles of interest:

Supported by Ruby 2.1.1 and Ruby on Rails 4.1.8