业务高速发展带来的变化
那么,我们得思考一下为什么会这样。在 N 年前,就有人想把软件从业者变成像制造工人一样的,不断流水线工作。但是这几乎没什么可能,因为要解决的问题域太复杂。虽然业界有很多规范、标准、套装软件,但是仍然未解决问题之万一。我们来看一下是如何复杂的。
以我们的一个 team 为例,7 个人 1 年做了 400 多个需求。平台能力在不断发展,有人说高速公路换轮胎,有人说飞机飞行换引擎,这样的事情也没少干。大家都知道满足需求,实现业务价值是软件的天职,至于为了更好适应未来发展的平台化能力也好,新特性也好只能在业务发展的过程中做掉。
在这么多需求的过程中,除了技术以外,对于业务包括规则要有深度把握,包括上下游的一些问题。如有评估不到位,问题就大了。分析到设计阶段的缺失,到代码、测试、发布这些阶段可能一如既往的缺失了。早些年,某些系统已经复杂到只有 1-2 个人能搞懂部分了,幸好这些系统今天都完成了拆分和治理。
技术债问题
技术债务是由 Ward Cunningham 在 1992 年的报告中创造的一个比喻,被定义为当我们有意或无意地做了错误的或不理想的技术决策所累积的债务。它和金融债务非常相似。一个人贷款了就会产生债务。如果他定期还款,那么所创建的债务是可以接受的,不会产生进一步的问题。但是,如果他不还款,就会以利息作为惩罚,并随着不还款次数的增加而增加。如果这个人很长一段时间不能支付任何款项,那么应计利息使得他更难以偿还债务。在极端情况下,该人不得不宣布自己破产。
为了快速做业务,采取简单粗暴的方案是大家表示支持的。[临时方案] 的毛病不在于这 2 个月临时了,而在于这个临时上线之后,再无人管了,俗称 [有人生、没人养]。1 年如果做 5 个临时方案,就等于欠了 5 笔债务。欠债并不可怕,怕的是没有偿还计划,或者借口没有时间,或者接口等业务不那么高速发展的时候。吊诡的是好的业务一定是永远都没有时间的,而差的业务确实不用发展了,因为被下线了,或者整个公司 close 了。So,珍惜高速发展的业务,记得去更换引擎,偿还债务,欠的,迟早要还的。有关技术债,推荐当当史大官人在周评比中名列前茅的文章:当技术宅遇上技术债,我个人觉得是这方面有调皮调性的好文章。
人、流程、文档的博弈
人、流程、制度、文化都是需要的。但面对复杂的问题域,人类有简单化思考的倾向。比如某兄弟把手工修改的代码通过自动生成工具覆盖掉了,这时我们有 2 种选择。1 是通过 2 个目录来区分,1 是搞一个检查工具来做合并前的 check。这些做法都没有问题,但是不要都靠脑子去记住。
一个存在 3 年以上的产品,当新人来到的时候,在第一个月他们总会提一个问题,xx 产品咋采取这样的技术啊;进入慢、一点文档都没有;只能看代码,代码写得还不咋的。当新人成了老人,他们对更新的新人解答的时候,会说我们当年更惨,只有看代码是靠谱的。对了,小强是非常了解某一块的,有问题找他,比看文档有用。我们不得不承认的事实包括:
写多少文档,如何维护 [活文档] 仍是一个大问题
关键时刻靠人传、帮、带,靠传承
采用不能 cover 的工具和框架
技术人员有采用新工具、新语言、新开源产品的追求。当全栈、多语言风潮席卷各社区的时候,不罗列一堆名词真心都不好意思出来打招呼。另外还涉及到技术带头人的偏好问题。
某电商的朋友这样讲述了他们的故事:...... 可能更多时候是业务方变动太大,因为创始人不懂技术。然后这种模式没有可借鉴的,因此在业务上一直都是在变动,然后就形成了一种业务混乱的感觉...... 后来,招了 CTO,CTO 是以前做移动语音云平台的,他们都是用数据库 oracle 来做业务,因此来公司后,改第二版时候把大量的业务逻辑转移到数据库里用存储过程来解决,现在的系统就是乱七八糟了。此为 CTO 经验偏好症!
另外,组织架构、业务架构和技术架构息息相关。银行的某兄弟有一波吐槽:esb 核心的理念还是服务化,但是我们行里实际情况,服务的梳理一开始就没做好,而且从目前的组织架构来说也很难有起色(服务梳理这块主要靠科技,业务参与程度太低),而且所有服务的发布都是通过 esb,造成 esb 这边是个开发热点。而且,服务化要业务参与进来还需要大 boss 那边驱动了~银行的业务很多时候都是打太极,只管各自的一亩三分地...
一般的文章也好,分享也好。多是讲成功的 case,讲讲走过的弯路其实对于广大人民群众是更喜闻乐见的。[雪球服务化实践历程] 这篇文章谈到他们采用 finagle 的情况,颇有启发性。
唐福林演讲中说到:“雪球的 scala 技术团队免不了有一些人员更替,有转产品的,有转管理的,有转去做另外的业务项目的,导致后面的框架升级和二次开发力量严重不足。加上 finagle 自己迭代速度快,向后兼任又差,整个一个 no zuo no die why you try 的感觉”。于是,唐福林个人花了差不多两周的时间,做了一个简单版本 rpc 框架的尝试。得益于在微博做 motan 框架的经验和教训,框架开发很快,开发出来后,拿给整个技术团队做讨论的时候,才发现问题很多:再后来,团队在针对 rpc 框架的接下来需求的讨论过程中,越讨论越觉得方向有一些偏:大家对基础设施需求的重点并不是在 rpc 调用框架,而更多在于:大量的小服务,开发业务逻辑的便捷性,升级基础包的便捷性,单节点的运行状态,数据收集,监控报警的便捷性等等。于是,在未来,会把接下来服务化工作的重点定义成:微服务化,具体来说,就是开发并维护一个满足雪球自己业务需要的微服务容器。
复杂的问题域
随着业务的发展,对于可用性的诉求也越来越高。比如你曾经是单机房部署、然后演变成同城异机房、最后又发展到异地机房。因为有异地机房,对于 RPC 的路由复杂度就增加了,我得知道是路由到那个机房的;同样的,在开发环境、线下测试环境要模拟几种部署的情况亦是有复杂度的。
再举一个例子,有一个系统作支付链路的规则决策,起初可能就 4 万行代码;后来增加到 8 万,现在又增加到 10 万。代码行增加了,该应用的职责增加了,也可能调用逻辑的运算复杂度。那么如何保持对外 API 的 TPS 不降低,RT 不降低?
每次 release 不仅要完成功能用例的构建,亦要完成性能的测试。
质量意识
意识是很重要的,比如值班 oncall,随时待命。如果没有被叫醒或者打不通电话就比较糟糕了。我们一般还有备份 AB 角机制。
其实经过分析,80% 的线上问题不是那么难的。其本质是未遵循规定动作。比如修改了代码未充分验证。就修改了几行,咋看都不会出错。从内建质量的角度,我们一般有 N 条质量防线,一个问题被遗留到线上,往往有 3 个以上的措施都失守了。
大家知道,航空飞行是马虎不得的。最近看到一篇报纸谈飞行作风问题,我觉得对软件研发质量仍有类比作用和启发效果。
文章提到几点经验,颇有借鉴意义:
不忘初心:严格遵守 SOP(标准操作程序)
减少侥幸心理、增强风险意识
狠抓作风养成
严厉处罚无后果违章,既要结果,又要过程正确
文章深刻的提到,随着飞行经历的增加,许多程序显得啰嗦、许多检查显得多余、以至于越飞程序越少、多做越简化且不把规章当回事...
总之,质量问题就是达摩克利斯之剑高悬于空中。你不注意它,它就会在某一天降落。上述提到的复杂度问题、业务高速发展、技术债、对于工具的掌握能力等都可能为品质埋下了隐患。能不能破,如何破?
选自右军墨问专栏: