程序员如何看软件管理?从写代码的程序员到做管理的程序员,作者从程序员的视角讲述了软件开发实践中沟通和流程的理解和第一手体验。作者认为,灵活,简单,直接,清楚是有效(effective)且高效(efficient)的沟通和流程的不二法门。
从 2009 年公司成立算下来,已有八九年的光景了,虽然时间不算很短了,但总体上公司还是以起步的模式运营。我加入公司转眼间也过了五个年头,从写程序的程序员开始,逐步过渡到了现在的俗称所谓的“管理”岗位。严格地讲,公司对我的职责范围并没有清楚的界定。
根据我的经验,在起步公司做事情,职责范围基本上是自己测试出来的。一件事情做完了,顺风顺水,上下欢喜,虽名份所关,亦当仁不让;另一件事情忙(盲)着去做了,吃力不讨好,天怒人怨,虽侥幸得成,亦下不为例。
我的这个角色有一点儿尴尬,甚至没有一个明确的名称,所以,我戏称这个不知道名字的角色是“不是程序员的程序员”。原因在于,虽然没有太多机会生产加入到产品中的代码了,但是在工作中还是在用程序员的脑子来思考和解决大大小小的各种问题。
公司的情况有些特殊,总部位于美国的硅谷。大部分的产品、销售和市场团队都在美国;而所有的工程师团队在北京这边。我的工作内容可用繁和杂两个字来概括:负责产品的发布,保证新版本的内容和质量;作为北京工程师团队和美国产品团队的一个联结点,组织两边的沟通和讨论,包括需求,问题,设计,实现,以及项目的优先级和进度;而在北京工程师团队这边,协调攻关需要跨团队合作的项目;参与讨论产品的新功能的设计、实现和测试,审核相关的文档。另外,凡是和项目及产品相关的,而所有的开发工程师和测试工程师不大会关注的事情,比如管理 git 的开发分支,监管重要分支上的代码提交,甚至于作为替补,帮忙合并和编译代码。救火队长的即成的事实让习惯成自然,虽欲懈怠,奚可焉?!
因此,沟通(communication)是我日常最重要的事情。和不同角色的人们包括开发工程师,测试工程师,支持工程师,架构师,产品经理,市场销售通过交谈、文档 、会议、邮件弄明白和讲清楚生产线两头的故事。
一头是用户的故事,即需求和问题;一头是代码的故事,即设计和实现;中间穿插着项目的优先级和进度。帮助大家了解这些故事,是我对公司的主要价值。在一个忙碌的工作日上午,从 9 点到办公室到 11 点半去吃午餐,我参加了三个会议,仔细阅读了 20+个邮件,大致浏览了 30+个邮件,写了 14 个邮件,我私下开玩笑说这个上午很对得起公司付我的薪水了。
伟大的艺术作品是人世间和自然界的美的反映,这里所说的美并不是我们平常所说的美丽的那种美,而是在 Clive Bell 的著作《Art》中所描述的哲学意义上的终极真实(Ultimate Reality)的那种美,即有意味的形式(Significant Form)。
艺术家从艺术的角度发现并理解了这种美,并把它表达在画布上和音乐里。因此,艺术家的能力一方面表现在对美的发现和理解;另一方面表现在对美的表达。因此,我认为,发现,理解和表达便是艺术创造力的全部。同样地,高质量的软件产品是目标用户的真实意愿在自身中的映射。这种意愿常常是微妙的,模糊的,难以描述的。甚至连用户自己都不真正知道想要的究竟是什么,有时看到产品时,用户才发觉和实际的使用场景南辕北辙。发现和理解用户的真实需求,是产品经理的创造力;将需求表达在程序的设计上和代码的实现里,是程序员兼架构师的创造力;验证代码和需求的契合程度,即代码的正确性,是测试工程师的创造力。
因此,理解,表达和验证是软件创造力的三位一体的组合,而理解是这个组合的基础和前提。不妨拿修改一个 BUG 为例,首要的问题是:有稳定的重现步骤吗?根本原因是什么?解决的办法是什么?是否有其他的解决办法?
知道导致问题的根本原因,代码的修改才不会对其他正确的功能产生副作用,避免质量的倒退(Quality Regression);有稳定的重现步骤,BUG 修改后,才有相应的验证方法。这样,最终才能够有信心把新的版本交付给用户。因此,对一个 BUG 的理解包含在解决它的过程中,即可重现,知道根本原因和解决方法,修改后可验证。
最糟糕的情形莫过于此:BUG 不能清楚的描述,不知道重现的步骤,或者似乎可以重现,也不确定是否和应用场景相同。程序员可以修改一个知道不知道什么(Known Unknown)或知道要知道什么(Known Known)的 BUG,可怎样解决一个不知道不知道什么(Unknown Unknown)的 BUG 呢?仅凭臆测猜着去修改一个似有若无的 BUG,其结果不问可知了。
艺术作品的创作大都是一个人独立完成,所以艺术家是孤僻的,默默的去发现,理解和表达心中那份儿独特的不为人知的美。而大型软件系统的开发却热闹多了,是产品经理、架构师、程序员、测试工程师这些不同角色的人们共同合作的劳动成果,若要把所有参与到软件实践中的人们的创造力(发现,理解和表达)正确地贯彻到最终的产品中,需要有效且高效的沟通。
尊重和信任是良好沟通的开始和第一要义。公司研发的是专业性很强的网络交换机的操作系统软件,在网络工业界,只有经过长时间的经验积累,才有可能成为某个方面的专家。正如没有包治百病的全能医生一样,也很少有这样的全才,对设备软硬件的方方面面的所有细节都了如指掌。
所以,我常常提醒自己,要以谦卑的学习的态度,充分地相信和尊重每个工程师在其所熟悉的领域的专业和技能。事实上,在沟通的过程中,我学到了太多太多的专业知识。老实讲,像我这种只是纸上谈兵的人对有实战经验的网络工程师怀有真诚的敬意。
沟通是双向的,一方面是听的明白,一方面是讲的清楚。而我的主要任务是倾听和提问,目的是理解。长期的作为程序员的计算思维的训练,我最深刻的体会是程序员之间的对话要用程序员的语言:一方面听要听得出问题的关键和本质,脑子要清醒,不要像《天龙八部》里面的包二先生,深陷于表面的细枝末节而缠夹不清;另一方面问要以具体的用例问具体的问题,具体的用例和具体的问题才能让讨论不断引向深入。
对于不了解的事情,不可能一上手就门儿清,问出专业水准的具体的问题。通过听和问的交互,剥丝抽茧,由浅入深,事情的真相就会逐渐浮出水面。这个过程有点儿象用 google 搜索一个完全不了解的问题的答案,开始时只有一个模糊的概念,连准确的关键词都不知道,只能得到一些相关的中间结果,慢慢地从这些中间结果中得到和问题越来越接近的关键词,最终检索到想要的答案。
讲的清楚靠的不是伶牙俐齿和能说会道,仿佛兮若口悬黄河,滔滔不绝,实际上却离题万里,不知所云。讲的清楚是言必有中,说到点子上,用最简单和最直接的方式传递最准确的信息。一件事情表达不到位,多半是因为了解地不够,想不明白当然就讲不清楚。程序员常常借助于软件的层次结构进行系统地思考和论述,低层的基础设施向上层的功能应用提供接口,当前层隐藏了所有低层的实现细节,给出了更高级别的抽象。
有的工程师工作在软件的更低层,比如开发驱动代码的系统工程师;有的工程师工作在软件的较高层,比如测试工程师的工作基于最高级别的抽象层次,即暴露给用户的接口如 CLI(Command Line Interface)或 GUI(Graphic User Interface)。
在我看来,无论是开发工程师还是测试工程师都是工作在不同抽象层次上的程序员,应有共同的语言和思维方式。眉毛胡子一把抓必然导致混淆,思考的方向有效地聚焦在特定功能的特定的软件层次上才容易把问题想明白讲清楚。关注的抽象层次或高(浅)或低(深),功能的范围或大(宽)或小(窄),重要的是厘清针对该功能的该层次的相关的接口的细节,去除似是而非的模糊猜想,有啥问题不能搞懂呢?!看问题看得深,看得准,看得透,功夫常在诗外,日常少一些蹭热度,少一些刷存在感,多一些专研业务,胸中有点儿墨,庶几可侍矣!
无论说还是问都必须建立在事实即数据和逻辑的基础上,不能以虚拟的事实和臆测的逻辑主导讨论的方向,以新的混淆堆叠到老的混淆之上,在极度的挫败与沮丧的气氛中消斫着彼此的信任。
讨论一旦陷入这种痴人呓语的梦境,再继续下去,不过是浪费时间。这种情形下,多说无益,不如去做。研究代码,查阅资料,收集新的数据,然后,再来决定何去何从。毕竟都是程序员,最好一竿子插到底,拿出代码来看,那才是熟悉的味道。借助于数学语言,可以减少许多表达上的歧义。比如,使用二维以至于多维的矩阵表呈现不同类型多种情况的组合,往往达到事半功倍的效果。
建设性的讨论和沟通的焦点常常集中地放在具体的问题、具体的案例和具体的需求上,大家保持在同一个频道,彼此的启发和知识的互补有助于理解事物的本质。尽量避免天马行空般的哲学争辩,比如,事实还没有完全澄清,便迅速的转向与讨论的对象毫不相干的抽象的流程和方法论,弄了半天,还不知道正题是什么。
“坐议立谈,无人能及,随机应变,百无一能。”那些雍容华贵的清谈,看似高雅,其实不过是穷嚼蛆的无稽之谈,除了误国然而并没有什么卵用,吾深恨之。
在任何情况下,都必须讲真实的故事。比如在发布产品的新版本时,哪些已知的问题尚未解决,哪些测试的案例没有覆盖,使用上有哪些限制,都必须有一说一地在文档(如 Release Notes)中一一指明。有基于此才可能有效地管理用户对发布版本的期望。面临用户紧急需求的时间压力时,不能以牺牲产品的质量来追求效率,更不能草率地答应不切实际的时间表,尽管过度承诺(over commit)时说 OK 的那一刻大家都很兴奋,上下“充满了快活的空气”。当逾期不能交付或由于赶时间交付了质量糟糕的版本时,一时的快意于用户造成了永久的长痛,进退失据之间,又何以挽回与用户双输的残局呢?!
事无巨细,尤其是工作中的那些琐碎的杂务(miscellaneous),唯有耐烦些,以勤谨自勉。为此,我大概是办公室走路最多的人。多数工程师只关注自己负责的领域,个人自扫门前雪。其实也没有什么不好,专业的人做专业的事儿,这样更有利于专注于一点并做到极致。
如下图所示,每个人的工作相互之间不可避免地会有少许重叠的交集,与此同时,也不可避免地会留下一些无人理会的空白。这些空白多半是些细枝末节的“脏活儿”,看似无关紧要,然而,细节常常决定一切,发布新版本时,忘记更新版本号就可能造成极大的困扰。因此,总要有人多操一份心,来填补这些空白的部分。
总而言之,一方面要小心谨慎,有责任心,临事以惧;另一方面,更重要的是,要有能力,有办法,好谋而成。尽量用技术的手段保证不出差错,可以由程序完成的任务绝不用人工来做。对任何一件事情,程序员的方法是把它看做开发一项新的功能,事先准备一个类似于测试计划的检查列表(checklist);事后一一对照检查,测试验证完毕,哪里还有意外发生?!
多操一些大家都不操的心,当然是极好的事儿。需要注意的是,千万不要讨人嫌,乱操别人家的闲心。一定要耐得住寂寞,知道克制。成功不必在我,任何一个进展顺利的项目,最好是做一个观棋不语的真君子,只要知趣地在旁边默默地看着就好。需要帮助,人家自然会过来找你。大概人性使然,挥斥方遒,指点江山,是多少人的梦想?!谈笑间神州大定,权力带来的快感达到了高潮,爽之极矣,谁不想?据称特朗普曾半当真地半开玩笑地打起了阅兵的主意,莫非他想在山呼海啸般的“首长好”中过把总统瘾?美国的总统毕竟“配不上”阅兵的礼遇,结果在山呼海啸般的骂声中,未曾出师便黯然收兵了。聪明的程序员总是知道什么时候做什么事儿,何须别人瞎指挥?不懂装懂,轻率地指点别人的江山,常常自取其辱而于事无补。
流程是一个常常引起争论的话题。同样的情形,事情搞砸了,或归罪于糟糕的流程束缚了大家的手脚,这是大公司的通病;或归罪于没有流程或只有形同虚设的流程,这是小公司的鄙陋。
我认为,《创新者的窘境》对流程的概念做了最好的诠释,即有效的流程是可复制的成功。流程是可变的,而不是僵化的;流程是灵活的,而不是教条的。我们把在软件开发实践中那些行之有效的做法,固定下来,即是流程。比如开始一个新的重要的项目,我们常常由对项目最懂的工程师领衔,临时组织一个跨开发与测试的动态小组(Dynamic Team),根据项目需要,随时加入新的成员,而完成任务的成员及时退出,项目做完后,小组全部解散。正是这种临时拼凑的貌似杂牌军的动态开发小组迸发出了无与伦比的战斗力和创造力,常常高效快速地完成不可能的艰难任务。
我们的团队常常同时有好几个这样的动态小组工作在不同的项目上。这完全是一个不具文的流程,有的同事在完成任务退出时甚至不知道自己被拉进了一个动态小组。
流程是用来解决问题而不是制造问题,我的意思是说,并非所有的开发实践都可以套用流程,为了流程而流程,等于自觉地向僵化和教条的鬼蜮伸出了橄榄枝。
记得当年在 IBM 时,我所在的部门照本宣科地模仿所谓的敏捷开发(Aigile Software Development )流程。每天早上,所有的开发和测试小组开始工作前,都要单独聚在一起开一个长至半个小时的例会(SCRUM meeting),检查一下当前的状态,并协调下一步的任务。听起来蛮不错,问题是在我们已有的流程中,每天每周已经有很多类似的会议在不停地同步项目的状态了,工程师们有无数的机会向大大小小的经理们不断地报告自己做了什么,正在做什么,还有哪些没做。
在 IBM 的组织架构里,有管人的人事经理(People Mamager),有管事的项目经理(Project Manager),若没有那么多的会议,这些经理们充沛的精力又往哪里释放呢?印象中 IBM 最吃紧的资源就是会议室。于是,工程师们不得不再把一天中最美好的时光献给无聊的会议。一日之计在于晨,如果大家在头脑最好使的时候思考一下当天要解决的问题,不是更有意义吗?所以,任何流程在执行的过程中,必须保持足够的灵活性。例如,我们要求提交到主干分支的代码必须经过审查和测试。而对于简单地修改,比如只是更改一个字符串,审查和测试就是多此一举,这种情况下,只要言语一声,允许直接把代码合并到主干分支。
事事讲流程,事事走流程,架屋叠床,常常是向官僚主义发出了邀请函。《后汉书》讲到一个很精彩的故事,值得像我们这样的初创公司借鉴。马援的同乡好友公孙述称帝于蜀,马援前往投奔,以为见到公孙述后,“既至当握手欢如平生”。没想到,公孙述并不急于和马援接谈天下大势,却摆起了的帝王的臭排场。以盛大的仪式接见他,让人肉麻的繁文缛节一一表演之后,“欲授援以封侯大将军印”。可是马援对公孙述这个沐猴而冠的猪脑壳的底细看得穿而又穿,“如偶人形,妄自尊大,井底蛙尔”。因而辞归,专意于东方的刘秀。相比之下,马援一到,刘秀马上引见于宣德殿,简易若是。促膝长谈,“自夕达旦,开心见诚,无所隐伏,阔达多大节”。在那个“非独君择臣,臣亦择君”的乱世,马援追随光武,成就了大功。有志于天下者,矢石交攻之际,千枪万刃之中,匹马纵横,岂有闲心汲汲于缛节耶!
初创公司的处境本就艰辛,程序是一行代码一行代码写出来的,质量是一个用例一个用例测出来的。撸起袖子把好的产品干出来,或许能够勉强保持一线生机的希望。说到底,这一切取决于工程师的素质。优秀的工程师一将难求,拿一些不合时宜的流程约束他,羁縻他,限制他,耐烦他,折腾他,非所以谋生存与发展而重人才与技术也。
见怪不怪,有些喜欢生活在安乐窝(comfort zone)中的平庸的工程师仿佛得了流程病。言必称流程,拿流程当作不思进取的挡箭牌。事情弄坏了,流程变成了推诿搪塞的口实。完全不知道责任是什么,油瓶倒了都不会去扶,为什么要扶呢?流程里面并没有规定我扶啊。凡事都要听流程,何必要到办公室上班呢?被送到幼儿园按照老师的指令做个乖宝宝不是更好吗?
作者简介
贾彦民,目前就职于 PICA8。本科与研究生就读于重庆大学,2007 年获中国科学院软件研究所计算机软件与理论博士学位。爱读书,喜欢爬山与摄影(历史、文学、数学)。
评论 2 条评论