了解其他人的代码

时间:2009-01-26 11:33:41

标签: visualization legacy legacy-code

我偶尔不幸的是必须改变很旧的,<打击>不好 记录和不好 设计代码。

进行简单的更改通常需要很长时间,因为现有代码的结构并不多,而且在我感觉到事情发生之前,我真的必须阅读很多代码。

我认为在这种情况下可以提供很多帮助的工具可以让人们可以看到代码的概述,然后甚至可以深入了解更多细节。我怀疑这样的工具很难做到,因为它试图找到很少或没有的结构。

我想这不是一个真正的问题,而是一种沉思。我应该把它变成一个问题 - 其他人做些什么来帮助他们了解其他人的代码,好的和坏的?

16 个答案:

答案 0 :(得分:4)

嗯,这是一个很难的,很多时候说这么短的时间......

1)如果你可以运行代码,它会让生活变得更容易,断点(尤其是有条件的)断点就是你的朋友。

2)纯粹主义者的方法是编写一些单元测试,用于已知功能,然后重构以改进代码和理解,然后重新测试。如果事情破裂,那么创建更多单元测试 - 重复直到无聊/旧/移动到新项目

3)ReSharper善于展示使用的东西,例如调用方法的东西,它是静态的但是一个好的开始,它有助于重构。

4)许多.net事件被编码为公共事件,事件在最好的时候可能很难调试。将它们重新编码为私有,并使用添加/删除属性。然后,您可以使用断点来查看正在监听事件的内容。

BTW - 我在.Net领域玩,并且喜欢帮助做这类工作的工具,比如Joel有没有人知道一个好的动态代码审查工具?

答案 1 :(得分:4)

过去我被要求取得一些NASTY代码的所有权 - 包括工作和“玩”。

我接手代码的大多数业余爱好者只是进行了一些代码,以便在几次迭代中完成他们所需的代码。它总是一个巨大的乱乱乱糟糟的库A调用B,回调到A,调用C,调用B等等。很多时候他们使用线程而不是关键部分是可见的。

我发现获得代码处理的最佳/唯一方法是从OS入口点[main()]开始,并构建我自己的调用堆栈图,显示调用树。你真的不需要在一开始就构建一个完整的树。只需跟踪您在每个阶段正在处理的部分,您就可以获得足够好的处理能力。

最重要的是,使用你能找到的最大的死树片和一支笔。把它全部放在你面前,这样你就不必在屏幕或页面上前后跳跃,这样可以简化生活。

编辑:有很多关于编码标准的讨论...他们只会让糟糕的代码看起来与良好的代码一致(并且通常更难发现)。编码标准并不总能使维护代码更容易。

答案 2 :(得分:3)

我定期这样做。并开发了一些工具和技巧。

  • 尝试获得一般概述(对象图或其他)。
  • 记录您的发现。
  • 测试您的假设(特别是对于模糊的代码)。

问题在于,大多数公司都会对结果表示赞赏。这就是为什么一些程序员快速编写糟糕的代码并转向另一个项目的原因。所以你留下了垃圾,而你的老板将你的缓慢进展与快速和肮脏的家伙进行比较。 (幸运的是,我现在的雇主不同)。

答案 3 :(得分:2)

我通常使用组件使用的各种关键方式的UML序列图。我不知道任何可以自动生成它们的工具,但许多UML工具(如BoUML和EA Sparx)可以从源代码创建类/操作,从而节省了一些输入。

答案 4 :(得分:2)

关于这种情况的最终文本是Michael Feathers的“有效使用遗留代码”。正如S. Lott所说,进行一些单元测试以建立滞后代码的行为。一旦你有了那些你可以开始重构。在Object Mentor网站上似乎有一个示例章节available

答案 5 :(得分:1)

有关通过单元测试获取遗留应用程序的建议,请参阅Unit Testing Legacy ASP.NET Webforms Applications

有许多类似的问题和答案。这是搜索https://stackoverflow.com/search?q=unit+test+legacy

关键在于,如果您正在为该遗产编写单元测试,那么了解遗留问题可能是最简单的。

答案 6 :(得分:1)

我没有很好的运行工具来自动审查记录不良/执行的代码,导致混乱/设计糟糕的程序通常转换为不太有用的模型。这并不令人兴奋或立刻有所回报,但我已经获得了最好的结果,选择了一个点并逐行跟踪程序执行,记录和添加注释,并在适用的地方重构。

答案 7 :(得分:1)

在许多情况下,一个好的IDE(EMACS或Eclipse)可以提供帮助。同样在UNIX平台上,有一些用于交叉引用(etags,ctags)或检查(lint)或gcc的工具,其中打开了许多警告选项。

首先,在尝试理解一个函数/方法之前,我会稍微重构一下以适应您的编码约定(空格,大括号,缩进),并删除大多数注释,如果它们看起来是错误的。

然后我会重构和评论你理解的部分,并尝试在整个源代码树中查找/ grep这些部分并在那里重构它们。

