热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

程序员如何高效读代码?

最近在看Twitter的Oauth2的库的源代码(simplegeopython-oauth2·GitHub),看不进去啊...整个库有些自成体系的感觉,看上去联系很紧密,所以从哪里开始看都不方便。从上往下看代码的话,肯定会被各种函数看晕。从main()开始看的话,也会被好多层的调用搞晕。因为之前对Python的Http请求的库并不熟悉(如httplib2,requests),经常会需要看
最近在看Twitter的Oauth2的库的源代码(simplegeo/python-oauth2 · GitHub),看不进去啊...整个库有些自成体系的感觉,看上去联系很紧密,所以从哪里开始看都不方便。从上往下看代码的话,肯定会被各种函数看晕。从main()开始看的话,也会被好多层的调用搞晕。因为之前对Python的Http请求的库并不熟悉(如httplib2, requests),经常会需要看一下其它库的一些内容,更晕了...

现在总是觉得自己明白大致的流程,但总有大段的函数看不懂,结合文档看也总有很多地方不明白。自己就是想看明白一些,然后对这个库做一些改进(因为有些API的Oauth流程和其它API的有区别,所以我想改进一下Oauth的过程)。但现在的理解程度,完全达不到这个要求啊...(这两天找到了一个新的库,可以满足我的要求,但我还是想搞明白怎么读代码比较好...)

各位资深的程序员们,我应该怎么做才好呢...

回复内容:

先看文档,再看单元测试。 Code Reading (豆瓣) (副题是 The Open Source Perspective,适合题主需求)
代码阅读 (豆瓣) (中译本) 之前也是读代码很慢,后来代码写的多了读这些开源项目的速度就明显快了。
读代码慢就是对常用函数和常用库不熟,不熟悉python常用的编程技巧,读代码的时候精力太分散,读代码是一句一句的读,还需要经常上网查语法什么的,没有办法把精力放在代码的整体结构上,即使是每行代码都看明白了还是不知道整个程序的逻辑,同时耗费精力比较大,很快就累了,效率很低。
熟悉了常用库和编程技巧之后读代码的时候很多功能自己都实现过类似的,扫一眼就看明白了,很多函数扫一眼就知道什么功能,思路不会被不懂得语法或者编程技巧打断,一直停留在程序的逻辑上,这样看代码就轻松多了,而且很快,基本上小的项目随便翻翻就知道它的思路了,大的项目的话其实不用全都把握,只要把与自己要看的部分相关的熟悉了就好了。
读代码快的人也并不是什么都会比你快,当他们碰到一些没见过的东西时也是需要查询,自己写一些例子来熟悉,也要花一些时间,熟悉单个知识点也并不比你快。
文档和测试用例对于楼主目前的阶段来说用处不大,这些东西只能是在你读代码变快了以后锦上添花的东西,很多时候看看文档和测试用例会加快理解这个库的速度,起个和代码对照的作用
如果想要通过熟悉这个库来提高编程水平的话,就把里面用到的第三方库和编程技巧自己多写写,这样回过头来看就知道作者为什么这么写了,很多代码看起来很复杂其实思路很简单的。 一开始我也觉得是自己没有掌握方法,一度还想去买一本很著名的教人读代码的书,后来没买,因为不知不觉我就发现我读代码越来越容易了。
你觉得调用栈跳来跳去的记不住是吧?你觉得模块功能联系太多反馈回路太复杂是吧?其实真正原因是你脑子不够用!
一开始,我读一个三四千行的代码要做上千字的笔记看上一俩星期,后来就不用了,读下来函数调用栈都在脑子里,最多画个草图标一下各模块依赖关系。后来有一次给新人讲模块,用SI,函数间点来点去点得飞快,最后发现我这一口气已经走了几十个函数了。
计算机跑程序,调用栈太多会耗尽内存死机,人读代码,大脑的调用栈太多就会耗尽记忆力然后晕掉,解决办法就是多读代码,把你大脑能够支持更深的调用栈深度的记忆力的潜力开发出来。等突破临界点了你自然会懂怎么读。 先骂作者,然后找个小点的例子调试。 多看,猛看,看了几十万行规模的系统后再看其他系统就自然如履平地。

原文地址:Aaron Liu - Welcome to my blog! • 阅读源代码的几个步骤

需要技能:程序调试能力.

1,跑通程序.

2,运行程序的核心功能,从外部了解它的运行方式.

3,阅读核心功能相关的官方文档.

4,读核心功能对应的源代码(即核心模块)和单元测试,从内部大概了解一下核心模块之间的联系.

5,提出一个关于源码的问题(比如状态机如何运作,filters分为几层等),试图解决.

6,浏览该问题相关代码和测试,然后边调试边解决问题,(不要在代码非常不熟悉的情况下就开始调试,过长的程序栈会消耗太多时间).

7,继续提出问题,直至核心模块烂熟于心.

8,(可选)与同学同事交流学习该模块,或写成博客与网友分享,以加深记忆,获取反馈.这次你很有可能会发现理解上的漏洞或错误,进行查漏补缺吧.

