slouchpie
Is it "better" to crash when missing preloads or to always ensure preloads assocs?
Greetings comrades
We are having a friendly discussion at work about whether it is better to always preload or to let it crash.
For illumination, consider these 2 variations of function which lives in some Chats module:
Option 1
def is_safe?(chat) do
Enum.all?(chat.messages, &safe_message?/1)
end
Option 2
def is_safe?(chat) do
chat = Repo.preload(chat, :messages)
Enum.all?(chat.messages, &safe_message?/1)
end
Some people prefer option 1 because it avoids a situation where we might be calling Repo.preload without realizing it. They believe the function should simply crash if preloads are missing, putting the onus on the developer to ensure all necessary preloads are present. The stipulation here is that the developer must write tests to ensure actual user flows that call this function are preloading before calling it.
Other people prefer option 2 because it avoids crashing. Crashing LiveViews can result in a crash loop which hammers the database.
Personally I prefer option 1 but I think the choice is quite subjective.
I am simply asking for opinions. I do not expect a “one true way” answer or overall consensus. Scribble your baseless reckonings with complete abandon.
Most Liked
al2o3cr
One hazard with option 2 is that if somebody decides to call is_safe? for each chat in a list, you’re right back in N+1 query trouble.
A solution I’ve used in production was to have a helper called ensure_preload that behaves differently in production vs test:
- in test, it crashes with a detailed message about what’s missing if the preloaded data isn’t there
- in production, it does the requested preload and logs a message (and/or sends a notification to your exception tracker)
That way production is never broken (just slow) but code that’s covered by tests is verified to work efficiently.
sodapopcan
Not a direct answer but to me there is nothing subjective about having side effects in a predicate function. If I’m just asking a question I don’t expect anything to happen, ever.
katafrakt
I think this is a great question and we should have more discussion of this kind in Elixir community.
In my opinion the question could be rephrased as: are you ok with this function having a dependency on the Repo, that is a low-level persistence concern? Does it fit this place in you application?
In general, I think Ecto.Repo tends to leak all over the application, because we are passing around Ecto schemas, on which it’s possible to call functions like Repo.preload. I sometimes wish it was not called Ecto.Repo and would make way to have proper repositories in the app that return structs that are completely disconnected from the persistence concerns. But this is just a digression.
I like the heuristic that predicate function should not generally have side effects. Because a database call definitely is a side effects (in terms of functional programming, pure functions etc.), even if not a very “dangerous” one. That being said, there might be case in which having side effects for such functions is ok. I’m just not sure how this is in your case.
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









