为何我们的代码难以阅读

任何程序员都能写出机器可以阅读的代码,但只有好的程序员才能写出人可以阅读的代码。这句话道出了要写出容易阅读的代码的困难。但是这些困难到底是什么,我们应该如何认识它,正是本文想要探索的问题。

词汇和命名

词汇是思考的材料,如果我们的词汇贫乏,我们的思考也必然破碎。优秀的作家和普通人的差别,很大程度是在词汇的丰富程度上面。据说丘吉尔能掌握四万个英语词汇,而一般中国人,能有几千个词汇量已经很少见了。因此我们在用英语来写代码的时候,常常会陷入词汇不够的困难境地。我们在程序代码中,往往看到很多类似icount, var, num这样名字的变量;还有很多叫做manager, controllor的类,这些都是因为我们想不到应该如何命名导致的。除了名词缺乏,我们的动词往往也很缺乏,证明就是:我们的很多函数名都叫Process(), Run(),Poll(),Loop()诸如此类。如果我们把程序源代码看成是一篇文章,那么这篇文章的词汇,就是各种变量和函数的名字。如果我们在命名上困难重重,这篇文章也一定晦涩难懂。

命名上的困难,除了是因为我们英语词汇量太小以外,另外一个原因,是我们对于业务领域的不了解。我们在接到需求后,往往就急着开始所谓设计和开发:我们会说在这里要用一个哈希表来存放数据,那里用一个回调函数来处理异步结果。——如果我们把程序看成仅仅是一些数据和算法组合,那么我们的命名必然也只是局限于这些数据结构、算法的概念上,比如我们常见到xxMap的结构体,还有xxCallback的函数指针。用这样一堆名字构建起来的程序,就好像摩斯电码一样难以理解。尽管在这些看起来都差不多的字符背后,实现的是一个鲜活而独特的业务需求,但是光看字面是完全无法想象出来的。这个问题实际上也很好解决,就是我们在写程序之前,多去了解这个程序所在的应用领域,看看这个应用领域里面到底是有些什么样的词汇。比如一个商业应用中,就会有Bill、Invoice、Deal等等专用词汇,在游戏应用中,有Player 、NPC、Monster这些概念……我们可以在几乎任何时候,都能从这些业务领域中攫取大量的词汇,来替换掉计算机领域中少的可怜的几个词。如果我们真正的把代码中的命名,变成应用领域的词汇,那么这样的代码片段,就是一个描述某种业务领域的文章,如此,可读性就能大大的加强。

命名本身并不影响程序的运行,但是我们也没必要直接写出好像被扰码器处理过一样的代码。如果我们的命名词汇既准确也生动,那么我们的代码一定也是非常容易读懂的。特别是,我们阅读代码的目的常常不是要评估代码的算法,而仅仅是找到某段业务逻辑的位置来进行修改,这样一个和业务逻辑有关联的命名,能让我们快速跳过大量不相干的代码,直接定位到需要修改的地方,这对代码维护是非常有利的。

语法和模型

传说上帝为了惩罚傲慢自大的人类,让人类开始说不同的语言,而因为说着不同语言,人们无法合作,就无法合力建造巴别通天塔去挑战上帝了。这个故事说明了,语言的不同,能造成多么大的沟通障碍。我以自己少的可怜的语言知识,都能发现不同语言之间,一些重要的区别,是如何阻碍人类之间的沟通的。

第一个是语序问题:汉语和英语,语序都是主谓宾结构的,但是日语和韩语,语序则是主宾谓的,当我们说“我爱你”的时候,在日语韩语的语法是“我你爱”。这种语序上的差异,会导致整个表达方式的不同,从而造成严重的沟通障碍。这样看起来好像汉语和英语还挺接近,但是在定语状语的语序上,这两种语言又是不一样的,汉语的定语在修饰对象的前面,而英语即可在前,也常常在后,比如Man in black。

第二个是语言态度的结合问题。我们常常听到韩语有“思密达”的结尾,实际上这个词汇没有实际含义,只是表示尊敬的含义。在日文中也有大量的这种词汇。这是所谓粘连语的特征,但是在汉语中,我们则使用不同的敬语词汇来表达,比如我们称你为“您”,而英语则通过不同的虚词用法如would来表达敬语语气。我们不得不说人类语言真的是非常复杂。

然而我说了一堆各种人类语言的不同,这和计算机源代码有什么关系呢?毕竟我们用的C/JAVA这些计算机语言,这种语言是不存在上面自然语言的差异的啊?——其实这是有非常重要的关系的,因为我们希望源代码是容易理解的,往往是以自然语言作为标志物的。我们都在尽量的想把源代码写成自然语言的文章,但是如果我们的这个努力目标,自然语言是不一样的,那么我们的努力方向都可能是错误的。因此,如果我们是想让中国程序员更容易看懂,我们可能要尽量维持命名的定语在前,我们可能要把参数列表定义成主、宾的次序。

各种自然语言的不同之处除了上面所说的,还有一个重要的差异,是在于词汇的分布不同。英语中的名词比汉语要多的多,因此才会出现所谓中国的“羊”年,在英语中都不知道应该如何翻译的情况,因为英语中绵羊、山羊都是不同的词。而汉语中的动词,则比英语的多,英语有大量的动词含义是通过动词短语来表达的,比如give in/give up,汉语就是完全不同的“让步”和“放弃”。这个差别体现在编程上是非常关键的,我们知道,面向对象编程,需要以对象类型来对业务代码建模,而由于汉语名词的缺乏,我们常常表达一个对象时,找不到一个专有名词,而是用“做什么什么的东西”来表达这个对象,这对我们代码的设计造成极大的困扰。因为行为的特征在对象上往往是不够稳定的,一旦我们以行为作对象的名字,而这个对象在后续的迭代中被修改行为,就很容易出现名不副实的情况。因此我们在设计面向对象代码的时候,还真的不能仅仅以汉语的习惯去设计,而是要多找找有没有专门表达这个对象的英语名词。

重复和耦合

我们如果想写出如同自然语言一样易读的软件代码,那么我们就一定要以自然语言写文章的结构。但是很可惜的是,自然语言的文章以传情达意为目的,而软件代码主要是控制电脑工作的任务列表。这两者之间有一个重要的差异,就在于“语句”的存在形式上。

我们知道,代码是一行行执行的,而电脑对于数据的处理,往往存在很多类似的、重复的处理步骤。而我们写一篇文章,肯定不会让某一个描述过的句子,反反复复的出现在所有需要的地方。我们会用一些概念词汇来代表这些重复提到的概念,我们会有很多专属名词和缩写,比如“婚戒”“爆炒”这类稍微复杂一些的词汇。这种词汇和说法,能让文章变得简单清晰,突出重点。

其实我们的源代码也可以做到这点,基本的做法就是“封装”:我们把类似的、重复的代码封装成子函数;我们用继承的方法来构建相似的数据对象。如果我们还能用恰如其分的名字来命名这些子函数和子类型,那么我们的代码就能避免长篇累牍的重复代码,从而能让我们更容易的理解。也许,这种封装是一种“额外”的劳动,因为CPU可不管这些,如果你只是想算出结果来,那么完全可以一个函数从头写到尾。但是如果你有意识的做一些有具体业务含义的封装,你会得到另外一个好处,就是代码能更方便的重用。代码重用的首要条件是代码可理解,封装正是对复杂的实现过程的屏蔽,从而让人可以快速理解。而业务领域的重复逻辑是非常常见的,如果代码刚好是一些典型的业务流程,那么这些对应流程的代码,就一定能被重用到大量的类似业务流程的处理那里,这样的好处不言而喻。

总结

这篇文章并没有很深入的去描述,如何从技术角度编写出可读的代码,而主要是关注软件代码和自然语言的差异和联系。因为自然语言本身是我们理解世界的基本工具,所以我们的软件代码,也应该要针对自然语言的特点去设计,才能满足我们人类对代码的理解需求。

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。如有不同意见,欢迎后台留言探讨。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2016-06-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏顶级程序员

千万不要嫁给程序猿,我是认真的

点击上方蓝色字体关注「顶级程序员」 千万不要嫁给程序猿, 因为程序猿的手机永远24小时保持开机,随时都可以向他抱怨、哭诉、查岗。 不小心成怨妇了,有木有? ? ...

3146
来自专栏数据科学与人工智能

【数据可视化】数据可视化的正确操作方法

数据可视化,是一种用来将复杂信息数据清晰表述出来的强大有力的工具。通过可视化信息,我们的大脑可以更有效地合成和保留信息内容,增强对信息的理解。但是如果不正确数据...

2036
来自专栏数据派THU

【独家】一文读懂关联分析

前言 关联分析是数据挖掘中一项基础又重要的技术,是一种在大型数据库中发现变量之间有趣关系的方法。说到数据挖掘的案例,相信很多人都会首先想到沃尔玛超市发现购买尿布...

2177
来自专栏机器学习算法原理与实践

Apriori算法原理总结

    Apriori算法是常用的用于挖掘出数据关联规则的算法,它用来找出数据值中频繁出现的数据集合,找出这些集合的模式有助于我们做一些决策。比如在常见的超市购...

552
来自专栏数据结构与算法

网络最大流算法—Dinic算法及优化

前置知识 网络最大流入门 前言 Dinic在信息学奥赛中是一种最常用的求网络最大流的算法。 它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐 ...

3367
来自专栏大数据文摘

理解偏倚:可靠结果的先决条件

812
来自专栏前端架构

计算机模型与体系架构的发展——从图灵机到云计算机

按照图灵(Alan Turing)给出的计算机模型,计算机是由一个有限状态读写头和一个存储器构成。有限状态读写头从一个初始状态开始,对存储器上的(输入)数据进行...

612
来自专栏互联网大杂烩

最优化模型 数据挖掘之优化模型

最短路径问题、网络最大流问题、最小费用最大流问题、最小生成树问题(MST)、旅行商问题(TSP)、图的着色问题。

472
来自专栏CDA数据分析师

R语言的好与坏丨讲座中字视频丨附讲座PDF

R是一种用于分析数据的领域特定语言。为什么数据分析需要自己的领域特定语言(DSL) ? R语言擅长些什么,不擅长什么?开发人员该如何利用R语言的优势并减轻其弱点...

2119
来自专栏Java面试通关手册

技术面试中常见的几道智力题 来看看你会做几道?

我自己总结的Java学习的系统知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailc...

1965

扫描关注云+社区