Is there any tooling or recommended way to find dead code? As my application starts to grow things can get a little messy especially with autogenerated contexts in phoenix.
Dialyzer is a static analysis tool that identifies software discrepancies, such as definite type errors, code that has become dead or unreachable because of programming error, and unnecessary tests, in single Erlang modules or entire (sets of) applications.
The compiler gives you a warning for unreachable functions. That means private functions which are not called in the module where these are defined are throwing such warnings. But public functions that are never called anywhere are not checked by the compiler.
I am (very) slowly working on that one to work with compiler tracer. I can push my branch (I thought it is pushed) where I am trying to implement such and if you have any PR then it will be more than welcome.
You might also be able to use Erlangās Xref in a Mix Task. It has options:
locals_not_used(*)
Returns a list of local functions that have not been locally used.
exports_not_used
Returns a list of exported functions that have not been externally used. Note that in modules mode, M:behaviour_info/1 is never reported as unused.
The only way I can think of doing it would be to instrument all the code, then run the service and subject it to a barrage of automated testing then finally have it produce a report ala coveralls detailing code that hadnāt been executed.
The problem is, even coveralls isnāt great, particularly when macros are being used.
Maybe someone could implement a compiler plugin that could instrument the code in this manner.
In the world of Java such a thing is relativelyly trivial, simply use BCEL (byte code enhancement library) and implement an agent which instruments class files with the extra instructions as they are loaded in.
From what I understand, Erlang doesnāt provide such a facility, at least in a way that doesnāt involve learning how the compiler works.
The problem with these approaches is that quite a lot of dynamic invocation (:erlang.apply/3) happens in Erlang/Elixir projects and dialyser/xref and friends canāt be aware of whatās being invoked when the call site is dynamic.
My initial interest was in trying to prune the Riak codebase as it was littered with so much half-implemented, never invoked, rewritten 4 times, copied and pasted cruft that open source development would struggle to get anywhere with it. Dead code detector would have allowed to delete a huge portion of dead code paths.
Hey @hauleth I was trying your branch over the weekend but couldnāt get it to return any results I have a reasonably large codebase that could be a good test here. Let me know if you are interested on syncing for this.
In some codebases in the past, Iāve also added probes to the code, delivering an event if a code is used, to assess if the code path is never actually used. It takes a bit of time to get a correct assessment that way, but it helps when everybody is gone
Interesting, the thing Iām dealing with right now is I have a phoenix context that really bubble up in size, especially with all the pre-generated code. There are technically tests for all that code that might or might not actually be used.
Sure! It can take various forms depending on the context. The first step is to identify a good āhot spotā candidate, something that you have doubt about.
If itās a top-level something, it is easy. It can get more hairy if it is lower-level stuff, which in some cases require to create proxies on top of objects, or use (outside of Elixir, havenāt used that in Elixir yet!) AOP (aspect-oriented-programming) interceptors.
To actually track the event I use various techniques: it can be just a simple āmagic wordā in the logs (but then I make sure to avoid logging at a costly place), or use some form of counter depending on what is available in the system (e.g. statsd or any other metric system).
I usually deploy to production for a long time (can be as long as. months if needed, on long-term maintenance apps), and make sure that the information is captured.
You need to make sure the āprobeā wonāt take your system down in a way or another!