【问题标题】:The best approach to modular programming in DelphiDelphi中模块化编程的最佳方法
【发布时间】:2011-08-15 15:58:13
【问题描述】:

这是我在here 开始的讨论的继续。我想找到模块化 Delphi 源代码的最佳方法,因为我在这个领域没有经验。我将不胜感激您的所有建议。

让我把我已经写过的东西贴出来there。

我工作的公司开发的软件由 100 多个模块组成(其中大部分是不同设备的驱动程序)。它们中的大多数共享相同的代码 - 在大多数情况下是类。问题是这些类并不总是放在单独的、独立的 PAS 单元中。我的意思是共享代码通常被放入包含特定于模块的代码的单元中。这意味着当您修复共享类中的错误时,仅将其定义的 PAS 单元复制到所有软件模块中并重新编译它们是不够的。不幸的是,您必须将固定的代码片段一个接一个地复制并粘贴到适当的单元和类中。这需要很多时间,而这正是我希望在不久的将来通过选择正确的方法来消除的问题 - 请帮助我。

我认为使用与 EXE 一起分发的 BPL 会是一个很好的解决方案,但它也有一些缺点,正如前面讨论中提到的那样。最糟糕的问题是,如果每个 EXE 需要多个 BPL,我们的技术支持人员必须知道哪个 EXE 需要哪些 BPL,然后为最终用户提供适当的文件。只要我们没有软件更新程序,这对我们的技术人员和最终用户来说都是一笔大买卖。他们肯定会迷路和生气:-/。

还可能出现兼容性问题 - 如果一个 BPL 由多个 EXE 共享,则对该 BPL 的修改可能对一个 EXE 有利而对其他一些 EXE 不利。

那么我应该怎么做才能在这么多项目中更快地修复错误?我想到了以下方法之一。如果您有更好的想法,请告诉我。

  • 将共享代码放入单独和独立的 PAS 单元中,因此当其中一个有错误修复时,将其复制到所有项目(覆盖旧文件)并重新编译所有项目就足够了。这意味着每个单元的复制次数与使用它的项目数量一样多。

就很少修改的代码而言,此解决方案似乎没问题。但我们也有具有通用功能和程序的 PA 单元,这些单元经常进行修改。每次有人向该文件添加新函数时,都无法执行相同的过程(复制和重新编译这么多项目)。

  • 为所有共享代码创建 BPL,但将它们链接到 EXE,以便 EXE 是独立的。

对我来说,这似乎是现在最好的解决方案,但也有一些缺点。如果我在 BPL 中修复错误,每个程序员都必须在他们的计算机上更新 BPL。如果他们忘记这样做怎么办?但是,我认为这是一个小问题。如果我们注意互相通知变化,一切都应该没问题。你怎么看?

  • 最后一个想法,由 CodeInChaos 提出(我不知道我是否理解正确)。在项目之间共享 PAS 文件。这可能意味着我们必须将共享代码存储在一个单独的文件夹中,并让所有项目都在那里搜索该代码,对吧?我猜,每当需要修改项目时,都必须从 SVN 连同共享文件夹一起下载。共享代码中的每次更改都必须重新编译使用该代码的每个项目。

请帮我选择一个好的解决方案。我只是不希望公司因为一种愚蠢的软件开发方法而在错误修复上浪费更多的时间和金钱。到目前为止没有人关心它,你可以想象它会导致多少问题。

非常感谢。

【问题讨论】:

  • 同一个函数不要有两个副本。曾经。 SVN 很难实现您想要做的事情,但我认为您需要 SVN 外部。我投票决定转到程序员那里你应该得到更好的回应。
  • @David Microsoft 在其 Office 产品的源代码中做到了这一点。 (Scott Berkun,“项目管理的艺术”)为什么?如果在一个副本中引入错误,其他产品不会受到影响。
  • @mjn 我不敢相信。我认为你在重新讲述这个故事有点扭曲。
  • @mjn 如果一个错误被修复了,他们不会在其他人中修复它?

标签: delphi bpl modularization


【解决方案1】:

你说:

  • 为所有共享代码创建 BPL,但将它们链接到 EXE,所以 EXE 是独立的。

您不能将 BPL 链接到可执行文件中。您只是在 BPL 中的单独单元中进行链接。这样,您实际上根本就使用甚至需要 BPL。

BPL 旨在用作共享代码,即将共享的代码放入一个或多个 BPL 中,并使用来自每个 .exe、.dll 或其他 .bpls 的代码。错误修正(如果它们不更改 BPL 的公共接口)只需要重新分发一个固定的 BPL。

