Live data from Hacker News

Burying your dead code

eng.grandrounds.com

31–40 of 49 posts

Re: Burying your dead code

#31

PHPStorm/IntelliJ has this feature where it marks any unused functions as gray. If you want to find where used functions are used, simply hit Ctrl-G and it'll show you all the places.

At least in PHP it depends on making sure the rest of your code-ecosystem has good annotations/type-hints. Especially if you have any code doing stuff like:

    return new $className();

Re: Burying your dead code

#33
post #19

> Removing dead code from your codebase is a simple process at its core: find the dead parts, prove that they’re dead, and delete them. The tricky part is in that second step, but after a little trial and error, we discovered a couple tricks to speed up the process. The tricky part shouldn't be the second step. The second step shouldn't even exist. How is it that in this day and age, your compiler can't tell you defi…

Finding all dead code would mean solving the halting problem, even in the simplified case when you're not writing a library whose consumers may no longer use an exposed function.

Now we're discussing the meaning of "dead code". I'm pretty certain that the OP was referring to methods that have no callsites. That doesn't require much in the way of proof, the git bisect seems to be more about identifying when it became dead. Now if you have methods that have existing callsites, but aren't being called, then yes, you may need to solve the halting problem to prove that no basis path that is actually followed calls the code in question.

Of course in a dynamic language, or one with reflection, then the distinctions are blurry

Re: Burying your dead code

#34
post #32

There shouldn't be discussion around this topic without mentioning Unused: https://unused.codes I've run that through many projects over the last year and it's been pretty instrumental in finding the low-hanging stuff easy to pick off.

Because Unused can't guarantee non-use (hooray metaprogramming and inheritance chains) it can't guarantee accuracy, but it gets close. `git bisect` and a good test suite is your friend (it also identifies methods/functions that are ONLY ever tested and don't look to be used anywhere else).

The underlying premise is that, by leveraging ctags and the ability to search for the presence of tokens within a directory, it can estimate what's used based on occurrence frequency and location. Because of this, it's language-agnostic.

Biggest removal I've worked on is ~1500 LOC (a large chunk being JSON); however, I've seen the results from some of our client work at thoughtbot, which have surpassed 3k-4kLOC.

Re: Burying your dead code

#35
post #17

Earlier quoted context omitted.

Wouldn't a test suite help with that?

Well, that depends. If you have 100% coverage, you don't have dead code. But just because code is tested doesn't mean that it's actually in use outside of the test suite. There's lots of ways that code could become dead, even if it's still accessible via a test suite.

Right. But it seems it might help with the tombstoning if the tests hit the calls (rather than waiting until it happens by serendipity).

Re: Burying your dead code

#36
post #10

Earlier quoted context omitted.

I don't think it would work as well as we'd hope. Our projects aim for ever-increasing code coverage; it seems silly, esp as we get closer to 100%, but it seems to be pertinent here. If I were to refactor some function to no longer be used, one would hope/expect that code coverage for that function would be missing, and thus we'd realize (or at least be able to notice more easily) that it was dead code. However, unle…

If there was sufficient code coverage then the test would hopefully invoke a function that eventually calls on your potentially dead function.

I think the poster was saying that proper unit testing would give false positives.

Example: If I have a "dead" add() function with a unit test that asserts add(2,2) == 4, then code coverage would report that function being covered even if no other part of the codebase uses it anymore.

Re: Burying your dead code

#37
post #7

Earlier quoted context omitted.

And so in Ruby, we use test frameworks with advanced mocking, as well as runtime-reflection coverage measurement. Metaprogramming: the cause of, and solution to, all of life's problems.

> And so in Ruby, we use test frameworks with advanced mocking, as well as runtime-reflection coverage measurement. No matter how many times you say it, that doesn't make it true.

Care to elaborate?

Re: Burying your dead code

#38
post #37

Earlier quoted context omitted.

> And so in Ruby, we use test frameworks with advanced mocking, as well as runtime-reflection coverage measurement. No matter how many times you say it, that doesn't make it true.

Care to elaborate?

I think he means that you seem to be speaking for all of the Ruby community (that is, people who write Ruby code). I've personally seen that not all of the Ruby community writes tests, because I've seen Ruby code that doesn't have tests. In fact, I've had coworkers who work with Ruby in multiple jobs in different industries, and in all cases the Ruby application had very few or no tests.

Re: Burying your dead code

#39
post #17
post #9

Earlier quoted context omitted.

I've used tombstoning as well. The biggest problem is that you have to let it run long enough to determine if anyone is actually using that method - and with sections of an application that are not oft-used, you could be waiting a very long time to find out.

Wouldn't a test suite help with that?

If the original developers wrote one, it might help.

Re: Burying your dead code

#40
post #3

Static analysis is your friend here. TypeScript, Rust, and C# can all identify dead code and report errors or warnings from that, and can perform "find all usage" searches across a workspace.

Static analysis is very useful to identify unreachable code given that it can see all the code depending on it.

It doesn't help with potentially reachable but unused cpdepaths, which in my experience make up for the most of 'dead' code.

Think of the functionality in an application that nobody uses or of obsolete API version when all the clients use a more recent version.

Post reply on HN