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

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

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

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

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

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


当前回答

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

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

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

其他回答

另一本你可能会觉得有趣/有用的书是《重构》。

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

Find some code in the file which is relatively stable (not changing fast, and doesn't vary much between branches) and could stand as an independent unit. Move this into its own file, and for that matter into its own class, in all branches. Because it's stable, this won't cause (many) "awkward" merges that have to be applied to a different file from the one they were originally made on, when you merge the change from one branch to another. Repeat. Find some code in the file which basically only applies to a small number of branches, and could stand alone. Doesn't matter whether it's changing fast or not, because of the small number of branches. Move this into its own classes and files. Repeat.

因此,我们去掉了到处都一样的代码,以及特定于某些分支的代码。

This leaves you with a nucleus of badly-managed code - it's needed everywhere, but it's different in every branch (and/or it changes constantly so that some branches are running behind others), and yet it's in a single file that you're unsuccessfully trying to merge between branches. Stop doing that. Branch the file permanently, perhaps by renaming it in each branch. It's not "main" any more, it's "main for configuration X". OK, so you lose the ability to apply the same change to multiple branches by merging, but this is in any case the core of code where merging doesn't work very well. If you're having to manually manage the merges anyway to deal with conflicts, then it's no loss to manually apply them independently on each branch.

我认为你说这种SCC无关紧要是错误的,因为例如git的合并能力可能比你正在使用的合并工具更好。因此,核心问题“合并困难”发生在不同scc的不同时期。但是,您不太可能更改scc,因此这个问题可能无关紧要。

我的0.05欧分:

重新设计整个混乱的系统,考虑到技术和业务需求,将其拆分为子系统(=许多并行维护轨道,每个并行维护轨道的代码库可能不同,显然需要高可修改性等等)。

在划分子系统时,分析变化最大的地方,并将其与不变的部分分开。这应该会显示出问题所在。将最易变化的部分分离到它们自己的模块中(例如dll),这样模块API就可以保持完整,而不需要一直破坏BC。这样,如果需要,您可以为不同的维护分支部署不同版本的模块,同时保持核心不变。

重新设计很可能需要一个单独的项目,试图做一个移动的目标是行不通的。

至于源代码历史,我的意见是:为了新代码忘掉它吧。但是请将历史记录保存在某个地方,以便在需要时进行检查。我打赌你开始之后就不那么需要它了。

对于这个项目,您很可能需要得到管理层的支持。你可以用更快的开发时间、更少的bug、更容易的维护和更少的混乱来反驳。类似于“积极地使我们的关键软件资产具有未来的可靠性和维护可行性”:)

至少这是我开始解决问题的方式。

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

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