Behaviours in Elixir, which macro to use ? ( use VS behaviour? )

In some cases you don’t even need @behaviour.

For example with GenServer it is enough implement a simple module with the callback handlers that don’t have a default implementation and then simply specify the (callback) module name when using GenServer.start_link/3 (something that only became apparent to me when I read Replacing GenEvent by a Supervisor + GenServer).

Of course that isn’t recommended practice because @behaviour gives you a direct clue that you are looking at a callback module (with some very specific constraints).

Also keep in mind that behaviours are an Erlang/OTP concept while module attributes and hygienic macros only exist in the Elixir space (Erlang has it’s own style of macros).

So behaviours with a base implementation in Erlang like gen_server don’t rely on Elixir mechanisms (though conceivably an Elixir wrapper could add it’s own extensions).


My mental model for behaviours revolves around Kernel.apply/3 (or perhaps more accurately :erlang.apply/3) and specifically its argument types:

@spec apply(m, function_name, args) :: any() when m: module(), function_name: atom(), args: [any()]

i.e.

  • the behaviour module establishes the convention which function_names will be called with what type of arguments args.
  • the callback module m implements the function_names which are capable of processing the args as supplied by the behaviour module.
1 Like