查看原文
其他

关于程序员的职业操守,从《匠艺整洁之道》谈起

吴欣蔚(蓄昂) 大淘宝技术 2022-07-13

《匠艺整洁之道》是鲍勃大叔的整洁系列新书。这本书主要从纪律、标准、操守三个方面阐述了软件从业者应该如何要求自己,提升研发质量、效率、道德水准,本文主要围绕《匠艺整洁之道》的第三部分 -- 操守,聊一聊我们程序员该如何自我约束、自我提升。



为什么程序员需要职业操守?


  行业的壮


这个问题还得从软件行业的发展说起。软件行业从诞生(1935)至今(2022),已经八十多年的历史了。


在这期间,整个软件行业有了巨大的发展:

  1. 从业人员已经过亿

  2. 计算机/电子设备的数量超过人类数量

  3. 软件监控和协调着全社会的运转



大众对计算机及软件的认知,从早年的以机器为主,到现在以机器背后的程序员为主。早期《星际迷航》、《太空奥德赛》等以机器 / 计算机作为重要角色。而随着个人计算机的出现,《黑客帝国》、《战争游戏》等电影逐渐以程序员作为救世主,程序员正脱去神秘的面纱,被社会所了解和接纳。


--->


  影响面扩大


作为程序员,我们虽然不是各种规则的制定者,但我们编写了运行这些规则的代码,并在全面监控和协调我们生活的机器中执行。换句话说:程序员们统治着这个世界。

我们编写的软件,记录着日程表、货物的运输、商品的交易,控制着汽车的方向盘、火箭卫星,甚至还能影响法律的颁布或执行。

因为软件出错而导致的惨剧,在各行各业都有案例:
  1. 科研:地面软件出错,使用了错误的单位,导致火星气候探测者号在火星大气层中下降太深,被撕成了碎片。
  2. 医疗:Therac-25 放射治疗机事故。由于进程冲突,Therac-25 用高能电子束导致 3 人丧生,还烧伤了另外 3 人。
  3. 商业:因为用错标识符,遗留在系统中的死代码被激活,导致骑士资本集团在 45 分钟内损失了 4.6 亿美元。
  4. 交通:丰田汽车的堆栈溢出漏洞,可能导致汽车加速失控,最终可能导致多达 89 人遇难。

当发生一些事情时,会有人需要为此负责,人们会要求程序员们说清楚如何防止这种错误再次发生。

因此,作为程序员的我们,亟需有明确的职业操守以进行自我约束,为的是让软件行业能有更大的发展,也为我们自己能有更好的职业发展。

思考:
你是否有出现过故障,造成的最坏影响是什么?是否对社会造成了影响?

什么是职业操守?


  职业操守的定义


WIKI 里对职业操守的定义是 指人们在从事职业活动中必须遵从的最低道德底线和行业规范。



在职业活动中,有一些公认的职业操守,如:

  1. 诚信的价值观

  2. 诚实地制作工作报告

  3. 不要泄密给竞争对手



同时,各个行业也有各自细分的职业操守,如:

  1. 医生:救死扶伤,爱岗敬业

  2. 魔术师:不公开魔术的秘密

  3. 公安干警:重视调查研究,处理案件不捕风捉影,主观臆断

  4. 法律工作者:忠于宪法和法律,坚持以事实为根据

  5. 教师:为人师表,关爱学生

  6. ...



在 《匠艺整洁之道》 里,鲍勃大叔 提出了 10 条软件开发人员的职业操守。


  软件开发人员的职业操守


以下摘自 《匠艺整洁之道》 :

为捍卫和维护计算机程序员职业的荣誉,我承诺,尽我的能力和判断力:
我不写有害的代码。
我生产的代码将永远是我最好的作品。我不会故意让那些在行为或结构上有缺陷的代码累积起来。
我将在每次发布时提供快速、确定和可重复的证据,证明代码的每个元素都能正常工作。
我将经常进行小规模的发布,不妨碍其他人的进展。
我将无畏地、毫不留情地利用一切机会改进我的创作。我绝不让它变更差。
我将尽我所能尽可能地提高自己和他人的生产力。我不会做任何降低生产力的事。
我将一直确保其他人能够补上我的位置,我也能够为其他人补位。
我将给出在数量级和精确度上都靠谱的预估。我不会做出没有把握的承诺。
如果我的程序员同事拥有足够的操守、标准、纪律和技能,就能赢得我的尊重。任何其他的属性或特征都不会成为我尊重程序员同事的因素。
我永远不会停止学习和改进我的技艺。

程序员的职业操守?


鲍勃大叔提出的这 10 条誓言可以分为三个类型:伤害、集成、团队合作,我们针对这三个类型分别展开聊聊。


  关于伤害


我不写有害的代码。
我生产的代码将永远是我最好的作品。我不会故意让那些在行为或结构上有缺陷的代码累积起来。
我将在每次发布时提供快速、确定和可重复的证据,证明代码的每个元素都能正常工作。


  • 何谓伤害


我们编写的软件每时每刻都在对这个社会产生着影响。我们任何无意中的行为,都可能会给这个社会带来意想不到的伤害。

