Debugging 处理神的物体

Debugging 处理神的物体,debugging,language-agnostic,god-object,Debugging,Language Agnostic,God Object,我在一个中等规模的团队中工作,我经常会遇到这些非常大的类文件。我的第一个倾向是用刀子攻击他们,但这通常只会让事情变得更糟,让我陷入一种糟糕的心态 例如,假设您刚刚得到一个windows服务来处理。现在这个服务有一个bug,你需要弄清楚这个服务做了什么,然后才能有希望修复它。您打开服务,看到有人决定只使用一个文件来完成所有操作。启动方法在那里,停止方法,定时器,所有的处理和功能。我说的是数千行代码。不超过一百行代码的方法很少见 现在假设你不能重写整个类,而这些上帝类将不断出现,那么处理它们的最佳方

我在一个中等规模的团队中工作,我经常会遇到这些非常大的类文件。我的第一个倾向是用刀子攻击他们,但这通常只会让事情变得更糟,让我陷入一种糟糕的心态

例如,假设您刚刚得到一个windows服务来处理。现在这个服务有一个bug,你需要弄清楚这个服务做了什么,然后才能有希望修复它。您打开服务,看到有人决定只使用一个文件来完成所有操作。启动方法在那里,停止方法,定时器,所有的处理和功能。我说的是数千行代码。不超过一百行代码的方法很少见

现在假设你不能重写整个类,而这些上帝类将不断出现,那么处理它们的最佳方法是什么?你从哪里开始?你想先完成什么?你是如何处理这类事情的,而不只是想被刺伤

如果你有一些策略来控制你的脾气,那也是受欢迎的

到目前为止的提示:

  • 建立测试覆盖率
  • 代码折叠
  • 重新组织现有方法
  • 记录发现的行为
  • 以渐进式改进为目标
  • 编辑:

    查尔斯·康威推荐了一个播客,结果证明非常有用

    MichaelFeathers(播客中的家伙)从这样一个前提开始:我们太害怕将一个项目脱离源代码控制,直接玩它,然后扔掉更改。我可以说我对此感到内疚

    他基本上是说把你想了解更多的东西拿走,然后开始把它拆开。发现它的依赖关系,然后打破它们。无论它走到哪里,都要跟着它走

    很棒的提示
    以其他地方使用的大型类为例,让它实现emtpy接口。然后使用类获取代码,并让它实例化接口。这将为您提供代码中该大型类的所有依赖项的完整列表。

    这让我想起了我当前的工作以及我第一次加入时的情况。他们没有让我重写任何东西,因为我有相同的论点,“这些类太大了,写得太差了!没人可能理解它们,更不用说给它们添加新功能了。”

    因此,我要做的第一件事是确保在您希望改变的领域后面有全面的测试。至少这样,您就有机会更改代码,并且不会有(太多)参数(希望如此)。所谓测试,我指的是通过集成或验收测试对组件进行功能测试,并确保其100%覆盖。如果测试很好,那么您应该能够自信地更改代码,方法是将大类拆分为小类,消除重复等。 如果你能在giant类中移动东西并以某种逻辑的方式组织它,那么你可以在不同的块上放置折叠


    隐藏所有东西,你就回到了C模式,除了使用折叠而不是单独的文件。

    即使你不能重构文件,也要尝试重新组织它。移动方法/函数,使它们至少在文件中按逻辑组织。然后加入大量的注释,解释每个部分。不,您还没有重写程序,但至少现在您可以正确地阅读它,下次您需要处理该文件时,您将收到许多由您编写的注释(希望这意味着您能够理解它们)这将帮助您处理该程序。

    我要做的第一件事是编写一些单元测试来框住当前行为,假设没有单元测试。然后我将从需要进行更改的区域开始,并尝试清理该方法——即在引入更改之前重构工作代码。使用常见的重构技术从现有的长方法中提取和重用方法,使它们更易于理解。提取方法时,在代码中查找存在类似代码的其他位置,将该区域框起来,然后重用刚刚提取的方法

    寻找“连接在一起”的方法组,这些方法组可以分解为它们自己的类。编写一些关于这些类应该如何工作的测试,如果需要,使用现有代码作为模板构建类,然后将新类替换到现有代码中,删除它们替换的方法。同样,使用测试来确保你没有破坏任何东西


    对现有代码进行足够的改进,使您感觉可以以干净的方式实现新功能/修复。然后编写新特性/修复程序的测试,并实现以通过测试。不要觉得你必须在第一次就把一切都修好。以逐步改进为目标,但始终保持代码比您发现的更好。

    哎哟!听起来像是我工作的地方

    看一看。它在如何处理残暴的代码方面有一些精髓

    DotNetRocks最近做了一项关于使用遗留代码的研究。没有什么神奇的药丸能让它起作用


    我听到的最好的建议是开始在测试中增量包装代码。

    我也遇到过这种情况

    就我个人而言,我会先打印代码(是的,可能有很多页)。然后,我在不属于任何“主循环”或只是辅助函数的代码部分周围画一个框,并确保我首先理解这些内容。原因是他们可能在课堂主体中多次被提及,知道他们做什么很好

    其次,我确定了主要的算法,并使用数字和字母交替的编号系统将它们分解为各个部分(这很难看,但对我来说效果很好)。例如,您可以查看算法的一部分,深度为4“levels”,编号为b