前言
挺多人问过我「如何阅读已有代码」这个问题,希望我能有一个好方法。有些人希望通过阅读「优质项目」(比如 Linux 内核)得到提高,改进自己的代码质量。对于这个问题,我一般都不好回答,因为我很少从阅读别人的代码得到提升。我对自己阅读的代码有很高的标准,因为世界上存在太多风格差劲的代码,阅读它们会损害自己的思维。同样的道理,我也不会阅读风格差劲的文章。
正文
但这并不等于我无法跟其它程序员交流和共事,我有别的办法。比起阅读代码,我更喜欢别人给我讲解他们的代码,用简单的语言或者图形来解释他们的思想。有了思想,我自然知道如何把它变成代码,而且是优雅的代码。很多人的代码我不会去看,但如果他们给我讲,我是可以接受的。
如果有同事请我帮他改进代码,我不会拿起代码埋头就看,因为我知道看代码往往是事倍功半,甚至完全没用。我会让他们先在白板上给我解释那些代码是什么意思。我的同事们都发现,把我讲明白是需要费一番工夫的。因为我的要求非常高,只要有一点不明白,我就会让他们重新讲。还得画图,我会让他们反复改进画出来的图,直到我能一眼看明白为止。如果图形是 3D 的,我会让他们给我压缩成 2D 的,理解了之后再推广到 3D。我无法理解复杂的,高维度的概念,他们必须把它给我变得很简单。
所以跟我讲代码可能需要费很多时间,但这是值得的。我明白了之后,往往能挖出其他人都难以看清楚的要点。给我讲解事情,也能提升他们自己的思维和语言能力,帮助他们简化思想。很多时候我根本没看代码,通过给我讲解,后来他们自己就把代码给简化了。节省了我的脑力和视力,他们也得到了提高。
我最近一次看别人的代码是在 Intel,我们改了 PyTorch 的代码。那不是一次愉悦的经历,因为虽然很多人觉得 PyTorch 好用,它内部的代码却是晦涩而难以理解的。PyTorch 不是 Intel 自己的东西,所以没有人可以给我讲。修改 PyTorch 代码,增加新功能的时候,我发现很难从代码本身看明白应该改哪里。后来我发现,原因在于 PyTorch 的编译构架里自动生成了很多代码,导致你无法理解一些代码是怎么来的。
比如他们有好几个自己设计的文件格式,里面有一些特殊的文本,决定了如何在编译时生成代码。你得理解这些文件在说什么,而那不是任何已知的语言。这些文件被一些 Python 脚本读进去,吐出来一些奇怪的 C++,CUDA,或者 Python 代码。这其实是一种 DSL,我已经在之前的文章中解释过 DSL 带来的问题。要往 PyTorch 里面加功能,你就得理解这些脚本是如何处理这些 DSL,生成代码。而这些脚本写得也比较混乱和草率,所以就是头痛加头痛。
最后我发现,没有办法完全依靠这些代码本身来理解它。那么怎么解决这个问题呢?幸好,网络上有 PyTorch 的内部工程师写了篇 blog,解释 PyTorch 如何组织代码。Blog 的作者 E. Z. Yang 我见过一面,是在一次 PL 学术会议上。他当时在 MIT 读书,一个挺聪明的小伙子。不过看了这 blog 也只能初步知道它做了什么,应该碰大概哪些文件,而这些每天都可能变化。
这篇 blog 还提到,某几个目录里面是历史遗留代码,如果你不知道那是什么,那么请不要碰!看看那几个目录,里面都是一些利用 C 语言的宏处理生成代码的模板,而它使用 C 语言宏的方式还跟普通的用法不一样。在我看来,所谓「宏」(macro)和 「元编程」(metaprogramming) 本身就是巨大的误区,而 PyTorch 对宏的用法还如此奇怪,自作聪明。
你以为看了这篇 blog 就能理解 PyTorch 代码了吗?不,仍然是每天各种碰壁。大量的经验都来自折腾和碰壁。多个人同时在进行这些事情,然后分享自己的经验。讨论会内容经常是:「我发现要做这个,得在这个文件里加这个,然后在那个文件里加那个…… 然后好像就行了。」 下次开会又有人说:「我发现不是像你说的那样,还得改这里和这里,而那里不是关键……」 许多的知其然不知其所以然,盲人摸象,因为「所以然」已经被 PyTorch 的作者们掩盖在一堆堆混乱的 DSL 下面了。
所以我从 PyTorch 的代码里面学到了什么呢?什么都没有。我只看到各种软件开发的误区在反复上演。如果他们在早期得到我的建议,根本不可能把代码组织成这种样子,不可能有这么多的宏处理,代码生成,DSL。PyTorch 之类的深度学习框架,本质上是某种简单编程语言的解释器,只不过这些语言写出来的函数可以求导而已。
很多人都不知道,有一天我用不到一百行 Scheme 代码就写出了一个「深度学习框架」,它其实是一个小的编程语言。虽然没有性能可言,没有 GPU 加速,功能也不完善,但它抓住了 PyTorch 等大型框架的本质——用这个语言写出来的函数能自动求导。这种洞察力才是最关键的东西,只要抓住了关键,细节都可以在需要的时候琢磨出来。几十行代码反复琢磨,往往能帮助你看透上百万行的项目里隐藏的秘密。
很多人以为看大型项目可以提升自己,而没有看到大型项目不过是几十行核心代码的扩展,很多部分是低水平重复。几十行平庸甚至晦涩的代码,重复一万次,就成了几十万行。看那些低水平重复的部分,是得不到什么提升的。造就我今天的编程能力和洞察力的,不是几百万行的大型项目,而是小到几行,几十行之短的练习。不要小看了这些短小的代码,它们就是编程最精髓的东西。反反复复琢磨这些短小的代码,不断改进和提炼里面的结构,磨砺自己的思维。逐渐的,你的认识水平就超越了这些几百万行,让人头痛的项目。
所以我如何阅读别人的代码呢?Don’t。如果有条件,我就让代码的作者给我讲,而不是去阅读它。如果作者不合作,而我真的要使用那个项目的代码,我才会去折腾它。那么如何折腾别人的代码呢?我有另外一套办法。
本文为选摘文章,版权归 YinWang 所有,转载请注明出处!
本文链接:https://quchao.net/How-To-Read-Code.html
友情提示:如果博客部分链接出现404,请留言或者联系博主修复。



