Elixir - Behaviour vs. Protocol20 Nov 2018
A behaviour is a way to say: give me a module as argument and I will invoke the following callbacks on it.
Protocol is a behaviour with the dispatching logic so you don’t need to hand roll it nor impose a particular implementation in the user module.
But for practical purposes I don’t see that a behaviour is any different to a protocol, other than a behaviour forces the glue logic into the datastructure module, rather than allowing it to live outside that module, as with a protocol?
I’m not even sure that behaviour qualifies as polymorphism, because it’s not a data driven dispatch. You use the generic behaviour (e.g. GenServer), and make it concrete by providing your callback module - a plugin that is essentially a bunch of functions. The generic logic then drives the process and invokes the callback module when some concrete decisions need to be made.
Since behaviour is type agnostic, we can get some flexible properties. For example in GenServer:
- the same type (struct) can be used as the state of different concrete GenServers
- a single GenServer can easily mutate its state into some other type at any point in time
This can surely be implemented with protocols as well, but I think the result would require more boilerplate on behalf of the client programmer.
So in my mind, a behaviour is more appropriate when the generic logic doesn’t care about the data at all. It may take some data from the concrete implementation and return it later to that same implementation (which is exactly what GenServer does), but it doesn’t perform any operations itself with that data.
In my opinion, if you want to vary Heap implementations, I think protocols are the initial way to go here, since you’re doing a data based polymorphism.
a behaviour with dispatching logic,
data based polymorphism.
behaviour is more appropriate when
generic logic doesn't care about the data
doesn't perform any operations with that data but
invokes the callback
module when some concrete decisions need to be made.