Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What should and should not be in an Erlang header (.hrl) file?

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 image 917
2rs2ts Avatar asked May 06 '13 16:05

2rs2ts


3 Answers

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.

like image 71
kjw0188 Avatar answered Nov 08 '22 14:11

kjw0188


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.

like image 22
rvirding Avatar answered Nov 08 '22 15:11

rvirding


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.

like image 4
jeremyong Avatar answered Nov 08 '22 13:11

jeremyong