I'm a bit confused on what an .hrl
file should be used for. It's my understanding that .hrl
files can contain any valid Erlang code and that using the -include
directive will essentially insert the code in the .hrl
file into any module which includes it.
What sort of code is appropriate to put in these .hrl
files, then? Erlang's programming rules state the following in regards to records:
If the record is to be used in several modules, its definition should be placed in a header file (with suffix .hrl) that is included from the modules.
As a result, I have formed the habit of doing this in my code. However, I like to put things such as instantiation and comparison functions for records, as well as type definitions, in my headers as well (since this is the sort of thing I would do in C). Is this bad form? Should types be exported from an .erl
file instead, even if they are used in multiple modules? There seems to be no documentation on best practices regarding Erlang headers available.
LIke C, the include statement literally adds the contents of the included file into the erl file. Therefore, putting any actual code in the hrl files will cause that code to be copied everywhere you include it. This would lead to unnecessary duplication of functionality in every Erlang module.
I would place any actual Erlang code in its own erl module, and any record definitions, type specifications, or common macros in hrl files. Record definitions and type specifications aren't compiled into the binary files, so they are safe to include in multiple files.
Typically you put things in a .hrl
which you want to share between modules, usually record definitions and macros. Things which are meant to be purely local to a module you would not put in a .hrl
file. So a purely local record definition, for example the local state in a server, would not go in a .hrl
but only in the module defining the server. Same with macro definitions. You should always avoid unnecessarily exposing internal information.
As the include file is directly inserted into the including file then any code contained in it will be duplicated in each module which includes it. You generally don't want to do this.
I use hrl files to store various fixtures for use in my unit tests. I don't like using them in actual production code for anything. Having the same function imported in different locations makes it hard to reason about the code. It is more preferable to just have that code in a separate module and export it explicitly. Types can also be exported explicitly with the -export_type directive.
I don't even like sharing records with it (even though this is the only way to share records). For this, I prefer having a module manage nothing but that method with appropriate get and set functions. Shared records is a disaster waiting to happen and makes code upgrades trickier.
In short, don't use them for anything important.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With