wiki:InterfaceLayers

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 three interface functions in the ri module: check_layered_arch/2, show_layered_arch/2 and show_layered_arch/3. The first two both take two parameters: {Name, ModSpecs} and {AllowFrom, AllowTo} as described above. The third has an extra parameter, which defines the name of the generated .dot file. The function ri:check_layered_arch/2 outputs the functions that violate the layer access restrictions, while ri:show_layered_arch/2 and ri:show_layered_arch/3 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}],"restrictions.dot").
Last modified 13 years ago Last modified on May 26, 2012, 11:18:52 AM