Removing unreachable code
In a principled statically typed language, you should always know whether the code is actually reachable or not: remove it, compile, if there is no error it was not reachable.
Unfortunately, not all languages are statically typed, and not all statically typed languages are principled. Things that could go wrong include (1) reflection and (2) unprincipled overloading.
If you use a dynamic language, or a language with sufficiently powerful reflection that the piece of code under scrutiny could potentially be accessed at run-time via reflection, then you cannot rely on the compiler. Such languages include Python, Ruby or Java.
If you use a language with unprincipled overloading, then merely removing an overload could simply switch the overload resolution to another overload silently. Some such languages allow you to program a compile-time warning/error associated with the usage of the code, otherwise you cannot rely on the compiler. Such languages include Java (use
@Deprecated) or C++ (use
So, unless you are very lucky to work with strict languages (Rust comes to mind), you may really be shooting yourself in the foot by trusting the compiler. And unfortunately test suites are generally incomplete so of not much more help either.
Cue the next section...
Removing potentially unused code
More likely, the code is actually referenced, however you suspect that in practice the branches of code that reference it are never taken.
In this case, no matter the language, the code is demonstrably reachable, and only run-time instrumentation can be used.
In the past, I've successfully used a 3-phases approach to removing such code:
- On each branch suspected NOT to be taken, log a warning.
- After one cycle, throw an exception/return an error upon entering the specific piece of code.
- After another cycle, delete the code.
What's a cycle? It's the cycle of usage of the code. For example, for a financial application I would expect a short monthly cycle (with salaries being paid at the end of the month) and a long yearly cycle. In this case, you have to wait at least a year to verify that no warning is ever emitted for the end-of-year inventory could use code paths that are otherwise never used.
Hopefully, most applications have shorter cycles.
I advise putting a TODO comment, with a date, advising on when to move on to the next step. And a reminder in your calendar.