Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
edelgado opened this issue Oct 13, 2017 · 3 comments
Open

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

edelgado opened this issue Oct 13, 2017 · 3 comments

Comments

@edelgado
Copy link

👋 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
Copy link
Contributor

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
Copy link
Author

edelgado commented Oct 13, 2017

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
Copy link
Contributor

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! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants