Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force layered source code structure in Delphi

Tags:

delphi

In our organisation we would like to force layered structure of source code. Each unit would be in certain "level" and units would be able to use only units in same or lower level.

Example:

Suppose we have these units: L1_A.pas, L1_B.pas, L2_C.pas, L2_D.pas, L3_E.pas (LX_ means "level X").

L1_A and L1_B can use each other. L2_C and L2_D can use all L1_* units and each other. L3_E can use all other units.

If L1_* unit tried to use either L2_* unit or L3_* unit, we need to abort compilation and produce some error ("Unit in lower level tried to use unit in higher level").

Have we coded in C (or other language with preprocessor), we would for example define LEVEL_1, LEVEL_2, LEVEL_3 constants and in all 1st (resp. 2nd) level units check if eihter LEVEL_2 or LEVEL_3 (resp. LEVEL_3) constants were defined in which case we would emit relevant error.

Delphi defines (defined by {$DEFINE}) don't have effect outside unit in which they were defined. Named constants and constant expressions can be used outside, but which one we see depends on the order of units in uses (ie if L1_A defines const Level=1 and L2_C const Level=2 and L1_B contains using L2_C, L1_A than Level in L1_B would be 2).

I came up only with naming convention [LX_Unit.pas (or LX.Unit.pas), where X is level and Unit is "real" unit name], and checking with a script in svn commit hook.

We would like to use only basic Delphi (no external tools).

like image 260
andowero Avatar asked Mar 18 '19 09:03

andowero


1 Answers

But you can check for constants. It doesn't matter if several units define the same one, and what their type or value is, as long as its name matches a certain pattern. In a way, such a constant is like an "exported" $define:

const
  Level3 = 3; 
  • Unit X has constant Level1
  • Unit Y has constant Level3
  • Unit Z has constant Level3
 uses
   X, Y, Z; // Z.Level3 hides Y.Level3, but that doesn't matter.

 {$IF declared(Level3)}

As the documentation states:

Declared returns True if the argument passed to it is a valid declared Delphi identifier visible within the current scope.

like image 107
Rudy Velthuis Avatar answered Nov 15 '22 06:11

Rudy Velthuis