nathanl
Is `mix xref graph --label compile-connected` overzealous?
I’m confronted with a case where mix xref graph --label compile-connected --fail-above 0 would force me to refactor something which seems unnecessary. I’ll give a simplified example, starting with an expected case and then showing my case.
Expected case
Here is a clear transitive compile-time dependency, where A depends on B which depends on C.
(Note: pretend that each of these modules is in its own file.)
- If
C.hello/0changes, that meansBneeds to recompile andB.hello/0changes - If
B.hello/0changes, that meansAneeds to recompile andA.hello/0changes
defmodule A do
@hello B.hello()
def hello, do: @hello
end
defmodule B do
@hello C.hello()
def hello, do: @hello
end
defmodule C do
def hello, do: "hello"
end
We can find this out like this:
$ mix xref graph --label compile-connected --fail-above 0
lib/a.ex
└── lib/b.ex (compile)
** (Mix) Too many references (found: 1, permitted: 0)
If we want to know “why is it bad that A depends on B? What does B depend on?”, we can check:
$ mix xref graph --source lib/b.ex
lib/b.ex
└── lib/c.ex (compile)
(Tangential point: it would be nice if the first command would show this automatically; its output implies “A shouldn’t depend on B” when maybe the truth is that B shouldn’t depend on C.)
A More Confusing Case
Here is a more confusing case, like the one I’m facing:
- If
C.world/0changes, that meansBneeds to recompile andB.world/0changes - If
B.world/0changes, I’m pretty sure that A isn’t going to compile any differently, but because theAdepends at compile time onBforB.hello/0, it will get (needlessly?) recompiled.
defmodule A do
@hello B.hello()
def hello, do: @hello
end
defmodule B do
@hello "hello"
def hello, do: @hello
def world, do: C.world()
end
defmodule C do
def world, do: "world"
end
The mix xref commands above see these two situations as the same, even though to me they seem quite different. This seems like a shortcoming of mix xref and/or the compile process.
Am I wrong?
Most Liked
nathanl
Further conversation in Elixir Slack with Michał Muskała:
Me: So this is a case of “in theory it would be nice if it could be more granular, but that would be hard to implement”? I think in the case that I showed, recompiling
Ais wasted work
Michał Muskała: Yes, in this case it is. Tracking this however is very complex - the graphs can get pretty big and just maintaining them might be more expensive than just doing some of the extra compilations
al2o3cr
My interpretation of this situation is that you’re tracking more detail in your mental model of the compiler than the compiler actually uses.
“C.world/0 changes” is just “C changes” to the compiler.
Popular in Discussions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









