最近有一位猎头顾问打电话询问是否有换工作的意向,对推荐的公司和职位的描述为:"我们这里有一家非常关注软件质量的公司,在寻找一位不仅能完成有挑战的软件开发任务,并且还对代码质量有非常高追求的软件工程师。"。
很难得猎头顾问会以这样的切入点来推荐职位,而不是诸如 "我们是互联网公司","我们是著名互联网公司","我们可以提供业内领先的薪资","我们创业的方向是行业的趋势","我们提供创业公司期权","我们提供人体工程座椅","我们公司漂亮妹子多" 等等。
谁会为了把椅子或者每天能看公司漂亮的前台妹子而跳槽呢?将这些描述可以概括成一点,就是 "我们给的钱多"。诚然,好的薪水是可以招募到杰出的软件工程师的。然而,优秀的软件工程师通常已经得到了较好的薪水,所以如果不是给出足够的量,不一定会为五斗米而折腰。大多数的软件工程师更看重的是技术兴趣,所以诸如 "来我们这做 Openstack 吧","我们需要用 Go 实现 Docker 相关组件的人才" 看起来更有吸引力。
而软件质量,代码风格,则是另一个吸引优秀工程师的方向。追求卓越软件质量的工程师,通常有着自己的软件设计与实现思路,并在不断的实践中锤炼出自己的编程风格和代码品味。这一类工程师,其实无关使用什么语言、做什么产品,他们会始终保持自己的品味,追求软件实现的卓越,进而产出高质量的软件。更重要的是,优秀的工程师希望与更多优秀的工程师合作,并更愿意工作在崇尚代码质量的氛围中。
一般条件下,对软件质量的要求通常与软件生命周期的长短相关。按照软件生命周期的长短,我们可以将软件公司分为两类:
快公司:创业公司,互联网公司。推崇快速开发,快速试错。软件生命周期较短,代码质量相对要求不高。
慢公司:传统行业软件公司,产品公司。推崇稳定可靠的软件设计。软件生命周期较长,代码质量相对要求较高。
软件生命周期的长短,通常也决定了实现软件所使用的编程语言。比如,快公司通常会使用 PHP/Python/Ruby 等动态类型语言,而慢公司通常会选择 C/C++/C#/Java 等静态类型语言。
当猎头顾问还没有说出公司的名字之前,我们也可以大体猜测出该公司所属的行业方向或软件产品类型。比如,该公司可能来自传统的金融、电信、医疗、石油、ERP 行业等,这些行业中有 IBM、Huawei、GE、Schlumberger、SAP 等等世界 500 强巨头更重视软件质量。当然,通常推崇软件质量的公司中,大概率条件下碰到的会是外企,即使是中小外企,也会对软件质量有相对较高的要求。对于产品类型,越是接近 Mission Critical 的产品形态则对软件质量的要求越高。各种软件中间件的软件质量要求也相对较高,比如内存数据库、Message Queue 等。或者如果区分 Framework 和 Application,则 Framework 的软件质量显然要求更高。
每一家较成熟的软件公司,都会设计自己的软件编码规范,增强软件工程师的协同效应,相互之间可以读懂对方的代码。但实际操作中,又有多少人会执着遵守呢?编码规范并不能保证产生出好代码,那代码编写的好坏又如何具体衡量呢?笔者经历过的公司中,多半都是以软件发布后的 Bug 数量来衡量软件的质量的,这种统计形式简单粗暴,优点就是可以量化,缺点就是很难评判出软件代码编写的优雅程度。我听过一则笑话,说软件质量也不能做的太好,软件一定要有 Bug,这样客户才会买我们的服务,而我们就是靠后期卖服务赚钱的。好吧,情何以堪~~
好了,说了这么多,好像文不切题,这篇文章不是叫《代码的印象派》吗?和上面说的这些有什么关系呀?
关系就在于,软件质量与代码编写的优雅程度息息相关。而是否能编写出优雅的代码与软件工程师的个人风格和品味息息相关。
在软件工程领域,通常生命周期长的软件会有着更高的软件质量需求,描述软件质量的内容可以参考下面两篇文章。
Quality 是什么?
软件质量模型
在各种软件质量模型的描述中,都包含着软件可维护性(Maintainability)这一属性。而越是生命周期长的软件,对其软件可维护性的要求越高。而提高软件可维护性的根本方式就是编写可阅读的代码,让其他人理解代码的时间最小化。代码生来就是为人阅读的,只是顺便在机器上执行以完成功能。
在漫长的软件生命周期中,我们有很多机会去修改软件代码,比如发现了新的 Bug、增加新的功能、改进已有功能等。修改代码的第一步当然就是阅读代码,以了解当前的设计和思路。如果代码都读不懂的话,何谈修改呢?还有,大概率条件下,修复自己实现模块的 Bug 的人通常就是你自己,如果时隔几个月后自己都读不懂自己编写的代码,会是什么感受呢?
所以,如何编写出易读的代码就成了问题的关键。而能否编写出易读代码,则直接取决于软件工程师自己的的编程风格和代码品味。
在《孙子兵法》中有云:"上兵伐谋,其次伐交,其次伐兵,其下攻城。攻城之法,为不得已。" 对应到软件领域,软件架构师可以通过出色的系统分析来构建可演进的软件架构,讲究谋略;而软件工程师则通过良好的设计和编程风格来完成攻城任务,讲究方法。
Paul Graham 的《黑客与画家》中描述了黑客与画家的共同点,就是他们都是创作者,并且都在努力创作优秀的作品。画家创作的作品就是画,内嵌着自己的风格和品味。软件工程师的作品就是软件和代码,如果可以的话,你可以将代码打印成卷,出版成书,只是,阅读的人会向你那样幸福吗?
画家的作品都会保留下来,如果你把一个画家的作品按照时间顺序排列,就会发现每幅画所用的技巧,都是建立在上一幅作品学到的东西之上。某幅作品如果特别出众,你往往能在更早期的作品中找到类似的版本。软件工程师也是通过实践来学些编程,并且所进行的工作也是具有原创性的,通常不会有他人的完美的成果可以依靠,如果有的话我们为什么还要再造轮子呢?
创作者的另一个学习途径是通过范例。对于画家而言,临摹大师的作品一直是传统美术教育的一部分,因为临摹迫使你仔细观察一幅画是如何完成的。软件工程师也可以通过学习优秀的程序源码来学会编程,不是看其执行结果,而是看源码实现思路和风格。优秀的软件一定都是在软件工程师对软件美的不懈追求中实现的,现如今有众多优秀的开源软件存在,如果你查看优秀软件的内部,就会发现,即使在那些不被人知的部分,也同样被优美的实现着。
所以说,代码是有画面感的,看一段代码就可以了解一个软件工程师的风格,进而塑造出该工程师在你心目中的印象。工作中,我们每天都在阅读同事们的代码,进而对不同的同事产生不同的印象,对各种不同印象的感受也在不断影响着自身风格的塑造。代码的印象派,说的就是,你想让你的同事对你产生何种印象呢?
笔者不能自诩为我就是那类有着良好的编程风格,并且代码品味高雅的软件工程师,只能说,我还在向这个目标努力着。风格和品味不是一朝一夕就能养成的,世间存在多少种风格我们也无法列举,而说某种风格比另一种风格要好也会陷入无意的争辩。况且,软件工程师多少都会有点自恋情节,在没有见到更好的代码之前,始终都会感觉自己写出的代码就是好代码,并且有时不管你说什么,咱就是这个味儿!
我个人总结了几点关于优雅代码风格的描述:
代码简单:不隐藏设计者的意图,抽象干净利落,控制语句直截了当。
接口清晰:类型接口表现力直白,字面表达含义,API 相互呼应以增强可测试性。
依赖项少:依赖关系越少越好,依赖少证明内聚程度高,低耦合利于自动测试,便于重构。
没有重复:重复代码意味着某些概念或想法没有在代码中良好的体现,及时重构消除重复。
战术分层:代码分层清晰,隔离明确,减少间接依赖,划清名空间,理清目录。
性能最优:局部代码性能调至最优,减少后期因性能问题修改代码的机会。
自动测试:测试与产品代码同等重要,自动测试覆盖 80% 的代码,剩余 20% 选择性测试。
下面,我会列举一些我在工作中遇到的不同的编程风格,用切身的体会来感悟代码的风格和品味。当然,吐槽为主,因为据说在 Code Review 时记录说 "我擦" 的数量就可以衡量代码的好坏。
变量
关于变量,很遗憾,不得不提变量的命名。时至今日,在 Code Review 中仍然可以看到下面这样的代码。
|
|