Alternative names to defmodulep (split thread)

Yeah and that was a bit confusing for me at start. I though how could I fetch them from other module. Btw. you probably did not noticed, but there is option to do it. :077:

yup, that’s 100% right
Now try to do that as a newbie and post a question on forum asking why it’s not working … It’s exactly why there should not follow same naming.

Or maybe other example. Write a library with def and defp macros. Think now some library is using it and somebody want to contribute to it. Unfortunately your implementation does not support guards, so commits which looks good fails which confuses everyone. In hundreds of lines file you need to find import or use which confuses everyone. Good if you are adding all declarations at top of file and you don’t have much of them …

Sorry, but I did not get what you mean by this. Is naked, shaved and young man still Santa Claus? :smiley: It’s like lake without water is still lake. Of course it’s normal for Python developer:

https://elixirforum.com/t/programming-related-jokes-thread/10652/21?u=eiji

but definitely not for Erlang developer. :smiley:

Look that Erlang private functions are definitely not like Python private methods. Same difference is in defp vs defmodulep. They have even different use case. First makes specific function private for specific module and second makes module magically hidden (for example scoped using some prefix). Hidden does not means private. Look that if there could be public database which is hidden and accessible only on specific IP address which is not assigned to any domain. It’s hard to find it, but it does not mean you can’t reach it. If you can reach it then it’s not private (again following what Erlang offers as “private”).

defmodule Example do
  defmacro defmodulep(name, opts, do: block) do
    quote do
      defmodule Module.concat(Private, unquote(name)) do
        @visible_to unquote(opts[:visible_to])

        unquote(block)
      end
    end
  end

  # requirep definition goes here
end

Such code would simply add Private. prefix before module, so you can’t access this module directly, but this just not mean that you can’t access it using Private. prefix. Private modules therefore are not protected (like private functions). They are basically still Public, but hidden under prefix/scope.

Look if I would say that last day I had guest then what would you think? You would probably think about human in my flat/house, but I actually I could mean bot on website. Both human and bot can be guests, they could have actually same privileges and they even could want same thing, but this does not mean that they are exactly same. Basically bot and human are 100% different - they could use same tools, one could imitate other, but if we would say about them with same words then other people could misunderstand what we are talking about.

We could even group all pets under one “pet” word, because all are pets. Now you need to guess which pet I’m talking about, because they don’t have their own names like cat or dog. If you firstly thing about dog and you would hear from me that I let it go on his way (like cat does) then you would be confused why I did it. You would call somebody to catch it and they therefore would assume that you are talking about dog. Well … you basically talking about dog, but you actually you are talking about cat even if you did not noticed it. That’s confusion and mess.

From my experience more you assume is more problems in future. Having same naming (private) for 2 different similar, but different things (hiding and protecting) would not give anything good. Every developer was newbie, so he/she should remember how much things he/she wrongly assumed. While = operator is confusing it’s important for Elixir itself. If we can we should not confuse newbie and don’t let assume too many things.

Coming from this point people (much more experienced from me) defined rules which makes everyone’s code easier to understand like proper indention, max line length, max function length and also proper naming. I believe most of things could be generalized to x, y and z variables, but this does not mean that it should be done in such way.

And that makes them not private. There is even no way to protect use “private” modules in other apps. Still I could wrote defmodule Ecto.MyHack do … end and I would be able to access all internal modules which are scoped for Ecto.* modules only.

Again all what I mean is assuming what typical newbie do. Let’s say you have really important core function which you don’t want to be accessed. When you hear about “private” modules then you most probably assuming that they are working as same as private functions. If we would use synonym then newbie think: Hey … why it's named differently? Does it not work like this one …?. This makes newbie curious about it and answer for his question would be available in documentation. If we would have same naming and newbie would assume that it’s working as same then he would not even look at documentation and would not notice that’s not working in same way. Wrong assumption could make code vulnerable and it could be pretty easy used with simple hacks I mentioned few times.

Imagine that someone would write library and instead of using private functions all write calls would be in private modules. This would allow to access them and write data for example without protection (like function guards) which is … not needed for “private” modules, because they are like private function, right? If I can imagine something like this in “5 min” then what could do expert taking his time with coffee cup?

ERROR: WRONG ASSUMPTION FOUND !!!

  • Declaring the module visibility per package or application. The Elixir language and the compiler do not have the concept of “applications”. Applications and packages are purely a build tool construct. In a way this is great, because the language is small and we build features on top, but it also means we cannot implement a construct such as visibility per package as part of the language.

Also you really did not get why this proposal was created. It’s not about protecting specific module - it’s more about don’t give so easy access without any warning/error (depends on scenario). Access is still possible no matter if by hacks or not. It’s not going to be protected in future. This proposal does not mean that core team want to introduce private modules which in future would not allow to be accessed. This is all about don’t ignore reaching internal API.

Even if core team would change mind then they can’t change behavior of already implemented functionality until next major release i.e. 2.0.0. I don’t believe that 2.0.0 would be planned soon as there are not enough changes for such major version. Look that 2.0.0 means breaking backward compatibility, so core team would probably not dot it as often as you imagine, because there would be lots of problems with already created packages. Think that all authors of all packages would need to check if there are not any breaking changes in their code. This is lots of work and it would be definitely announced much before it’s release.

ok, I’m totally messed now …

Did you read proposal and why it was proposed? It was exactly because people tried to access things which they should not and it was not talked in contents of not used libraries, but lots of question/issues about “… not working after upgrade”. If there would be a way to access private functions I believe that lots of people would do so and I’m not exception here. I really often want to change one line in function which relies on few private functions, but copying them means maintaining all of this just for one line change and all fixes to this code would need to be tracked by me and patched in my version as well.

I’m curious what you mean by “experienced” developers, because if I remember correctly those awesome people which wrote absinthe had problems with upgrading Elixir too. Here are only few examples which are already mentioned:

and the complete list is really long.

Look I don’t believe that José Valim would create such proposal for few newbies … There was lots of problems which I have noticed too using popular 3rd-party libraries.


Maybe after all of that you would not understand - no problem. I would like only to write why it’s so important for me. As a newbie I saw monkey patching in Ruby used only once for one line function. I liked it way too much. I end up with monkey patching lots of functions, because I just saw other people do that. Of course it was not only one thing I did wrong and mostly it’s all because I assumed too much. It’s why taking care about whole code (not only naming) is so much important for me.

Hope that helped :slight_smile:

1 Like