R代码的可读性与编程风格

最近收到不少R编程方面的求助,请求帮忙修改代码。不过有些人的代码, 实在很难看懂。 计算机代码是高度考验逻辑思维、记忆力和想象力的,代码的每一步都应该简单直接,易于理解, 这样整个脚本才能容易理解。

为了能看懂这些代码,对相关的求助也必须提出基本要求: 必须要有R脚本和数据,二者缺一不可, 否则这活儿根本接不了。本来帮忙看代码,帮回答或者解决技术问题就是义务性的,看到糟糕的代码,不知道要多耗费多少脑细胞, 心情也差了很多。

看看收到的R代码有什么常见问题:

1. 脚本没有列明目的

R脚本一般是为了计算或者绘图, 如果目的不够明确, 说明作者可能没有想清楚。 如果脚本想要干什么都说不清楚, 是没有办法将目标化繁为简, 用计算机语言实现的。 所以最重要的一步, 就是要在计算机脚本最前面写一个标题, 上面说清楚这个脚本是干什么的, 是谁写的,什么时候写的。

2. 重要步骤没有备注,重要函数和算法没有列出参考文献

计算机语言中, 一些核心的算法, 往往是最复杂的, 也是程序的核心部分,最好能有清楚的注释, 有时候还要列出参考文献, 以便核对。 否则计算机代码就很容易成为天书。

3. 变量名极短,常用a、b、c、d等命名但是没有注释

让计算机代码成为天书的另外一种方法就是使用极为简短的变量名, a, b, c, d, var 或者 data这样的变量名, 一个星期之后,连编写代码的人也看不懂了。 计算机代码要想能让人看懂,变量名称要有良好的注释, 最好能自明其意, 同时变量名称之间不能太相似。 trait, community, species, specielist, community_structure, res_pd都是好的变量名,而 a, b, var, t, data, 都是不好的变量名。 说到这里,不得不说一下变量命名的风格:有人建议用大小写命名区分变量的不同部分, 增加可读性, 例如 ComStruct, 这本来无可厚非, 但是输入过程中频繁切换大小写, 其实是很麻烦的事,最好能避免。有人建议用点 . 分隔,也就是com.struct,这本来是很好的选择,但是.也用来做S3子函数的命名, 所以有时候用.命名并不十分妥当。 我个人比较推荐用下环线分隔不同的部分,例如 com_struct, 这样在Notepad++等编辑器里面也更容易找到同一个词, 便于查看数据处理的流程。

4. 没有缩进

代码没有良好的缩进,说明编写代码的人没有很好的编程习惯, 或多或少会造成阅读的障碍。

5. 变量重复命名,同一变量出现多次或者用常用函数名命名

让人费解的是, 变量名称有几乎无数种可能,但有些人偏偏喜欢让某变量名在一个脚本中要反复出现,并且不断覆盖前面的变量。 这样做的后果就是,检查脚本的时候自己都糊涂了, 不知道哪个函数控制哪个变量。 最可怕的是data 作为变量名出现多次。 要知道, data在R中是调取内部数据的函数,所有的变量在取名的时候应该避免和R的常用函数重名。

6. 运算过程过于隐晦, 在不必要的时候使用apply函数或者循环

简单明了的代码,才能长远。 但是有些代码太复杂了, 复杂的原因是因为运算过程太隐晦, 太难理解,例如本来就没有几个要读取的数据表,不知道为什么要用sapply或者for循环来读取,造成读取后的数据结果复杂, 难以访问。 任何一个单层循环或者多层循环,看似复杂, 其实都是从最简单的一层数据开始的,然后用[i]或者[j]控制下标的走向完成循环。 apply函数家族实现了矢量预算,能节省循环,但为了简单明了,编程时应该尽量避开循环和apply函数。apply虽好, 但最好也不要贪杯。

7. <- 或者 = 两侧缺少空格

在<- 或者 = 两侧加上空格, 是R用户的基本修养, 这里就不多说了。

说了这么多, 只是希望所见到的R脚本能够:目标明确,结构清楚,变量自己能表明自己的意思,尽量不用注释,也能够看懂。 当然,关键语句的注释仍然是必不可少的。要编写高质量R脚本, 有兴趣的老师同学还可以参考 Google R风格指南 https://google.github.io/styleguide/Rguide.xml 或其中文版 https://nanx.me/rstyle/ 。 虽然风格是只是形式上的, 但好的风格会对编程有很大的帮助。

2017-9-19 初稿

2018-2-22 修改