如何/如果仅使用表单和数据模块重构 Delphi 程序

Posted

技术标签:

【中文标题】如何/如果仅使用表单和数据模块重构 Delphi 程序【英文标题】:How / if to refactor a Delphi program using only forms and data modules 【发布时间】:2010-10-07 15:43:10 【问题描述】:

在多年将 Delphi 程序编码为表单和数据模块中不可测试的代码(包括全局变量)之后,唯一的类是表单本身,包含表单 UI 本身所需的所有代码。

如何将代码转换为一组执行实际工作的类?我是否需要停止使用数据源/数据集并在课堂上做所有事情?我需要 ORM 吗?

通常需要重用表单中的代码,那么将逻辑转换为类是否有意义?

【问题讨论】:

【参考方案1】:

导入Modelmaker 是我面对现有的 Delphi 项目时的第一个操作。 Modelmaker 将协助您重构您的代码,因为:

以图形方式表示所有类、方法、变量等。 在 Delphi IDE(主菜单、弹出菜单、 单独的 Modelmaker 资源管理器, 工具栏、键盘快捷键)。这 集成让您可以快速 无需执行必要的操作 离开 IDE 它有一个专用的“重构”模块让您可以快速创建、移动 并重命名类和变量 不得不担心改变 底层代码。模型制造商将 自动更改名称和 所有单位的引用。

Modelmaker 的基本功能简单易学。 Modelmaker 就像任何其他好的生产力工具一样 - 你投入的越多,你得到的就越多。 Modelmaker 不是免费的,但可以通过提高生产力轻松收回成本。 我还没有找到更好的工具来重构遗留的 Delphi 代码。他们提供免费试用和一些不错的教程电影。 试试 Modelmaker,祝你好运...

【讨论】:

没有反对 ModelMaker,但你提到的所有东西都是现在内置的。不过,如果您有较旧的 Delphi,请 +1 提供帮助。 谢谢 - 我仍在使用 Delphi 5。我知道 Modelmaker 男孩与 Borland 签订了代码共享协议。 Delphi IDE 中集成了许多 Modelmaker 功能。我想如果所有 Modelmaker 功能都集成在 IDE 中,那么没有人会花 199 欧元购买许可证。 @Kris,实际上集成的重构功能不是来自 ModelMaker,而是来自 Borland Together(这更不友好)。我使用了 Delphi 默认建模,而且 ModelMaker 对于 Delphi 开发人员来说更容易掌握。 +1;请注意,ModelMaker 和 ModelMaker Code Explorer 是两个不同的产品。 ModelMaker 是 UML 工具,ModelMaker Code Explorer 是紧密集成在 Delphi IDE 中的重构工具。它比 IDE 中已经存在的重构工作得更好(一方面,因为它可以对未完全编译的代码进行操作,还因为它有更多更好的重构)。几个世纪以前,ModelMaker 被包含在 Delphi 中(在 Together 集成之前)。我希望他们继续这样做。内置重命名符号重构的好处是:它涵盖了您的整个项目。【参考方案2】:

我强烈推荐的另一本书——在我个人看来甚至比 Fowler 的“通用”重构书更合适——是"Working Effectively with Legacy Code" by Michael Feathers。它真正展示了您在进行此类工作时会遇到的主要障碍。哦,还有:重构遗留代码对你来说可能非常困难。我希望你能处理挫折......我喜欢这句话(不记得我从哪里得到它):“上帝能够在 6 天内创造世界,只是因为没有任何遗留代码”。祝你好运。 ;)

【讨论】:

【参考方案3】:

我在一个应用程序中遇到了这样的问题,我开始执行以下操作:

    为代码中的大多数通用逻辑定义主类。 在每个表单中,将处理事件内部业务逻辑的代码作为该表单中的函数/过程移动。 然后将这些函数/过程作为静态方法移动到这些类中。 最后只在表单中编写所需的代码,如验证 UI 和对类的调用。 对于全局变量,尽量省略,只需将值作为参数传递给方法。

我使用了静态方法,因为您可以更轻松地从事件中删除代码并直接调用它们,而无需为每个操作创建/释放对象。最初的设计并不是为了将表单与业务逻辑代码分开。

最终的应用程序不是完整的 OO,但它至少更容易测试方法,而不需要像以前那样与表单和事件进行交互。

有时您会觉得,如果您从头开始重新设计应用程序,会比进行更改以使其成为真正的 OO 设计更容易。

【讨论】:

【参考方案4】:

如果我遇到一个表单(或其他类)有太多责任,我通常遵循以下模式:

    为逻辑定义一个新类。 在表单中创建新类的成员变量。 在 onCreate 中创建类并在表单的 onDestroy 中释放它。 将单个逻辑(例如变量)移动到新类中。 将所有方法移动或创建到新类。 编译和测试。 继续,直到所有逻辑都放入新类中。 尝试将逻辑类与表单类解耦。 (如果您愿意,您甚至可以使用接口)。

存在单个类不够用的情况,所以创建更多类是没有问题的。而且这些类可以有其他类。

通过这些步骤,您可以解决大部分问题。

【讨论】:

不错的步骤,但有一个提示:为了尽可能减少耦合,不要将任何视觉控件传递给您的新类。如果你这样做了,那么你就限制了你换出 UI 控件的能力。如果您必须通过可视化控件(尤其是网格等),则将其全部隔离在另一个没有业务逻辑的类中。 我同意,可见控件是表单的责任。可以使用框架,但我不太喜欢将它们用于生产代码。 所有优点。依赖于特定数据库连接和数据表对象(TTable、ADO 数据集或 datasnap 等)的东西的单元可测试性如何...... @Warren P,使用数据库,您可以模拟整个数据库界面,也可以使用为每个测试设置的特殊测试数据库。我更喜欢后者,但它会减慢测试速度。【参考方案5】:

在了解你需要重构代码之后,如果你想要一个 OPF/ORM,我建议Jazz SDK

【讨论】:

【参考方案6】:

首先,我强烈建议您阅读 Martin Fowler 的《Refactoring》一书。

这将使您真正了解如何以最佳方式明智地引入对现有(非 OO)代码的更改以提高可维护性。

在您清楚地了解 ORM 会给您的应用程序带来什么好处(如果有的话)之前,我不会查看 ORM。

【讨论】:

以上是关于如何/如果仅使用表单和数据模块重构 Delphi 程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Delphi 将数据从 XML 导入 PDF 表单?

如何重构仅使用循环和简单数组的代码?

Delphi如何检测表单上任何地方的点击事件,包括其他组件

将 TForm 分配给一个变量 Delphi 以在其他单元中使用

将组件添加到表单时如何自动添加 Delphi 单元? [复制]

delphi 怎样让TWebBrowser向需要接收表单元素的页面发表单数据?(