如何摆脱if语句

时间:2014-12-26 20:20:56

标签: ruby-on-rails ruby design-patterns polymorphism decorator

这是我在Ruby on Rails应用程序中使用的bmr计算的虚假实现。

由于公式仅使用公制单位,因此如果将英制单位设置为用户的默认单位,则必须以某种方式将英制单位转换为公制。

我已经提出了这个代码。

就我个人而言,我认为这类小问题有很多代码。相反,使用多态性将超过工程。 如何改进这段代码?

require 'ostruct'
require 'delegate'

module BmrCalculator
  class Calculator
    def call(sex = :male, measurement_unit = :metric)
      user = OpenStruct.new(sex: sex, weight: 2, height: 2, measurement_unit: measurement_unit)

      if measurement_unit == :imperial #dont like it
        user = ImperialToMetricDecorator.new(user)
      end

      BmrCalculator.new.bmr(user)
    end

    class BmrCalculator
      def bmr(user)
        if user.sex == :male
          puts user.inspect
          puts 1 * user.weight + 2 * user.height + 3 #this formula works only with metric units
        else
          puts user.inspect
          puts 6 * user.weight + 3 * user.height + 5 #this formula works only with metric units
        end
      end
    end
  end

  class ImperialToMetricDecorator < SimpleDelegator
    def height
      (super * 2.54)
    end

    def weight
      (super / 2.2)
    end
  end

  Calculator.new.call(:male, :metric)
end

1 个答案:

答案 0 :(得分:3)

您可以使用OOP并创建有意义的表示来改进代码:

class Length < Float
end

class Feet < Length
  def to_meters
    ..
  end
end

class Meters < Length
  def to_feet
    ..
  end
end

class Gender < Object
end

class Male < Gender
  def bmr(weight)
    ...
  end
end


class Female < Gender
  def bmr(weight)
    ...
  end
end

这可能看起来像一个更多的代码,但它实际上更容易阅读,测试和维护。