复杂性是不可避免的,这就是进化的原理。

考虑系统复杂性对开发速度的影响因素

  • 红色区块:不利于开发速度
    
  • 绿色区块:有利提升开发效能
    
  • 黄色区块:需适度选择
    
  • 红线:造成下降
    
  • 绿线:造成增加
    
  • 星号:改善重点
    
  • 倒三角:危害重点
    

这里的解决复杂性,所指的是软件开发单位如何提升开发速度,想方设法加快开发效能;这可能是所有的CEO们都梦寐以求的,因为有太多的需求在排队等着要做了,但却偏偏卡在这里,一定要设法来加快开发单位的效能才是。

身为顾问,我经常受邀去诊断研发单位为何效能不彰的问题,习惯上我都会私下先跟负责人强调:“一个够好的需求,胜过作好无数个实用的功能。”在开发之前;多花一点时间排好需求开发的优先序才是上策。

但怎么说了却无法激发当事人的反思(基本上从来没有生效过)而有所改变。很快的他们就会要求各个部门配合我进行诊断作业,然后催促着要我交报告,急著做决策,那种急切心情很教人激赏,我又怎能辜负它呢。图片图片 上图是参考 Targetprocess 公司 Michael Dubakov 先生在 Blog 上所发表的著作(注2. 原文),它是拿来分析软体开发速度相关元素的极好的参考资料,这里我仅仅撷取与系统复杂性有关的区块翻译成中文。加了一点实作上的考量(原文抽象度太高),但在右上角我加进了「架构设计」的影响,并给予它和程序技巧区块一个 AND 的属性。意思是好的架构与好的程序技巧都能消减系统的复杂性。而程序设计巧甚至会受到架构设计的制约(限制),所以我擅自加了一个绿色的区块跟一个椭圆的符号。因为这也是我最常建议开发单位进行改善时的起始点(所以用三颗星来显示)。

快速直觉的抉择方式,往往缺少了深思熟虑。

针对解决复杂统架构实作的通则

技术债 Technical debt


这个观念是由 Wiki 之父 Ward Cunningham 先生提出来的,也是开发单位效率不彰最常见的元凶,就是只知道要求开发速度(注1. 技术债的真正定义,指工程师挑选了实践非最佳解决方案或编写非最佳程式码的刻意决定,以便能够更快地发布软体功能。),而忽略了自己正在提油救火,让约束(限制你开发速度的瓶颈)变得更大了。给它二颗星是因为我们应该正视并支持工程师适时作正确抉择的心态,勇于去挑战技术债才是对提升效能作出最好的贡献。 开发单位其实在邀请外部顾问作诊断之前,都已经作了自我改善的努力,而他们所作的努力也不是完全没有效用,只是经常是改在所谓的最大的限制之前,因此看不到功效,成了一种无效的优化(局部优化,参考工程师的机会成本)。身为顾问必须避开重蹈覆辙,所以要先找到最大的约束才能开始解题(请参考限制理论)。

一个好的需求,胜过作好无数个实用的功能。

程序码的黑洞


人类比病毒要复杂得多了(但这并不意味着人们可以更好地生存着,事实是能活的最久的是适应性最好的,而非最强大的)。写程序是一种复杂性呈现指数型上升的拓普结构,一定会越写越复杂的,当程序写得越多,细部的逻辑就会越来越难以记得清楚也就越见复杂了,然后维护的负荷也跟着越来越大了。这是不变的真理,我们要学会(也只能够)适应这种复杂性,然后避免写出复杂的程式,写程式时要努力去追求简洁而不是快速,正是所谓的简约至上。

学会删减程序码的习惯


程序码一旦被发布出去后就很少有人会去删减它了(执行的好好的,我为什么要去改它,万一改坏了怎么办),即便你觉得这段功能码根本没有人会去呼叫到它(所谓的死程式码),你还是会留着它然后幻想有一天你会需要它(它一定会再被用到的,一种沉没成本的谬误)。

所以我们在发布之后,就变得只增加程序码而不会去删减程序码了,当程序员写越多的程序就背负越多的维护债。这是一种非必要的复杂性(它会间接的拖慢你的开发效能),但你因为不敢删除它因此就会一直背负下去,但其实删减上线程序的习惯不但可以增加组织实施 DevOps 的能力,又能延续产品的生命周期,还能让维护作业更轻松些,CP值极高。但要怎么做呢?

上线后的重构作业


