# A better Module interaction pattern?

**URL:** <https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701>\
**Category:** Questions\
**Tags:** behaviours, learning-elixir\
**Created:** [October 13, 2024, 10:12am UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701 "2024-10-13T10:12:14Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 13, 2024, 10:12am UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/1 "2024-10-13T10:12:14Z")

</div>

I’m looking to improve this pattern.  
It is a pattern I use in a lot of my projects.

```elixir
defmodule Handler do
    def handle_request(data) do
        response = apply(@some_module_from_config, :parse, [data])

        # do_something_with_response(response)
        ...
    end
end

```

I then have customer specific implementations of `:parse` in separate modules, for example

```elixir
defmodule CustomerA do
    def parse(data) do
        # specific parsing of this data for Customer-A
    end
end

defmodule CustomerB do
    def parse(data) do
         # specific parsing of this data for Customer-B
    end
end

```

This works, but can it be improved?

Is there a benefit for example to have a @behaviour in Handler which defines `:parse` and `other functions`

Then each Customer module no implements `use Handler`

Please are their better patterns for doing this?

Thanks.

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [October 13, 2024, 10:49am UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/2 "2024-10-13T10:49:13Z")

</div>

> [@CharlesO](#):
>
> ` response = apply(@some_module_from_config, :parse, [data])`

No need to use `apply` as it’s much more useful if you have function name stored in variable.

```elixir
` response = @some_module_from_config.parse(data)`

```

> [@CharlesO](#):
>
> Is there a benefit for example to have a @behaviour in Handler which defines `:parse` and `other functions`

Not only it would not give you any benefit, but it would also be wrongly used.

In `Handler` module you have to define callbacks and / or macrocallbacks. You use `@behaviour` attribute in `CustomerA` and `CustomerB` modules. In this tiny example it’s not important at all, but in general you use this to make sure that all callbacks are implemented as `Elixir` gives compilation warning otherwise.

---

<div class="post-metadata">

**Author:** ![egze](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/egze/32/13522_2.png) [@egze](https://forum.elixirforum.com/u/egze)\
**Post date:** [October 13, 2024, 10:52am UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/3 "2024-10-13T10:52:53Z")

</div>

I also recommend watching the keynote from José [https://www.youtube.com/watch?v=agkXUp0hCW8](https://www.youtube.com/watch?v=agkXUp0hCW8)  
He goes into the topic what to use when.

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [October 13, 2024, 12:37pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/4 "2024-10-13T12:37:58Z")

</div>

How does your code branch on input data and decides which module to use?

I just recently had to do this and since I did not have a lot of modules and not too many input shapes I just made a router / dispatcher module that basically pattern-matches on the input and calls different module + function combo i.e.

```elixir
module = Commands.detect_by_args(input)
module.perform(args)

```

Where `Commands.detect_by_args/1` simply uses several pattern-matching function heads.

---

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 13, 2024, 1:05pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/5 "2024-10-13T13:05:01Z")

</div>

I’m trying to understand you point sir.

Say I have more functions in handler module, and i want to ensure that every customer module implements all the functions correctly, then just like GenServer we coukd use @behavior correct?

---

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 13, 2024, 1:11pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/6 "2024-10-13T13:11:56Z")

</div>

In my case i have the same app deployed to different customers.

Each customer has specific processing they need.

I implement a module per customer, then in config, i have a `customer_module_name` setting.

In this module, i do the customer specific processing.

The main app, looks for module name, then calls a function: `process_data`, which every customer module is expected to have implemented.

---

<div class="post-metadata">

**Author:** ![dimitarvp](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/dimitarvp/32/38664_2.png) [@dimitarvp](https://forum.elixirforum.com/u/dimitarvp)\
**Post date:** [October 13, 2024, 1:14pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/7 "2024-10-13T13:14:39Z")

</div>

Sounds like what I did but with multiple dispatchers (one per customer).

Why are you not satisfied with that solution?

---

<div class="post-metadata">

**Author:** ![Eiji](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/eiji/32/36743_2.png) [@Eiji](https://forum.elixirforum.com/u/Eiji)\
**Post date:** [October 13, 2024, 1:48pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/8 "2024-10-13T13:48:09Z")

</div>

Behaviours are well documented, so it would be easiest to check it out. For example here is a quote I was referring to:

> If a module adopting a given behaviour doesn’t implement one of the callbacks required by that behaviour, a compile-time warning will be generated.
> 
> Source: [Behaviours | Typespec reference @ Elixir’s documentation](https://hexdocs.pm/elixir/typespecs.html#behaviours)

---

<div class="post-metadata">

**Author:** ![al2o3cr](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/al2o3cr/32/3457_2.png) [@al2o3cr](https://forum.elixirforum.com/u/al2o3cr)\
**Post date:** [October 13, 2024, 10:30pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/9 "2024-10-13T22:30:39Z")

</div>

> [@CharlesO](#):
>
> Is there a benefit for example to have a @behaviour in Handler which defines `:parse` and `other functions`

The major benefit is compile-time checking:

- if `CustomerA` says `@behaviour Handler` but doesn’t supply callbacks with the correct arities, the compiler will complain
- (sometimes) Dialyzer will be able to prove that a function’s implementation fails to match the behaviour’s spec

As a side bonus, libraries like `mox` can use that same behaviour for their definitions.

---

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 14, 2024, 7:57am UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/10 "2024-10-14T07:57:06Z")

</div>

Please can you point to a simple reference implementation?  
I’ve not written this type of behavior module before.  
I understand it requires _macros_, yes?

---

<div class="post-metadata">

**Author:** ![thomas642daniel](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/t/8dc957/32.png) [@thomas642daniel](https://forum.elixirforum.com/u/thomas642daniel)\
**Post date:** [October 14, 2024, 1:18pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/11 "2024-10-14T13:18:42Z")

</div>

> [@CharlesO](#):
>
> I’m looking to improve this pattern.  
> It is a pattern I use in a lot of my projects.
> 
> ```elixir
> defmodule Handler do
> def handle_request(data) do
> response = apply(@some_module_from_config, :parse, [data])
> 
> # do_something_with_response(response)
> ...
> end
> end
> 
> ```
> 
> I then have customer specific implementations of `:parse` in separate modules, for example
> 
> ```elixir
> defmodule CustomerA do
> def parse(data) do
> # specific parsing of this data for Customer-A
> end
> end
> 
> defmodule CustomerB do
> def parse(data) do
> # specific parsing of this data for Customer-B
> end
> end
> 
> ```
> 
> This works, but can it be improved?
> 
> Is there a benefit for example to have a @behaviour in Handler which defines `:parse` and `other functions`
> 
> Then each Customer module no implements `use Handler`
> 
> Please are their better patterns for doing this?

Hello,

I love the idea of using behaviors here; it’s like setting a standard for a well-dressed party—everyone knows the dress code!

---

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 14, 2024, 1:31pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/12 "2024-10-14T13:31:59Z")

</div>

Please do you know how to setup the behaviors code?

---

<div class="post-metadata">

**Author:** ![D4no0](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/d4no0/32/33624_2.png) [@D4no0](https://forum.elixirforum.com/u/D4no0)\
**Post date:** [October 14, 2024, 2:19pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/13 "2024-10-14T14:19:34Z")

</div>

Nope, all you need is something like this:

```elixir
defmodule ParseBehavior do
  # Obviously replace any with your data types
  @callback parse(data :: any) :: any
end

defmodule CustomerA do
  @behaviour ParseBehavior 
end

```

If you don’t implement the specified callbacks you will get a compilation warning.

You can also have the variant with the default implementation:

```elixir
defmodule ParseBehavior do
  @callback parse(data :: any) :: any

  defmacro __using__ (_opts) do
    quote do
      @behaviour ParseBehavior
      
      def parse(data) do
        # This will be the default implementation if not overriden
      end

     defoverridable parse: 1
    end
  end
end

defmodule CustomerA do
   use ParseBehavior

  # This definition will override the default definition
  def parse(data) do
   
  end
end

```

I wouldn’t recommend using the variant with default implementation unless that is strictly required, as it makes the code harder to read.

---

<div class="post-metadata">

**Author:** ![CharlesO](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/charleso/32/34571_2.png) [@CharlesO](https://forum.elixirforum.com/u/CharlesO)\
**Post date:** [October 14, 2024, 2:26pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/14 "2024-10-14T14:26:41Z")

</div>

Please how do we get the return value from the customer module back to the behavior module?

For example, say CustomerA implements parse/1, how can that result be used in ParseBehavior module?

---

<div class="post-metadata">

**Author:** ![D4no0](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/d4no0/32/33624_2.png) [@D4no0](https://forum.elixirforum.com/u/D4no0)\
**Post date:** [October 14, 2024, 2:49pm UTC](https://forum.elixirforum.com/t/a-better-module-interaction-pattern/66701/15 "2024-10-14T14:49:42Z")

</div>

You can’t, the module that defines behavior whole point is to make sure that you are implementing the required functions, it’s up to you how you call them afterwards.

You can either use the pattern you are already using with `apply/3` or you can call directly the function, as module names are just plain atoms:

```elixir
my_modules = [CustomerA, CustomerB]
for module <- my_modules do
  module.parse(data)
end

```

You could add some compile-time checks to ensure that the module you are calling has the behavior declared, but I don’t see a lot of value from that.
