[erlang-questions] Are packaged modules the way to go ?

cyril Romain c.romain@REDACTED
Thu Jan 8 00:59:35 CET 2009


Hi,

Bengt Kleberg wrote:
> I belive it shows that the existing packaged modules are not a
> sufficiently good idea to warrant official adaptation.
>   

Indeed.... Thanks for the link, it's a long but worth reading thread!


After a deeper look, here is my feedback about packaged modules. I'll 
give objective facts first, before somewhat subjective notes about 
packaged modules.


_WITHOUT PACKAGED MODULES_

A project without packaged modules:
 - has a flat module structure (i.e. there are no modules within modules).
 - generally has, if not always, its sources files (*.erl) in one 
directory with no subdirectory. Same things for binary files (*.beam).
 - the name of a module is the name of the Erlang file (without 
extension) and vice versa.

And consequently:
 - tends to use the following name convention to avoid file/module name 
clashes: myapplication_mycomponent_mymodule.erl (sometimes there is no 
mycomponent, and more rarely no myapplication in the name). 
Abbreviations such as myapp instead of myapplication are often use to 
avoid very long name.
 - can use macros to avoid using long module name within the code. E.g. 
-define(MYMOD, myapplication_mycomponent_mymodule), and calling 
?MYMOD:foo().
 - the project file structure makes Emakefile quite straightforward to 
write. A one liner Emakefile may even suffice: {'src/*', [debug_info, 
{outdir, "ebin"}, {i, "include"}]}.
 - tools analyzing Erlang files or project file structure [1] can rely 
on the following statement: the file name is the module name and vice versa.


_WITH PACKAGED MODULES_

A project with packaged modules:
 - has a tree module structure.
 - generally suggest (resp. require) the source (resp. the binary) file 
structure to follow the tree module structure.
 - the name of a module can differ from the file name (the full module 
name is actually a part of the file path, with . instead of /).
 - a module in a package requires additional import of the top-most 
modules used in the code. Indeed you need to either:
    - use the prefix . to specify that you are referring to the root 
package.
    - add an 'import' statement at the top of the module.
E.g. to use the standard library 'lists' module: you would either use 
'.lists:reverse' instead of 'lists:reverse', or you have to -import(lists).
Anther example if a module in a package defines -behaviour(supervisor), 
you have to -import(supervisor) or to use the . prefix to call 
supervisor functions.

And consequently:
 - short file names can be used. mymodule.erl can actually defines 
-module(myapplication.mycomponent.mymodule).
 - make code more readable and easier to maintain, because no need to 
specify the namespace when calling function defined in mymodule.
 - require more complex Emakefile to dispatch .beam files in a directory 
structure following the module namespace structure.
 - allow multiple Erlang files to have the same name, as long as they 
define modules in different namespace. E.g the ~/ebin/core/net.beam, 
~/ebin/plugin/net.beam and Erlang kernel's net.beam files can coexist 
with the respective core.net, plugin.net and net module names.
 - the full module name should be read from the Erlang file to be known. 
Indeed in /a/path/to/mymodule.erl, the module name could be 'mymodule' 
or 'to.mymodule' or etc.


_NOTES_:

Packages modules suggest to the developers to split their software into 
sub-component, which is good IMHO. Project containing ton of source 
files are indeed easier to work with when split into orthogonal 
components, with one directory per component and where code dependencies 
are more clear.
Of course it can be achieved without packaged module and one can badly 
design and split their packaged modules, but packages modules just 
strongly suggest this good software development practice.

Packages modules, as they are now, have some drawbacks though:

In regards to developer's code:
     - using the prefix . for top-most module breaks code consistency 
between top-most and non-to-most modules, unless you or Erlang would 
enforce that prefix to be used everywhere.
     - additional import tends to conflict with the 'don't use import' 
Erlang programming rule [1].
However it nicely solves the too_much_long_names in code issue without 
using UPPERCASEMACROS.

Some unexpected "bugs" can also show up when using module packages. For 
instance:
     - code:where_is_code(Filename) looks for the file in code path but 
not in sub-directories, so it is unable to find packaged module.
     - code:get_object_code(Mod) can succeed while Mod:module_info() 
fails, when e.g. Mod = test.plugin.net but the module name actually is 
plugin.net.


It is also worth noting that packaged modules:
 1. does not solves name clash issues. It only substitutes name clash 
issues by module namespace clash issues. Indeed if you use for instance 
two Erlang projects using packages that pick the same name and namespace 
for a module, the code will clash.
 2. implies more complexity in tools analyzing Erlang files or project 
file structure such as debugger, dialyzer, Emakefile, etc. Indeed those 
tools cannot assume the filename is the module name and vice versa anymore.
 3. are not supported yet by some useful tools (dialyzer, Erlang 
automake, etc.). E.g. dialyzer assumes the file name is the module name 
and vice versa, and therefore fails to analyze projects with duplicate 
Erlang files name, even if those files define modules in different 
namespace.
 4. last but not least, it breaks referential transparency in some way [2].

Further discussion about packages can be found on the Erlang mailing 
list. See [3] and [4].


Although packaged modules seems a good idea, I'm still wondering if they 
are worth it due the above notes, and in regards to the Erlang code 
consistency in general.
I'm tempted to say that packaged modules are good and can enforce 
consistency, but only if widely adopted by Erlang developers and widely 
supported by tools.
Unfortunately for now it just look like it adds more confusion than 
consistency :-(

If there is a consensus about no adoption, are packaged modules planned 
to be removed from Erlang/OTP releases ?
Any official decision or thought on this subject ?

Sorry for the long mail. Hope it will be useful.
Best regards,

  Cyril

PS: for some reason Joe Armstrong does not mention packaged modules in 
his last book. Hope I'm not reviving an old flame ware here!
If you notice something wrong or that I didn't mentioned, please let 
everyone know.

[1] http://www.erlang.se/doc/programming_rules.shtml#HDR26
[2] 
http://www.erlang.org/pipermail/erlang-questions/2006-October/023749.html
[3] http://www.erlang.org/pipermail/erlang-questions/2003-April/008571.html
[4] 
http://www.erlang.org/pipermail/erlang-questions/2006-November/023768.html






More information about the erlang-questions mailing list