代码避坑小指南

代码避坑小指南

前两天接手了一位北大研究生的项目代码,真是……一言难尽。

回想起来真是一段艰难的日子。正好借此机会从一个编程小白的视角,总结下我被搞崩溃的种种原因、以及我踩过的各式各样常见坑。水平着实有限,谨以一篇小小的避坑指南,与大家分享。

干货无聊预警,非专业人士可以散啦~(唉,一不小心破坏了本公众号的文艺形象( ̄▽ ̄) )

一、不写注释的代码都是耍流氓!

当我拿到1000+行的项目代码,发现只有寥寥几个小标题时,空气一瞬凝固,身边暴然腾起汹涌烈焰。

某大佬曾一脸炫耀地和我说,他的代码从来不写注释。当时以为这就是大佬的范儿,后来渐渐搞不懂这有什么好炫耀的——是从来不和别人合作、还是代码层级太低任谁都一目了然?我猜,这炫耀的大概只能是记忆力,或懒吧。

当然啦,指的是项目代码;若是十几行的课堂小测,懒的话就算了呗。

二、先“顶层设计”、按层次逻辑依次展开

我拿到的代码的章节是这个样子的:

一、准备工作

任务一、统计岗位对编程能力的要求

……

任务四、描述性统计

任务五、绘制薪资密度图

……

任务十一、聚类模型

……

有了“一”,那么“二”哪去了啊。忽然又从“任务一”开始排序到最后——这是要逼死强迫症啊。

任务一明显是生成变量的一部分,很简单地几行代码,硬说也算能和“描述性统计”并列吧;但是“绘制密度图”不应该包含于“描述性统计”章节嘛?可是代码就搞成了并列关系。

看逻辑混乱的代码,整个人也是凌乱的。前前后后翻看好几遍,才知道究竟哪里是在做什么。

问题应该出在着手开始做之前,并没有对全局有一个整体概览。像写一篇好文章,其文章的线索脉络、整体架构、笔墨分配一定是动笔前就有所思考的;一个课题或者项目的开始应该是由整体布局开始的。在确定了大方向之后,再细化各个子课题,再在每个子课题中细化为实际操作的步骤。

如果有行动之前的“顶层设计”,代码的层测逻辑就顺理成章地顺畅了;迷迷糊糊地做完了,想再把歪歪斜斜的脚印东挪西凑显得端庄,就真的很艰难了。

三、Robustness

不仅对于统计方法,把代码写得Robust也很重要的。

我接手项目之后对原数据做了一个清洗,大概删除了10%的样本,想看看最终模型表现是否有提升。然而,再跑源代码就出现了各种迷之报错。

What? 我只是清洗了下原数据啊,代码完全没动啊,怎么感觉就被直接碰瓷了呢。

逐行检查源代码发现,他里边有好多诸如此类的东西:

还有更长一点的:

暂且不说这种循环其实很低效(用which一行解决的问题非搞个循环),这4887528都是什么鬼!

仔细一研究,data_fin数据集行数和列数。

这样的编程就很不robust,我稍微清洗下原数据就完全塌了。

建议再简单的数字都采用“调用”形式。本例中要把48875换做 nrow(data_fin) 、把 28换做 rcol(data_fin)。如果是基于模型继续做一些事儿,可以直接从模型结果里调用相关数值,一些额外的参数可以从summary(model)里边调用,可能需要用到$、@、[]、[[]]之类的符号,不详述。

虽然你心中明确知道这个值具体是多少,但是也最好不要翘数字赋值;把代码通过相互调用勾连起来,当后期需要有一些变动时候,可以“牵一发而动全身”,简单高效,而且不会出错。

四、适度封装

学C的时候,老师倡导“造工具”的思想;就是说编程时第一步先创造工具,第二步再用这个工具解决你的问题。

我觉得这个不仅是一个技能,更是一种哲学思想;这样的工作、编程方式会带来思维方式乃至生活方式的改变——此文暂不展开。

在这里我想强调一下“封装”这种技巧、和适度封装的优势。

所谓“封装”,其实就是造工具的过程,也是将问题分解的过程。(就像组装套娃~)

比如任务是建一个砖墙。从底层直接上手的话,操作大概是:码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥、码砖、抹水泥……

从上往下其实任务可以分解:建一个砖墙=码N层砖,而码1层砖=拿M个砖头、抹M次水泥。 于是底层的操作可以被封装:把拿一个砖头、抹一下水泥封装成名为“搞定一砖”的函数,把调用“搞定一砖”M次封装成“搞定一层”函数,再把调用N次“搞定一层”封装成“建墙”。

这样的好处有三个:一来你再也不用关注每一个建墙的细节,直接用墙;二来代码会简化很多很多,忽略掉所有重复的、不需要的细节;三来很方便修改,如全局变量一样,“牵一发而动全身”。

我接受的这个项目其实很简单,清洗完数据就只有简单的回归和聚类模型,却写了蔚为壮观的1000+行。究其原因,所有东西都没封装,大量地复制粘贴来堆砌,毫无美感;而且后期修改和维护起来真是要了老命。

五、变量规范命名

所有初学者的变量永远是abc。但做一个项目可千万别abcdefg这么排列变量,就算是自己的代码也会成为天书的。

比较推荐的Google的代码规范。诚然,遵守规范写代码时候会更费劲,因为一个变量名会很长、不如abc那么敲得顺手;动不动就出现大写字母,shift用得很烦。但符合规范的代码写出来,可读性不是一般的强;我相信,当你遇到问题要回看、修改、优化之前大批量代码时,一定会感谢当初的“规范操作”。

最基础的,应该尽量命名规范:变量名称为小写英文,函数名称大写首字母;命名与其含义相关,单词或层次之间’.’或’_’相连。

至于代码格式,虽然也有标准,不过我觉得可以有你的“个人”风格。我比较喜欢用换行和缩进来展现层次。像不同参数之间我会换行(方便注释)、不同层级标题下代码有基础缩进(像#下的代码一般不缩进,####下的就整体缩进4个字符)。

六、实用小技巧速查

一下分享一下我整理的常用的一些小技巧:主要是一些比较冷门的调参、调用和报错的解决方案,和常用却总忘记的函数,希望能帮助到需要的同学~

欢迎大家留言补充和交流~

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181205G1K4JJ00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券