我在一个中等规模的团队工作,我经常遇到这些痛苦的大班文件。我的第一个倾向是用刀子去找他们,但这通常会让事情变得更糟,让我陷入困境。
例如,假设您刚刚获得了Windows服务。现在这个服务中存在一个错误,你需要弄清楚服务的作用,然后你才有希望修复它。你打开服务,看到有人决定只使用一个文件。 Start方法就在那里,Stop方法,Timers,所有处理和功能。我正在谈论成千上万行代码。一百行代码下的方法很少见。
现在假设你不能重写整个班级,而这些神班只会不断出现,处理它们的最佳方法是什么?你从哪里开始的?你先尝试做什么?你是如何应对这种事情的,而不只是想让所有的人都陷入困境。
如果你有一些策略只是为了控制你的脾气,那也是受欢迎的。
提示远:
编辑:
查尔斯康威推荐一个播客,结果非常有帮助。 link
Michael Feathers(播客中的人)开头的前提是,他们太害怕简单地将一个项目从源代码控制中取出来,直接玩它然后扔掉这些变化。我可以说我对此感到内疚。他基本上说要拿你想要了解的项目,然后开始将它拆开。发现它的依赖关系,然后打破它们。随处可见。
精彩提示 获取在别处使用的大类,并使其实现一个emtpy接口。然后使用类获取代码并让它实例化接口。这将为您提供代码中该大型类的所有依赖项的完整列表。
答案 0 :(得分:9)
哎哟!听起来像我用来工作的地方。
看看Working effectivly with legacy code。它有一些关于如何处理恶劣代码的宝石。
DotNetRocks最近使用遗留代码进行了show。没有神奇的药丸可以使它发挥作用。
我听到的最好的建议是在测试中逐步包装代码。
答案 1 :(得分:4)
这让我想起了我目前的工作以及我刚加入的时间。他们没有让我重写任何东西,因为我有同样的论点,“这些类太大而且编写得很糟糕!没有人能够理解它们,更不用说为它们添加新功能了。”
所以我要做的第一件事就是确保在你想要改变的领域背后有全面的测试。至少那时你将有机会改变代码而没有(太多)参数(希望如此)。通过测试,我的意思是在功能上通过集成或验收测试来测试组件,并确保它100%覆盖。如果测试是好的,那么你应该能够通过将大类拆分成较小的类,摆脱重复等来自信地改变代码等。
答案 2 :(得分:4)
即使您无法重构文件,也请尝试重新组织它。移动方法/函数,使它们至少在逻辑上组织在文件中。然后提出许多解释每个部分的评论。不,你没有重写程序,但至少现在你可以正确阅读它,下次你必须处理文件时,你会有很多评论,由你写的(希望这意味着你会能够理解它们,这将有助于你处理该计划。
答案 3 :(得分:3)
代码折叠可以提供帮助。 如果你可以在巨型类中移动东西并以某种逻辑方式组织它,那么你可以在各个块周围放置折叠。
隐藏翻译,你会回到C范式,除了折叠而不是单独的文件。
答案 4 :(得分:3)
我也遇到过这种情况。
我个人首先打印出代码(是的,可能是很多页面)。然后我在代码段周围绘制一个框,这些代码段不是任何“主循环”的一部分,或者只是辅助函数,并确保我首先理解这些东西。原因是他们可能在班级主体中被多次提及,知道他们做了什么很好
其次,我确定了主要的算法并使用编号系统将它们分解成它们的部分,这个编号系统在数字和字母之间交替(它很难看,但对我来说效果很好)。例如,你可能会看到4“级别”深度的算法的一部分,编号将是1.b.3.e或其他一些可怕的东西。请注意,当我说级别时,我不是直接指控制块或范围,而是我已经确定了算法的步骤和子步骤。
然后,这只是阅读和重新阅读算法的问题。当你开始时听起来好像很多时候,但我发现这样做会产生一种理解大量逻辑的自然能力。此外,如果您发现归因于此代码的错误,则可以提前将其在纸上进行视觉分解,这有助于您稍后“导航”代码,因为您已经在脑中有了一种地图。
如果你的老板在你有某种形式的UML描述它之前不认为你理解了某些东西,那么如果你假装子步骤级别是水平表示的不同“类”并且从头开始,那么UML序列图可能会有所帮助。 -finish从上到下垂直表示。
答案 5 :(得分:3)
我感觉到你的痛苦。对于涉及在我的计算机上处理数字电视数据的业余爱好项目,我曾经解决过这样的问题。一位硬件论坛上的人写了一个很棒的工具来录制节目,看到所有内容,等等。此外,他做了非常重要的工作,解决了违反标准的真实广播信号中的错误。他在线程安排方面做了出色的工作,以确保无论如何,你都不会丢失那些实时数据包:在旧的Pentium上,他可以同时录制四个流,同时还可以玩Doom而且永远不会丢失一个包。简而言之,这段代码包含了大量的知识。我希望能把一些东西放到我自己的项目中。
我得到了源代码。 一个文件,22,000行C,无抽象。我花了几个小时阅读它;所有这些伟大的工作,但都做得很糟糕。我无法重复使用一行甚至一个想法。
我不确定这个故事的寓意是什么,但是如果我在工作中被迫使用这些东西,我会乞求允许一次一个芯片碎片,构建单元测试对于每一件作品,并最终从作品中发展出一种新的,明智的东西。这种方法与尝试重构和维护大型砖块有点不同,但我宁愿让遗留代码保持不变,试图并行建立一个新系统。
答案 6 :(得分:2)
我要做的第一件事就是编写一些单元测试来装箱当前行为,假设已经没有。然后我将从需要进行更改的区域开始,并尝试清除该方法 - 即在引入更改之前重构工作代码。使用常见的重构技术从现有的长方法中提取和重用方法,使它们更容易理解。提取方法时,在代码中查找存在类似代码的其他位置,选中该区域,然后重用刚刚提取的方法。
查找可以分解为各自类的“挂在一起”的方法组。编写一些关于这些类应该如何工作的测试,如果需要,使用现有代码作为模板构建类,然后将新类替换为现有代码,删除它们替换的方法。再次,使用您的测试来确保您没有破坏任何东西。
对现有代码进行充分改进,以便您能够以干净的方式实现新功能/修复。然后编写新功能/修复的测试并实现以通过测试。不要觉得你必须在第一次修理所有东西。旨在逐步改进,但始终保持代码比您发现的更好。