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

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

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

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

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

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


当前回答

这是一个困难而有趣的重构。

首先,将实现与接口分离。将这个巨大的文件转换为一个只转发调用和参数的空shell。这样,你可以创建责任有限的组件,而不会影响任何调用者(他们仍然调用巨大的文件/模块/类)。

为了做到这一点,您还需要寻找新的潜在组件的创建时间。根据构造函数的发送方式,在拥有所有参数之前,对参数进行堆叠可能非常棘手。

然后,您可以查找调用者并让他们调用您的组件。这是简单的部分。

其他回答

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

首先向它添加注释。参考函数被调用的位置以及是否可以移动物体。这可以让事情动起来。你真的需要评估它的代码基础有多脆弱。然后将公共功能转移到一起。一次做一些小改变。

合并不会像将来获得30000个LOC文件那样是一个大噩梦。所以:

停止向该文件添加更多代码。 把它。


如果你不能在重构过程中停止编码,你可以暂时保留这个大文件,至少不向它添加更多的代码:因为它包含一个“主类”,你可以从它继承,并将继承的带有重载函数的类保留在几个新的小而设计良好的文件中。

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

如果这个大的SWITCH(我认为是有的)成为主要的维护问题,你可以重构它,使用字典和命令模式,并从现有的代码中删除所有的开关逻辑到加载器,加载器填充该映射,即:

    // declaration
    std::map<ID, ICommand*> dispatchTable;
    ...

    // populating using some loader
    dispatchTable[id] = concreteCommand;

    ...
    // using
    dispatchTable[id]->Execute();

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

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

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