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

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

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

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

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

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


当前回答

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

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文件历史,我认为最好的方法是告诉您的源代码控制系统各个片段文件都是原始文件的副本。然后,它将保存该文件中保存的部分的历史,当然,它也将记录大部分被“删除”。

其他回答

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

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

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

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

下面是我所想到的解决这些问题的唯一办法。所述方法的实际增益是演化的累进性。这里没有革命,否则你很快就会陷入麻烦。

在原来的主类上面插入一个新的cpp类。目前,它基本上会将所有调用重定向到当前的主类,但目标是使这个新类的API尽可能清晰和简洁。

一旦完成了这些,就可以在新类中添加新功能。

至于现有的功能,当它们变得足够稳定时,您必须逐步将它们移动到新的类中。对于这段代码,您将失去SCC帮助,但是对此没有太多办法。只要选择合适的时机。

我知道这并不完美,但我希望它能有所帮助,这个过程必须适应您的需要!

额外的信息

注意,Git是一个SCC,它可以从一个文件跟踪代码片段到另一个文件。我听说过关于它的好东西,所以它可以帮助你逐步转移你的工作。

Git是围绕blob的概念构建的,如果我理解正确的话,blob表示代码文件的片段。在不同的文件中移动这些片段,Git会找到它们,即使您修改了它们。除了下面评论中提到的Linus Torvalds的视频之外,我还没有找到关于这个问题的一些清楚的东西。

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

我猜一下,如果这段代码为10个客户服务,并且包含代码变体,那么您可能有很多针对特定客户的带有变体的代码克隆

我很想对你的11000行文件进行克隆检测。(事实上,如果你把它发给我,我会用我的c++克隆检测器[见生物],并把答案发给你)。

这将显示任何克隆,以及这些克隆是如何变化的。有了这些信息,重构代码就变得相当容易了。