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

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

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

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

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

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


当前回答

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

其他回答

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

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

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

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

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

正如你所描述的,主要的问题是区分拆分前和拆分后,合并bug修复等。围绕它的工具。用Perl、Ruby等语言硬编码一个脚本不会花那么长时间,就可以去除分离前和分离后的连接所产生的大部分噪音。用最简单的方法处理噪音:

在连接前/过程中删除某些行(例如包括警卫) 如果有必要,从diff输出中删除其他内容

您甚至可以这样做,只要有签入,连接就会运行,并且您已经准备好了一些与单文件版本不同的东西。

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

这并不是一个大问题的答案,而是一个具体问题的理论解决方案:

Figure out where you want to split the big file into subfiles. Put comments in some special format at each of those points. Write a fairly trivial script that will break the file apart into subfiles at those points. (Perhaps the special comments have embedded filenames that the script can use as instructions for how to split it.) It should preserve the comments as part of the splitting. Run the script. Delete the original file. When you need to merge from a branch, first recreate the big file by concatenating the pieces back together, do the merge, and then re-split it.

另外,如果您想要保存SCC文件历史,我认为最好的方法是告诉您的源代码控制系统各个片段文件都是原始文件的副本。然后,它将保存该文件中保存的部分的历史,当然,它也将记录大部分被“删除”。

一个重要的建议:不要将重构和错误修复混合在一起。您需要的是程序的版本与以前的版本相同,只是源代码不同。

一种方法是开始将最小的函数/部分分割到它自己的文件中,然后使用头文件include(从而将main.cpp转换为#includes列表,这本身听起来有点代码味道*尽管我不是c++专家),但至少现在它被分割为文件)。

然后,您可以尝试将所有维护版本切换到“新的”main.cpp或任何您的结构。再次重申:没有其他更改或错误修复,因为跟踪这些是令人困惑的地狱。

另一件事:尽管您可能希望一次性完成整个重构,但您可能会贪多嚼不烂。也许只是选择一两个“部分”,把它们放到所有的版本中,然后为你的客户增加一些更多的价值(毕竟,重构并不会直接增加价值,所以它是一种成本,必须被证明是合理的),然后再选择另外一两个部分。

显然,这需要团队中的一些纪律来实际使用拆分文件,而不是一直向main.cpp中添加新内容,但是,尝试进行一次大规模的重构可能不是最佳的行动方案。