熟悉大型代码库的最佳方法是什么?
join已经存在的大型代码库的现有团队可能会令人望而生畏。 什么是最好的方法;
- 广阔; 试着从代码中得到关于所有东西如何链接的一般概述
- 狭窄; 重点关注一小段代码,了解它们如何完全工作
- select一个function来开发和学习
- 尝试从类图和uml中获得洞察,如果可用(和最新)
- 还有其他的东西吗?
我正在研究目前约20k行的C ++应用程序和库(编辑:在macros伟计划的小事!)。 在行业中,我想你会得到一个有经验的程序员的介绍。 但是,如果情况并非如此,您可以如何尽快开始增值?
–
答案摘要:
- 在debugging模式下浏览代码,看看它是如何工作的
- 与比你更熟悉代码库的人配对,轮stream成为编码人员和观看/讨论人员。 在团队成员之间轮换合作伙伴,以便知识传播。
- 编写unit testing。 从你认为代码如何工作的断言开始。 如果结果如你所料,你可能已经明白了代码。 如果不是的话,你就有一个难题要解决和/或查询。 (谢谢Donal,这是一个很好的答案)
- 通过现有的function代码unit testing,类似于上面的方式
- 阅读UML,Doxygen生成的类图和其他文档,以获得广泛的代码感觉。
- 进行小的编辑或错误修复,然后逐渐build立起来
- 记笔记,不要跳进去开始发展; 花费时间理解比生成杂乱或不恰当的代码更有价值。
这篇文章是“最好的方式 – 熟悉自己的代码库”的部分副本
如果可能,从一些小任务开始,debugging你的问题的代码。 在debugging模式下单步执行代码是学习工作原理的最简单方法。
另一个select是为你感兴趣的function编写testing。设置testing工具是build立系统依赖关系和状态所在的好方法。 每个testing都以关于您认为系统应该工作的方式开始。 如果事实certificate,这样做,你已经取得了一些成果,你有一些工作示例代码来重现它。 如果不这样做,你就有一个难题要解决,而且需要一系列的追问。
我通常build议那些尚未提及的人的一点是,在成为开发人员之前,成为现有代码库的合格用户是非常重要的。 当新的开发者进入我们的大型软件项目时,我build议他们在尝试编写代码之前花时间成为专家用户。
也许这是显而易见的,但是我看到很多人试图跳入代码太快,因为他们急于开始取得进展。
这是相当依赖于什么样的学习者和你是什么样的程序员,但是:
- 首先宽泛 – 你需要一个范围和大小的想法。 这可能包括略读docs / uml,如果他们是好的。 如果这是一个长期的项目,而且你需要对所有事情有充分的了解,那么我可能会正确地阅读这些文档。 再次, 如果他们是好的。
- 狭窄 – select一些可pipe理的东西,并试图理解它。 获取代码的“味道”。
- select一个function – 如果你有自信,可能与你刚刚看过的function不一样,并开始做一些小的改动。
- 迭代 – 评估事情的进展情况,看看能否从更深入地重复早期步骤中受益。
配对严格轮换。
如果可能的话,当通过文档/代码库时,尝试采用严格的轮换配对。 意思是说,你们两个人坐在一起固定一段时间(比如2个小时的时间),然后你转换成对,一个人将继续工作,而另一个转移到另一个合作伙伴的另一个任务。
成对的时候,你们都会拿起一块知识,这些知识可以在轮换发生的时候送给团队的其他成员。 这样做还有一个好处,那就是当一个新的组合在一起时,从事这个任务的人(在这种情况下,调查代码)就可以用一种更容易理解的方式总结和解释这些概念。 随着时间的推移,每个人都应该有一个相似的理解水平,并希望避免“哦,只有约翰知道这一点的代码”症候群。
从我可以告诉你的情况,你有一个很好的数字(3双),但是,如果你是分布式的,或不工作在相同的时间尺度,这是不可能的。
我会build议运行Doxygen来获取最新的类图,然后进行一段时间的广泛的。 这给你一个快速的大图,你可以使用,因为你与代码密切和肮脏。
我同意这完全取决于你是什么types的学习者。 话虽如此,我曾经在两家有很大代码基础的公司开始。 通常,我这样工作:
如果可能的话,在查看任何function代码之前,我会经过已经写好的unit testing。 这些通常可以帮助很多。 如果他们不可用,那么我做以下。
首先,我在很大程度上忽略了实现,只看头文件,或只是类接口。 我试图弄清楚每个class级的目的是什么。 其次,我从一个最重要的领域开始,深入实施一个层次。 这很难衡量,所以偶尔我只是从最高层开始,并在文件列表中按照我的方式。 我称之为广度优先学习。 在开始这一步之后,我通常会深入了解其余的代码。 最初的广度优先看起来有助于巩固/修复我从界面层面得到的任何想法,然后深入分析的外观向我展示了用于实现系统的模式以及不同的devise思路。 深度优先,我的意思是你基本上通过使用debugging程序的步骤,逐步进入每个function,看看它是如何工作的,等等。 这对于大型系统来说显然是不可能的,但是20k LOC并不是那么多。 🙂
与另一位熟悉系统的程序员合作开发一个新function或修复一个错误。 这是我见过的最好的方法。
我认为你需要把这个绑定到一个特定的任务上。 当你有时间的时候,你可以select任何你喜欢的方式。
当你有什么需要完成的时候,给自己一个狭隘的焦点,把它完成。
让团队把你修正错误两周(如果你有两个星期)。 他们会很乐意让某人为此承担责任,在这段时间结束的时候,你会花很多时间来解决与图书馆的问题,你可能会很清楚地知道这一点。
如果它有unit testing(我打赌它没有)。 从小处着手,确保unit testing不会失败。 如果你盯着整个代码库,你的眼睛就会黯然失色,你会感到不知所措。
如果没有unit testing,则需要关注所需的function。 运行应用程序并查看您的function应该影响的结果。 然后开始查看代码,试图找出应用程序如何创build你想改变的东西。 最后改变它,并检查结果是否以你想要的方式出现。
你提到它是一个应用程序和一个库。 首先更改应用程序,并坚持使用该库作为用户。 那么在你学习图书馆之后,它会更容易改变。
从上到下的方法,应用程序可能有一个主循环或主gui控制所有的行动。 值得了解应用程序的主要控制stream程。 这是值得阅读的代码,让自己的应用程序的主要stream程的广泛概述。 如果它是一个GUI应用程序,创build一个文件,显示哪些屏幕,以及如何从一个屏幕到另一个。 如果它是一个命令行应用程序,处理是如何完成的。
即使在公司中,采用这种方法也并不罕见。 通常没有人完全理解应用程序是如何工作的。 人们没有时间向你展示。 他们喜欢具体问题的具体问题,所以你必须自己挖掘和实验。 然后,一旦你得到你的具体问题,你可以尝试隔离该应用程序的知识来源,并要求它。
首先了解“问题领域”(是一个工资系统?库存?实时控制或其他)。 如果你不明白用户使用的行话,你永远不会理解代码。
然后看看对象模型; 可能已经有了一个图表,或者您可能需要对其进行反向工程(手动或使用Dougbuild议的工具)。 在这个阶段,你也可以调查数据库(如果有的话),如果应该遵循对象模型,但不可能,这一点很重要。
看看更改历史logging或错误数据库,如果有一个区域出现了很多,请先查看一下。 这并不意味着写得不好,而是人人都用这个。
最后,保留一些笔记(我更喜欢维基)。
- 现有的人可以用它来理智检查你的假设,并帮助你。
- 您将需要稍后参考。
- 队中的下一个新人真的很感谢你。
我也有类似的情况。 我会说你走这样的:
- 如果它是一个数据库驱动的应用程序,则从数据库开始,尝试理解每个表,其字段以及它与其他表的关系。
- 一旦使用底层存储,就可以向上移动到ORM层。 那些表格必须在代码中有某种表示forms。
- 一旦完成,继续前进,从这些对象来自何方何处。 接口? 什么接口? 任何validation? 他们在进入数据存储之前进行了哪些预处理?
这将使您更好地熟悉系统。 请记住,只有当你很清楚地知道什么是testing以及为什么需要testing时才试图编写或理解unit testing。
而且,如果一个大型应用程序不是靠数据库驱动的,我build议采用其他方法:
- 这个系统的主要目标是什么?
- 系统的主要组成部分是什么,然后解决这个问题?
- 这些组件之间有什么相互作用? 制作描绘组件依赖关系的图表。 询问已经在使用它的人。 这些组件必须在彼此之间交换一些东西,所以试图弄清楚这些(就像IO可能将File对象返回给GUI一样)
- 一旦对此感到满意,就可以深入了解其中最不依赖的组件。 现在研究这个组件是如何进一步分类的,以及它们是如何相互作用的。 这样你总共有一个组件的挂起
- 移到下一个最小的依赖组件
- 到最后,转到核心组件,这个组件通常会依赖于你已经解决的许多其他组件
- 在查看核心组件时,您可能会回头看看之前检查过的组件,所以不要担心继续努力!
对于第一个策略:以这个stackoverflow网站为例。 检查数据存储,存储的内容,如何存储,这些项目在代码中的表示方式,以及在UI中如何显示这些项目。 一旦他们回到数据存储区,他们从哪里来,以及在他们身上发生了什么样的处理。
第二个以文字处理器为例。 那里有什么组件? IO,UI,页面等。 这些如何相互作用? 随着您进一步学习,继续前进。
放松。 书写的代码是一个人的思维方式,冻结逻辑和思维方式,需要时间来阅读这个思想。
首先,如果您有团队成员可以使用代码的经验,您应该安排他们与您一起对代码进行概述。 每个团队成员应该为您提供有关其专业领域的信息。 让多人解释事物通常是有价值的,因为有些人会比别人解释得更好,有些人会比别人更好地理解。
然后,你需要开始阅读代码一段时间没有任何压力(如果你的老板会提供的话,几天或一周)。 它通常有助于自己编译/构build项目,并且能够以debugging模式运行项目,以便您可以逐步完成代码。 然后,开始弄湿你的脚,修理小虫子,并做小改进。 希望你很快就能做好一个中型项目的准备,以后再做一个大项目。 在你走的时候继续依靠你的队友 – 通常你可以find一个愿意指导你的队友。
如果你挣扎的话,不要对自己太苛刻 – 这很正常。 理解一个庞大的代码库可能需要很长时间,也许几年。 事实上,经常是这样的,即使过了几年,代码的某些部分仍然有点吓人和不透明。 当你在项目之间停下来的时候,你可以深入到这些领域,你会经常发现,经过几次尝试,你甚至可以把那些部分弄清楚。
祝你好运!
您可能要考虑查看源代码逆向工程工具。 有两个我知道的工具:
- SWAG工具包(仅限Linux) 链接
- 包豪斯学术 商业
这两种工具都提供了类似的function集,其中包括可以生成软件模块之间关系图的静态分析。
这主要包括调用图和types/类的权限。 查看这些信息应该能让你很好地了解代码的各个部分是如何相互关联的。 使用这些信息,您可以深入了解您最感兴趣的零件的实际来源,并且需要首先了解/修改。
我发现只要跳到代码可以有点压倒一切。 尝试阅读尽可能多的关于devise的文档。 这将有希望解释每个组件的目的和结构。 如果现有的开发人员可以带你通过它,但这并不总是可能的,那么这是最好的。
一旦您对代码的高级结构感到满意,请尝试修复一两个错误。 这将帮助您掌握实际的代码。
我喜欢所有的答案,说你应该使用像Doxygen这样的工具来得到一个类图,并首先尝试了解大局。 我完全同意这种说法。
也就是说,这在很大程度上取决于代码开始的程度。 如果它是一个巨大的混乱,这将是很难学习。 如果它干净,组织得当,不应该那么糟糕。
请参阅此答案 ,了解如何使用testing覆盖率工具来查找感兴趣的function的代码,而无需了解该function的位置,或者如何将其分布到多个模块中。
(无耻的营销提前)
你应该检查nWire 。 这是一个用于导航和可视化大型代码库的Eclipse插件。 我们的许多客户通过打印主要stream程的可视化来使用它来打入新的开发者。