有个朋友最近一直觉得自己有点胖,该减肥了。不过周一心情不太好,听说美食可以消除郁闷,所以先对自己好一点。周二难得食堂做的是自己一直喜欢吃的东西,不吃可惜了,干脆吃爽了再说。周三天气不好,反正不能出去锻炼,干脆再懒一天。周四太忙了,总得好好吃饭吧?周五……下周再说吧。直到有一天,逛街买衣服,发现衣服不知不觉已经大了一个号。赶紧健康饮食,每天尽可能的控制热量,这才慢慢瘦回来了。
有个朋友一直觉得房间里乱七八糟东西太多,院子里枯枝落叶也没收拾。可是一到周末,不是有聚会,就是要加班,再要么就是出远门,或者累了犯懒……一直到有一天家里要来客人,这才勤快起来,赶紧打扫。家里又整洁起来。
有个朋友喜欢一个人,却总觉得对方若即若离的。干脆断吧,今天也狠不下心,明天又舍不得……直到有一天,亲眼看见他对另一个女生好,才痛快的放手了。
有个朋友最近一直觉得太累了,该休息了,不能再熬夜、加班了。可是今天有急活,明天有重要的活,后天有自己想做的活……直到有一天真的生病了,还病的不轻,这才去留意一下自己的身体信号,好好歇一天。
鬼扯完了。
其实我们平时工作中有时候的技术债务也是类似的。知道一件事如果不做,早晚麻烦会找回来。但是因为总有一些更紧要的事情耽误了,就耽误下来了。
快到年底了,新产品要发布了,各个项目要收尾了,本来想总结一下哪些技术债务真的给我们带来了麻烦,却发现似乎没有很多。回想起来,得益于整个团队里几个很好的做法。
首先就是系统设计的框架是对的。什么叫对的呢?主要有两点:一是它可以有效处理所有的主流的、常见的、可预见的情况。二是对于未知的、可能出现的特殊情况,系统设计中一个很小的变动就能解决问题。这一点感触尤为明显。今年我们主要做的是 API,开始做不久的时候,我也写过一篇文章 API 杂谈。这个 API 最先支持两种产品。后来一边开发的过程中,我们又加入好几种产品的支持,每个产品在产品功能上都改过好几次需求。但是整体的 API 自始至终,并没有发现任何设计上的大缺陷,让整个系统需要大规模重构。当然确实也遇到一些之前没有想到的情况,但是都在一些适当的扩展和调整后就可以处理。
要做到这一点其实很难,没有在相关领域的丰富经验是做不到的。所幸我们组的老大在支付领域浸淫了近十年。最初 API 设计原型拿给他看,几乎每次立马他就能提出一个场景问你该怎么处理。这样来回讨论修改,很多细节的地方也能想得很远。虽然当初设计花的时间挺久,但是后来产品上的种种需求提出来的时候,我们的设计或是本身就可以很好地支持,或是很快能想出一个不需要大改动的解决方案。
不用去 Hack 自己的系统以完成某个产品需求,其实是降低技术债务最事半功倍的一步。
第二就是所有工程师的主人翁意识。每个公司都有一套任务管理系统,例如 Asana 或者 JIRA 之类的。因为我们是多个项目共用的 API,也就会有多个项目组协作开发。在整个产品的开发流程中,我们每个组员都有一个很明确的 Scope,也就有相应的 Ownership。开发中的每一次 Code Review,提出的建议,有些可以立马采纳并放到代码改动集里。有些很快就会做的,会加一个 TODO 和负责这个 TODO 的人的名字。这样保证每个工程师随时可以在代码库中快速找到自己需要完成的代码改动。如果是更复杂一些的任务,大家往往给自己 Create 一个 Asana Task 或者 JIRA ticket。这些任务每周都会 Review,保证不会丢失或者遗忘。
第三是一定要有健全的 Monitoring 和测试机制。这是保证一些性能等相关的 Metrics 在整个开发过程中能保持 Healthy。比如开发中所有 DB 的访问量和增长速度是不是正常。比如任何改动对一个 Request 响应时间会不会有影响等等。这样才能保证一些系统级的债务不会悄无声息地埋伏下来。
第四是可以定期做一些处理技术债务的活动。我们每年一到两次,产品开发没那么紧的时候,会安排 Fix it Week 或者 Clean up Week 等。说白了就是拿出一周时间,大家找个风景宜人的地方,一边建立感情,一边专门用来处理任务队列里优先级比较低,或是工作量比较大的代码清理或者 bug。有时候也会分组,给每个任务或者 bug 一个分值,这样做成竞赛模式,赢的小组还有奖励等。用愉快的方式解决实际的问题。更多程序员解读:www.yangfenzi.com/tag/chengxvyuan
最后,年度计划或者季度计划,都会把一些大的技术债务和系统重构需求提上日程。确保在问题找到我们之前,我们先找到他们。例如重写某些 Service,大规模的重构等。这些只有在来年或下个季度里实实在在地有资源分配下去,才有可能执行。
当然,最重要的,其实还是把技术债务的重要性提到一个被认可的位置上。工程师们如果能预见一个债务可能导致的问题,自然就会愿意花时间去处理。在某些公司,如何与产品经理沟通,以达成共识,也是关键的一个环节。
【文/朱赟 (嘀嗒嘀嗒 微信公号:AngelaTalk)】
————————————————————————————————————————————————————
术语”技术债务“是由Ward Cunningham首次提出,指的是开发团队在设计或架构选型时从短期效应的角度选择了一个易于实现的方案,但从长远来看,这种方案会带来更消极的影响,亦即开发团队所欠的债务。敏捷专家们就技术债务到底是什么以及如何对其进行分类给出了自己的看法。
Martin Fowler认为下面的定义最能表现技术债务的含义:
技术债务类似于金融债务,它也会产生利息,这里的利息其实就是指由于鲁莽的设计决策导致需要在未来的开发中付出更多努力的后果。我们可以选择继续支付利息,也可以通过重构之前鲁莽的设计来将本金一次付清。虽然一次性付清本金需要代价,但却可以降低未来的利息。
Steve McConnell将技术债务分为两类:
无意的——由于经验的缺乏导致初级开发者编写了质量低劣的代码。
有意的——团队根据当前而非未来进行设计选型,这种方式可能很快就能解决当前的问题,但却很拙劣。
Bob大叔补充到,有时人们将坏味道也看作是技术债务,但这是错误的,他说:
坏味道并非技术债务。坏味道就是坏味道。技术债务的评价标准是真实的项目约束,这些约束是风险和好处并存的。坏味道的产生永远都不是理性的结果,而是由懒惰和外行导致的,未来也没有机会偿还了。坏味道总是意味着损失。
Bob大叔说技术债务让人们时刻牢记保持代码的整洁,就好像一个人在背负巨大的抵押债务时需要时刻保持警醒一样。他又说一旦团队决定采纳技术债务,那就意味着保持代码的整洁将变得空前的重要。如果不这样,情况很快就会变得糟糕不堪,偿还这些债务的代价也变得越来越大。
Martin Fowler认为坏味道也是技术债务,只不过是另一种形式的技术债务而已。他觉得坏味道是一种不计后果(reckless)的债务,相对于根据精确计算而得来的谨慎的(prudent)债务而言,坏味道会让问题变得更加严重。他又加上了故意(deliberate)以及无意(inadvertent)从而将技术债务划分为四个象限。
Martin通过如下示例将技术债务划分为4个象限:
不计后果,故意的——团队没有时间做设计,仅仅给出了一个匆忙做出的方案,缺乏对质量的预见。
谨慎,故意的——尽管有很多已知的缺陷,但团队必须现在交付产品,同时对此造成的后果心中有数。
不计后果,无意的——团队压根就不知道基本的设计原则,更不用说引入的坏味道了。
谨慎,无意的——那些拥有优秀设计师的团队很容易遇到这种情况。他们交付的方案具有商业价值,但在完成方案后才明白什么才是最好的方案。
综上所述,实际的项目中将不可避免地存在技术债务问题,这是无法杜绝的,但问题的关键在于千万不能引入不计后果的债务,因为它会持续不断地产生坏味道,也很难对付。
·氧分子网(http://www.yangfenzi.com)延伸阅读:
➤ 硅谷Airbnb资深女程序员朱赟的编程之路,从汇编到C++、Java
➤ 程序员的黄金时代 王欣、赖霖枫、邹胜龙、程浩、冯鑫的那些事