随着时间的推移,你会得到一个更好的代码,你喜欢与之合作。

答案 8 :(得分:1)

我个人做了大量的图表绘制,并弄清楚了结构的骨骼。

fad de jour(可能非常正确)让我编写单元测试来测试我的断言,并为我对系统所做的更改建立一个安全网。

一旦我到达了一个我很熟悉的地方,知道系统的作用,我会尽可能地以最安全的方式修复错误,并希望我的安全网接近完成。

然而,那只是我。 ;)

答案 9 :(得分:1)

我一直在使用ReSharper的重构功能来帮助我处理最近继承的一堆项目。因此,为了弄清楚另一个程序员非常糟糕的结构化,未记录的代码,我实际上是从重构它开始的。

清理代码,正确地重命名方法,类和名称空间,提取方法都是结构上的变化,可以揭示一段代码应该做什么。这可能听起来违反了你不“知道”的重构代码,但是让我抓紧,ReSharper真的允许你这样做。以红鲱鱼死码为例。您在类中看到一个方法,或者可能是一个奇怪命名的变量。您可以从尝试查找用法开始,或者进行文本搜索,但ReSharper实际上会检测死代码并将其着色为灰色。只要你打开一个文件,你就会看到灰色和带有滚动条标志的文件,过去会混淆红色鲱鱼。

还有许多其他技巧,可能还有很多其他工具可以做类似的事情,但我是ReSharper的垃圾。

干杯。

答案 10 :(得分:1)

从用户的角度密切了解该软件。通过研究和与用户界面交互,可以了解底层结构。

答案 11 :(得分:1)

  • 打印输出
  • 白板
  • 很多信纸
  • 很多星巴克

能够为所有可怜的东西涂鸦是我最有用的方法。通常我会尝试制作基本的代码结构图,然后最终会比图表本身更有用,从而出现了很多“嗯,这很有趣......”。自动化工具可能比我给予他们的信任更有帮助,但找到这些有趣位的价值超过了我快速生成的图表的价值。

对于图表,我主要查找数据的去向。它来自哪里,它最终在哪里,以及它在路上经历了什么。一般来说,数据发生的情况似乎给整体布局留下了好印象,如果我正在重写,还会有一些骨头回归。

答案 12 :(得分:1)

当我处理遗留代码时,我并不试图理解整个系统。这将导致复杂性过载和随后的大脑爆炸。

相反,我采用了系统的一个特性,并尝试从头到尾完全理解它是如何工作的。我通常会调试代码,从UI代码中我可以找到特定功能的点开始(因为这通常是我一开始就能找到的唯一东西)。然后我将在GUI中执行一些操作,并在代码中向下钻取到数据库中然后备份。这通常可以完全理解系统的至少一个特征,有时也可以深入了解系统的其他部分。

一旦我理解了要调用的函数以及涉及的存储过程,表和视图,我就会搜索代码以找出应用程序的其他部分依赖于这些相同的函数/过程。这就是我如何确定我将要做出的改变是否会破坏系统中的任何其他内容。

尝试制作数据库和/或代码结构的图表有时也很有用,但有时它只是如此糟糕或太疯狂,以至于最好忽略整个系统而只关注那个部分。你需要改变。

答案 13 :(得分:1)

我最大的问题是我(目前)有一个非常大的系统可以在相当短的时间内理解(我在这一点上怜悯合约开发人员)并且没有很多经验这样做(以前很幸运足以成为从头开始设计的人。)

我使用的一种方法是尝试理解变量,方法,类等命名的含义。这很有用,因为它(希望越来越多)从原子级别嵌入一系列思想的高级视图

我这样说是因为通常开发人员会将他们的元素(他们认为的内容)命名为有意义的,并提供对其预期功能的深入了解。诚然,这是有缺陷的,如果开发人员对他们的程序有缺陷的理解,术语或(通常情况下,imho)试图听起来很聪明。有多少开发人员看过关键字或类名,然后才第一次在字典中查找该术语?

答案 14 :(得分:1)

我强烈推荐BOUML。这是一个免费的UML建模工具,其中:

  • 非常快(有史以来创建的最快的UML工具,请查看benchmarks),
  • 拥有坚如磐石的C ++导入支持,
  • 具有很好的SVG导出支持,这很重要,因为以矢量格式查看大图,其在例如Firefox,非常方便(您可以在“鸟瞰”视图和类详细信息视图之间快速切换),
  • 功能齐全,精心开发(查看development history,很难相信可以取得如此快速的进展)。

所以:将您的代码导入BOUML并在那里查看,或导出到SVG并在Firefox中查看。

答案 15 :(得分:0)

这完全取决于贵公司正在使用的标准和编码规则。

如果每个人都以不同的方式编码,那么很难维护其他程序员代码等,如果你决定使用什么标准有一些规则,一切都会好的:)注意:你不必做很多规则,因为人们应该有自己喜欢的风格编码的可能性,否则你会非常惊讶。