Uber open-sources tool to automatically clean up stale code
infoq.com
infoq.com
The paper Pirahna: Reducing Feature Flag Debt at Uber is at https://github.com/uber/piranha/blob/master/report.pdf.
The English language confuses a native German speaker once again!
However you can definitely use "open-source" as a verb: "I open-sourced my last project." It's pretty common. And in this case "OSS" stands for "open-source", not "open-source software".
What's confusing you is that when we use the abbreviation "OSS" we're really intended people to read that as "open-source" even though the abbreviation technically means "open-source software". btw, you would never verbally spell out "OSS"—chiefly because it's the same number of syllables as "open-source".
I haven't used it yet myself, but discovered it during a search inspired by this post and thought it would be worth sharing. Definitely a trickier problem to solve for dynamic languages, but looks useful.
Some considerations: you'll need some sort of storage mechanism for these flags - is that a centralized configuration service for all your services? Maybe just a table in your database? But database / network calls are expensive to be adding to every single time your code executes the path in question - maybe it makes sense for your service to cache these values locally...but then doesn't that lose part of the purpose of 'fast rollbacks'? Maybe instead of a local cache you spin up a redis instance - but what if this goes down? Will all your instances default to the same value? Etc, etc, etc.
I'm not saying this approach is bad, only that it has complexity, and I find I generally can get away without it.
If you want to get fancy with changes (and I've seen it done) you have something else capable of controlling that percentage setting that is tied in to your monitoring. Start out low, say 1% of requests hitting the new path. Automatically ramp up over time to full 100%. If you see failures, automatically drop back to 0% until it can be ascertained that the failure didn't come from the new code.
But, we've got good frameworks in place such that at the call sites where behavior diverges, it's just checking a boolean.
if PermissionController.get().get(MyPerm.class): doA() else: doB().
I suspect this is pretty common, and its still easy to do the dead code elimination on.
oh, but if a behavior changes when a feature flag is active, there's a very strong case for it to be pluggable behavior strategy, so I like these so much better as an unconditional call to `self.getThingStrategy().execute()`
Also, if the logic gets more complicated than just an if statement (if Permision... and date < cutoffdate: etc) you don't further pollute the parent function.
Better would be for whatever ThingFactory or getThingService instantiates the Thing to make the decision, and compute it up front.
If-else statements in application logic tangle the concepts of "what should be done and why?" with "let me do this Way 1" and "let me do this Way 2". Ideally a typical service (or model or similar) shouldn't be aware that "feature flags" as a concept exist, and this should be regarded as inimical to their encapsulation. It should just know that it delegates a decision to Way N.
I’d be nice to have a tool to clean it up. But the use cases is slightly different than this one.
We have quite a few online services in production of which I'm sure have a lot of code that isn't executed/touched by our users.
As an example I'm thinking about code in if statements that are never reached because the statement always returns False. These tools discussed aren't capable of detecting such stale code.
Any suggestions?
Based on my understanding of unused codes, a) unused codes is used to delete deadcode independent of features b) determining the deadcode is based on their usage in tests c) unclear whether the code is flagged for deletion or a patch created.
I assume you would rather cleanup your program from dead code, rather than strip it down to the bone from live functions :)
> Although generally described as highly predatory and primarily feeding on fish, piranha diets vary extensively, leading to their classification as omnivorous. In addition to fish (occasionally even their own species), documented food items for piranhas include other vertebrates (mammals, birds, reptiles), invertebrates (insects, crustaceans), fruits, seeds, leaves and detritus. The diet often shifts with age and size.
> In another study of more than 250 Serrasalmus rhombeus at Ji-Paraná (Machado) River, 75% to 81% (depending on season) of the stomach content was fish, but about 10% was fruits or seeds
The typical diet of red-bellied piranhas includes insects, worms, crustaceans, and fish.[13] In packs up to hundreds, piranhas have been known to feed on animals as large as egrets or capybara. Despite the piranha's reputation as a dangerous carnivore, it is actually primarily a scavenger and forager, and will mainly eat plants and insects during the rainy season when food is abundant. ~ Wikipedia.
How does Pirahna clean itself?
Uber isn’t trivial
Most drivers use a 3rd party app in practice but uber probably needs to run mapping to avoid a source of weakness/cost.
(Could be totally wrong about incentive structure)
It all sounds like anyone can put something like that together, but try scaling up to billions of users.
> These nonfunctional feature flags represent technical debt, making it difficult for developers to work on the codebase, and can bloat our apps, requiring unnecessary operations that impact performance for the end user and potentially impact overall app reliability.
> Removing this debt can be time-intensive for our engineers, preventing them from working on newer features.