
Uber open-sources tool to automatically clean up stale code - imheretolearn
https://www.infoq.com/news/2020/06/uber-piranha/
======
tjalfi
Pirahna, Uber's code cleanup tool, was previously discussed at
[https://news.ycombinator.com/item?id=23516823](https://news.ycombinator.com/item?id=23516823).

The paper Pirahna: Reducing Feature Flag Debt at Uber is at
[https://github.com/uber/piranha/blob/master/report.pdf](https://github.com/uber/piranha/blob/master/report.pdf).

------
burtonator
We just wrote one that does something similar for Typescript if anyone wants
us to OSS it... The idea is that any stale code causes a HUGE amount of
headache and removing it can be a life safer.

~~~
mkr-plse
Piranha author here -- Will you be willing to contribute it to Piranha?

~~~
tomkinson
@burtonator yes curious what you have or maybe it's a better fit under
Piranha?

------
squillful
A similar tool, Vulture, exists for Python:
[https://github.com/jendrikseipp/vulture](https://github.com/jendrikseipp/vulture)

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.

------
erik_seaberg
I'm surprised to see that Boolean feature flags are common. We almost always
ramp up percentages of UUID space or randomly chosen requests, to reduce the
blast radius of a bad change.

~~~
cdcarter
At $JOB, we have feature flags of innumerable shapes and sizes. Some are based
on account standing, some are % gradual rollout at random, others are a more
thoughtful low-risk to high-risk rollout across customers and hosts. Some are
manual flipped per customer/only on certain dev hosts. Literally anything you
can think of, we have tied behavior to it.

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.

~~~
fennecfoxen
> if PermissionController.get().get(MyPerm.class): doA() else: doB().

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()`

~~~
anamexis
Won't `getThingStrategy()` do something like `if
PermissionController.get().get(MyPerm.class): doA() else: doB()` ?

~~~
fennecfoxen
Naah, but at least that would make the decision simple and clear (if condition
return doA else return doB).

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.

~~~
vanviegen
That sounds a lot like enterprisy Java programming. I'm not always thrilled to
work with the results of that. :-)

------
therealdrag0
The latest place I work has a dusty monolith full of skeletons and zombies.
They’ve been migrating off it to micro services for like 5 years now.

I’d be nice to have a tool to clean it up. But the use cases is slightly
different than this one.

~~~
mkr-plse
Can you elaborate further? It will be interesting to see other use cases for
code cleanup.

------
bartkappenburg
I like the concept using an analyzer like this but I've been looking for a
tool that removes code that isn't perse stale but isn't executed for, say, x
amount of time.

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?

~~~
mkr-plse
Do you already know the code that is not executed? If not, dynamic program
analyses can help with identify the regions of code that are untouched (e.g.,
take a look at javaagent for Java programs). Subsequently, you can use some
form of reachability analysis to determine which code blocks to delete without
causing a compilation failure.

------
creyes
Is this drastically different than
[https://unused.codes/](https://unused.codes/) ?

~~~
dahfizz
From a quick reading, yes. Your tool identifies code that is never run. The
featured tool identifies code that never _will be_ run if we make X change to
the API.

~~~
creyes
oh interesting, tbanks for the clarification!

------
W4ldi
lol, I just thought about writing a script that does excactly that for
javascript code. For easy implementation I thought about using
annotations/comments that tell the script what to delete once a feature switch
is being deleted.

------
joering2
Total nit pick, but I think Piranha is a totally wrong name here. Piranhas
mostly feed on fresh meat, its known they are excited and eager to attack when
victim moves in water, reassuring predator that its a healthy meat. Much
better name would be Scavenger, or Vulture - a bird of prey that eats on dead
meat.

I assume you would rather cleanup your program from dead code, rather than
strip it down to the bone from live functions :)

~~~
detaro
As far as I know that aspect of Piranhas is overhyped in popular culture, and
they're pretty much omnivores, hunting fresh prey, scavenging on carcasses and
eating plant matter. Agreed though that naming it after a pure scavenger would
make more sense.

~~~
Kaze404
Wikipedia (and the sources listed) contradict this comment, saying Piranhas
are vicious carnivores, with some even exhibiting cannibal behavior.

[https://pt.m.wikipedia.org/wiki/Piranha](https://pt.m.wikipedia.org/wiki/Piranha)

~~~
judge2020
English:
[https://en.wikipedia.org/wiki/Piranha](https://en.wikipedia.org/wiki/Piranha)

> 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

------
stevefan1999
/jokes

How does Pirahna clean itself?

------
laydn
I find it strange that a company which provides taxi hailing/routing
technology felt the need to write a code cleanup tool.

~~~
read_if_gay_
You can make most of the Big N sound silly like this. Amazon? Basically a
warehouse. Netflix, YouTube? They just stream video. Facebook, Twitter? CRUD
websites.

It all sounds like anyone can put something like that together, but try
scaling up to billions of users.

~~~
speedgoose
For sure if you remove the scalability challenges and profits optimizations
techniques, these websites aren't that exciting for engineers.

