你的位置: 首页 > 新闻博客 > 技术博客

Delphi/Object Pascal全局变量策略

2024-02-28 22:20:48

全局变量通常被认为是不友好的。在涉及状态变量时尤其如此。然而,由于我的工作重点一直并将继续关注遗留项目,全局变量是需要管理的现实问题。


维护一个拥有许多全局变量的项目是一项挑战。根据所使用的名称,其中一个问题可能是如何发现这些变量的所有写入内容。如果项目很大,搜索起来就会很麻烦。


创建一个包含全局变量的类。为每个变量创建一个私有字段变量,并只通过属性提供访问。这样做有点费事,但好处是可以在设置器中设置断点,以发现变量何时被写入。此外,你还必须修改访问变量的客户端模块,在新类中添加类实例名称以引用这些变量。


请看这个非常简单的类:

type

   TMyGlobals = class

private

    FWindowsDocumentsDir: string;

    function GetWindowsDocumentsDir: string;

public

    property WindowsDocumentsDir: string read GetWindowsDocumentsDir;

end;

var

   MyGlobals: TMyGlobals;


由于 Windows 临时目录在程序实例的生命周期中不太可能更改,因此您可以在类的初始化期间收集它,并且无论程序在哪里需要使用它,只需引用它即可:

...

SaveToFile(MyGlobals.WindowsTempDir + MyFileName);


该变量的 getter 可能如下所示:

function TMyGlobals.GetWindowsDocumentsDir: string;

var

   FilePath: array [0..MAX_PATH] of char;

begin

    if FWindowsDocumentsDir.IsEmpty then

    begin

        ShGetSpecialFolderPath(0, FilePath, CSIDL_Personal, False);

        FWindowsDocumentsDir := IncludeTrailingPathDelimiter(FilePath);

   end;

   Result := FWindowsDocumentsDir;

end;

请注意,在这样的类中,当您存储路径名时,您需要确保路径名以路径分隔符结束。这样做可以避免在应用代码中大量调用 IncludeTrailingPathDelimiter。


这个示例太小,没有什么用处,但在遗留项目中,您可能会找到数十个全局变量,甚至更多。将它们封装起来将有助于使得代码更清晰易读。


你的 globals 类模块必须添加到其他模块的 uses 子句中。不过,你也可以删除对之前包含全局变量的模块的引用。反过来,您也可以减少项目中的单元依赖周期。在大型复杂模块中定义的变量会产生依赖循环,每次引用都会使循环问题成倍增加。你将保持 globals 类非常干净,没有单元依赖循环,因此当它可以被引用而不是一个更复杂的模块时,你将享受到好处。

您可能还会发现,您的项目在许多地方使用了类型常量。这种做法已被弃用,常量的性质取决于编译器的设置。如果使用了 {$J+} 或 {$WRITEABLECONST ON},那么它们就不是常量,而是可以写入的。但是,类的成员可以通过仅公开读取访问权限来充当常量,如本示例所示。变量的设置可以像本示例中一样完成,也可以通过类构造函数或类中的显式初始化过程来完成。我发现当需要一个名义常量时,这种实现方式更好。


封装是 OOP 的核心特征,正如这里所建议的,封装也是重构遗留项目的有效工具。



QQ在线咨询
售前咨询
0531-66900120
售后服务
13287796906
QQ在线咨询
售前咨询
0531-66900120
售后服务
13287796906