fireproofsocks

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?

Most Liked

dgmcguire

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

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

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.

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
JulienCorb
I am trying to implement my new.html.eex file to create new posts on my website. new.html.eex: <h1>Create Post</h1> <%= ...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: The documentation above suggests that while ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New

Other popular topics Top

marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39297 209
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 47930 226
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

We're in Beta

About us Mission Statement