如何在没有任何文档的情况下读取数千行代码?[关闭]


12

以前,我正在为WPF项目寻找良好的TimeLine控件。我在这里找到了一个答案,该答案将我定向到此CodePlex项目

现在,我想更改代码以满足我的文化需求。但是有一些不匹配!

我的问题是:

您如何与成千上万的代码交互?

编辑:

任何捷径都会很棒!


3
要求加薪。它总是有帮助的。(他们可以以此为动力)
显示名称

2
将头顶在桌子上,直到一切都变得清晰起来。
jellyfishtree

19
你怎么吃大象?...一次咬一口。
比尔

1
@Jalal这就是他们想要您考虑的内容。
Mateen Ulhaq 2011年

2
对于需要基本认知技能的任何工作,@ DisplayName,胡萝卜和坚持激励的方法已被证明是一个糟糕的解决方案。动机的科学比奖赏系统更为复杂。看看丹·平克(Dan Pink)的“驾驶:关于促使我们前进的令人惊讶的真相”,这是令人震惊的读物。或查看此视频以获取压缩版本。youtube.com/watch?v=u6XAPnuFjJc
瑞安·泰勒

Answers:


37

当您对源代码有足够的理解后,便可以添加注释。随着您越来越多地理解,请大力重构这些注释。


3
+1是一种不错的方法,是在浏览源代码时实际编写文档。以及为什么将您的贡献发还给运营协调员?

1
+1另外,如果您修改了代码,请确保同时也更改注释,以免后代对所做的事情感到困惑。做所有这些文档感到羞耻,并且让人讨厌它,因为这是错误的!
Michael K 2010年

1
如果原始项目在分布式源代码控制系统(如git)中,则最好进行分叉,以增量方式提交更改并以某种方式进行更改,以便以后可以有选择地将更改合并回原始文件

8
  1. 单步执行代码
  2. 根据需要重命名
  3. 根据需要进行重构
  4. 重复直到您完全理解

...,代码将感谢您。;-)


7
仅仅因为更容易而在生产代码中更改随机位置并不是一个好主意。仅功能请求应引起代码修改,重构是功能请求。无论您有多出色,代码都会中断,有时客户会依赖愚蠢的副作用。仅重构您非常确定的代码。请记住,即使单元测试也不能保证任何事情。
编码员

同意,但是重构只是为了尝试设计可以帮助您理解为什么按原样编写代码(或确认您做得不好/很奇怪)。您不必保留这些更改。
瑞奇·克拉克森

+1编码器。目前,这个答案甚至没有提到单元测试。害怕。
MarkJ 2012年

抱歉,这并不意味着要进行重大重构。在谈论更多关于次要重构,清理类型的东西。因此,最终,您明白了代码的目的是显而易见的。
约翰·麦金太尔

5

采取单个操作,再次调试代码以查找该操作是如何完成的。用简单的语言写下来以获得更好的理解!


我通常也会这样做,直到遇到无法在调试模式下运行的项目!它总是在启动过程中崩溃!:(但它在发布模式下运行良好:S
Afriza N. Arief

@afriza他妈的什么。那是一些严重的错误代码,请检查它会给您带来什么错误。
Daniel S

@afriza,第一件事要解决!

4

Joel Spolsky在他的博客(现在找不到该文章)上写的东西确实让我感到困惑:

他说代码不是人类的自然语言,但是作为程序员,我们很容易被认为是这样,并且我们应该能够这样阅读。因此,我们中的许多人都在查看新代码,并希望能够“阅读”并立即理解它,就好像它是英文的一段文本一样。

因此,我认为关键是基本上要缓慢,有条理和科学。正如其他人所说的那样-在您进行评论时(甚至重构)。不要陷入“我应该只是看一下并立即理解”的思想观念。

哦,是的,我有时还是会陷入这个陷阱。“按照我说的做,而不是像我那样做”,以及所有这些。:)


