所以我们在项目中有这个巨大的mainmodule.cpp源文件(11000行很大吗?),每次我不得不触摸它时,我都会畏缩。

由于这个文件是如此的核心和大,它不断积累越来越多的代码,我想不出一个好方法来让它实际上开始缩小。

该文件在我们产品的几个(> 10)维护版本中被使用和积极更改,因此很难重构它。如果我“简单地”将其拆分为3个文件,那么从维护版本合并回更改将成为一场噩梦。而且,如果您拆分具有如此长而丰富历史的文件,跟踪和检查SCC历史中的旧更改突然变得非常困难。

这个文件基本上包含了我们程序的“主类”(主要的内部工作调度和协调),所以每次添加一个特性,它也会影响这个文件,每次它的增长。:-(

在这种情况下你会怎么做?关于如何在不打乱SCC工作流程的情况下将新特性移动到单独的源文件中,您有什么想法吗?

(注意:我们使用c++和Visual Studio;我们使用AccuRev作为SCC,但我认为SCC的类型在这里并不重要;我们使用Araxis Merge来做实际的文件比较和合并)


当前回答

永远不要再碰这个文件和代码! 对待就像你被困住了一样。开始为编码在那里的功能编写适配器。 用不同的单元编写新代码,只与封装怪物功能的适配器对话。 ... 如果以上只有一项是不可能的,那就辞职去找一份新工作。

其他回答

一种不太危险的方法是对所有的线变化进行历史性的观察。有没有特定的函数比其他函数更稳定?可以说是变化的热点。

如果某一行在几年内没有被更改过,你可以将它移到另一个文件中,而不用太担心。我会看一下用最后一次修改注释的源代码,看看是否有任何函数可以提取出来。

好吧,我理解你的痛苦:)我也参与过一些这样的项目,它并不漂亮。这个问题没有简单的答案。

一种可行的方法是开始在所有函数中添加安全保护,也就是说,检查方法中的参数、前置/后置条件,然后最终添加单元测试,以便捕获源的当前功能。一旦你有了这些,你就可以更好地重构代码,因为如果你忘记了什么,你就会有断言和错误弹出来提醒你。

有时候,重构带来的痛苦可能会大于好处。那么,最好是让原始项目处于伪维护状态,从头开始,然后增量地添加野兽的功能。

我发现有一件事很有用(我现在正在做,尽管没有达到你所面临的规模),那就是将方法提取为类(方法对象重构)。不同版本中不同的方法将成为不同的类,这些类可以被注入到公共库中,以提供您所需的不同行为。

考虑以更合理的方式重写整个应用程序的方法。也许可以重写其中的一小部分作为原型,看看你的想法是否可行。

如果您已经确定了一个可行的解决方案,那么相应地重构应用程序。

如果所有产生更合理架构的尝试都失败了,那么至少您知道解决方案可能是重新定义程序的功能。

这是一个经典的例子,一个已知的反设计模式,称为blob。花点时间阅读我在这里指出的文章,也许你会发现一些有用的东西。此外,如果这个项目像它看起来的那样大,您应该考虑一些设计来防止发展成您无法控制的代码。