svs.io
← Back to blogClarity over Brevity in Method Calls
A method name is actually just one part of a method invocation and since methods take arguments, one can use the arguments to provide a lot more clarity of what the method is doing than simply restricting oneslef to the method name. Infact, methods with names like make_person_an_outside_subscriber_if_all_accesses_revoked
are just begging for a plethora of methods like make_person_an_inside_subscriber_if_all_accesses_not_revoked
, make_person_an_outside_observer_if_some_accesses_revoked
and so on. I am not sure I would like to work with such an API, let alone maintain it.
Instead, my suggestion is to for clear method invocations. Clear method invocations are a much better indicator of a well thought out API, where reading and writing the code starts to seem very natural. For example, the above method call would seem just as natural if called as
@person.set_role(:to => :outside_observer, :if => :all_accesses_revoked?)
Just as readable and without the deleterious effects on your API.
Interestingly, the method definition of set_role
suffers a bit, and here’s where we have an aesthetic tradeoff.
class Person | |
attr_accessor :name, :role | |
def initialize(name, role) | |
@name, @role = name, role | |
end | |
# options is a Hash with the following keys | |
# :to -> the role to set to | |
# :if -> a Symbol. This method will be called and must return true in order to set the role | |
def set_role(options) | |
raise ArgumentError.new('Must specify :to and :if') unless options.slice(:to,:if).count < 2 | |
cond = self.send(options[:if]) if options[:if].class == Symbol | |
@role = options[:to] if cond | |
end | |
end | |
p = Person.new("svs",:inside_subscriber) | |
p.set_role(:to => :outside_subscriber, :if => :all_access_revoked?) |
However, I would much rather write some Tomdoc on the method than pollute my API. Clearly this is a matter of choice. The ideal solution of course would be named arguments, which will come in Ruby 2.0.