支持一下
在读别人的代码中,不要带着自己的思维去读别人的代码,你需要像了解一个新朋友一样去读他的代码,把他的代码看成一个新生事物去对待,只有有这样的意识就不会在读代码时产生痛苦的感觉了
删掉重写
哈哈,真皮
在读别人的代码中,不要带着自己的思维去读别人的代码,你需要像了解一个新朋友一样去读他的代码,把他的代码看成一个新生事物去对待,只有有这样的意识就不会在读代码时产生痛苦的感觉了
然后你会发现你的新朋友鼻子眼睛嘴巴长得和你一模一样,扒开内酷才能看到你需要的东西
因为每个人写代码的习惯都会很不一样,所以真的很难再次去看清楚,或者说再次修改
阅读和修改别人的代码真的非常累,非必要情况我一定不会这么做,如果非要这么做我的方法是做标记 (原代码如果有详细的注释最好),然后画结构,再在上面做二次开发。
尤其是人员调动频繁的公司,有些不规范的代码没法看了,注释没有,经过不知道多少个人手,你绝对不想看
我今天才发现你写了好多docker的,我搜索签到 =、= ,原作者没有发布cookie版本,老版本无法支持验证码,这样就没啥意思了,用cookie跳过是好办法。
哈哈,最近忙除了主要的其他基本都没维护了。
签到直接用我这个就可以,目前是全网最好的,带延迟功能,还有自定义时间,还有复制粘贴功能。
汗,知道了,你的评论不支持Emoji,难怪变空白了,汗颜,我是想问你工作没受到疫情影响么,我都呆家里1个月,受不了了
为什么刚才回复的是空白,
可能自动过滤Emoji了,不过不应该吧