[转载] 软件研发的实用主义思考
|导语 我们在以实用为目的去做事情的时候,很容易受到一些思维误区的干扰,自以为自己是追求实用的,但实际上早已经谬之千里,却不自知
什么是软件研发的实用主义?
实际上,软件研发架构的各种理论方法,其本质都是围绕着“实用”来进行设计的。所以,事实上不应该有什么软件研发的工作方法是不属于实用主义的,一切的软件架构,软件设计,软件研发管理的方法,都应该是属于实用主义。
但为什么我还是要提出这个题目,来探讨这个问题?
那是因为我们在以实用为目的去做事情的时候,很容易受到一些思维误区的干扰,自以为自己是追求实用的,但实际上早已经谬之千里,却不自知。
那,有些什么样的误区干扰呢?我结合在腾讯十多年的工作,和前后数十个不同特色的研发团队深度合作的经验来看,目力所及,归纳了四大误区。
误区一:技术上的主次混淆
没有人会认为自己是一个主次不分的笨蛋,但实际上,团队合作过程中表现出来的综合智商就是低于个体智商的。 再加上,团队中,总是会掺杂一些“不知道自己不知道”的盲目者。最终会把团队带向歧途。
举一个在腾讯内,很典型很常见的例子。
本来有一个团队,可能原本他们是负责一款软件APP的研发,在执行工作的过程中,发现自己缺少了一个基础组件。这个组件可能是一个crash率的监控组件,也可能是一个为了解决性能问题而诞生的性能监控组件,还可能是性能辅助工具或者日志工具组件,等等。所以他们就会安排员工自己去做这样一套工具组件出来。
当工具组件开发完成,也能够满足自己使用的同时,他们就会诞生一个想法,就是这个工具组件,在旁的团队是不是也需要?这样常见的工具,很大概率大家都会需要吧?如果我们把这个组件推广出去,我们的技术价值是不是就会扩大?研发同事是不是就有更多的晋升素材?大家似乎能从中捞到好处,而且是以技术的名义,看起来还很正义。这样的想法,大概率都是一拍即合的。
这个想法本身没有错,如果说我们有充分的时间精力,或者说我们确实做出了一个通用化的工具,而通用的价值也足够大的话,是可以去做这个事情,但是现实往往是很复杂。有可能他的主项目处于人力紧缺的一个状态,有可能他们的业务正在生死边缘,都快做不下去了,有可能主业务那边还在拼命招人,却招不够,找不到合适的人才。但是,这边却又拎着一支技术队伍去做以通用化为目的的技术工具。那么最后的结果是什么呢?那就是浪费了更多的人力和时间。
那这件事能不能够成功呢?
首先他还不一定能够成功,对吧?即便他能够成功,它也仅仅只是给别的团队提供了一个不一定很适用的工具。别的产品团队拿过去用,可能还会抱怨说这个工具不太好用。自己还得持续投入人力去不断完善。因为每个团队有自己软件架构的一些特色特点,用法特征,对吧?你做成通用化的,别人拿去不一定是最好用的,原本只做给自己用,完全以自己的使用方法习惯和团队的成员的特色去结合,是很好用的。但是他把它通用化之后,有可能自己也不一定好用了,别人也不一定是最适用的,虽然它可能有一定用途。即便最终有人用了,那旁的团队能给到他什么呢?能支持他的业务成功么?显然不太可能。
所以,我们要思考一下,我们在一家大公司里,做这样的一些小的基础工具产生的价值,和我们做出一个真正意义成功的产品的价值的对比,差异有多大?完全不在一个量级吧,一款产品的大成功是决定性的价值,而一个或者好多个通用的小工具,其价值能与之相提并论么?
误区二:管理懒惰 与 重度规范化问题
还有一个误区就是来自于 规范化,为什么规范化也会形成干扰呢?规范化不是好事么?如果一个事情是很容易能看出来问题的,就不会叫做误区了。我们都能明白,日常生活中,最可怕的人就是面像和善的斯文败类了,对吧?因为你被表象迷惑了。
继续举一个例子:比如说某个团队复盘说他们的研发效率低下的问题,复盘的过程,会去追究为什么研发效率低?然后,追究出来原因是他们的团队的同事在这些模块接口的调用用法之间老是搞错,或者找不到正确的用法,于是又另起炉灶开新的接口,形成各种垃圾代码山。或者说把接口用错,模块重度耦合,牵一发动全身,等等。这些都会制造很多的时间成本,而且还必然会导致一些质量问题。
所以,面对这种情况,如果技术管理的主导者,自己的技术能力不够强悍而又厌倦了无休止的讨论后,会很容易能够想到的,不需要太动脑子的方法就是:“我们要增加注释,把接口的规范统一整理,把架构和目录统一整理,要让软件变得更加易读,架构更加清晰”。当然,这个内容本身是很正义的,听起来也貌似很美好。【注:他们大概率没有能力去想到,员工能力培养的方法问题,技术骨干的甄别技巧问题,以及,其实应该由技术总负责人自己亲自设计架构等核心 因素… …】
一个听起来很正义的事情要推行下去的话,是容易得到大家的支持的,对吧?但是真是去推行的时候就会发现问题了,因为没有去定义注释写到什么程度是合格的,架构清晰到什么程度是合格的,于是就需要有专人来做这样的规范。
这个时候团队里面就会开始形成了分工,会有专人来负责这些规范化的事情,而负责规范化事情的同时,他的KPI和他的核心职责就是让规范足够的极致。这一下就开始完蛋了。
大家可以想象到一定会有过度的规范制定出来,对吧? 因为既然有专人来干这个事情,就会有人把这种事情当做KPI或者OKR。这种规则,即便严苛,但因为一开始这个是所有人都举手所赞成支持的事情,后面怎么可能自己又跳出来反对呢?所以,反对的声音都是很渺小的,于是他们的团队的成员就会形成一种:”我感觉这件事情有点不对,但是我又说不上来哪里不对“ 的感受。
最后的结果是什么?就是会开始形成一些有意或无意的抗争,或者是执行怠慢。
那么负责执行规范的人就会发现规范大家都很支持,却很难执行,因为大家有反抗情绪。他们的领导层往往会在事后,收到执行上出现困难的一些声音之后,开始举行一个反思会,或者说复盘会,去思考他们这么做是对的吗?
他们很快会发现这件事情上,单就规则本身来讨论,它一定是一个正确的事情,所以他们没有办法去把复盘出来“这个事不需要继续进行”的结论。而且大概率会复盘出另一个结论,就是:”这件事情要继续做,而且是坚决的做,没有执行好是因为不够严格,规则还不够明细,奖惩措施没有落实到人。做得好的应当奖励,树立标杆,执行不好的人要有惩罚!”
接下来,他们就会开始细化如何用更强制的措施让这个事情能够执行得更好,怎样甑别那些干扰的人,不愿意严格执行的人。而强制的措施最容易想到不太用动脑子就能想到的解决方法就是打分,打分就可以量化,就不用去个例化分析了,因为个例化分析太难了,团队的人那么多,情况那么多对吧?
他们急切的希望制定很多的一刀切的规则标准,拿着这些一刀切的规则和标准去要求大家,这样才不会老是遇到争议。
根据这些标准来量化大家做的事情,这个时候团队的失败就进入到中后期了,因为他们所有的时间和精力就开始围绕着分数去进行工作了。团队成员的目标倒是很明确了,把分数做高就对了。但是,这是整个团队的最终目标么?
监管团队的人在制定规则,他的KPI他的思考变成了思考规则,而做事情的人变成了围绕分数去进行工作。
本来我们是应该围绕着产品的成功去工作的,但是,这个产品如何才能成功这件事,是谁在负责?这个时候,已经几乎没有人负责了,只有领导大老板自己一个人在负责。但是他又想不明白有什么不对劲?因为他安排下去做的事情都是围绕着他的目标想要做好而推导出来的事情,最后却做得一团糟,所有人都在努力,却都没有围绕最终目标去做。
其实背后的原理就来自于一个偷懒的行为:就是他们不想具体案例具体分析了,他们希望制定统一标准之后,大家统一的来套这个标准就好了,不要有谁去挑战规则。这个才是问题的症结。
当然,实用主义也不是说我们就不要规则了。因为有些事情它的量级很高,量级很大,如果每一个问题都要具体案例具体分析,大家也累不过来。这种时候,是需要真正的技术领导者来统筹全局的,对问题的洞悉不应该来自于层层传递,而是本身的深度理解。
例如大部分软件足够庞大后,会碰到的多线程带来的稳定性问题,会引入层层叠叠的规范和规则,以及层层叠叠的架构保护措施。几乎无穷无尽,最后还是解决不干净线程问题。而我会要求企业微信的线程数量严格控制,io都是一个线程,网络也都是一个线程,再加上UI主线程,常规情况下只有互不干扰的3个线程。当然,也允许特例,但是非常有限,都需要懂这套规则背后原理的人来审核。几年下来,企业微信这样一个几千万行的超大型软件系统,几乎不会遇到任何线程上的质量问题。这为我们的快速迭代提供了极大的助力。当然,这个只是无数措施中不起眼的一小条而已。最关键的是,主负责人,自己理解是否对。
当然,团队里的核心人物数量有限,当事情的量级达到一定程度的时候,我们一定会迫不得已会去用一些自动化的或者说一刀切的规则化的方式去做事情,这些规则化实施的时候,一定要遵循一个原则:就是这个规则面对一些个例的时候,要有一个方法去衡量边界,越界的,就必须有足够能力的技术leader来独立分析解决问题。要不然技术leader干什么呢?只管人不管技术就不是合格的技术leader了。
规则不能贪多,不能一开始就妄图制定涵盖一切的规则。规则太多就没有办法做到每一条规则都完美化了。当我们定规则定的太快太多,又长时间不更新不回溯,它们就会形成我们前面讲的失败的案例的结果,对吧?
所以规则要少要精,而且要时常的复盘,对一些不能够完美化的规则,要及时的清理。不要太过懒惰的试图去批量的进行规范化,规范化一定要有节制。尤其是,有些事情,过去这样做是对的,今天,不这样做可能才是对的。
误区三、架构经验的拿来主义
“架构师”这个职务名称,听起来比程序员 或者 开发,要高大上得多。这个名称也就成为我们软件技术人的重要追求之一。大家都希望自己被称呼为架构师,而不是程序员。
不要小看这种力量,这种影响会让技术团队中的相当多人,以学习足够多的和架构技术相关的名词为荣。
学习知识还能有错?这当然没有错,学海无涯,多学总是好事。但问题就出在“纸上谈兵的故事”。学成孔乙己可不是什么好事。软件架构这种东西,我始终不认为它是一种数理级别的定理级知识,我更倾向于它是经验型知识。
怎么理解经验型知识呢?
就比如,骑自行车,游泳,这些技能都是经验型技能。这种技能有个特点,就是你没有办法通过阅读甚至背诵一本《游泳技巧大全》而实现游泳技能的提升。你必须自己下水去呛水,骑上车去摔跤,然后才可能真的学会。
我曾经和一个合作团队的同事去讨论一套合作的技术方案,我提出了一套接口用法,可以相对比较容易的快速的达成双方的目标,然而我却受到了对方合作团队一个年轻同事的激烈反驳,他认为我的架构不满足架构上的某某什么原则什么理论,讲了一大串名词。最后,我们还要花费大量的时间和精力,和他逐条掰扯这样做的具体问题到底在哪里。如果真的按他说的做,除了架构上有一种莫名的数学上的美以外,没有在任何维护成本,开发速度,质量控制上的明显优势。这个就是典型的经验拿来主义。
所以我在做技术招聘的面试的时候,不管面什么内容,哪怕是问TCP和UDP有什么差别,这样基础性的问题,我喜欢反复追问的都是,UDP与TCP各自存在的价值分别是什么?为什么两种方法要同时存在? 我要的是这个分析过程,要的不是背诵TCP的各种基础结构,各种理论定义。我要的是TCP的每一个结构为什么要长这样?而不是那样?它当初形成的推导过程有没有思考过?只有学会了推导过程,在你遇到问题的时候,才能够通过思考的方式去进行这个事情,应该怎么做?什么方法是可以拿来用的,对吧?
我们千万要警惕团队里有人把别人写的书,做的学问,编的文章,当做像三字经一样在你面前背诵,跟你说这是某某曰过,所以要按这样做。 我并不是反对去学习别人的经验,反而我很提倡多学习别人的经验,但问题是说经验拿过来用的时候,我们用的方法一定是渔法,而非鱼本身。要了解这个经验它是怎么来的,经验创造出来的一个过程,推导这个经验的过程 如果和我们当前遇到的情况很契合,所以我们才用它,而不是说因为这个经验是一个牛人说的,是一个大佬写的,是来自于一个很成功的项目得出的,于是得出我们要用,这是完全没有逻辑的,对吧?
辨别和理解这些经验的过程,或者说,自己创造属于自己经验的过程,是需要大量实践的练习与深度思考一起进行的。其实,这条误区的背后,是培养技术人才的核心技巧之一。如果有时间,我以后再写专门的文章详细讲解。
误区四、性能洁癖主义
这个误区貌似比较容易理解,只是有时候,它的存在像一个阳谋,我们知道不对劲,但却无能为力。
一般技术团队,在人多了之后,队伍里面会出现各种各样角色的人,一定会有一些完美主义倾向的,有洁癖症的一些人,他们会掺杂在里面,就会导致我们在做事情的时候容易偏离核心目的。
当然,说到这里,有些读者可能会误解我的意思。会理解为“做性能要适可而止”。但,这不是我想表达的!
做性能,我是倾向于能尽可能的做到现有条件下的极致化。只有极致化的性能才能在竞争中脱颖而出,这个非常关键的,如果我们做不到,往往是资源不够,或者能力不够,而不是决心不够,这个不是什么误区。我要讲的误区,是:“我们往往因为追求常规的性能参数,而丧失更重要的体验级性能” 这才是很多人,难以跳脱出来的误区。
继续举一个例子:大家都在传微信诞生之初,腾讯内部有三个团队都在做微信,最后是张小龙的团队胜出。这个故事不是完全真实,但是确实也是有故事的原型的。我就是当时其中一个团队的技术负责人,也确实有在和张小龙的团队竞争(当然,龙哥现在已经是我的老板了)。我们当时的产品叫做Q信,用Q信来发IM消息,语音消息,图片消息。过程中,要解决一个问题“移动端信号不如有线网的稳定的情况下,如何做到像系统短信一样极高的发送成功率?”那时候,3G时代还在巅峰,4G尚未完全普及,一部分用户还依然在使用网络极差的2G。基于当时的条件下,我们对信号弱,发送失败的情况设计了大量的重试策略,动态化的重试步长,网络探测策略,等等各种复杂规则… …
但是,我们发现,无论怎么做,发送消息失败的概率,以及发送成功的速度,都还是明显弱于微信。我们始终无法正确预测用户什么时候突然进入电梯没有信号了,什么时候又出了电梯,什么时候又进入隧道没有信号了… … 而微信却仿佛能够预测未来一样,总是在用户走出电梯的一瞬间,把消息发送成功。
我们的问题出在哪?
我在反复琢磨了很久并对微信抓包分析之后,才后知后觉。其实一切都很简单,是我们自己错误的性能追求框死了自己。因为我们做了多年的移动端App,对移动端App省电的经验深入骨髓,这样的经验前提下,我们所有的重试策略都会制定时间间隔,重试次数,我们像洁癖症患者一样,不允许任何无畏的耗电。压根不会跨出省电的大前提去设计技术方案。而微信的做法,简单粗暴,在消息发送不成功的时候,快速的多次不断的重试。当然可以在用户打开电梯门,网络恢复的一瞬间,马上发送消息成功!我们犯了一个致命的错误,就是我们并没有去计算我们通过这套复杂的省电规则,到底节省了多少电?节省的这点有限的电量(后来证明,由于异端场景的概率问题,节省的电量极少),能否比得上一个发消息速度极快且极其稳定不惧网络波动的软件,带来用户的信心的价值? 一款产品的成功,掺杂着无数条类似这样能勘破常规误区,能直命靶心的思维尖刀!而在当时欠缺这套能力的Q信,显然差距还比较明显。
再重复一遍,我当时犯的错误是:“我们往往因为追求常规的性能参数,而丧失更重要的体验级性能 ”
总结:
坊间有流传,企业微信以几百人的产研团队完成常规团队需要数千人才能完成的工作。互联网行业的八卦产业也着实无孔不入。但是,我也确实为企业微信的研发团队而骄傲。这算是外界对团队研发效率的肯定吧。
企业微信包含着Win、Mac、Android、iOS、Web、小程序、Server 共七大平台,合计超过6500W行代码。横跨 教育、零售、餐饮、政务、工业、医疗、IT 等等诸多行业的垂直功能。这已经是一套超大型的综合型软件系统了。 其中的OA系统、HR系统、日程系统、协作系统、邮件系统、客服系统、CRM系统 … … 这类大体量的独立的,专业型的功能就有近百个之多,其中的相当一部分,单独拎一个出来,就足够养活一整家普通的IT公司了。例如hr系统,voip通话系统,对我们来说也就是10人左右的研发FT就能快速完成的系统,而某些友商产品可能需要数百人的长时间协作才能完成迭代。这其实有太多效率型的影响因素,从管理到技术再到人才,有非常多的经验值得分享。如果这篇文章有足够多的人感兴趣,我会再继续分享更多更深的知识。
当然,写这篇文章,不是想说我们已经做得有多好,相反,企业微信的研发上也还有很多问题需要去解决,有需要补课的地方还很多,以一敌十的背后也是有诸多牺牲的。只是,我们相信目前阶段下,是抓对了一些重点。因此,我想,把阶段性有效的知识先记录下来,并不断打磨才是要务。企业微信在后续的阶段,还有很多真正的更难的挑战。当然,我们也无惧挑战,去做到一些更NB的事情,人生才更有意义,不是么?