Background
I have an umbrella project that has several apps. One of these apps, is called manager
and it has a Public API that is used by other apps.
The file where all of this happens does two things at the same time:
- Specifies the behaviour of the Public API
- Defers to the implementation of the Public API
Code
Here is an example of such a file:
defmodule Manager do
alias Manager.{Interpreter, PriceAnalyst}
@callback activate(String.t, String.t) :: any
@callback valid_strategy?(String.t) :: boolean
##### Implementation #####
@behaviour __MODULE__
@impl __MODULE__
defdelegate valid_strategy?(strategy), to: PriceAnalyst
@impl __MODULE__
defdelegate activate(syndicate, strategy), to: Interpreter
end
Problem
Now, the problem with this is that it doesn’t really work. Specifically, this code generates the error:
got “@impl Manager” for function valid_strategy?/1 but this behaviour does not specify such callback. There are no known callbacks, please specify the proper @behaviour and make sure it defines callbacks
Which is crazy to me, because I am defining the callbacks.
Alternative Code
Another way of doing the same thing that avoids the error would be:
defmodule Manager do
alias Manager.{Interpreter, PriceAnalyst}
@callback valid_strategy?(String.t) :: boolean
@spec valid_strategy?(String.t) :: boolean
defdelegate valid_strategy?(strategy), to: PriceAnalyst
@callback activate(String.t, String.t) :: any
@spec activate(String.t, String.t) :: any
defdelegate activate(syndicate, strategy), to: Interpreter
end
However this way I run the risk of deviating the defdelegate from the callback, since this is not implementing any behaviour. This is not a risk I want to incur into.
Questions
So, by now I am sure some of you may be asking:
- If this file does 2 things, why not have 2 files?
And it is a fair question. The problem here is:
- What would I name such files?
- Where would I put them? (what would be the folder structure in this project?)
Both questions have no clear answer to me.
So, a couple of final questions remain:
- How can I avoid the behaviour error?
- How would you solve this issue?