> I guess what I'm ultimately confused about is what *absolutely
> necessitates* a runtime dependency becoming a transitive compile time
> dependency.
>

defmodule A do
  def const, do: 13
end

defmodule B do
  def const, do: A.const()
end

defmodule C do
  @const B.const()
end

C depends on B at compile-time. B depends on A at runtime. Still, if A
changes, C must be recompiled.

There is zero chance we will allow developers to bypass this behaviour
because, if you get this wrong (now or in the future when the project
evolves), then your users will increasingly run into situations where an
interactive build emits different results than a full build. And those will
be impossible to understand why in large projects. In turn this will
ultimately harm developers confidence on projects, who will then proceed to
perform full builds, "just to be sure", and harm productivity.

Once again, the runtime dependency is not the root cause. *You must remove
the compile-time dependencies OR isolate runtime deps from compile-time
deps*. I understand users are familiar with how Ash works today but, in my
opinion, this discussion is indicative of design issues. I also understand
change is frustrating, but sometimes it is necessary, especially as we
recognize patterns that can be harmful once projects grow. Elixir changed
how configuration works because it was unproductive for large projects.
Phoenix moved helpers from from imports to aliases, due to similar
runtime-compile issues in large projects. Etc.


> In the case of Ash resources, they are introspectable configurations. Some
> modules that you get back when inspecting that configuration make sense to
> "do something with" at compile time. Others absolutely don't. In Ash these
> things are modeled as behaviours because that is the way that I can define
> a functional contract. Not being able to refer to modules in this way
> essentially forces us to bypass the compiler.
>

As mentioned before, the fact a dependency can be compile-time or runtime
can be problematic. You should have distinct entry-points for those.
Ideally, remove most compile-time configuration OR encapsulate it in a
single place instead of throughout the system.

I will bow out of the discussion for now because I believe I have given all
insight I have on the topic. Once again, I want to say bypassing the
compiler can be really harmful and I do not encourage this pattern. We make
the compiler smarter, whenever we can, but sometimes we have to make our
abstractions simpler too.

---

Marlus, feel free to start a separate thread if you need help with moving
to the @after_verify callback. That's what we are using for declarative
assigns in LiveView and I assume it is similar in capabilities to Surface.
If the assumption is not true, please let me know.

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BpWH5_YMZ8KQNJjtEV79Mn%2BafHczw_u4GJ8jva5GFyZg%40mail.gmail.com.

Reply via email to