23

我知道已经有关于 VB6 迁移的问题,但是我项目的代码库在这里带来了一些新问题。

我不得不说代码质量、结构和架构简直就是一场噩梦。有 2 个大项目:Nr.1 有 40 个表单、40 个模块和一些类文件,这个 EXE 是一种“基础系统”。Nr.2 有 80 个表格,20 个模块和一些类文件,这个 EXE 调用函数形成了“基础系统”。然后还有大约 10 个其他带有 GUI 的项目(每个 1-3 个表单)和另外 90 个非 GUI 项目,其中大部分是 EXE 文件,一些 DLL。DLL 是用 C、C++ 和 VB6 编写的。

代码自 10 年以来不断发展,并且一次主要由 1 个(糟糕的)开发人员编写。

  • 具有 500 行(甚至更多)的函数非常常见。
  • 90% 的 GUI 组件被命名为 text1, command2(1), …
  • 复制和粘贴无处不在,例如复制了一个包含 5000 行代码的 EXE 项目(没有 GUI),副本中唯一的变化是通过邮件而不是 FTP 发送文件(同一个项目还有 2 个另外的副本)。
  • 我曾经有一个小表格(15 个字段),我应该解决一个小问题(通常最多半小时),每次我更改某些内容时,它要么不起作用,要么在表格中产生新的错误。2 天后,我决定彻底重写表格,从旧表格中的约 20 条 SQL 语句中,只有 2 条在新表格中幸存下来。
  • 甚至不要询问代码中的注释……</li>

几个月前我接手了这个项目,我是唯一的维护者。变更请求和错误的流量持续(但很少),我们从客户那里获得维护预算,以保持软件运行并在法律要求方面“保持最新”。

我的选择

1) 从头开始​​重写——在这种情况下,我可以用 Java 编写它以实现可移植性。这里的问题是除了一些(旧的)用户帮助之外,没有文档,所以丑陋的代码就是“文档”。有一个人有高层知道软件应该怎么做。此外,很难说服管理层这样做,即使从长远来看可以节省大量成本,也存在政治问题。我也不能一次做一个(vb)项目,因为数据库结构并不比代码好,即也必须从头开始。所以我只能一次更改整个软件。

2)首先将代码迁移到主要项目的 VB.NET / C# 迁移,我已经对其进行了测试,并从 Project Nr.1 中获得了约 2000 条升级评论,其中大部分内容如 Screen.MousePointer 已更改,具有变体返回值的函数和很快。我的想法是在转换之后,为 DB 抽象创建类,更改代码以使用这些类并进行重构,迁移和更改其他项目,当所有代码都使用 DB 类时,更改 DB 结构。

3) 无论如何我必须在 VB6 中更改某些内容时重构代码(我已经部分地这样做了),并在某些时候重构其余部分。这样更容易看到原始功能,因为它是原始代码,当出现错误时,很明显它们不可能是迁移的结果。当代码被重构时(我假设它也会小 50-75%),将它迁移到 .NET 会更容易。然后更改数据库结构(然后进行另一轮重构……)。

未来有一些更大的改变要做(使其与 Win7 兼容,以及另一个影响大部分代码的大 CR),所以会有一个很好的机会来做这些改变,因为我必须经历反正很多代码。

我的问题是谁有迁移糟糕、丑陋的代码的经验/提示?您会建议哪些选项?

4

9 回答 9

20

我不得不经历同样的事情(没有文档和可怕代码的大型 VB6 应用程序。)。您可以采取的唯一安全合理的路线是第 3 条。要改进某些东西,您必须首先了解它。如果您选择路线 1 或 2,您肯定会遇到可怕的混乱。

请记住始终牢记您的最终目标是完全迁移到 .NET。在重构时,请考虑 VB6 糟糕的 OO 支持在 VB.NET 或 C# 中的样子。如果可能的话,改变你的代码以使迁移更容易。

您可能需要考虑将许多核心功能转移到 .NET DLL 中,并通过 COM 将其公开给 VB6。这将从您的 VB6 中删除大量可笑的代码,并有望留下大部分业务逻辑。

您需要记住的最重要的事情是不要成为牛仔。

  1. 为模块编写测试。
  2. 重构一个模块。
  3. 测试模块。
  4. 发布您的应用程序。
  5. 转到 1
于 2010-01-20T14:25:51.667 回答
11

代码一定要迁移吗?如果它没有,仍然可以达到它的目的,并且可以维护一半,那就别管它了,继续前进

在数小时、数周和数月的代码迁移之后,您将代码迁移到新语言的动力很快就会消失——尤其是在您提到的规模上。

从概念上讲,代码迁移的想法是一个绝妙的想法。很可能,这是一个可怕的混乱,你会讨厌这样做的生活。

