The Elements of Ruby Style: Predicate Methods
A method that returns true or false is called a "predicate method".
In Ruby, there is a naming convention where predicate methods end with a question mark. For instance, if you have an
Invoice class and are writing an instance method that returns whether the invoice has been paid or not, you would name the method
This idiom helps improve readability by making Ruby code read more like English:
puts "This invoice has been paid" if invoice.paid?
Predicate methods should always return
false. Because of the way that Ruby evaluates truthiness (
nil are false; everything else evaluates to true) some people will advocate simply returning a "truthy" value. An implementation of
Invoice#paid? that was truthy could look like this:
class TruthyInvoice attr_accessor :paid_at def paid? @paid_at end end invoice = TruthyInvoice.new invoice.paid? # nil invoice.paid_at = Time.now invoice.paid? # 2012-03-24 20:45:59 -0400
The above implementation of
paid? will work fine in conditionals.
However, the intent of the
paid? method is to tell you if the invoice has been paid, yet it is returning an instance of
Time. This is confusing. The method would better represent the author's intent if it always returned a boolean. The most common way to ensure that a method returns true or false is to use the not operator (
!) twice. This is read "not not" and would be used as follows:
class Invoice attr_accessor :paid_at def paid? !!@paid_at end end invoice = Invoice.new invoice.paid? # false invoice.paid_at = Time.now invoice.paid? # true
Using "not not" only requires two more keystrokes and it more closely matches the intent of the method. One of the maxims of good programming is to "be liberal in what you accept and strict in what you emit". Returning a boolean from predicate methods is being strict in what you emit.
More Articles on Software & Product Development
- Agile With a Lowercase “a”
- ”Agile“ is an adjective. It is not a noun. It isn’t something you do, it is something you are.
- How Do You End Up With A Great Product A Year From Now?
- Nail the next two weeks. 26 times in a row.
- Build it Twice
- Resist the urge to abstract until you've learned what is general to a class of problems and what is specific to each problem.