例如 人们发现大众汽车公司的程序员写了一些代码,故意阻挠 EPA 排放测试,影响有关部门对环境危害的评估,损害了这些汽车驾驶地所有人的健康。



如果我们放任自己,就会对自己,或者身边的人,甚至整个社会造成危害,包括:

  1. 对社会造成的伤害

  2. 对你的同行造成的伤害

  3. 对未来的程序员造成的伤害

  4. 对功能/结构造成的伤害


  • 直面伤害


上述大众汽车公司的程序员造成的危害 ,谁该为此负责?

作为程序员的我们,可能会这么说:"我只是在做我的工作,这不是我能控制得了的事情。"

但是,如果你明知道这么做会带来不好的后果但还继续这么做了,那你就需要为此后果承担一部分责任。请不要忘记,公司雇佣你作为软件开发工程师的重要理由之一,是你应该有能力识别出软件可能在什么情况下出问题,你需要在它产生麻烦之前找到它,并且有责任大声说出来。

避免伤害,尽力而为


思考:以下两种系统,哪个系统的价值更高?

  1. 工作完美,但不可修改

  2. 不能正确地做任何事情,但却容易修改



上述的两个系统,分别体现了软件的两个价值:

  1. 行为价值:让程序能够正确工作

  2. 结构价值:让程序易于调整


一个软件系统如果无法被改变,即使它能够正确工作,最终也摆脱不了被淘汰的命运:






一个软件系统要想能够提供长期价值,它就必须能够响应需求的变化。因此,除了最紧急的情况之外(对人、对公司、对社会造成灾难的情况),我们应该优先选用第二种系统。即使我们需要一点时间和金钱的投入,但在那之后,它就将可以永远继续工作。


坚持好结构,它与我们利益相关


为了能使软件能够提供长期价值,不对当下的同事、未来的同事造成伤害,就要求我们写出来的软件要有一个好的结构,一个好结构带来的价值有:

  1. 容易测试

  2. 容易修改

  3. 容易重用



要写出一个好的结构,往往要花我们更多的时间。我们经常会遇到这样的场景:

一个紧急的需求过来,要求我们在指定时间内完成并上线,但这些时间往往只够我们完成需求,同时你的老板也要求你尽快完成这个紧急需求。如果是你,会如何应对这种情况呢?



首先要记住的一点是:一个项目/软件的成功,对我们的事业、声誉有着直接的影响,它与我们的利益息息相关。因此,作为利益关联者,我们对系统的开发和结构有发言权;同时,我们也是工程师,公司雇佣我们,是因为我们知道如何构建软件系统,如何搭建这些系统的结构,并使其能够提供长期价值,我们需要确保系统不会因为坏行为和坏结构而遭到破坏。



回过头再来看这个问题,我们的老板了解结构吗?或者老板的理解仅限于行为吗?如果老板明确告诉你不要理会结构,应完全关注行为,我们该怎么办?


我们得拒绝,因为我们是工程师,是利益相关者。也许会有争斗、对抗,但我们的专业不允许我们退缩。也许你认为拒绝就会被解雇,但大多数情况下不会。因为大多数经理也期望为他们需要和相信的东西而奋斗,而且他们尊重那些愿意做同样事情的人(否则还会有那么多的技术沙龙、技术分享交流会吗?)。


  关于集成


我将经常进行小规模的发布,不妨碍其他人的进展。
我将无畏地、毫不留情地利用一切机会改进我的创作。我绝不让它变更差。
我将尽我所能尽可能地提高自己和他人的生产力。我不会做任何降低生产力的事。

  • 为什么需要关注集成


软件上的并发是指:同一时间可能有多个用户对同一数据进行读写操作。

软件的集成,也一样存在并发。当我们的项目不断变得复杂、庞大, 参与这个项目的开发人员变多的时候,每个人同时都在改动着各自的功能模块,软件集成冲突的问题会越来越突出,最终会成为瓶颈。

漫长的(集成)周期阻碍了团队的进步。因此,我们需要关注集成,关注它的周期。它与迭代有关,它与编辑/编译/测试周期有关。只有提升这些步骤的效率,我们才不会阻碍别人的进度、团队的进步。



  • 持续集成


软件行业经过这么多年的发展,已经有了不少解决方案。其中,持续集成就是一个很好的手段。


持续集成能够带来以下好处:

  1. 快速发现错误

  2. 防止分支大幅度偏离主干


持续集成并不能让我们消除Bug,但是能让它们非常容易被发现和改正;它可以让我们的软件在快速迭代的同时,仍能保持高质量,不阻碍别人进度。


  • 随机善意行为


鲍勃大叔在《代码整洁之道》里提到过的童子军军规:代码签入时要比签出时更整洁。


如果每次代码签入时,代码都比签出时干净,那么代码就不会腐坏。我们可以通过在每次检查代码时,对其进行随机善意行为来做到。任何善意的行为,无论多么微小,都不会被浪费。