正如我所说,决定 DLL 的公共接口,然后不要更改它。您可以添加例程、类型和类,但不应修改任何现有类、类型、接口、常量、全局变量等已在使用的公共接口。这样,可以轻松分发固定版本的 BPL。

但请注意,BPL 高度依赖于编译器版本。如果您使用新版本的编译器,您也必须重新编译 BPL。这就是为什么根据编译器版本为 BPL 提供 100、110 等后缀是有意义的。然后,使用编译器版本 15.0 编译的可执行文件将被告知使用后缀为 150 的 BPL,使用版本 14.0 编译的可执行文件将使用后缀为 140 的 BPL。这样,不同版本的 BPL 可以和平共存。后缀可以在项目选项中设置。

您如何管理不同的版本?用我的ComponentInstaller BPL 的结构创建一个目录(这是您可以在 Delphi/C++Builder/RAD Studio XE IDE 菜单组件 -> 安装组件下看到的专家):

Projects
  ComponentInstaller
    Common
    D2007
    D2009
    D2010
    DXE

Common 目录包含每个版本共享的 .pas 文件和资源(位图等),每个 Dxxxx 目录包含该特定 BPL 版本的 .dpk、.dproj 等。每个包都使用 Common 目录中的文件。这当然可以同时为多个 BPL 完成。

顺便说一句,版本控制系统可能会使这变得容易得多。只需确保为 BPL 的每个版本赋予不同的后缀即可。

如果您确实想要独立的可执行文件,则不要使用 BPL,而只需在单独的单元中链接即可。 “使用 BPL 编译”选项控制着这一点。

【讨论】:

  • 感谢您分享您的经验。让我再问你一个问题。您的示例基于同一 BPL 的多个版本。每个 BPL 版本都使用相同的目录和 .pas 文件。但是,让我用完全不同的代码创建另一个 BPL,它引用公共目录中的一些单元。现在,它应该直接引用那些文件(附加到项目中)还是应该只使用那些常见的 BPL 之一(通过在项目的需求列表中引用它)?您认为哪种方法更好?
  • 单元只能同时在 one 和 one only BPL 中。需要这种单元的其他 BPL 应该要求包含它的 BPL。考虑一下哪个单位应该去哪里是有意义的。我会画一个图表,哪个可执行文件和哪个单元需要什么,重新排列它直到你满意,然后再决定。
  • 好的,这就是我想听到的。谢谢。
  • 让我总结一下,结束讨论。共享代码被放入 BPL。 Pas 文件永远不会被复制——这种方法只接受 BPL 依赖项。每个程序员都会在他们的机器上安装所有共享的 BPL,并在有人修改任何这些 BPL 时更新它们(连同属于他们的 .pas 文件)。只要使用SVN似乎很容易。这一切都正确吗?
  • 如果其中一个 BPL 已修复错误,但 接口(它公开的函数、过程、类、类型、常量等) 没有修改,只是需要替换那个BPL。不必替换 BPL 或依赖于它的可执行文件。您可以添加到 BPL 的接口,但不能删除任何东西或修改它。
【解决方案2】:

从我的角度来看,尝试管理 Delphi 单元、库和可执行文件等工件时,您在错误的位置进行搜索。我建议你转过头来,基于Design patterns 实现重构代码。

例如所有常用功能都可以放在一个Singleton类中,常用类的实例可以用Abstract Factory构造,类可以通过接口的原生Delphi实现而不是直接使用来交互等等。甚至您可以选择为项目的所有公共部分实施Facade。

当然,模式的具体选择和实施细节取决于项目的具体情况,只有您可以决定哪些适用于您的情况。 我想,在以这种方式进行项目之后,您可以找到更自然的代码组织方式和解决问题的方法。

其他一些事情:

  1. 当然,您必须遵循@CodeInChaos 的建议,在所有项目之间共享一份源文件,而不是手动将其复制到每个项目。如果您采用某种标准来构建环境可能会很有用,这对所有开发人员都是强制性的(相同的文件夹结构、库的位置、环境设置)。
  2. 尝试分析构建和部署过程:对我来说,当解决方案不是使用最新版本的代码构建并且在部署前没有经过测试时,它看起来很不正常。 (这是针对您的“如果我在 BPL 中修复错误,每个程序员……”这句话)。
  3. 带有独立可执行文件的变体看起来更好,因为它显着简化了测试环境的组织和项目部署。只需选择适当的版本控制约定即可。

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多