9,开始阅读次核心模块,并重复3-7步骤.

10,如果还嫌不足,为该程序开发插件或库吧.

11,理解源码.
详情请查看我的PPT:如何阅读源代码.pptx_免费高速下载

问题导向阅读代码的方法分为外部和内部两个部分.

外部阅读:带着问题去看,自己提出一个程序常用的应用场景,然后自己去在程序上测试一些主要逻辑,比如后台添加了A,前台是否就生成了B?服务端修改了C,客户端会不会出现D之类.  

内部阅读:带着问题去看,提出一个如何写程序拓展的场景,(你以后想拓展这一块逻辑该怎么做?有没有内建的现成API可供调用),总之不要被文档带着思路走,要被问题带着思路走.

请大家多拍砖或补充,多谢.

这方面有好几本专门的书和文章,也有朋友提供了具体的、系统性的技巧,就不重复了。
还是从个人角度来建议,不求全面,主要是两点:
  1. 从弄清楚目标开始,逐层理解目标系统的设计思路到最后如何实现的具体细节;
  2. 如果有能力,甚至换位思考:与其说是阅读别人的代码,不如说是自己再设计实现一遍——那你是不是也是从弄清楚目标开始,然后提出解决思路,进一步得到解决方案,再分解成若干模块......逐层分解下去?那这样的话还会吃力么?
主要技巧大概说几个关键词吧:
  1. 自顶向下:从目标代码实现的功能、解决的问题(需求),逐层分解问题/解决问题的方法,自顶向下来阅读
  2. 提纲挈领:摸清框架而避免在某个细节停留,如果对某个细节有疑问,记录下来回头深入去看
  3. 广度优先:每次在一个层面上通读一遍(比如第一次掌握主要的几个模块和它们之间的关系,第二次则是几个主要的类,第三次可能到了方法/函数层面),确保广度优先而不是深度优先
  4. 理清目的,分离职责:在不同层面弄清楚每个模块、类、方法的目的/职责,而不是如何实现这个目的/职责。因为任何算法都是为某个职责、目的服务,弄清楚目的而不在于如何实现目的,弄清楚Why而不是How to

高效阅读代码的能力背后:
  1. 大脑的运行方式——和CPU很像,当需要跟进进入到下一个层面(深度)的时候,需要把当前断点记下来,相关信息压入“堆栈”暂时放一放,等进入下一个层面回来恢复到之前的断点工作状态。想想大脑的堆栈和准确记忆能力显然不如CPU,所以尽量避免在不同层次来回穿越,甚至过于深入。必要时,借助一些电脑软件来帮助你阅读,例如UML工具的类图、时序图等
  2. 重点在目标/职责是什么,然后才是如何实现目标/职责:任何系统都是为了解决具体问题而存在。如何解决问题则体现在解决方案,代码只是实现解决方案。而解决方案在不同层面体现为功能模块的组合、具体函数/方法的组合、具体的算法实现(方法内部)等等。
    所以需要自顶向下的分解问题、解决问题的思路,自顶逐层往下,每个层面都搞清楚这个层面的全局脉络(广度优先)。
  3. 题外:做开发的弟兄们最容易出现的问题就是过于关注“how to”这样的实现问题,常见的场景例如:看到别人做了一个什么系统、软件、功能,第一反应是“这个简单,我也会”、“哟,这是怎么实现的?我好像不会”——无论你会不会,请克制你的技术实现冲动。首要问题是:Why——为何要这么实现?那一定是为某个目标、职责服务的。当你阅读别人已经写好的代码,那些代码肯定是为一个个大大小小的目标、职责服务的,所以先忽略How to,搞清楚它们每一个目标/职责,暂时忽略细节。待都弄清楚了,再来挑你感兴趣的地方深入去分析,有的是时间和机会。
    ——请克制技术冲动、实现冲动,这对你的职业生涯是非常有帮助的。已经度过了类似阶段的朋友不妨回顾一下这里面的心得体会。越是对自己的技术实现能力不自信的阶段,越容易出现类似问题。
    其实任何行业,往往随着经验和能力提升,越来越熟练的在抽象层面思考、擅长运用“自顶向下”的分解能力,并且有很强的全局观和逻辑性来保证在任何一个层面的展开都系统而全面(其实基于上一层作为依据展开也不容易遗漏)。举个自己的例子:曾经我的简历上列明我精通、掌握、熟悉各种技术和平台还有各种经验案例等等,后来改成一句话——擅长高效解决问题,并乐于解决复杂问题和新问题,尤其享受用创新方式解决问题。简历上写的求职方向就不再限制于软件相关了——当然1,这与其说是个人能力提升了,不如说找到了自己努力和享受的方向。这样的阶段,至少在思维上已经脱离了具体的软件设计开发相关技术背景的限制,有勇气面对任何行业任何问题;当然2,不要脱离实际的选择专业性要求过于强的行业和工作岗位进行比较;当然3,这些行业里的从业人员不也存在同样的阶段性问题么?
思考和讨论这类问题,对个人成长有提速作用。