事实是,您可以“阅读”的英文文本通常是线性的,一开始通常很难理解代码的原因通常是因为它是非线性的,而技巧只是将其分解。开发人员使用的大量不同的实现习惯通常也无济于事,但是第一步通常是通过调试器运行代码,并使用断点来查看内容。尝试阅读它是没有意义的练习。认真的说,您上一次是什么时候才读过您编写的代码?(即开始到结束。)
ocodo 2011年

实际上,编写良好的代码很容易阅读,但不是文本。您只需扫描即可查看构建基块并了解核心结构,而无需阅读所有内容。不好的编码方法(例如旧的skool代码)或SOLID和模式的滥用会使这项任务非常困难。
编码员

4

SE-Radio 就此主题采访了Dave Thomas

这个播客集包含许多技巧和技术,可用于进入项目的“文化”并了解原始居民的生活。


关于Dave Thomas的经历的一个有趣的部分是,除了高级概述之外,文档(几乎)毫无例外比没有文档还要糟糕。(根据我的经验,这是因为大多数文档都是样板文件,它们从表面上理解了“什么”或“如何”,然后总是过时,以至于引起误导。)
Michael Kropat

2

我最近不得不使用一个超过100,000 LOC的项目来执行此操作。我的第一个想法是,从100个甚至1000个节点的图形中查看模式比从100,000行文本中查看模式更容易。

因此,我花了45分钟并编写了一个简短的(<100LOC)Python程序来解析所需的内容,并绘制对象关系。我生成了Graphviz源代码,这是一种非常容易生成的语言。(这里没有关于Python的特殊之处:Ruby或C#或Common Lisp或其他同样可以做到的事情。)

在其他项目上,我见过人们使用Graphviz来处理模块依赖关系,调用图,版本历史记录以及各种事情。有史以来最出色的程序可视化元工具。

(也许是因为我选择了编译器,但是我发现很奇怪,当程序员遇到问题时,答案似乎总是“编写程序!”,除非问题涉及程序的源代码。 )


1

在调试器运行时逐步调试它,这几乎是理解新的大型代码库的唯一方法。


2
当您有成千上万的代码行时(特别是当我们谈论数十或数百个KLOC时),并且/或者如果代码的一部分位于模板中,则这不是一个实际的选择。为了掌握新的(且文献记录不充分的)代码库,还必须与企业打交道,并尝试理解应该在其中运行代码的上下文。如果您可以通过调试器阅读代码并了解它,那么该代码库并不是那么大(大多数情况下
都不

如果代码库太大而无法在调试器中进行调试,那就不好了。看到代码对已知的输入和输出做出反应有助于将“什么”知识转换为“如何”知识。“为什么”这个问题永远无法用调试器来回答,但是调试时可能会在IDE中看到内联源注释。
grrussel 2011年

@grrussel我必须不同意,因为这不是我的工作……我不知道我是否具有代表性!我可以看到使用奇数断点(但仍然没有明确地逐步执行),并且确实使用IDE功能使我可以将一个片段与另一个片段联系起来。
Murph'4

1

要了解的是,确实没有捷径可至。(如果您对这句话有疑问,那么您的教育将受到极大的忽视。这是罗伯特·海因莱因(Robert A. Heinlein)的《陌生土地上的陌生人》。)

一次阅读一页,一次阅读一个例程。添加评论。绘制主要数据结构的图片。识别算法。利用以前的知识。

抵制启动调试器的诱惑。调试器视口太小:您一次只能看到一行,但实际上看不到您去过的地方或要去的地方。


调试器向代码解释了原始代码编写者对变量内部的约定(例如,他们希望使用Full-Path还是文件名或相对路径?)以及许多其他内容,因此我认为它仍然很重要
Afriza N. Arief

2
-1认为您很酷,因为您使用了“
grok


1

您需要使用线索。了解要查找的内容,并广泛使用环境或IDE的搜索功能,可以将您带到需要更改的代码的所需部分。

读取14000行的Java代码没有任何意义。搜索功能可助您一臂之力


0

不同的人有不同的学习风格,所以YMMV。在这种情况下,我要做的第一件事是至少读取一次整个代码库。这使我对一切都在哪里有了一个大致的了解。然后,我选择一个部分进行更详细的研究。数据结构将是一个很好的起点。一旦对发生的事情有了一个大致的了解,就可以对与第一部分进行交互的另一部分代码执行相同的操作。经过足够的迭代,我对代码的工作方式有了很好的了解。


0

与所有编程一样,最好的方法不仅是将大段未注释的代码分解为碎片。这既是您在头脑中还是在代码中视觉上都应该做的事情。这可能意味着添加大胆的注释或多个换行符。这在滚动浏览以查看片段时会有所帮助。尝试查找代码的逻辑块。

当然,当您了解位时,请针对当时的知识对其进行评论,并可能在注释中添加一些您不了解的内容。

我也建议不要从一开始就试图理解整个部分。相反,请尝试理解您现在需要了解的内容,然后再进行其余工作。


0

我将首先使用@shadow模式下Leo编辑器,并积极使用克隆节点。这样一来,您就可以为所研究的代码的每个部分添加注释和注释,而无需更改代码,并且注释始终位于上下文中,在所讨论的代码旁边。这是文档的示例工作流程:

例如,当我在Leo中修复错误时,我创建了一个普通节点来表示错误。这个错误节点是我查看Leo源代码中与该错误相关的所有数据的视图。当我发现与错误相关的代码时,我克隆了它们的节点并将它们移到错误节点下。我还将普通节点添加为bug节点的子节点。这些节点包含原始的错误报告,我如何修复该错误的描述,测试数据或我可能想要保留的任何其他说明。

创建Bug节点后,我将仅专注于该节点及其子节点。我可以检查错误节点及其子节点,而不必跳到大纲。我需要的一切都集中在一个地方。当我真正解决错误时,可以通过更改克隆来解决。同样,我不必在轮廓上跳动。整个轮廓的大小无关紧要:我只处理Bug节点及其子节点。这种极其狭窄的关注点使修复错误变得更加容易。


0

绘制源代码图:数据关系,功能关系,对象关系。确定聚合,数据流和代码流。图片远胜于注释,并且可以与代码分开存放。


0

在重构之前,请编写测试。很多测试。对至少可以调用的小代码块的非常具体的测试,因为这将取决于您继承的混乱的编写方式。

开始编写测试的好处是,您需要对代码有某种了解,然后才能进行测试,因此希望您编写的每个测试都将获得一点点知识。您还可以在假设和断言之间大量评论测试。

通过先进行测试,您不会冒风险更改代码中某些您无法了解的连锁反应的风险。重构代码时,您还将拥有一个安全网。


0

我使用诸如doxygen之类的工具来生成总体类图,然后增加我对每个类的作用的理解。

然后,我从错误队列中挑选了一些简单的错误(在我的经理为我分配硬错误之前:P),然后将该功能运行到调试器中,并尝试生成粗糙的数据流或代码流模型。

例如某些软件的导出功能:因此,我尝试了解如何读取源数据,可以使用我的类和代码流程图从代码(基本接口)中的什么位置评估是否正确读取了数据,哪些类负责有了类图和流程图,我认为理解的一半就完成了。


0

处理一个琐碎的缺陷,例如NullPointerException。首先要避免任何有关并发的事情,从本质上讲,这将涉及一次理解很多代码。

修复了一些错误之后,您可能会有一个不错的主意。无论如何对我有用。


-2

基本上,编写干净代码的动作应该从设计开始。如果我们使用OOP语言进行编码,请提供一个UML,与同行分享,并确信设计并不模糊。无论如何,我们的开发人员都应该相信设计可以解决问题,而不是模棱两可。

在编码方面,我们必须确保将设计转换为代码,即将Entity转换为类或struct,将函数转换为函数等。

我浏览了白皮书http://queue.acm.org/detail.cfm?id=2063168 ,其中讨论了编码样式或我们如何使用空格,缩进,字体变化,因为我们可以使用大多数IDE编写MUCH我们人类可以像机器一样了解的更清洁的代码。它着重于编写无注释代码,这样我们的代码将作为段落本身出现。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.