mgsnova / feature

A feature toggle library written in ruby
MIT License
182 stars 36 forks source link

Can I use it to wrap alternative method implementations? #52

Open edelgado opened 6 years ago

edelgado commented 6 years ago

👋 folks! is this a good or bad idea?

class MyClass
  Feature.without(:feature_name) do
    def my_method
      # implementation A
    end
  end
  Feature.with(:feature_name) do
    def my_method
      # implementation B
    end
  end
end

I thought about using the feature switcher inside the my_method method, but there may be other methods that only pertain to one or the other implementation such as:

class MyClass
  Feature.without(:feature_name) do
    def my_method
      # implementation A
      helper_method
    end
    def helper_method
      # some stuffs here. I only make sense in implementation A
    end
  end
  Feature.with(:feature_name) do
    def my_method
      # implementation B
    end
  end
end

Thoughts? And thanks!

will3216 commented 6 years ago

I like the concept, but it seems like you may run into definition asymmetries. That said, no matter what tool you give people, its their job to use it correctly, so that's not a huge deal.

If you do go down this path though, I would be sure to keep in mind hot-toggles (redis-based for instance) that can get toggled without a code-reload

edelgado commented 6 years ago

I also ran into problems with debuggers. I could no longer set breakpoints and step through the code wrapped on the feature switches. Probably the definition asymmetries you mention.

For now, I'm going with this approach:

class MyClass 
  def my_method
    Feature.with(:feature_name) do
      # Implementation A
      helper_method
    end
    Feature.without(:feature_name) do
      # Implementation B
    end
  end

  def helper_method
    Feature.with(:feature_name) do
      # Implementation
    end
    Feature.without(:feature_name) do
      raise NotImplemented
    end
  end
end

That keeps the definitions symmetric but the implementations vary. May also be a great or a terrible idea, but leaving it here for other folks that may be asking themselves similar questions. Feel free to close this issue if you don't have any other feedback for folks out there 🙂

will3216 commented 6 years ago

In the past, our use-case of this package was to facilitate continuous integration of features. The goal being to make releases safer by making them toggle-able. It ended up looking something like this:

def helper_method
  if Feature.active?(:feature_name)
    # New functionality
  else
    # Old functionality
  end

Then, once we the feature was validated, in a subsequent release we would remove the else branch and the feature toggle.

The reason I bring this up, is because we originally tried a format similar to the one you listed above and we found that as the number concurrent features increased, it became increasingly hard to reason about what was happening in the code. Whereas the if/else structure created a binary tree of logic which was much easier to maintain and understand.

Anyway, just my two cents, hope it helps! :)