想一想,你在修复缺陷的同时讨厌你现在的生活吗? 对于迁移项目,将其升级 100 倍。

只要有效,大多数企业就不会真正关心引擎盖下的内容。请记住,他们不是开发人员,不在乎修复它是多么痛苦(因为他们不是这样做的人)并激励企业花费数万美元带来代码是最新的,根本没有任何商业意义。

于 2010-01-20T14:27:27.860 回答
10

经历过类似的将14岁的代码迁移到VS2008

以下是一些提示:

  1. 删除对第 3 方组件的依赖。
  2. 考虑分阶段迁移,例如使用反向互操作。
  3. 颜色和字体需要手工处理。
  4. 迁移到 .NET 后注意数组中未初始化的对象
  5. 将错误更改为 Try Catch
  6. 在需要的地方使用 Microsoft.VisualBasic.Compatibility.VB6 命名空间。
  7. 将重构保持在最低限度,直到所有代码都转换为 .NET
  8. 注意 VB6 代码中基于非零的数组。
  9. 在 VB6 中重构(最小化)您的代码,以便它可以通过代码转换向导。
  10. 注意基于 1 的 VB6 控件,例如 ListView
  11. 使用同步锁来避免线程问题。
  12. 如果您正在手动重构 sub,请注意数据类型大小的变化,尤其是在使用文件 IO 时。

有一家公司可以帮助您完成整个过程(尽管我们没有使用它们) http://www.vbmigration.com/

于 2010-01-20T14:29:38.277 回答
6

查看 M. Feathers 的“有效地使用遗留代码” ——它讨论了增强、重构和迁移以及未经测试的代码的缺陷。

于 2010-01-20T14:41:46.143 回答
6

你在制定这个问题方面做得很好。谢谢提问!并感谢 stackoverflow 社区发布深思熟虑的回复(像往常一样)。

如果这是一个相当大的代码库,并且听起来像是(50-100 个相互关联的 VBP,200-500K LOC),那么您应该考虑投资迁移工具。考虑这个类比:如果您有大量数据要转换,即使源数据很脏并且与所需格式有很大不同,您也会使用工具。如果有人建议您应该重新输入数据,或者甚至进行粗略转换然后手动修复它,您会认为他们是疯了。同样拥有 120 个表单,该应用程序听起来像是提供了相当多的业务功能。该业务功能已经出现了多年的使用,无论喜欢与否,VB6 代码代表了该功能的完整、正式和经过生产测试的规范,以及关于应用程序如何在幕后工作的无数技术事实。“从头开始”重新收集、重新编码和重新测试所有这些功能/技术要求是非常昂贵和困难的。为了管理项目的成本和风险,您必须“兑现”遗留代码。问题是:如何做到这一点,并确保迁移后的拥有成本更低。

挑战与代码库的大小无关,而是与适应和利用 .NET 所需的重新设计细节有关。您需要确定使 VB6 代码“难看”代码的具体因素,为什么它“难看”,以及您必须/应该/想要如何在 .NET 中以不同的方式做这些事情。一旦您开始制定这些重新设计要求,您就可以开始在转换过程中实施它们,以便它们出现在您的 .NET 代码中。我们提倡的一般方法称为“工具辅助重写”,它的完成方式如下:

  1. 运行翻译
  2. 构建/审查/测试生成的代码以识别/改进所需的代码改进
  3. 如果生成的代码“足够好”,则转到 .NET 中完成工作
  4. 重新配置翻译器以实现所需的改进(如果合适)
  5. 转到 1

该工具的输出不需要“完美”(软件永远不会......)它只需要“足够好”。第 3 步中提到的“足够好”是一个关键问题。从本质上讲,它意味着代码质量——就被验证为功能正确和符合您的标准而言——是这样的,即开发团队知道完成迁移需要什么,然后继续运行/维护应用程序——而且它们是相信他们可以在给定的时间和资源限制内做到这一点。对于一个非常大的代码库,“足够好”就是“非常好”,因为尝试完成并随后维护低质量的迁移太昂贵且风险太大。一般来说,代码越大,预算越小,

还有一些关于“在 .NET 中完成工作”的想法:在 .NET 中拥有格式良好的代码是一个重要的里程碑。.NET 社区提供了很好的重构、分析和单元测试工具,可以帮助您加快完成迁移的工作。您将在此过程的早期使用 Visual Studio 来试验和改进重新设计,以及调试/测试应用程序。能够在 .NET 中使用整个代码库并在迁移工作的早期使用 Visual Studio 是工具辅助方法的关键优势(也是关键部分)。

当然,要做到这一点,您需要能够投资专门用于支持工具辅助重写的迁移工具集。Great Migrations的工具是我所知道的这一类别中唯一的工具。

