<div dir="ltr">You are welcome!<br><br>>> I am still not all the way there yet, but at a much better place than a few days ago.  <br>>> My current impression at this point is that the topic is nuanced and <br>>> perhaps I should be thinking more along the lines of <br>>> "quit THINKING of behaviours in terms of interfaces" or more generally, <br>>> "quit THINIKING in terms of interfaces at all"?<br><br>I don't think we can put the idea of "interface" away at all. We are surrounded<br>by "interfaces" in real life. For instance, the power outlet and electrical plug<br>is the interface. I'd rather say that it is better to go away from OOP's definition<br>of interface to more practical one. I'd say that the set of exported functions in the module<div>is the interface too.<br><div><br></div><div>And of course to get rid of unnecessary layers of abstractions. </div><div>As Joe Armstrong said: "The problem with object-oriented languages <br>is they’ve got all this implicit environment that they carry around with them. <br>You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."<br><br>>> As I type this I think most of my issues stem from the fear of changing <br>>> something in the future and not having compile-time checks to help me find <br>>> all the references (and I saw the behaviour as a nice compile-time check <br>>> (crutch?) that looked attractive).  This is probably a bigger and different <br>>> issue all together that I need to learn more about within the Erlang ecosystem.  <br>>> I am assuming it is some combination of supervision, Dialyzer, and really good tests but <br>>> I am sure I will learn this quite quickly after deploying some real stuff in the wild...  <br>>> I just would rather learn as much as I can before that time comes.<br><br>I highly recommend you to go deeper into the Erlang ecosystem. The process of transition<br>from other languages to the Erlang is much steeper than with other languages but definitely<br>more rewarding. <br>And I would recommend spending more time with tools but be careful though.<br>For example, due to dynamic nature of the language you write in your code something<br>like this:<br>    foo() -><br>        Result = hjsdfkjsdhfskjfhskhskhfskl:yutyrutyriuyiw(),<br>        ...<br>        <br>And it will compile. Because you can bring the module "hjsdfkjsdhfskjfhskhskhfskl" later<br>and the compiler doesn't know that. And the Dialyzer won't tell you anything...<br>But the "xref" tool may tell you that you are probably using an unknown function in an unknown module.<br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">ср, 25 авг. 2021 г. в 18:33, Brett Hemes <<a href="mailto:brhemes@mmm.com">brhemes@mmm.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">





<div lang="EN-US" style="overflow-wrap: break-word;">
<div class="gmail-m_-150899551228036556WordSection1">
<p class="MsoNormal">Thank you Stanislav for taking the time to iterate.  This is nice.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">> Though I am on the side of Alan Kay's definition of the OOP - objects communicating with messages.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">> Anyway, how you "slice" the world and how you make your abstractions - it is influenced by the "classic OOP".<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">> Of course it is very tempting to call behaviour an interface, because it looks like an interface.<u></u><u></u></p>
<p class="MsoNormal">> But it is not because the interface in Erlang are the functions, not a separate entity.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">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 ;)<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">That said, your answer does help; thank you again very much!<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">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"?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">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.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">> It is an instrument to remind you to implement functions.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">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.<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Thanks,<u></u><u></u></p>
<p class="MsoNormal">Brett<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> Stanislav Ledenev <<a href="mailto:s.ledenev@gmail.com" target="_blank">s.ledenev@gmail.com</a>> <br>
<b>Sent:</b> Wednesday, August 25, 2021 4:04 AM<br>
<b>To:</b> Brett Hemes <<a href="mailto:brhemes@mmm.com" target="_blank">brhemes@mmm.com</a>><br>
<b>Cc:</b> <a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<b>Subject:</b> [EXTERNAL] Re: Re: I am close to using a behaviour as a pure interface and I feel dirty...<u></u><u></u></p>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal">OK, I'll try to give you my opinion on this topic. If I understand your question correctly. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">It may look rude but please believe me it is not my intention to be rude.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Your examples for me are the evidence of the "classic OOP" poisoning.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Remark:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">I call it "classic" based on how the vast majority of the developers perceive the idea of objects and<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">interaction between them. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Though I am on the side of Alan Kay's definition of the OOP - objects communicating with messages.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Anyway, how you "slice" the world and how you make your abstractions - it is influenced by the "classic OOP".<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Erlang is the functional language (more or less) so abstractions are made the other way:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">1. Basic units are Module and Function;<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">2. Dynamic function calls - Module:Function(Args). So you can dynamically (in runtime) change the module;<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">3. Behaviour is just a hint for a compiler to check a Module for a presence of the required functions.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Based on these 3 points - when you write -behaviour(....) in a module you are just saying that<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">this module must have a bunch of functions implemented to be successfully compiled. It is not for<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">supporting your own abstractions. It is an instrument to remind you to implement functions.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">What you call "general" functionality in Erlang is simply a library implemented as module(s).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Of course it is very tempting to call behaviour an interface, because it looks like an interface.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">But it is not because the interface in Erlang are the functions, not a separate entity.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">Example of using behaviour from my own experience.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">As in almost any application I must have something where I store the data.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">And requirements are very vague. So I don't know if it would be Mnesia, PostgreSQL, file, space station or a toaster.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">So I've made the behaviour which defines functions for my business logic associated with storage.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">To make it simple it is like the CRUD operations on my entities. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">This behaviour is implemented as an independent rebar3 library, so other parties (sometimes remote) can include it as a dependency.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">But their implementations are included in the final application and what implementation will be used<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">is defined in the configuration file. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">(Pseudo) code is like this:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">callbacks_db.erl:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    -module(callbacks_db).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    -callback create(Entity::my_entity_t()) -> ok | {error, Result :: term()}.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">postgresql.erl:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    -module(postgresql).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    -behaviour(callbacks_db).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    create(Entity) -> ....<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">toaster_able_to_storage_data.erl:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    -module(toaster_able_to_storage_data).<u></u><u></u></p>
</div>
<div>
<div>
<p class="MsoNormal">    -behaviour(callbacks_db).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    create(Entity) -> ....<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
</div>
<div>
<p class="MsoNormal">main_app.config:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">     {main_app, [<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">         {db, #{mod => postgresql}} % If you are using a toaster use "toaster_able_to_storage_data"<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">     ]}<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">main_app.erl:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">    some_function(DBMod) -><u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        Entity = create_entity(...),<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">        DBmod:create(Entity).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">That is all about behaviour.<u></u><u></u></p>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div>
<p class="MsoNormal">ср, 25 авг. 2021 г. в 00:46, Brett Hemes <<a href="mailto:brhemes@mmm.com" target="_blank">brhemes@mmm.com</a>>:<u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal">> Erlang's behaviour is NOT an interface!<u></u><u></u></p>
<p class="MsoNormal">> If you are looking for some analogy from other languages the closest one is abstract classes in C#.<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">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.<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">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.<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">Aside: a colleague came across this repo (<a href="https://github.com/eldarko/epolymorph" target="_blank">https://github.com/eldarko/epolymorph</a>) while digging and the readme
 seems to capture my use case almost exactly...<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">Brett<u></u><u></u></p>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>

</blockquote></div>