功能标记最佳实践:方法内部或外部的条件?

时间:2013-05-14 10:35:24

标签: ruby design-patterns feature-detection

我们正在使用功能标记来启用/禁用系统中的某些功能。

我与我的同事讨论了为代码本身添加功能标志的标准方法:

考虑以下方法:

def featured_method
  do_this
  do_that
end

从我们代码中的大约15个不同的地方调用该方法。

如果在每次调用此方法之前启用该功能,是否建议添加检查:

if feature_enabled?(:feature_key)
  featured_method
end

或者在feature_method本身内部,像这样:

def featured_method
  if feature_enabled?(:feature_key)
    do_this
    do_that
  end
end

在方法本身内部具有条件的优点是显而易见的:干掉代码,以及当您想要永久添加特征时,只需从方法中删除条件。

在每次调用之前拥有条件的优点是,如果不进入featured_method代码本身就可以执行该方法是非常清楚的,这可以节省很多麻烦。

我想知道这些问题是否有另一种解决方案或标准。

2 个答案:

答案 0 :(得分:3)

我会合并两种方法。

这将导致呼叫方的DRY代码。它不会违反feature_method中的SRP,它会清楚地传达正在发生的事情 - 如果你能找到一个比我更好的名字:

def may_execute_featured_method
  featured_method if feature_enabled?(:feature_key)
end

def featured_method
  do_this
  do_that
end

来电者将使用may_execute_featured_method

答案 1 :(得分:1)

我很想将功能键控分成自己的模块,并像这样使用它:

class Foo

  include FeatureKeyed

  def foo
    'foo'
  end
  feature_keyed :foo

  def bar
    'bar'
  end
  feature_keyed :bar

end

foo = Foo.new
p foo.foo    # => "foo"
p foo.bar    # => FeatureKeyed::FeatureDisabled

这是模块:

module FeatureKeyed

  class FeatureDisabled < StandardError ; end

  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods

    def feature_keyed(method_name, feature_key = method_name)
      orig_method = instance_method(method_name)
      define_method method_name do |*args|
        raise FeatureDisabled unless feature_enabled?(feature_key)
        orig_method.bind(self).call *args
      end
    end

  end

  def feature_enabled?(feature_key)
    feature_key == :foo
  end

end

注意:

  • FEATURE_ENABLED?对已启用的功能名称进行硬编码。你会改变它。
  • 如果禁用某项功能,此代码会引发异常。您问题中的代码只会返回。做你的应用程序有意义的事情。如果您需要针对不同方法使用不同的“未启用”行为,则可以将该行为传递给feature_keyed。
  • 方法_feature_keyed_将采用第二个参数,即功能键。如果缺少,则将该方法的名称用作功能键。