Closed DianaOlympos closed 3 years ago
Hi @DianaOlympos 👋🏻
First of all, the rule is not talking about callback implementation, it's talking about callback usage (i.e. the piece of code where you write Module:the_callback(…)
).
Then, as it is stated in the rule docs…
For this rule to apply, it's assumed that callbacks defined for a particular behavior are only used within the same module that defines it. If you define behaviors in your project and you use their callbacks from other modules, you can add an ignore rule in
rebar.config
for it.
In other words, this rule assumes that you implement your non-OTP behaviors following these guidelines. If you don't abide by them, you should add an exception for this rule either by explicitly stating all the other rules in the rules
subsection of the hank
section of your rebar.config
or by adding only this one to the ignore
subsection, as explained here.
@DianaOlympos, @elbrujohalcon can probably confirm, but this is kind of similar to what Elvis already expects: that you implement your behaviour's usage in your behaviour file. I'm sure there's different use cases for this, but, at least for me, it's made my code much clearer.
I mean in this case, i cannot because the behaviour is basically just an interface for multiple backend for a data structure. The behaviour is the abstract data type for the different implementations.
@DianaOlympos Well… that's exactly the situation I was facing when I wrote the articles. That's the source of the following tip…
If you really only need to define a behavior to be sure that all your types provide similar interfaces, don’t be afraid to add functions like the one below to your generic modules:
-module(figure). -type t() :: #{module := module(), _ => _}. -callback area(t()) -> float(). -export([area/1]). -spec area(t()) -> float(). area(Figure = #{module := Module}) -> Module:area(Figure).
As you can see, the function
area/1
is just a middleman. Its only goal is to allow other modules to evaluatefigure:area(…)
with any figure created in a callback module that implements thefigure
behavior. The alternative would be to force callers to figure out the callback module and evaluate the dynamic call themselves.
This is how I would do it in your case: GameAnalytics/hyper#20
Either that or just move all the callbacks to hyper
and just use -behavior(hyper).
where you used -behavior(hyper_register).
before.
Or move the logic from hyper
to hyper_register
and leave hyper
just as a facade module that calls hyper_register
for the implementation.
I see. I need to modify that interface a lot anyway and for reference this is moving to the LivewareProblems as the source of truth cause the old GameAnalytucs one is not maintained anymore.
Thanks for the feedback!
Bug Description
Hank consider that all these callbacks are useless because "they are not used anywhere in the module". Which is true. They are all used in other modules. This is a pure definition of a behaviour.
To Reproduce
rebar3 hank
inhyper
Expected Behavior
Show nothing...
Additional Context