如何阅读别人的代码

本文涉及的产品
无影云电脑个人版,1个月黄金款+200核时
无影云电脑企业版,4核8GB 120小时 1个月
资源编排,不限时长
简介: 如何阅读别人的代码

    会读好源码,才能写出好代码 而且除了经常写代码,还要保持习惯看看别人是怎么写的,这里我只引出一个话题就是如何阅读别人的代码

image.gif编辑

    一个工整的代码就好比欣赏一个漂亮的美女一样让人赏心悦目,百看不厌,一个乱糟糟的代码就不忍直视,而且还要吐槽他,对于阅码无数的老司机而言,保持良好的编码和阅读习惯很重要,读别人的代码并不大费力,对于新手而言,我觉得这篇文章对你很有帮助。


保持阅读他人代码的习惯

       我个人认为时常保持阅读他人代码的习惯放到第一位,你读的越多,你就越容易读懂,很多设计的思路思想都是通用的(常用的一些设计模式你可以查看往期文章 设计模式---设计模式基本原则),相信当年你们的英语老师教英语的时候一直强调阅读和词汇量。

image.gif编辑

当你代码阅读量到达一个层级,就似乎打开了你的任督二脉,你能看懂作者是怎么实现的,从而进一步分析作者为什么要这样设计(你会发现为什么比怎么做更重要),不同的语言都有各自不同经典的源码,所以我很推荐大家看优质开源项目源码,不仅仅是代码写的漂亮,而且开源项目的readme都通俗易懂,帮助读者阅读理解他的思想和用法,另外社区基本上都比较活跃,你在阅读过程中遇到的一些问题几乎都能在github,StackOverflow上能找到

提示:所以阅读开源源码我建议先读说明文档,比如README,在阅读程序的时候往往能够从README文件中找到相应的说明,从而简化了源程序的阅读工作。如果源代码有文档目录,一般为doc或者docs,最好也在阅读源程序之前仔细阅读,因为这些文档同样起了很好的说明注释作用。从makefile文件入手,分析源代码的层次结构,找出哪个是主程序,哪些是函数包。这对于快速把握程序结构有很大帮助。从main函数入手,一步一步往下阅读,遇到可以猜测出意思来的简单的函数,可以跳过。但是一定要注意程序中使用的全局变量,可以把关键的数据结构说明拷贝到一个文本编辑器中以便随时查找。

我在这里推荐一些C++/go、node.js相关的开源项目:

C++语言: libevent,memcache, thrift, rabbitmq, 一款开源的MMOG游戏服务端引擎KBE(我只看了一部分,没坚持下来)

libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施。其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理。基于Reactor模式,效率较高,并且代码精简(4.15版本8000多行),是学习事件驱动编程的很好的资源。

Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。memcached用epoll来做事件循环(其实网络事件这块的逻辑大多数框架在设计使用上大同小异,真的是万变不离其宗),多线程的,使用Master-Worker的方式,其中主线程负责接收连接,然后将连接分给各个worker线程,在各个worker线程中完成命令的接收,处理和返回结果。内存分配则使用预先分配,预先分配一大块内存,然后接下来就从内存池中分配,这样可以减少内存的分配次数,提高效率。

Thrift 是一个软件框架(远程过程调用框架),用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引 擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务,thrift 允许你定义一个简单的定义文件中的数据类型和服务接口(类似于protobuf的结构文件)以作为输入文件,编译器生成代码用来方便地生成 RPC 客户端和服务器通信的无缝跨编程语言。著名的 Key-Value 存储服务器 Cassandra 就是使用 Thrift 作为其客户端 API 的。现在很多大型的服务器为了避免重复造轮子就直接使用thrift来做服务器和客户端,方便易用,但是这里也有一些使用上的坑,后边有机会我再分享thrift的专题

KBE 一款开源的 MMOG 游戏服务端引擎, 游戏上层业务逻辑使用Python来写,支持热更, 使用配套客户端插件能够快速与 (Unity3D、UE4、OGRE、HTML5、等等) 结合形成一个完整的客户端。

引擎使用 C++ 编写,开发者无需重复的实现游戏服务端通用的底层技术,这个和现在市面上很多bigworld的游戏服务器架构基本上相差不大,甚至市面上的一些游戏服务器架构也是借鉴了KBE的思想,开发者只需要将精力真正集中到游戏开发层面上来,服务器支持横向扩展。

GO语言: Beego,Gin,Leaf

Gin 是一个非常简约的框架。仅包含最基本的功能和库,使 Gin 成为开发高性能 REST API 的绝佳框架,具备完善的GET、POST、PUT、DELETE快捷方法,也可以方便地进行其他请求的处理,并且当今又流行前后端分离,那么作为后端支撑,Gin更适合眼前需求。

beego 是一个快速开发 Go 应用的 HTTP 框架,他可以用来快速开发 API、Web 及后端服务等各种应用,是一个 resetful 的框架 。支持如下特性:

MVC

REST

智能路由

日志调试

配置管理

模板自动渲染

layout 设计

中间件插入逻辑

方便的 JSON/XML 服务

Leaf 开源游戏服务器框架,注重运行效率 并追求极致的开发效率。Leaf 适用于几乎所有的游戏类型,简洁和易用的接口,尽可能的提升开发的效率稳定性。Leaf 总是尽可能的恢复运行过程中的错误,避免崩溃。多核支持。Leaf 通过模块机制和 leaf/go 尽可能的利用多核资源,同时又尽量避免各种副作用。   

node.j:

pomelo/pinus 适用于网页游戏、社交游戏、移动游戏的服务端,框架已经实现了网关,连接器,负载均衡,游戏业务主逻辑,db相关服务的剥离和封装,拥有强大的扩展性和伸缩性,比如网易狼人杀最早使用的是pomelo,后来团队将整个服务器的框架替换成了pinus,几乎是无缝迁移,而且使用这个框架可以使用插件化的思路随意改造使用自己的”轮子“,实现高可用。

eggjs:阿里开源的企业级 Node.js 框架,基于MVC设计思路,也是高度可扩展的插件机制,内置多进程管理,基于KOA开发,一般用于小游戏,或者大数据分析统计之类的服务

如果各位读者有推荐的开源源码,也可以在下方留言或者在公众平台留言私信给我。

建立代码层次和结构

          看代码不是看流水账作文,线性地往下看就行了。看代码是为了理解代码,在脑子里建立起源代码背后的层次和结构的映射。

          由大到小 ,为此,在开始分析项目之初,就要明确项目都包含了哪些模块(名称空间),类的层次和结构。每个包子项目,子模块大致做什么用。主要的类有哪些,各自的大致职责是什么。主要的类里面,又有哪些主要的方法。

         由粗见细,不要一开始就想把所有的细节搞清楚,否则你就会陷入“只见树木,不见森林”的困境。先要理清程序的脉络,知道那个模块是干什么的,那个类是干什么的,他们之间有什么样的联系。然后在一个一个问题深究。其思想就是,大面化下,再大而化小...你要细到什么程度,取决于你的要求及期望。一般我看到模块,类一层就不会看了,除非我对某个算法感兴趣,我也会仔细在研究之。其实这也是面向对象的设计思想,由上至下,而不是由下至上。无论你看到哪一层,你都可以说“我了解这个框架的实现”,只是看到的粒度不同而已。

        由上之下,逐步求精。任何的项目,有相当的代码是用来做一些琐碎的,事务性的事情的。再牛逼的代码也是要给业务提供服务和支持的,所以光理解框架主要干什么的,结构是什么样的还不行,你也要去熟悉他的业务流转是怎么走的,所以要高效地理解和把握代码,我们就要把握核心的业务逻辑了。对于代码中的一些主要方法,或者流程,可以梳理出它们的主要步骤,次要的东西可以忽略不管,需要的时候再关注。

调试和日志

         检验一个程序员的功力深浅其中一个要素就是看看他的debug调试能力。在阅读代码和分析问题过程中调试和加日志是不可缺少的,断点下在哪里最有可能定位问题所在,但又不浪费时间,记住断点并不是越多越好。什么时候应该用条件断点。碰到一个新的程序,你肯定要在入口Main里面下个断点,这个Main 就会分几个枝出来,然后对你感兴趣的枝再设断点,依次类推。当然,如何用更好的方法调试某个程序.是需要具体问题具体分析的,当然大多数case我们不可能逐一去调试的,毕竟我们分身乏术,对于一些关键的逻辑我们只是想看他走不走,有没有走到,值,状态是否有变化,那么打日志是简单直接的一种方式。

