Clarity 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.