👉导读
编程达人们在代码的舒适区里沉浸久了,会以为除了代码其他都不重要,事实上代码之外的事情,占据我们很大一部分时间,却又容易被忽略,因而高效的沟通协作、独立的思考精神也变得难能可贵。本文是《如何成为一名靠谱的程序员》的下篇,看完之后,你可能会对怎么开会沟通、怎么辩论 PK、怎么“置身事内”地参与项目规划等等有一些新的灵感。
👉目录
1 沟通协作
1.1 收到请回复
1.2 外部依赖的处理
1.3 应对紧急故障
1.4 如何组织多人会议
1.5 如何处理大量的沟通消息
1.6 避免低效率的追问式沟通
1.7 群聊的基本常识
1.8 在对抗中产出最佳决策
1.9 基于事实的讨论
2 独立思考
2.1 权利与责任
2.2 批判性思考
2.3 系统性思考
3 推荐阅读
01
沟通协作
沟通占据我们完成目标的大部分时间,沟通需求、反馈进度、总结进展等等。下面介绍一些常见场景的处理经验。
1.1 收到请回复
收到请回复,这是一个关乎个人品牌建设的大事。收到消息及时回复是职场人的共识,如果你收到消息不回复,容易给对方造成误解,一旦你养成习惯,也容易在与人沟通上出现理解偏差。企业微信有已读功能,当你已读却不回复消息时,容易给人造成无视、忽略的误解。你可以关掉这个功能,但读消息必回复的习惯建议养成并保持,也建议开启这个功能,并塑造及时回复的形象。
下面举两个对共识无认知,造成事故的负面案例:
案例1:同事 A 习惯性的不回复,他把沟通理解为单方向的消息通报,不仅自己这么做,且也认为别人可以这么做的,某次他在群里通知:“A DCache(注:一种存储服务) 要更换到 B DCache,这几个 IR(注:搜索召回平台) 的策略需要对应更改”。群里没有人回应他,而他也不觉得有问题,两个月后,线上业务还在访问 A DCache,而它已经下线,导致线上事故。他通知消息的群是一个小群,这几个 IR 策略的负责人都不在群里,群里的人都以为是其他人要负责跟进的,所以没有在群里响应,而同事 A 自己理解为:消息没有得到回复是正常的,我已经通知到位。这就是忽略沟通共识造成的事故,A 同事的沟通做法,也是一种推卸责任式通知:不管你们有没有收到,反正我是通知了,这是很不靠谱的行为。
案例2:同事 B 也有习惯性不回复的习惯,特别是在群聊中,并且认为别人也可以这么做。某次五一长假,他在群里通知五一值班安排,仅把消息贴到群里,并 @ 了多位负责人,但没有确认大家是否都回复,仅是看企业微信的“已读”,看到大家都已读,就认为大家都通知到了。后续某一天轮到同事 C 值班时,他没有做值班,导致线上告警没有人处理,造成事故。事后复盘时,同事 C 反馈没有收到通知,此时同事 B 无话可说,因为同事 C 确实没有回应确认他已经收到消息,同事 B 要负值班安排不到位导致事故的责任。
1.2 外部依赖的处理
当你依赖外部同事帮你完成某个功能、或者你负责一个大项目的某一块时,你需要了解项目的全貌,需要主驱动去跟对方沟通、跟进。
有几个沟通的原则:
1. 想清楚,沟通之前先想清楚你的诉求,思考是否全面,避免沟通过程浪费对方时间;
2. 礼貌沟通,譬如:
a. 说话之前先称呼对方,然后再描述要求,表达要有条理有逻辑;
b. 如果是远程沟通,要及时回应对方的信息;沟通效率: 当面沟通 > 电话沟通 > IM 沟通 > 邮件沟通;
3. 时间节点,需要对方给出完成时间承诺;
4. 签字画押,确保大家意见统一之后,通过邮件或者讨论群将讨论结果同步;
5. 进度跟进,协议达成之后,接下来就是不定期地跟对方沟通,确保进展顺利,或者是将不顺利的影响面降到最低;
6. 上升反馈,当事情无法按承诺执行,并且跟你对接的同事也无法很好地处理时(沟通不顺、能力不济、信息不足...等等多个方面原因),需要跟双方的上级做反馈。上升反馈可能会给对接同事造成很大的压力,这可能会影响到与该同事的下一次顺畅沟通,所以上升反馈非必要不使用;
一些常识:
当你找对方要时间节点时,可能会遇到:“还不知道,需要评估”、“事情太多,不好说”等等类似的无法给出时间点的情况。怎么办呢?
a. 一般人的做法:每天问一次,类似编程里的while死循环轮询,低效且让人烦躁。
b. 高效人士做法:让对方给出来什么时间点可以给出事情完成的时间点,类似编程里的事件通知,高效且有条理。
2. 外部依赖优先,在处理工作事项时,尽量优先处理有外部依赖的,因为这部分是最不可控的。
3. 最后,很重要的一点:即便你负责的是一个项目里的一小部分,你也需要知道整个项目的计划节奏,这有利于你做出更有全局观的决策。
1.3 应对紧急故障
紧急故障并不少见,如何成熟的处理,也是个人品牌建设的重点。同事在业务群里反馈你负责的某个业务出了故障。
靠谱的反应是这样的:
1. 及时响应。首先,你告知反馈者消息我已经收到:“收到,我们看一下。”
2. 阶段性反馈。如果问题非常严重,你马上通过干预工具临时解决问题,然后再回复:“问题原因还在调查,我们先通过干预工具将问题临时解决,避免对用户造成更大伤害。”
3. 总结反馈。case 解决之后,你再回复:“case 已经解决,case 现象是......,case 原因是......,case 解决情况是......” 。
4. 转出。如果这个 case 你调查之后发现是其他人的问题,你应该把球传给他,并给他提供必要的信息帮助。
一位不靠谱的同事他的表现可能是这样子:
1. 看到反馈不管不顾:他大概没办法成为我们的同事。
2. 看到反馈之后:闷头干活,快速地修复 case,然后再到群里回复:“case 已经解决.....”。 做事无交代,大家都在干着急。
3. 看到反馈之后:马上回复“收到,我们看一下”,然后发现不是自己的问题,私下把问题丢给了另一位同事,导致大家一直不知道事情进展。做事无回音,大家都在干着急。
4. 这位同事及时响应,也阶段性反馈,但是最后总结反馈的时候,没有给反馈者一个合理的预期,譬如:什么时候解决 case?这里解决的是一个 case 还是一类 case?
1.4 如何组织多人会议
1.4.1 常见的错误
在日常工作中,经常见到一些不专业的会议组织者,使得会议难以成行或者效率低下。会议组织者常见的错误包括:
1. 临时起意,并且特别强调是某位领导参加的会议,未经预约的会议容易失败,也会给其他人的工作计划造成干扰
2. 没有日程,会议没有加入到参会者日程,导致参会者时间做了其他安排
3. 没有会议议题,导致参会者无法决策到底需不需要参加,可能会浪费大家时间
4. 只是例行的信息传递,写邮件或者文档即可搞定的
5. 会议修改通知不到位,会议议题、参会者、参会时间等信息的调整没有及时同步修改
6. 没做好参会人挑选和会议控场,导致参会者虽然参会了,但心不在会议上,坐在会议室里写代码或者刷手机
1.4.2 会前
(1)组织者自审
会议组织者首先需要想清楚会议的目的是什么,是否一定要开会才能解决,会议有哪些议题,能否分阶段,哪些人需要参与,是否需要全程参与,参与需要提前准备什么事情,是否可以先做文档评审 等等。明确这些信息之后,发起会议预约,并把会议的关键信息给出。
自审要点:
会议的目的是什么?
会议有哪些议题,分为几个阶段?
哪些人必须全程参与,哪些人只需要部分参与?
参会者需要准备什么?
会议是必须线下还是线上?是否需要预定会议室?
(2)组织者预约会议
组织者通常需要先拉起沟通群,沟通群方便信息的快速同步,然后再做会议预约。预约信息包括:时间、地点、人物、议题、参会者需做的准备。
不同类型的会议,在给参会者传递会议信息上有不同的侧重点,对于知识分享类会议,应该突出“参会者能获得什么”;对于工作协同类会议,应该突出“参会者对项目有重大影响”。特别注意“参会者需做的准备”这一点,如果需要参会者先做文档评审,那么预约的会议时间需要在文档发出后,预留 1~2 天时间。在预约大家的会议时间时,应先参考参会者的日程表,给出几个可选的时间让大家选择,避免询问“大家什么时候有空”,甚至有时候可以先占住大家的日程表空闲时间,然后再询问是否可行。
下面举一个会议预约做得不够好的例子:
会议预约邮件错误示范:
错误的地方:
1. 时间:没有提早发出会议预约;会议有多个主题,没有针对多个主题排时间;本次分享是否真的需要 1 个半小时?
2. 人物:哪些人需要参与?必要参会者混在一长串文本中,不利于参会者快速的了解到;
3. 议题:会议主题的表达没有条理逻辑,一长串的介绍内容混在一起,主题容易分散,不利于只想参加部分主题的参会者,参会者也没办法快速了解到他能获得什么;
4. 重点不突出:本次分享重点在于给大家介绍怎么高效的使用,“反馈、改进”之类的话跟本次分享无关,没必要提。
会议预约邮件修正示范:
注:现在大家习惯用企业微信的日程预约,预约信息可以填写到会议的“描述”中。
(3)提早发出会议材料
建议会议材料需要提早发出,可以填写在会议的描述中,也可以放到群聊的公告中。提早发出材料可以让参会者有时间先做阅读和思考,有利于缩短会议时间,特别是项目需求评审、技术方案评审的文档材料,应该提早发出,并提醒参会者先做文档批阅,可以大幅度提升评审效果和会议效率。
(4)会议调整
会议目的、议题、参与人、材料、时间、地点等任何可能影响到参会者的信息修改,都应该及时修改预约日程,并确保参会者收到信息。
1.4.3 会中
(1)参会人。组织者要确保必要参会人必须出席,同时也避免临时拉人入会。如果会中才发现某个关键环节缺少参会者,应该搁置该项讨论,待下次再约或者小范围约聊。也尽量在会前做好充足准备,避免在会议中才发现缺参与者。
(2)控场。组织需要做好控场,确保会议围绕主题展开,避免偏航、避免陷入某个细节导致浪费集体的会议时间。
(3)记录。组织者需要指定会议记录人,确保达成的结论和待办事项不会遗漏。
错误案例:
在会议中间发现缺少某位必要参会者,于是临时电话他入会。这会打断他的工作安排,很不礼貌,并且他没有提早做准备,可能参会效果不佳。
在多方参与的汇报会议上讨论技术细节、在排期 PK 会议上讨论需求实现细节等等。这些细节只需要少数人参与,应该在线下或者其他小型会议上对齐,避免浪费他人时间。
1.4.4 会后
会议结束后,记录者需要立刻总结并在沟通群中或者邮件发出会议纪要,内容包括:会议达成的结论、待办事项及其负责人等,同时应再次和参会者确认纪要文字内容无错误、无遗漏。
到此会议全流程就结束了,待办事项可能会在后续的会议中继续跟进,或者是线下逐个处理,不管是哪种方式,都需要有人执行、有人检查验收。
1.5 如何处理大量的沟通消息
我们有各种途径去找某位同事,我们也被各种途径触达。当面、电话、邮件、企业微信、微信,企业微信群里还有大量的群聊说着不同的事情。大量的沟通消息,我们既担心处理不及时,又不想写代码被频繁打断,还担心忘记答复,怎么办呢?
首先不要逃避消息轰炸,这是无法回避的,应该正视并接受这种状态,然后设计流程解决问题。下面这套流程供参考:
1.5.1 设定响应的频率
(1)需要立刻响应的:
- 当面,当面找到你,肯定需要立刻响应,但如果当时时间不允许,确认紧急程度后可以另约时间;
- 电话,打电话的一般是紧急情况,需要立刻响应;
- 微信,通常工作事项都在企业微信上沟通,如果微信找你,是紧急情况,需要立刻查看,但如果有些同事组建了沟通日常业务需求的微信群,则建议做通知屏蔽,然后定期查看;
(2)短周期定期检查的通讯工具:
企业微信和微信,定期检查沟通消息,如果可以马上答复处理的则马上处理,否则给对方答复表示消息收到,同时标记为待办。企业微信和微信的待办记录通常是置顶。
(3)每天检查数次的通迅工具:
邮件,邮件通常不是需要高优响应的信息,可以在每天的固定时间点处理,譬如:上午到工位时、下午干活之前、离开公司前。
1.5.2 记录待办事项和处理
如果是企业微信,待办事项可以置顶,如果是其他途径的待办,可以记录到工作日志文档中。前面的《计划与执行》章节建议写个人工作日志,既用来复盘计划与执行,也可以用来记录待办事项,待办事项需要及时处理,避免企业微信置顶过多,全都置顶就相当于没有置顶,建议待办事项做到日清、周清。
1.5.3 邮件分类
虽然大家更喜欢用 IM 做沟通,但每天的各类通知邮件还是有不少,有些需要重点关注,有些则可忽略,建议建邮件过滤规则,将邮件分类,譬如:组织架构调整邮件、表彰邮件、告警邮件、工蜂通知邮件、OA 系统邮件 等等。
1.6 避免低效率的追问式沟通
在协作过程中,我们经常遇到需要咨询别人或者答复别人的情况,不同水平的协作者在这里会表现出不同的特征。
例子 1:
A 向 项目负责人承诺完成某个需求,今天接近 deadline。
● 负责人:明天能不能完成需求?
● A :不能。
● 负责人:遇到什么困难了?还需要多久?
例子 2:
某天在群里聊到业务有异常。
● 负责人:服务有超时监控吗?
● A 回答:有。
● 负责人继续追问:超时了吗?
例子 3:
某天在群里聊到业务有异常。
● 负责人:服务有超时监控吗?
● A 回答:没有。
● 负责人继续追问:能加上吗?
分析:
- 例子 1 中,项目负责人的沟通诉求是:A 按期完成,如果不能按期完成,请给出一个合理的理由以及新的排期。
- 例子 2 和 例子 3 中:负责人的沟通诉求是:有超时监控,那就给出数据;没有超时监控,那应该给出能加上的监控时间。
- 上述 3 个例子,A 在首次回答时,就应该把对方的核心述求回应出来,让对方不需要在这个问题上再次提问。如果 A 不了解对方的核心诉求时,也可以在回答的同时做反问。
总结:
沟通过程中,需要多想一步:对方的诉求是什么,避免在一个简单问题上陷入不断追问的低效率沟通中,当无法满足对方诉求时,也应该给对方一个预期。
1.7 群聊的基本常识
大家经常会在群里沟通,我介绍一些沟通的常识。
1.7.1 大群和小群
群聊的一个重要用途是信息广播,当有多个小群时,容易导致信息广播遗漏,譬如:作为“数据中介”的团队,一方面要对接合作方的数据源,一方面要分发给下游的数据应用团队,如果要拉一个上下游信息同步的沟通群,应该把多方都拉到一起,确保有一个可以全流程在线沟通的群聊环境。而当要单独聊一些技术细节时,则建议在开发小群中沟通,避免对其他不需要关注的人造成打扰。
1.7.2 群聊是集体沟通
很多人可能会说,谁不知道群聊是集体沟通呢?而据我观察,很多人并没有理解什么叫做“集体沟通”。举个例子:小 A 在群里问小 B 一个问题,小 B 觉得这个问题不适合在群里沟通,于是私聊小 A 解答,这时候群聊记录就停留在小 A 提问题,而没有人解答。按照“群聊是集体沟通”这个定义,小 B 应该在群聊中做出回应,譬如答复:“已私聊解决”。
群聊不只是沟通双方或者多方,还有大量的相关人在,为提高效率和避免误解,应当确保群聊信息是完整的。潜在的误解:“小 B 这人做事不靠谱,有人提问也不答复”、“这个问题我也关注,咋没有人答复,我再问一次”、“这个事情不重要,群里问题都没人解答”....
1.7.3 必要的总结陈述
你是否有遇到这种情况:某个群里聊了几十上百条聊天记录,他们好像达成了某个结论,或者暴露了某个问题,你想了解到底是什么,需要看几百条聊天记录。
突然被拉入到某个群里,附带了几十条聊天记录,拉你的人还说,“@xxx,看看这个问题”。你心里想,“卧槽,你就不能总结一下?”。这是不礼貌的行为,我说的是拉你进群的人。
对于沟通许久的群聊,建议做总结陈述,一方面确保沟通者意见一致,另一方面也让阅读者可以减少爬楼,提升效率。
1.7.4 有针对性的 @ 人
你有没有发现,当你 @all 的时候没有人理你,当你 @某个人 的时候,他才会答复你? 在大多数需要集体承担的场景都是如此,小时候上课时,老师提问,回答的志愿者总是稀缺甚至没有,点名是高效获得回答的解决办法。当你在群聊里想要高效获得答案时,@某个责任人 是最有效的,避免 @all。
1.8 在对抗中产出最佳决策
每个都在捍卫自己的目标,项目管理者要赶在 deadline 之前完成项目,开发者要确保做出高质量产品。
反面案例:
A:这个功能下周一必须上线
(B 知道这个功能至少要到下周五才能做完,但他还是答应了)
B:好的,我试试
下周一到了,功能带着很多 bug 上线,最终不得不回滚,给产品口碑造成伤害。这个案例合理的做法是,B 要尽力去争取更多的开发时间或者是功能做减法,而非简单地答应或者说“不”。
如果 B 轻易地答应,那么可能之前 B 的工时预估过于宽松,这是不靠谱的表现。但更可能的情况是 B 做出了错误的承诺,导致功能无法符合预期地上线。如果 B 粗暴地拒绝,又可能给人一种“不善协作”的标签,因此最合理的做法应该是结合工作计划(注:靠谱的程序员必须做工作计划),有理有据地给出拒绝理由,最终产品经理和工程师达成对产品最有力的协议,可能是功能做减法,也可能是另外约定一个上线时间。
1.9 基于事实的讨论
避免陷入偏执,辩论应该基于事实。我在做评审、需求沟通的时候,有时候会陷入长时间的讨论,很重要的一个原因是被评论者有了情绪,不是基于事实在做讨论,而是基于情感。
反面案例1:
代码评审人:这个成员变量应该在构造的时候就判断有效性,不应该在每一个成员函数里去判断空,这会有性能浪费。
代码开发者:防御编程,就应该判断空。
开发者不正面回应“性能浪费”这个关键点,转而引用不合适本场景的“原则”做诡辩,合理的讨论应该正面回应对方的论证,而不是回避对方的论证转而讨论其他。
反面案例2:
借用几年前的一个代码评审案例:
案例中的开发者明显有情绪,陷入了偏执。他没有正面回应评委提出的建议,反而去讨论无关紧要的笔误,以及后续进一步去讨论评委行为背后的动机,其实评委的动机很简单,就是为了让代码更好,开发者却认为评委在攻击他。我和你讲道理,你和我讲情感,没法聊。
反面案例3:
需求评审人:你要开发的这个需求,是真实的用户需求吗?有没有对用户的日志做分析?
需求提出者:还没有做分析,我作为一名资深的用户,有深刻的体会,这个需求做了一定有很大价值。
需求提出者在感性的表达需求的合理性,感性确实容易打动人心,但我们更希望看到基于数据的理性讨论,即便他说的是对的,也应该想办法在数字上能证明自己是对的。感情可以骗人,但数字不会,基于理性和数字,可以降低风险。
02
独立思考
2.1 权利与责任
从你为产品写的第一行代码开始,你便是这个产品的创造者,这是权力也是责任。产品成功或者失败,都有你的一份功劳,靠谱的程序员从来不会让自己“置身事外”。
有时候,我们会看到一些推卸责任式的话语,“这是产品经理 A 要加的挽留用户弹窗”、“我们领导说要用 C++ 来写业务代码”...... 就好像在说:“这都是他们做的错误决策,和我没关系”,但你不发声就表示你认可这个方案,不能说都是他们的错误。靠谱的程序员会“置身事内”,他们会积极参与方案的决策讨论,他会表达自己不一样的想法,并在和其他人的辩论中,得到最佳方案。
大多数情况下,我们都有充分讨论的环境,如果充分讨论之后,无法通过逻辑推导达成共识,那么我们可以更完整的说:“我并不认同这个方案,但谁也无法说服谁,最后领导拍板决策,事实证明我的想法更合理。”
如果极端情况下,遇到无法讨论又频繁决策错误的“一言堂”团队,这样的团队不适合靠谱的程序员,应该尽快洞察到这一点并离开。
2.2 批判性思考
作为独立思考的创造者,在评审需求、架构、代码时,都会先自问一句:“它应该是这个样子吗?”,然后去思考它最合理的设计。下面举几个例子。
2.2.1 例子1:告警邮件的设计
在做搜索中台 XSearch 项目早期,我们的告警通过邮件发出(后来修改为企业微信群),当时离线系统开发同事设计了邮件告警,样例如下:
这个邮件告警的标题设计不合理。我们看邮件,首先看到的是标题,点击之后才看到内容。这个告警标题无法让阅读者快速得知是哪个业务有告警,我们服务了上百个业务,不同业务有不同的关注人,每个告警都需要点开之后才能看到是哪个业务,效率太低。修正后样例:
优化后的版本,看标题即可知道是哪个业务出了问题,且标题内容亦不会长到难以阅读。
2.2.2 例子2:监控看板的设计
我们为搜索中台 XSearch 设计了一个看板,可以直接展示历史存量数据,而实时数据则需要跳到 007 监控页面(现在的伽利略监控),我们决定在看板上增加一个跳 007 监控页面的快链。前端开发同事给的第一版样式如下:
操作步骤:
1. 鼠标移动到页面右侧
2. 点击“监控”快链
3. 鼠标移动到页面中间
4. 下拉选择“地区”
5. 鼠标往下移动几厘米
6. 点击 007 监控链接
这一系列操作时间不长,最终也能实现目标,但很繁琐,我们可以做得更简单。
优化后的样式:
优化后的操作步骤:
1. 鼠标移动到页面右侧
2. 点击地区快链
减少了用户多次鼠标点击和移动操作。这不仅仅是体验的优化,更是保持极致追求的态度。可以点击一次鼠标完成的事情,不要点击两次,即便是一秒钟的优化,也是值得的。
2.2.3 例子3:微服务和单体服务的思考
22年底,我们团队接手并重构一套经过多次交接的数据接入和处理系统,之前也在《腾讯云开发者》公众上分享过《微服务回归单体,代码行数减少75%,性能提升1300%》,这次重构最大的一个改造点是从微服务服务改造为单体服务。微服务设计这些年在后台系统架构上得到广泛应用,我们很容易去讲它的合理性,但也自问一句“忘记微服务和单体服务的斗争,我们系统这么设计是合理的吗?”,很快我们就联想到,我们老系统有大量的服务间数据一致性容灾处理,进一步还能想到一个需求拆分到多个服务去实现带来的人力消耗。最后我们判断,微服务带来的好处无法抵消它的代价,前人的设计是错误的,我们需要一个单体服务。
我们的设计也不是一次成型,最初开发同事给的新设计方案是两个服务,又经过一番批评性思考和讨论之后,大家才达成共识,只需要一个服务。
靠谱的程序员会捕捉心灵中稍纵即逝的叛逆,去思考它的本质,去解答它应该是什么样子。另外,还有一点需要注意,有时候:“自由思考比畅所欲言更重要。”——《黑客与画家》
2.3 系统性思考
作为考虑周全的创造者,我们在思考问题时,想到的是这个产品的方方面面,它能做什么、它由哪些组成、它的使用者是谁、它依赖了谁等等,系统性的考虑问题,看到的是一系列的问题点,这一个个“点”组成“面”。下面举几个例子。
2.3.1 例子1:我们给接口调用增加了重试
某同事 A 接手一套老系统,在完成系统串讲后,他在工作计划里列了很多项优化工作:
● 解决企业微信群的业务告警
● 数据处理从 20 分钟优化到 10分钟
● 接入代码规范和安全流水线,解决所有警告
● 接口调用增加失败重试
● ...
从串讲的 TODO 来看,确实需要做这些事情,但是总感觉哪里不对劲。譬如,为什么接口调用要增加失败重试?看起来是为了提高稳定性。那增加重试就能达到这个效果吗?看起来也不是,代码里的异常没有捕获,这也影响稳定性。只看到个别优化点,而无法全面的看待系统,是缺乏系统性思考的体现,这也是直觉这里不太对劲的原因。
系统性思考一般可以借鉴《金字塔原理》,先提出一个目标,然后基于目标思考需要做哪些事项,把事项穷举出来。以“接口调用增加失败重试”为例,这是一个事项,这个事项的目标是“提升稳定性”,因此我们最关键的目标应该定义为:提升稳定性,然后基于提升稳定性穷举出要做的事项,调整如下:
提升系统稳定性,事项拆解如下:
○ 接口调用增加失败重试
○ 代码内增加异常捕获防御
○ 接入 CI 流水线,修复代码规范和代码安全警告
○ ...
上述的例子是从某个事项抽象到目标,然后再从目标穷举事项。有时候有经验的我们也可以直接正向推导,后台系统不外乎:功能、成本、性能、效率、稳定性这些点,把它们映射到自己的系统上做穷举。
2.3.2 例子2:客户需要一匹更快的马
某天我在评审团队同事个人工作计划的时候,发现有一个需求:利用多线程加速数据处理。我很奇怪,这个业务索引量很少,每半小时全量重算一次,每次只需要20分钟,为什么要做加速呢?仔细咨询后才知道,因为有两个反馈:
(1)产品经理反馈,数据处理太慢了,导致他给某游戏配置的同义词、标签等干预不能及时在线上生效;
(2)合作伙伴反馈,数据处理太慢了,导致他配置的某游戏实时字段(一些活动信息)需要 60 分钟才能在线上生效;
总的来说,我们的协作方都在反馈数据处理太慢,导致干预不能及时生效。因此,我们的一线开发同事就去分析为什么慢,最终得到优化思路:多个计算任务之间并行实现加速 50%。于是就制定多线程优化计划。
这是一个典型的“浮于表面”分析需求的案例,和“客户要一匹更快的马”类似,实际上协作方想要的是干预更快生效,而不是数据处理更快,数据处理更快是实现目标的手段之一,但不是完整方案,我们只负责数据处理环节,数据到上线生效还有一系列的上线流程,只优化个别流程并不能很好的达到目标,并且协作方的本质诉求是个别数据的修改能更快生效,而不是他们嘴里说的“数据处理更快”。这个需求,我们应该是基于“怎么让个别数据修改能更快生效”这个本质诉求,去分析全链路所有流程,才能寻找到最佳的解法。
2.3.3 例子3:客户认为离线批量数据传输用 RPC 接口更好
我们团队负责外部数据的接入和处理,并将处理后的数据存放到 COS(云对象存储)上,由使用方拉取。某天新的使用团队建议我们提供 RPC(远程过程调用) 接口,理由是 COS 用起来不方便,而 RPC 接口更灵活。我们负责对接的同事小 A,想了下觉得批量数据用 RPC 提供不方便,于是退而求其次,建议通过 MySQL 提供数据。
客户希望用 RPC,而小 A 评估后发现 RPC 很难实现,所以他建议用 MySQL。看起来好像很合乎技术方案 PK 的常见做法,大家都退一步,选择一个双方都能接受的方案。实际上是这样吗?
客户为什么会认为 COS 不方便,为什么会认为 RPC 接口更适合来传输批量数据?小 A 没有深入了解,便轻率地接受了客户“COS 不方便”的结论,进而去思考满足客户诉求的其他方案,这也是缺乏独立思考、缺乏系统性思考的体现。
我们和客户进一步深入沟通之后,才了解到:
1. 他们团队较少使用 COS,而 RPC 接口用的很多,他们对外提供的检索服务也是采用 RPC 接口实现的;
2. 他们认为 COS 需要做数据完整性校验,相比 RPC 接口工作量较大。
看起来不是 COS 不好,而是业务团队用得不习惯,我们再进一步分析使用 RPC 接口或者 MySQL 存储的不利:
1. 使用 RPC 接口来传递批量数据,需要考虑数据分页,而分页之后进一步需要考虑数据版本,需要做不少容错保护,复杂度较高
2. 使用 MySQL 来传递批量数据,在新老数据版本上也需要做较多工作,要么是数据按版本分表;要么是在一个表里增加一个版本号信息,然后需要处理同时读写出现的资源竞争。总的来说,也有一定的复杂度
相对来说,用 COS 来存储批量数据,复杂度是最低的,最后我们还是继续采用 COS 来做数据传输。
客户提出来的解决方案,未必是最佳方案,我们应该深入的和对方聊聊,他做出这个设计的缘由,而不是对方说要什么就是什么,单方面的信息是有限的,更多的信息汇聚才能产生最合适的方案。
03
推荐阅读
尽管我期望本文可以为读者讲解什么是靠谱的程序员,但每个的人遭遇不尽相同,在成为靠谱程序员的路上,很容易有各种困惑,除了请教导师,还可以阅读一些书籍,下面推荐一些我阅读过觉得不错,且适合所有程序员的书籍:
编程知识:《重构-改善既有代码的设计》
软件工程:《Google 软件工程》、《持续交付2.0》
沟通表达:《金字塔原理》、《一本小小的红色写作书》
时间管理:《高效能人士的七个习惯》、《卓有成效的管理者》
元知识:《程序员修炼之道:通向务实的最高境界》(注:第一版也不错)、《程序员的职业素养》、《黑客与画家》
-End-
原创作者|吴银光