def foo name, value, state, start_at, end_at, is_new # something weird is going on endNever waste time (money) and cheerfulness by trying to deal with code like the above. Refactor it! There are several options, depending on the use case.
1. Deal with parameter objects!
If the method signature consists of parameters, which are likely to be properties of the same object, it is healthy to assign the entire object itself.class Food attr_accessor :name, :kcal, :freshness_date end class Consumer < Person def eats food_name, kcal, freshness_date return if self.allergies.includes?(food_name) or freshness_date.eql?(Date.today) self.kcal += kcal end endcan be refactored to:
class Consumer < Person def eats food return if self.allergies.includes?(food.name) or food.freshness_date < Date.today self.kcal += food.kcal end endWith parameter objects, the method signature is way more resistant against changes and therefore more stable in the long run. Furthermore if the logic needs to be reused, the method can be extracted into a module easily.
2. Introduce named parameters!
The more generalized the methods logic or the lower the abstraction level, the more the methods parameter list is likely to consist of optional parameters. Sometimes such methods look like:class Food def initialize name, kcal=0, freshness_date=nil, preservative=nil @name = name @kcal = kcal @freshness_date = freshness_date @preservative = preservative end end Food.new 'Apple', nil, nil, falsewhich is awkward (since nil is always a bad choice). It should be refactored to:
class Food def initialize name, options={} @name = name @kcal = options[:kcal] @freshness_date = options[:freshness_date] @preservative = options[:preservative] end end Food.new 'Apple', preservative: falsePlease note the way more expressive object instantiation. Besides adding new optional parameters to the options Hash is easy and does not affect existing code.
3. Replace Parameter with Explicit Methods!
Some use cases do not require a parameter list at all and those parameters should be set explicitly. The object instantiation example again:class Food def initialize name, kcal=0, freshness_date=nil, preservative=nil @name = name @kcal = kcal @freshness_date = freshness_date @preservative = preservative end end Food.new 'Apple', nil, nil, falsebut his time defining values with explicit messages:
class Food attr_accessor :kcal, :freshness_date, :preservative def initialize name @name = name end end apple = Food.new 'Apple' apple.preservative = false
Further articles of interest:
- Express boolean parameters the Ruby way!
- Remove boolean parameters from your Ruby API!
- Chain your Ruby methods!
Supported by Ruby 2.1.1
Keine Kommentare:
Kommentar veröffentlichen