一般的重构作业指的是写完程序后或在 code review 之后立即进行「重构程序码」的动作(重构程序码时是既不修正错误,又不增加新的功能的一种行为)。 它是用于提高程式码的可读性或者改变程式码内部的结构与设计,并且移除死程式码,使其在未来更容易被维护。在极限编程式设计(XP)中,重构需要自动化的单元测试来支援(马丁·福勒的名著《重构》是值得经典的参考书籍)。 但这里所指的是更需要勇气的在上线之后作重构的程式码,目的是;删减那些所谓的死程式码,就是没有被用到的功用、无人在使用的程式码。它需要支撑的就不只是自动化的单元测试了,而是完整的 DevOps作业(经典的思维问题是: 漏改一行程式码你需要多久才能修正它呢?)。

漏改一行程序码你需要多久才能修正它呢?

让新人快速入门的好方法,也是解决复杂系统开发、维护的良方;是
建立部门好的 knowledge Base 系统,运用好的文件资讯揭露系统的复杂性。

结语


作为改善开发效能顾问的双管齐下手法;一是运用敏捷与精益(看板)来改善开发流程的效能。另一是深入商业领域探讨对此领域(domain)的技术债。上图中绿色的区块;是指可以增加开发效能的行为。常用的起手式是实作看板;让看见瓶颈就能知道如何改善的一种透明化的视觉驱动改善方法)。 再来是对技术债进行盘整,这是因为许多开发部门因为专案时程太赶了,选择长期忽略会拖慢他们开发效率的技术债(只增不减无视于技术债的存在,没有将解技术债的需求排进正常开发流程),这是人为的因素,可以运用架构与技能(Skills)的提升来避免它。 其它的绿色区块: 严谨的开发纪律(敏捷所谓简单规范)与短时间激励(对团队运用的激励方法增加短时间的产能)则属于管理上的措施,需要与主管一同配合实施(这属于人事的问题,老实说;比较难有短时间的改善成效)。 红色的区块;是指增加系统复杂性的行为。给「不稳定缓慢测试」二个倒三角的原因是效能不彰的团队多半是因为返工过多的原因(做一次整合测试要花上大半天的时间),说穿了;就是 Bugs 太多了。团队花过多的时间在返工(处理同一件事)上。 解题之道是重视测试让测试变得快速而顺畅,自然能让团队愿意花时间去做测试,能更积极的去重视开发品质,有趣的是当你重视测试的时候,团队的纪律会自然提升,这一点也有助于推行「严谨的开发纪律」的绿色区块。 最后,是大家都喜欢的自由式 coding(Cowboy coding),一种自由 coding 的模式,老实说;我们都是这么开始的,一种可以充分享受 coding 乐趣而不需要背负任何责任的行为模式,可惜的是;现实中每一行的程式码都有它必须正确完成任务的责任,我们要为软体产品负责、对团队负责所以责任大于自由,我们必须严谨的遵循程式员的开发纪律,遵守团队 code review 里的规范。 黄色的区块;是指作多了反而降低开发效能的行为。例如过多的重构或是花太多时间在解技术债,都会降低开发团队的效能。 要解决软体系统太复杂的问题;需要在架构上、coding 技巧上以及管理层面上进行改善,许多开发单位的主管都以为能够雇用到更优秀的工程师自然就能克服更复杂的系统问题(有一点银弹的味道),乍看起来这个想法好像是对的,但在现实环境下这种想法是行不通的(可能有一点用),因为专案工作不是单独一个人就可以完成的,开发团队需要频繁沟通才能协作或必须先问清楚(在复杂系统之下,光是要弄清楚应该找谁来问问题,这种问来问去的沟通本身就是最大的成本)就可以占据掉任何一个聪明人的所有上班时间了,因此你很难只靠优秀的人才就能有效的降低系统太复杂的问题。你需要持续去进行改善,但在改善以前需先分析目前最大的瓶颈(约束)在哪里,针对它来进行改善。若是顺序弄错了先改到最大瓶颈之前的约束,则对达成目标或提升整体的效能都不会有所帮助的(请参考限制理论中的关键链)。

工程师的沟通;就是你中断我、我中断你,彼此都无法专注的工作了。
工程师的会议;就是大家一起暂停coding的作业。

链条的强度取决于最脆弱的一环,而不是整体的强度 注1. 技术债的真正定义 这个观念是由 Wiki 之父 Ward Cunningham 先生提出来的,技术债务是一种机会成本,工程师挑选了实践非最佳解决方案或编写非最佳代码的刻意决定,以便更快地发布软件。如果工程师是在一种无知的状态下,设计了不好的解决方案,就不能算是技术债,纯粹是程式设计的技巧太差。 注2. 参考 Targetprocess 公司 Michael Dubakov 先生的文章,原图如下:

还不过瘾?GOPS 全球运维大会 2020 · 上海站火爆来袭,来看看干货满满的大会日程: