您将如何开始改进一个非常糟糕的系统?

在您建议创建单元测试和重构之前,让我解释一下我的意思。我可以使用这些技术,但在这种情况下这是毫无意义的。

事实上,这个系统已经很糟糕了,它无法做它需要做的事情。

例如,系统应该计算它发送了多少条消息。它大多数情况下有效,但在某些情况下它“忘记”增加消息计数器的值。问题是,许多其他模块都有自己的解决方法,都建立在这个计数器的基础上,如果我更正计数器,整个系统将变得比目前更糟糕。解决方案可能是修改所有模块并删除它们自己的更正,但对于 150 多个模块,需要如此多的协调,我无法承担。

更糟糕的是,有些问题的解决方法不是在系统本身,而是在人们的头脑中。例如,系统不能在一个消息组中表示多于四个相关消息。某些服务需要将五个消息组合在一起。会计部门知道这一限制,每次计算这些服务的消息时,他们都会计算消息组并将其乘以 5/4 以获得正确的消息数。绝对没有关于这些偏差的文档,也没有人知道系统中现在存在多少这样的东西。

那么您将如何开始改进这个系统呢?你会采取什么策略?

一些额外的事情:我是一支单人部队,致力于此,因此雇用足够的人员并重新设计/重构系统并不是一个可以接受的答案。在几周或几个月内,我确实应该展示出一些明显的进展,因此在几年内自己进行重构也不是一个选择。

一些技术细节:该系统是用 Java 和 PHP 编写的,但我认为这并不重要。它背后有两个数据库,一个是Oracle,一个是PostgreSQL。除了前面提到的缺陷之外,代码本身也有味道,它的编写和记录确实很糟糕。

附加信息:

计数器问题不是同步问题。counter++语句被添加到一些模块中,而没有添加到其他一些模块中。一个快速但肮脏的修复方法是将它们添加到丢失的地方。长期的解决方案是让它成为需要它的模块的一个方面,这样以后就不可能忘记它。我对修复此类问题没有任何问题,但如果我进行此更改,我将破坏 10 多个其他模块。

更新:

我接受了 Greg D 的回答。即使我更喜欢亚当·贝莱尔(Adam Bellaire)的作品,但知道什么是最理想的也无济于事。感谢大家的回答。

有帮助吗?

解决方案

  1. 扑灭火灾。如果存在任何关键优先级问题,无论它们是什么,您都必须先处理它们。如果必须,请将其删除,使用臭臭的代码库就可以了。你知道你会改进它。这是针对您报告的任何人的销售技巧。
  2. 选择一些悬而未决的成果。我认为你对这个特定的软件比较新,并且你被重新负责处理它。在代码的相关子系统中找到一些显然容易出现的问题,这些问题不应该花费一两天的时间来解决,并修复它们。这可能涉及重构,或者可能不涉及。目标是熟悉系统和原作者的风格。你可能不会很幸运(在我之前使用我的系统的两位不称职的人之一总是用四个标点符号而不是一个标点符号来修复他的评论,这使得很容易区分谁编写了特定的代码段。),但是你会深入了解作者的弱点,所以你知道要注意什么。例如,与全球状态的广泛紧密结合与对语言工具的不良理解。
  3. 设定一个大目标。如果您的体验与我的相似,那么当您执行上一步时,您会发现自己处于特定的意大利面条代码中。这是你需要解开的第一个结。根据您的经验,您已经了解了原始作者可能做错的组件和知识(因此,您需要注意什么),您可以开始为系统的这个子集设想更好的模型。如果你仍然需要维护一些凌乱的界面来维护功能,请不要担心,只需一步一步。
  4. 泡沫,冲洗,重复! :)

    考虑到时间,请考虑在接口下方的一个级别为系统的其余部分添加新模型的单元测试。不要通过使用它们的测试在代码中雕刻坏接口,你将在以后的迭代中更改它们。

    解决您提到的特定问题:

    当您遇到用户正在手动解决的情况时,与用户讨论有关更改它的信息。如果您在更改时间之前提供更改,请确认他们将接受更改。如果他们不想要改变,那么你的工作就是保持破碎的行为。

    当您遇到多个其他组件已经解决的错误组件时,我支持并行组件技术。创建一个计数器,该计数器可以处理现有 的工作方式。提供类似的(或者,如果实际的,相同的)接口并将新组件滑入代码库。当您触摸解决损坏的外部组件时,请尝试使用新组件替换旧组件。类似的接口可以方便地移植代码,如果新的组件出现故障,旧的组件仍然存在。在可以之前不要删除旧组件。

其他提示

现在有人问你什么?您是否被要求实现功能或修复错误?他们甚至知道他们想要你做什么吗?

