wiki:InterfaceLayers

Version 6 (modified by manualwiki, 13 years ago) (diff)

InterfaceLayers page improved

Interface layers

In large program systems, groups of compilation units (in the case of Erlang, modules) usually form logical layers. A desired property of such systems is that code in one layer should only use the layer immediately below it, and conversely, provide functionality only for the layer immediately above it. This page shows how you can define such layers and find functions that access layers that they are not supposed to.

Defining interface layers

We use a list to represent the hierarchy of the interface layers, starting with the lowest layer. Layers are described with tuples {Name, ModSpecs} :: {atom(), [modspec()]}, where Name is the name of the layer, and ModSpecs is a list that can contain any of the following.

Erlang termDescriptionExampleExample description
atom()the name of a loaded moduleone1the module one1
{'gn',module,ModIdx}the identifier of a module node{'gn',module,2}module #2 in the graph representation
string() containing a regexpa regular expression for module names"^(/home/user)/[a-zA-Z0-9_/]+(/layer1)$"files from a layer1 directory under /home/user
string()name of a file that contains regexps"layer1_regexps.txt"regexps inside layer1_regexps.txt

Define additional relations

Sometimes, it is desirable to allow calls between layers that do not conform to the above. For that purpose, we use a list of {AllowFrom, AllowTo} :: {atom(), atom()} pairs, where AllowFrom and AllowTo are layer names.

Interface functions

We currently have two interface functions in the ri module: check_layered_arch/2 and show_layered_arch/2. Both take two parameters, {Name, ModSpecs} and {AllowFrom, AllowTo} as described above. The function ri:check_layered_arch/2 outputs the functions that violate the layer access restrictions, while ri:show_layered_arch/2 visualises the layers in a graph with the layer violations highlighted.

Examples

ri:check_layered_arch(
    [ {il1,["^(/home/user/layers/layer1)$"]},
      {il2,["^(/home/user/layers/layer2)$"]},
      {il3,["regexp3"]}],
    []).
ri:show_layered_arch(
    [ {il1,["^(/home/user/layers/layer1)$"]},
      {il2,["^(/home/user/layers/layer2)$"]},
      {il3,["regexp3"]}],
    []).
ri:show_layered_arch(
    [ {il1,["^(/home/user/layers/layer1)$"]},
      {il2,["^(/home/user/layers/layer2)$"]},
      {il3,["regexp3"]}],
    [{il1,il3}]).