在我们的组织中,我们希望强制使用源代码的分层结构。每个单元都处于某个“级别”,并且每个单元只能使用相同或更低级别的单元。
示例:
假设我们具有以下单位:L1_A.pas
,L1_B.pas
,L2_C.pas
,L2_D.pas
,L3_E.pas
(LX_
表示“ X级”)
L1_A
和L1_B
可以互相使用。 L2_C
和L2_D
可以同时使用所有L1_*
个单位。 L3_E
可以使用所有其他单位。
如果L1_*
单元尝试使用L2_*
单元或L3_*
单元,则我们需要中止编译并产生一些错误(“较低级别的单元尝试使用较高级别的单元“)。
如果我们使用C语言(或其他带有预处理器的语言)进行编码,则可以例如定义LEVEL_1
,LEVEL_2
,LEVEL_3
常数以及所有第1(第2)级单位检查是否定义了LEVEL_2
或LEVEL_3
(分别为LEVEL_3
)常量,在这种情况下,我们会发出相关错误。
Delphi定义(由{$DEFINE}
定义)在定义它们的单元之外无效。可以在外部使用已命名的常量和常量表达式,但是我们看到的常量取决于uses
中单位的顺序(即L1_A
定义了const Level=1
和L2_C
{{1 }}和const Level=2
包含L1_B
,而using L2_C, L1_A
中的Level
将是L1_B
)。
我只想出了命名约定[2
(或LX.Unit.pas),其中LX_Unit.pas
是级别,X
是“真实”单元名称],并使用Unit
中的脚本提交钩子。
我们只想使用基本的Delphi(不使用外部工具)。
答案 0 :(得分:9)
但是您可以检查常量。几个单位定义相同的单位,以及它们的类型或值是什么都无所谓,只要其名称与某个模式匹配即可。从某种意义上说,这样的常数就像“导出的” $define
:
const
Level3 = 3;
uses
X, Y, Z; // Z.Level3 hides Y.Level3, but that doesn't matter.
{$IF declared(Level3)}
如果传递给它的参数是在当前范围内可见的有效声明的Delphi标识符,则Declared 返回 True 。
答案 1 :(得分:6)
就像Rudy所说的那样,您可以使用普通常数,并在每个单位中重复它们。
请注意,单元可以包含在接口部分以及实现部分中。在第2级单元的 implementation 部分中包含第3级单元,不会使第3级常量在第2级单元的 interface 部分的范围内。因此,为了完全安全,您需要在接口部分设置常量(首先将其公开),并在实现部分中检查常量。
我至少要在包含的文件中放入检查,也许还有常量。在每个单元中,您都可以包含该级别的文件。
因此,每个第1级单元的“实现”部分将在“ uses”子句之后:
{$include level1check.inc}
在该文件中,您可以进行检查,并使用相当优雅的FATAL消息指令让编译器保释。然后level1check.inc看起来像这样:
{$IF Declared(level2)}
{$MESSAGE FATAL 'Cannot include a level 2 unit in a level 1 unit'}
{$ENDIF}
{$IF Declared(level3)}
{$MESSAGE FATAL 'Cannot include a level 3 unit in a level 1 unit'}
{$ENDIF}
我想知道是什么阻止开发人员作弊?如果他们可以修改uses子句,那么他们也可以删除或避开该支票。您可能需要在构建管道中强制执行此操作,但是如果执行此操作,也许可以使用更优雅的方法进行检查,例如,只需获取level1,level2和level3单元名称并扫描使用情况即可。每个level1和level2单元的子句都用于非法单元。
答案 2 :(得分:5)
在L1 * .pas中包含
boolean first = true;
if(somthing && first) {
val = implMethod1();
first = false;
} else {
val = implMethod2();
first = true;
}
然后在其他单位使用
CONST Level1 = TRUE;
或
{$IF Declared(Level1) }
等
您可能可以从那里找出其余的内容:-)