免责声明:我为大迁徙工作。我们的网站上有更多信息——包括有关如何使用该工具帮助将超过 1M LOC 的 VB6 迁移到重新设计的 C# 的案例研究,以及详细描述产品和方法的 gmStudio 用户手册。

于 2010-01-21T18:03:34.993 回答
2

与我做过的一些东西相比,它听起来很小。尽管如此,还有另一种方法可以与上面 PeanutPower 所示的方法结合使用。

答案是构建一个框架,允许您一次剪切程序的各个部分并逐个转换它们。

例如,插入一个数据库适配器“层”来处理对数据库的所有调用,然后一个接一个地删除 SQL 之外的每一个,并将其替换为对 db 层的调用。旧呼叫仍将直接进行,而新呼叫通过该层。最终,所有调用都将通过该层,您可以更改后端数据库。

您可以通过扩展框架“层”以覆盖该功能,对代码的任何其他部分执行相同操作。

将其从 VB6 转移到 VB.NET(例如)的关键是使用 Interop 库 - 这是一篇文章:http: //support.microsoft.com/kb/817248

另一个,很久以后的想法:获取 MZ-Tools 并使用他们的分析工具来查找冗余代码并将其删除。我设法消除了公司旧产品中大约 5% 到 10% 的代码。

于 2010-01-20T16:07:44.303 回答
2

从您对这个项目的描述来看,听起来您可能可以同时重构和迁移。您显然将采用大量冗余代码并对其进行整合;作为整合的一部分,您可能还可以在 .NET 中重写它(即冗余代码)。

这不适用于 UI 的东西。但它适用于数据库和业务逻辑的东西。例如,我没有看到您的代码,但我敢打赌,您的应用程序中的大多数组合框都由Form_Load创建 ADO 记录集并循环它们的形式(可能复制并粘贴到)中的方法填充。这可以重构为 .NET 数据访问类并轻松集成到现有表单中。它还可能允许您将缓存的神奇世界引入此应用程序,这将是很好的,因为这可能会导致明显的性能改进。

可见的改进很重要。除非您的管理层完全认同这样做的必要性,否则这是一项非常高风险的工作。如果您发现自己告诉您的管理层,由于重构中的问题,给定 CR 的实施时间将比他们预期的要长,那将是非常糟糕的。即使你有完全的支持,你也不希望出现这种情况,但如果你的支持是部分的,那就更糟了。可见的改进将大大减轻这种情况。

此外,关于重构遗留代码问题的文献越来越多。你需要在它之上。在深入研究之前,您了解的越多,您的体验就会越好。我自己没有读过 Michael Feathers 的书,但如果我站在你的立场上,这是我会做的第一件事。

于 2010-01-20T17:07:50.363 回答
2

在完成了多个迁移项目之后,首先要做的是明确您的迁移目标是什么。这些可能因组织而异,但它们有助于在实际迁移项目期间确定优先级。它还有助于更好地评估收益与风险和成本。

就像其他人提到的那样,重要的是要认识到迁移过程不会自动提高代码的质量。因此,如果您的主要目标是重构(仅此而已),那么您应该意识到可能需要数周或数月才能获得功能等效的代码(取决于代码大小和迁移复杂性)。

话虽如此,除了单元测试套件之外,.NET 确实有一些非常好的重构和代码分析工具。可以自定义诸如 ArtinSoft 的Visual Basic Upgrade Companion之类的自动转换工具,以强制执行编码标准或在转换过程中显着改进代码。这与ReSharper等其他代码修改工具的结合将大大加快您向 .NET 的过渡。

以我的经验,只要您知道涉及手动工作,迁移项目就是一个可管理的项目。商业工具具有评估模式,可以帮助量化迁移工作,并让您了解迁移中可能面临的挑战。

如果您更喜欢低风险和低成本的解决方案,我会坚持重构代码,着眼于最终迁移。我有客户对这种方法有效。因此,当需要迁移他们的代码时,已经解决了几件事。

基本上,任何新的自定义控件都应该用 .NET 编写并作为 ActiveX 控件公开以供 VB6 应用程序使用。同样,新的 DLL 函数应该放在可以通过 COM 使用的 .NET 程序集中。这样,当需要迁移时,您就不必担心那些控件或库。

于 2010-02-02T22:58:59.210 回答
1

不要从头开始重写。听起来这将花费您很长时间,并且您很可能会在代码中引入新(旧)错误。

我会考虑缓慢而简单地重构代码。从小处着手。令人惊讶的是,您可以多快地将代码重构为更易于管理的东西。并且您应该能够在您执行的每个折射块结束时保持代码“工作”。

更新: 值得注意的是,自动迁移只会将您的问题转移到另一种语言。

于 2010-01-20T14:28:49.210 回答