如果你没有人力、时间或资源来“修复”整个系统,那么你所能做的就是舀水。你说你应该能够在几个月内取得一些“明显的进步”。好吧,由于系统像您所描述的那样糟糕,您实际上可能会使系统变得更糟。在做一些引人注目的事情的压力下,您只需添加代码,并使系统变得更加复杂。

最终你需要重构。没有其他办法了。如果您能找到最终用户可见的重构方法, 那将是理想的, ,即使需要6-9个月或一年而不是“几个月”。但是,如果不能,那么您可以选择:

  • 重构,尽管你付出了努力,但还是有被视为“没有完成任何事情”的风险
  • 不要重构,完成“看得见的”目标,让系统变得更加复杂,有一天更难重构。(也许当你找到更好的工作后,希望下一个开发人员永远不会知道你住在哪里。)

哪一种对您个人最有利取决于您公司的文化。他们有一天会决定雇用更多的开发人员,还是用其他产品完全取代这个系统?

相反,如果你“修复一些东西”的努力实际上破坏了其他东西,他们会理解你被要求单枪匹马解决的怪物吗?

这里没有简单的答案,抱歉。您必须根据您独特的个人情况进行评估。

这是一本完整的书,基本上会说单元测试和重构,但有更多关于如何做的实用建议

http://ecx.images-amazon.com/images/I/51RCXGPXQ8L._SL500_AA240_.jpg

http://www.amazon.com/Working-Effectively-Legacy-Robert -Martin / DP / 0131177052

使用Windows资源管理器打开包含此系统的目录。然后,按Ctrl-A,然后按Shift-Delete。这听起来像是你案件的改进。

严重的是:该计数器听起来像是有线程安全问题。我会锁定不断增加的功能。

关于系统的其他部分,你不能做不可能的事情,所以尽量做到可能。您需要从两个方面攻击您的系统。首先处理更明显问题的问题,以便显示进度。与此同时,你应该处理更多的基础设施问题,这样你有一天就有可能真正解决这个问题。

祝你好运,也许消息来源与你同在。

选择一个中等难度的区域进行重构。仅使用现有代码的方法签名创建原始代码的框架;甚至可以使用界面。然后开始乱砍。你甚至可以指出“新的”直到你找到它们的方法。

然后,测试,测试,测试。由于没有任何单元测试,可能只是使用老式的语音激活单元测试(人)?或者随时编写自己的测试。

记录您进入某种存储库时的进度,包括挫折和问题,以便当下一个获得此项目的可怜的骗子不在您所在的位置时:)。

完成第一部分后,继续下一部分。关键是要建立在渐进式进步之上,这就是为什么你不应该首先从最难的部分开始;让事情变得士气低落太容易了。

Joel有几篇关于重写/重构的文章:

http://www.joelonsoftware.com/articles/fog0000000069.html

http://www.joelonsoftware.com/articles/fog0000000348.html

我已经使用具有相同特征的遗留系统近三年了,并且没有我所知道的捷径。

使用我们的遗留系统最让我困扰的是我不允许修复一些错误,因为如果修复它们,许多其他功能可能会破坏。这需要丑陋的解决方法或创建旧版本的旧功能。然后可以一次用新的函数替换对旧函数的调用(在测试时)。

我不确定你的任务的目标是什么,但我强烈建议你尽可能少地触摸代码。只做你需要做的事。

您可能希望通过面试人员记录尽可能多的文件。这是一项艰巨的任务,因为你不知道要问哪些问题,人们会忘记很多细节。

除此之外:确保你获得报酬和足够的道德支持。会有哭泣和咬牙切齿......

嗯,你需要从某个地方开始,听起来有些错误需要修复。我会解决这些错误,快速获得重构,并在此过程中编写任何单元测试。我还会使用像 SourceMonitor 这样的工具来识别一些最“复杂”的代码部分在系统中,看看我是否可以以任何方式简化他们的设计。最终,你必须接受这将是一个缓慢的过程,并朝着更好的系统迈出一小步。

我会尝试选择一部分可以快速提取和重写的系统。即使它没有做太多,你也可以很快地显示进度,并且你没有直接与遗留代码接口的问题。

希望如果你可以选择一些这样的任务,他们会看到你取得明显的进展,你可以提出一个论据,雇用更多的人来重写更大的模块。当系统的某些部分依赖于破坏的行为时,您没有太多选择,只能在修复任何内容之前将其分开。

希望你能逐步建立一支能够改写整个团队的团队。

所有这一切都必须与一些体面的培训齐头并进,否则人们的旧习惯会坚持下去,当事情无法按预期发挥作用时,你的工作将受到责备。

祝你好运!

弃用当前存在的有问题的所有内容,并编写可正常工作的新内容。尽可能多地记录有关改变的内容,并在指向本文档的地方放置大红色闪烁标志。

通过这样做,您可以保持现有的错误(那些正在被其他地方补偿的错误),而不会减慢您获得实际工作系统的进度。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top