4

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

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

考虑以下方法:

def featured_method
  do_this
  do_that
end

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

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

if feature_enabled?(:feature_key)
  featured_method
end

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

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

将条件包含在方法本身的优势是显而易见的:干涸代码,并且当您想要永久添加功能时,您只需从方法中删除条件即可。

在每次调用之前都有条件的好处是,在不进入featured_method代码本身的情况下,该方法是否被执行非常清楚,这可以省去很多麻烦。

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

4

2 回答 2

3

我会合并这两种方法。

这将导致调用方的 DRY 代码。它不会违反 SRP 中的 SRP,feature_method并且会清楚地传达正在发生的事情 - 如果您能找到比我更好的名称:

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

于 2013-05-14T10:42:42.047 回答
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_keyed。
  • _feature_keyed_ 方法将采用第二个参数,即功能键。如果缺少,方法的名称将用作特征键。
于 2013-05-14T14:53:06.770 回答