我们可以通过增加测试的覆盖率(但不应该变为管理指标),来协助我们改进代码,协助我们写出更加健壮的代码。


另一个有效的随机善意行为是简单的清理--以改进为目的的重构。我们可以从一些简单的手段入手,如:

  1. 优化字段的命名,让代码可读性更强

  2. 清理无用代码,减少理解成本

  3. 调整代码结构,保持代码的灵活性


  关于团队合作


我将一直确保其他人能够补上我的位置,我也能够为其他人补位。

我将给出在数量级和精确度上都靠谱的预估。我不会做出没有把握的承诺。

如果我的程序员同事拥有足够的操守、标准、纪律和技能,就能赢得我的尊重。任何其他的属性或特征都不会成为我尊重程序员同事的因素。

我永远不会停止学习和改进我的技艺。


上述几点主要是关于团队合作相关的誓言,总结起来主要为以下几点:
  1. 有团队精神,能够被补位,避免团队因知识断层而陷入瘫痪
  2. 诚实合理地预估,不轻易承诺
  3. 只尊重职业技能、纪律、标准和操守,不因其他因素彼此歧视
  4. 永不停止学习,跟上行业的变化是对职业的尊重,也是对自己的事业负责


  • 诚实合理地预估,不轻易承诺


系一双鞋带需要多久?也许你可以很快地说出:20秒左右。因为系鞋带这件事几乎天天都在做,你可以相当快速、准确地给出合理的预估。


那如果要你写一个系鞋带的教程,需要多久?你是否没有办法快速准确地做出一个预估?你需要考虑这个教程的受众、是否需要图文并茂、篇幅限制 ……



这正是我们作为程序员经常会遇到的问题:预估工时。我们面临的用户可能都是计算机新手,他们对软件可能一窍不通,我们必须要写出使用要足够简单软件,并拥有足够详细的使用说明……


当一位经理来找你说:“我在星期二之前需要这个。” 你被这个问题困住了,因为你不知道你是否能在星期二之前完成这件事。也许你做过类似的事情,花个两三天就搞定了;也许这里面藏着一个跟你之前做过的都不一样的技术难点,你不知道能否按时完成。


所以当你被要求估计某件事时,你不能给出一个具体的时间,因为那是谎言,你不知道你是否能够在特定的时间完成它,你需要考虑到最好和最坏的情况。如果你确实给了一个精确的时间,那最好能咬牙完成它。因为你在做出承诺,所以你最好准时完成它,不要有任何借口。



要给出一个合理的预估,可以这么做:

  1. 不要轻易给出一个具体时间,诚实地保持诚实

  2. 对项目的预估不能只是一个交付日期,而是一个时间范围

    进行工作项拆解,找出隐藏在里面的模糊因子(不确定因素)

    与经理交流,花更多时间细化模糊因子,如此来回递归式操作

  3. 针对最好情况、最坏情况、普通情况,分别估计其可能发生的概率,再针对这3种情况预估日期范围


  • 永不停止学习


我们所处的行业在过去几十年,经历了快速变化,而且这个变化还在持续,我们必须跟上。这就意味着我们必须持续学习,持续阅读图书、博客、参加技术交流会等等。我们的雇主没有责任培训我们,我们需要对自己的事业负责。学习是自己的事,我们要弄清楚该学什么,花多少时间学。因此,除了工作时间之外,每周投入10~20小时的时间来培养和维护我们的事业吧,这是保持我们专业性的做法。

写在最后


“The simplest way to describe craftsmanship is pride of workmanship. It is the mindset that you are working on something important and you are going to do it well."

程序员是一个技术含量很高的职业,但也必须受非技术概念的约束(标准和道德规范)。只有通过这些标准和道德规范的约束,才会让我们这个行业越走越好。它约束我们的行为,对我们提出更高的要求,在提升我们竞争力的同时,也会给我们带来更多的成就感。

让我们一起尽力的努力做到最好,做一个有『良知』的程序员!

参考内容


《匠艺整洁之道》  作者:Robert C·Martin

团队介绍


欢迎加入淘宝移动技术中台,团队成员大牛云集,有阿里移动中间件的创始人员、鹰眼全链路追踪平台核心成员、更有一群热爱技术,期望用技术推动业务的小伙伴。

淘宝移动技术中台,推进淘系(淘宝、天猫等)架构升级,致力于为淘系、整个集团提供基础核心能力、产品与解决方案:

  1. 业务高可用的解决方案与核心能力(应用高可用:为业务提供自适应限流、隔离与熔断的柔性高可用解决方案,站点高可用:故障自愈、多机房与异地容灾与快速切流恢复);

  2. 新一代的业务研发模式FaaS(一站式函数研发Gaia平台);

  3. 下一代网络协议QUIC实现与落地;

  4. 移动中间件(API网关MTop、域名调度AMDC、消息/推送、文件上传AUS、移动配置推送Orange 等等)。

期待一起参与加入淘系基础平台的建设~简历投至方式 :zebin.xuzb@alibaba-inc.com


✿  拓展阅读
 
作者|吴欣蔚(蓄昂) 
编辑|橙子君

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存