为何我们的代码难以阅读

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

词汇和命名

词汇是思考的材料,如果我们的词汇贫乏,我们的思考也必然破碎。优秀的作家和普通人的差别,很大程度是在词汇的丰富程度上面。据说丘吉尔能掌握四万个英语词汇,而一般中国人,能有几千个词汇量已经很少见了。因此我们在用英语来写代码的时候,常常会陷入词汇不够的困难境地。我们在程序代码中,往往看到很多类似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 条评论
登录 后参与评论

相关文章

来自专栏技术专栏

《数据仓库工具箱》- 第三章零售业务中的知识点汇总

维度定义的是谁,什么时候,在哪的问题,作为聚合查询中的查询条件,分组条件,排序条件

942
来自专栏智能算法

图像处理库综述

当需要做一些图像处理方面的学习和研究的时候,首要任务就是选择一套合适的图像处理类库,本文主要简单介绍下各家图像库的一些优缺点。OpenCV,Intel ...

3767
来自专栏韩伟的专栏

论可复用的游戏服务器端开发框架(四)

战斗系统的模型构建思考 战斗系统是一个游戏的玩法核心,也是游戏之间差别最大的地方,想要建立可复用的模型,可谓困难最大。但是,游戏的玩法本身也是有分类和传承的。需...

2943
来自专栏大数据文摘

快问快答 | 助教带你学习数据科学(附答疑视频领取)

1282
来自专栏PPV课数据科学社区

项目实战:如何构建知识图谱

作者丨徐阿衡 学校丨卡耐基梅隆大学硕士 研究方向丨QA系统 实践了下怎么建一个简单的知识图谱,两个版本,一个从 0 开始(start from scratch)...

7355
来自专栏机器之心

资源 | OpenAI开源机器人模拟Python库mujoco-py:可高效处理并行模拟

选自OpenAI 机器之心编译 参与:黄小天 OpenAI 宣布开源一个高性能的 Python 库,它可用于使用 MuJoCo 引擎(在上年的机器人研究中开发出...

3184
来自专栏新智元

【深度学习框架的未来】李沐:AWS开源端到端AI框架编译器NNVM

【新智元导读】AWS AI主任科学家李沐今天在官博发表文章,介绍了一种新的编译器NNVM,可以大大简化新的AI前端框架和后端硬件的设计,在各种前端和后端为用户提...

3415
来自专栏CSDN技术头条

数据专家必知必会的7款Python工具

如果你有志于做一个数据专家,你就应该保持一颗好奇心,总是不断探索,学习,问各种问题。在线入门教程和视频教程能帮你走出第一步,但是最好的方式就是通过熟悉各种已经在...

2116
来自专栏大数据和云计算技术

知识图谱扫盲

近两年来,随着Linking Open Data等项目的全面展开,语义Web数据源的数量激增,大量RDF数据被发布。互联网正从仅包含网页和网页之间超链接的文档万...

5716
来自专栏大数据文摘

用Python也能进军金融领域?这有一份股票交易策略开发指南

1964

扫码关注云+社区