I've never understood how Feature Flags can be used like that. For example say I have a button component that needs to be refactored and it used in hundred of places throughout the codebase. How can I use feature flags to prevent a long running branch? (Serious question :))
Do I keep both implementations around and everywhere a button is used switch on a flag, that seems quite messy, and I have to go and delete the switches on the flag everywhere when I'm finished. Or I could abstract that out into a function or use dependency injection to choose the right button, but that just seems to be adding another layer of complication, that some future dev is going to wonder why exists when there is only one implementation of the button.
Compared to having a long running branch that I periodically merge the main branch into to keep up to date with the current development without impacting the code that is due to released in 2 days (as it is every 2 weeks)
You do need some sort of seam at the point of use so that the feature flag logic can be hidden behind a lookup function. For example in Rails you might include your button code via a partial template. You could use a view helper to provide the name of the partial and that helper could respond with different names depending on the feature flag:
I would say abstracting it out into a function or using dependency injection, and having a centralized switch statement is the way to go. I don't see why you would need to break your interface for most refactors, and if you DO have to, that means your code had a major issue anyway.
Additionally, how is the "just using git for feature management" alternative better? With a feature flag you can enable and disable the feature easily without a deployment. With git, you have to do a revert/rollback/whatever to ship a fix.
I struggle to think of an effective way to reuse a button component over and over again without using a function or dependency injection. If you are speaking of react: Those are functions. That HTML you are using is actually just some syntactical sugar around functions.
You would not keep both versions of the button around permanently. You would merge the branch into your master branch, and enable the feature for the desired environments. When all environments are using the new refactor, and it has been verified to be working, you open a pull request to delete the old version of the refactor and purge the feature flag.
"Well, that is still complicated!" That is true, there is still process around managing features with feature flags. The benefit is that feature flags are easy to grok. It is an if statement. Your application state is no longer contained in an interminably long git log. Instead, it can be determined by checking your feature flag configuration.
> Compared to having a long running branch that I periodically merge the main branch into to keep up to date with the current development without impacting the code that is due to released in 2 days (as it is every 2 weeks)
This becomes laborious over time. If you have many people working on a codebase, the feature branch will constantly break and you will have to go back in fix it.
What if someone has to revert something on the main branch that you have merged with your feature branch? You are now in merge-hell and you have to spend a bunch of time figuring out how to make your branch and the fucked-up master branch have the proper code in them.
What if someone on your team does a hard-reset to the master branch? ( Well just don't do that! Oh, sorry, I didn't realize you were the tech lead for your place of business, and get to decide how everyone else solves their various problems. ) Now your branch is out of date and you have to revert commits and fuck around with your feature branch, and HOPE that you actually unfuck your version history properly.
Look at the alternative: You uncheck a box on a web GUI, the bug is contained, you go in and fix it, deploy it, and re-enable the feature.
Your "what if we just don't worry about it, and not solve the problem" suggestion here does exactly that: Ignores the problem we are all experiencing, and then does NOTHING to solve it.
Do I keep both implementations around and everywhere a button is used switch on a flag, that seems quite messy, and I have to go and delete the switches on the flag everywhere when I'm finished. Or I could abstract that out into a function or use dependency injection to choose the right button, but that just seems to be adding another layer of complication, that some future dev is going to wonder why exists when there is only one implementation of the button.
Compared to having a long running branch that I periodically merge the main branch into to keep up to date with the current development without impacting the code that is due to released in 2 days (as it is every 2 weeks)