个人以为有几种基础能力:
运算能力(大脑的堆栈容量)决定了能处理问题的大小和复杂程度(有生理上限)、思维模式(方法论)决定了处理大和复杂的问题效果和效率(扩充了生理上限)、自我克制(理解甚至控制生理本能)决定了排除干扰的能力,然后是经验积累(可重用模块:分为模式级别和具体实现级别的经验)。
——如同一个优秀的棋手。

母亲说我小时候喜欢玩线团和整理纽扣,可以坐在一个地方一动不动一个下午直到解开一个线团。
随着成长,我已经不满足于解开各种线团,甚至解开越来越大、越来越复杂的线团,而是尝试和追求另外一种方式:各角度观察、推理,理清头绪之后找准一个线头,拎起来轻轻一抖——哇,整个线团优雅的解开了——爽!

一个真正的领导者,在人群中默默观察,对外接的刺激不要立即有反应(自我克制),做那个清醒的了解目标和团队和自己的人(全局观),找到解决方法后选择最恰当的方式去影响和驱动周围的人。未必是聚光灯下的领导者,却是实际上的领导者,不需要权力就能驱动整个组织往有效解决问题的方向推进的领导者。
看过《安德的游戏》的朋友,推荐它的姐妹篇《安德的影子》,主角小豆子就是极好的例子(避免剧透到此打住)。

再往后。。。一下子没想好怎么表达,先打住吧,有朋友有兴趣我再分享进一步的心得。

最后,到这里也只好匿了,呵呵。 1. 要建立层次和结构
看代码不是看小说,线性地往下看就行了。看代码是为了理解代码,在脑子里建立起源代码背后的层次和结构的映射。为此,在开始分析项目之初,就要明确代码的子项目,包(名称空间),类的层次和结构,主要由哪些包构成,每个包大致做什么用。主要的类有哪些,各自的大致职责是什么。主要的类里面,又有哪些主要的方法。

2. 要抓住主干
任何的项目,有相当的代码是用来做一些琐碎的,事务性的事情的。要高效地理解和把握代码,我们就要把握主干。对于代码中的一些主要方法,或者流程,可以梳理出它们的主要步骤,次要的东西可以忽略不管,需要的时候再关注。

3. 要形成文档
如前面的几位答友所说,人脑子不善于记住方法间的进进出出之类的东西,在我们分析这些东西的同时,用一种有效的方式,把分析的结果记录下来,既保存了工作成果,更重要的是,帮助我们更容易进行分析,向深挖的时候,知道现在自己在哪里,向回退的时候,又退得出来,不至于迷路。类图,序列图,都是有用的文档形式,也可以用自己定义的更灵活的图表。好记性不如烂笔头,勤快动脑同时也勤快动手,看代码会容易很多。

4. 要合理运用各种可用手段
静态分析,当然是分析代码的基本手段;但是除了静态分析,如果你的代码也是可以运行的,运行它,观察它的调用堆栈,LOG,或者用调试工具进行跟踪。对于那些主要的方法,流程,有必要用动态跟踪的方式,弄清楚它的过程。这也会比静态分析更直接,更快地告诉你它到底走过哪些路径,执行了哪些方法。

个人习惯先看文档说明了解功能了再做个 demo,明白基础的功能后就从这个熟悉的点切入去看。


我还见过直接硬啃代码的牛人,对他而言,这种方式简单粗暴,速度快效果好。

推荐阅读
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 学习SLAM的女生,很酷
    本文介绍了学习SLAM的女生的故事,她们选择SLAM作为研究方向,面临各种学习挑战,但坚持不懈,最终获得成功。文章鼓励未来想走科研道路的女生勇敢追求自己的梦想,同时提到了一位正在英国攻读硕士学位的女生与SLAM结缘的经历。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • Python字典推导式及循环列表生成字典方法
    本文介绍了Python中使用字典推导式和循环列表生成字典的方法,包括通过循环列表生成相应的字典,并给出了执行结果。详细讲解了代码实现过程。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了Python版Protobuf的安装和使用方法,包括版本选择、编译配置、示例代码等内容。通过学习本教程,您将了解如何在Python中使用Protobuf进行数据序列化和反序列化操作,以及相关的注意事项和技巧。 ... [详细]
  • 自动轮播,反转播放的ViewPagerAdapter的使用方法和效果展示
    本文介绍了如何使用自动轮播、反转播放的ViewPagerAdapter,并展示了其效果。该ViewPagerAdapter支持无限循环、触摸暂停、切换缩放等功能。同时提供了使用GIF.gif的示例和github地址。通过LoopFragmentPagerAdapter类的getActualCount、getActualItem和getActualPagerTitle方法可以实现自定义的循环效果和标题展示。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 2022年的风口:你看不起的行业,真的很挣钱!
    本文介绍了2022年的风口,探讨了一份稳定的副业收入对于普通人增加收入的重要性,以及如何抓住风口来实现赚钱的目标。文章指出,拼命工作并不一定能让人有钱,而是需要顺应时代的方向。 ... [详细]
author-avatar
水灵ruru
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有