= 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 term||Description||Example||Example description|| ||{{{atom()}}}||the name of a loaded module||{{{one1}}}||the module {{{one1}}}|| ||{'gn',module,!ModIdx}||the identifier of a module node||{'gn',module,2}||module !#2 in the graph representation|| ||{{{string()}}} containing a regexp||a 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}]). }}}