fireproofsocks
Functional equivalent of OO parent/child code sharing
This is more of a philosophical question hoping for some best-practices or practical suggestions to help write better code.
I’m working with behaviours and callbacks and it provides a sensible way to organize code into different implementations, e.g. modules that implement vendor-specific business rules.
Sometimes I want multiple implementations to refer to a shared function because it does something onerous or complicated. This makes sense from an OO perspective where you have an abstract base class and then children classes: the children classes can call methods on the parent classes, so they don’t have to re-write code.
In a functional language, however, I feel like it is a potential smell when the implementation calls shared functions. I would prefer that the implementations are NOT dependent on anything else: it would be cleaner if those modules were completely isolated.
What are ways to share/reuse functions that perform complex tasks?
- Option 1: each implementation lists a dependency
- Option 2: each implementation returns a more complex result and then the dispatching module can interpret the results and perform the more complex operations there.
- Others?
First Post!
OvermindDL1
The whole ‘parent/child’ thing implies an inheritance hierarchy, although you can model that in functional languages it is usually poor form to do so, rather composition is what should be done.
Hmm, this is rather open ended, I’m not sure what “implementation” is in this context or “lists a dependency” is?
Unsure on implementation again, but dispatching can be done in quite a variety of ways from witnesses to protocols to far far more. It really depends on ‘what’ is being done.
It might be good to give precise examples so they can be converted into a more functional style that would be a good comparison. ![]()
Most Liked
dgmcguire
Sometimes I want multiple implementations to refer to a shared function because it does something onerous or complicated.
Simply calling that function to do work in the context of each module you want to use it would satisfy the need for re-use. Are you asking how you should organize shared functions? Because I’m also interested in how people choose to organize shared functions.
Personally I’m fine just having a Utils module or similar that encapsulates the often reused functions. Often reused functions to me implies a generic function and as such it seems fine to organize generic functions under a generic namespace.
imetallica
You can have an behaviour with a “standard” implementation, much in the same line on how GenServer, Behaviour, GenStage, works.
As an example: elixir/lib/elixir/lib/gen_server.ex at main · elixir-lang/elixir · GitHub
imetallica
You may want something like this:
defmodule Shared.OrderHandling do
@callback do_something(foo, bar)
defmacro __using__(opts) do
quote location: :keep, bind_quoted: [opts: opts] do
@behaviour Shared.OrderHandling
def do_something(foo, bar), do: ... your default implementation here
def complex_operation, do: ... your implementation here ...
def i_can_also_override(bar), do: ... your implementation ...
defoverridable i_can_also_override: 1, do_something: 2
end
end
end
Then in your AppOne application:
defmodule AppOne.VendorOne do
use Shared.OrderHandling
# Now you can override the implementation of i_can_also_override and do_something
def do_something(foo, bar), do: ...
end
Same for VendorTwo.
Last Post!
LostKobrakai
If you want to keep dependencies small then extract OrderHandling in it’s own package and make your main application as well as VendorOne and VendorTwo depend on it. If you no longer need OrderHandling you can easily scrap it from all three packages. Also your vendors don’t depend on your main application but they can still be used together based on the behaviour of OrderHandling.
Popular in Questions
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
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









