... should I?
I have some servers that carry around references to other (let’s call them child) servers. Each of the referenced child servers are doing their own thing and are implemented as different modules but also share some common functions (albeit with different implementations). At some point, I end up fetching a reference to a child server and want to make a call that is common to all of the child servers. As of right now I do not know what specific type (module) the child server is, only that they ALL offer some subset of functionality.
Assuming I am not approaching this entirely wrong (which could be the case) I have identified two leading options for my case:
1) use a behaviour (perhaps improperly) as a pure interface (i.e., with only callbacks and no "general" functionality). For a child implemented in a `my_child_mod` module that implements behaviour `my_iface`, this could result in calls like `my_iface:a_common_fun(ChildServerRef)` after fetching the child server reference where I use the behaviour's module to access the child's functionality... OR
2) store the particular module of each child with the reference and use the stored module name at time of the call (and know/assume that all children have some shared functionality). So using some tuple or similar `{my_child_mod, ChildServerRef}` (versus just the reference) could result in a call like `my_child_mod:a_common_fun(ChildServerRef)` after fetching the reference info (as a tuple).
I, perhaps naively, gravitate towards #1 above for various reasons (compile-time checks, only having to carry around refs, my C++ background, etc.), but the internet (and ferd in particular here (https://stackoverflow.com/questions/4119477/implementing-interfaces-in-erlang/4119615#4119615)) seems to imply that this is not the Erlang way (despite finding OTP cases like this: https://github.com/erlang/otp/blob/master/lib/ssh/src/ssh_sftpd_file_api.erl). ... shame on me?
I am trying very hard to leave my C++ past behind and do things in the Erlang way, but need a little help in this particular case...
Thanks,
Brett
> Erlang's behaviour is NOT an interface!
> If you are looking for some analogy from other languages the closest one is abstract classes in C#.
This isn’t very helpful... it is the exact same response I find in the forums with no reasoning behind it. I don’t need analogies either; I understand what behaviours are “supposed” to be from the documentation and comments (perhaps this wasn’t made clear by my post). Where I fall short is “why” are behaviours limited to such and why aren’t more people asking the same questions I am stuck on (regarding polymorphism)? My logic was: yes, this has been asked and discussed some in the past with no real resolution that I could find... therefore, users must be content/accepting of the tools provided. I am not so naive to think I am the first to need/want such, so there must be a disconnect.
I posted my example to motivate my questioning hoping for some insight and/or comfort. As of now, I have proceeded with storing “meta refs” to my child servers that are module/reference tuples (along with some dangerous and future-maintenance-issue-causing assumptions regarding their “interface”)... and it’s works... it just smells, and I am always eager to learn and find the right/better/best way.
Aside: a colleague came across this repo (https://github.com/eldarko/epolymorph) while digging and the readme seems to capture my use case almost exactly...
Brett
Brujo! Yes I read both of these (and your other stuff too) some time back and they have been (and still are) very helpful on my journey. I just watched the presentation earlier today coincidentally in my search and it confirmed most of what I have learned but still doesn’t tackle my deeper questions like (“am I doing something stupid to even arrive at this line of questioning?” and “why shouldn’t I have a delegate behaviour and/or one of just callbacks?”, etc.).
Thanks!
Brett
Historically, have there ever been discussion of including stuff like this in the language itself?
Brett
Thank you Stanislav for taking the time to iterate. This is nice.
> Though I am on the side of Alan Kay's definition of the OOP - objects communicating with messages.
> Anyway, how you "slice" the world and how you make your abstractions - it is influenced by the "classic OOP".
> Of course it is very tempting to call behaviour an interface, because it looks like an interface.
> But it is not because the interface in Erlang are the functions, not a separate entity.
Indeed, but all of the teaching texts are very quick to advocate wrapping your implementations with API calls that delegate to the underlying implementation. This in my mind adds a layer of abstraction on top of pure message passing... abstractions that play to the weaknesses of "poisoned" practitioners ;)
That said, your answer does help; thank you again very much!
I am still not all the way there yet, but at a much better place than a few days ago. My current impression at this point is that the topic is nuanced and perhaps I should be thinking more along the lines of "quit THINKING of behaviours in terms of interfaces" or more generally, "quit THINIKING in terms of interfaces at all"?
I found it interesting in your example you call `create/1` in main_app at runtime using `DBmod` where my misguided thinking would have tried to use `callbacks_db` instead (interface thinking). ...this might be my disconnect.
> It is an instrument to remind you to implement functions.
As I type this I think most of my issues stem from the fear of changing something in the future and not having compile-time checks to help me find all the references (and I saw the behaviour as a nice compile-time check (crutch?) that looked attractive). This is probably a bigger and different issue all together that I need to learn more about within the Erlang ecosystem. I am assuming it is some combination of supervision, Dialyzer, and really good tests but I am sure I will learn this quite quickly after deploying some real stuff in the wild... I just would rather learn as much as I can before that time comes.
Thanks,
Brett
From: Stanislav Ledenev <s.le...@gmail.com>
Sent: Wednesday, August 25, 2021 4:04 AM
To: Brett Hemes <brh...@mmm.com>
Cc: erlang-q...@erlang.org