文档化或笔记整理

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

    • 一边阅读代码一边写注释。这是我用过的最好的方法,对代码理解得更深入,看一些重要代码或者特别难懂的代码时挺有用。更何况,注释也是一种文档嘛。
    • 一边阅读代码一边绘制UML。这个方法适用于类之间的关系较复杂和调用层次较深的情况,我一般都是先绘制顺序图,然后为顺序图中的类绘制关系图。
    • 通过Debug来跟踪程序的主要执行过程,这样就可以分清主次了,阅读的时候更有针对性。
    • 类的快速阅读。先弄清楚它在继承链中的位置,看看它的内部状态,也就是成员变量,一般来说,类的对外接口都是对成员变量的访问、加工、代理等,然后看看它的对外接口,也就是公有成员函数,识别核心的一个或多个函数,这时候你应该可以大概了解这个类的职责或作用了。可能这个类是某个设计模式中的一个组成部分,所以,设计模式的掌握对代码的快速阅读也是很有帮助的。
    • 带着问题去阅读。比如想了解android中的消息机制,那么看看Looper、Handler、MessegeQueue这几个类就可以了,其他的不要去看,要不然就跑题了。

    下面列几个阅读源码时所处的情景,在特定场景下用哪些方法:    

    不太熟悉业务逻辑,还不是很清楚它是干啥的,可以用3、5。

    代码量很大,有几十万行,甚至百万行,可以用2、3、5。

    你无法看见程序的运行过程,比如没有用户界面,也有可能是无法运行的,可以用3、5。

    设计复杂,用了大量的设计模式,调用链很深,可以用1、2、3、4、5。

    时间有限,没有那么多时间让你看源码,可以用3、5。

    相关实践学习
    日志服务之使用Nginx模式采集日志
    本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
    相关文章
    |
    7月前
    |
    NoSQL Java 应用服务中间件
    关于阅读源码
    【1月更文挑战第12天】关于阅读源码
    |
    JavaScript 程序员 API
    程序员为什么会在开发中阅读源码?
    作为程序员的大家想必都会在开发的时候,去阅读源码。在实际开发中,开发者经常需要阅读和理解源代码,阅读源码是一种非常有用的技能,它可以帮助程序员更好地了解代码、解决问题、学习新技术和提高编码能力。阅读源码的过程实质上是对软件构建技术和架构深度的一种持续学习和理解。阅读源码可以揭示代码的内在逻辑,这被看作是对技术深度理解的一种体现,它能提高我们对技术的理解程度。结合阅读《Node 中的 AsyncLocalStorage 的前世今生和未来》这篇文章之后,我深刻体会到了作为开发者阅读源码的重要性和必要性。通过阅读这篇文章,我对 AsyncLocalStorage 的实现原理和使用方式有了更深入的理解
    236 3
    程序员为什么会在开发中阅读源码?
    |
    缓存 算法 安全
    程序员写代码为什么要阅读源码?
    阅读一篇技术文章,畅聊一个技术话题。本期文章推荐的是《Node 中的 AsyncLocalStorage 的前世今生和未来》,一起来聊聊开发者阅读源码的这件事。阅读源码的过程实质上是对软件构建技术和架构深度的一种持续学习和理解。阅读源码可以揭示代码的内在逻辑,可以对技术深度的理解,也能提高对技术的理解程度。然而,仅仅阅读源码并不能代替实践操作,因为通过实践,可以更加全面的理解代码的深度和进展。
    156 1
    |
    设计模式 分布式计算 资源调度
    如何阅读源码
    如何阅读源码
    216 0
    |
    编译器 C语言 数据安全/隐私保护
    C++day12笔记无代码
    C++day12笔记
    336 0
    |
    分布式计算 搜索推荐 前端开发
    学会阅读源码后,我觉得自己better了
    学会阅读源码后,我觉得自己better了
    193 0
    |
    前端开发 Java 数据库连接
    阅读《不止代码》之心得分享
    阅读链接为:https://102.alibaba.com/downloadFile.do?file=1530517140411/Codelife.pdf 强烈推荐读一读 我大致浏览过一遍+重新选了几篇文章细看了一遍,有如下体会。
    2124 0
    |
    人工智能 算法 NoSQL
    阅读札记
    我在 GitHub 上创建了一个关于 Reading 的 repo, 里面可以分享一些关于论文的阅读经验或者是一些精彩论文介绍亦或是精品博客之类的. 欢迎大家在此仓库提交一些新的, 优秀的资源! Github 地址是: https://q735613050.
    1301 0
    |
    SQL XML Java
    如何快速阅读源码
    本文探讨在需要了解一个开源项目时,如何快速的理清开源项目的代码逻辑! 以下是个人认为行之有效的方法: 先「跑起来」 自顶向下拆解 深入细节 延伸改进 本文以Mybatis为例来进行演示! 先“跑起来” 程序界有个老传统,学习新技术时都是从「Hello World」开始的!无论是学习新语言时,打印...
    1224 0
    下一篇
    DataWorks