入职 ThoughtWorks 后,公司邮箱曾收到一篇内部博客大赛的文章《真正的敏捷工作流 —— GitHub flow》,我心想“我一个 GitHub 公民应该会很适应 TW 吧”?
果然…… 不要立 flag……
敏捷不是什么
大多数人对敏捷开发的理解主要停留在 ——
敏捷开发周期短
瀑布开发周期长
而我觉得,更本质的区别在于 ——
敏捷是灵活的,拥抱变化
瀑布是死板的,宁可一无所成,也绝不“犯错”
但我在 TW 前两个项目的工作中发现,一些小伙伴把敏捷实践奉为金科玉律,不容改变……
陷入技术争论
CORS 重不重要?
来 TW 的第一个项目是个内部中台项目,虽然迭代 1 的需求很简单,但创始人们一开始就志在推广到公司各团队,甚至独立对外出售或开源,前后端分离的架构迟早要面对跨域问题。后端从一开始就开启 HTTP CORS 会极大地方便前端开发,各大后端框架也早就有成熟的中间件来一键化处理,比如 Node.JS 的 Koa 框架 ——
- 安装中间件
npm install @koa/cors
- 启用中间件
import Koa from 'koa';
import CORS from '@koa/cors';
new Koa().use(CORS());
一分钟搞定!即便 Java、Spring 写法繁琐一点,一刻钟够不够?
但我和同为新入职员工的 M 君一同向 Java 后端主程建议此事,他却以多种理由拒绝 ——
- 前端 webpack 自己先代理一下(之前代理出了一些罕见 bug,否则我们不会提出早开跨域)
- CORS 可能引起 CSRF 等安全问题(两者根本风马牛不相及,不懂的自己 Google)
- CORS 优先级不高,应该先抓紧做功能
- 敏捷提倡代码集体所有制,若这个点对你真的很重要,我们没时间但你有时间,你可以直接去改(若本项目是 Node.JS 后端,我一人 JavaScript 前后端一把梭,还真不用麻烦你)
结果就这么简单一事儿,用各种理由和我俩争执一上午,代码都没写就吃午饭了…… 说好的“着急做卡”呢?
【八卦】第二天 M 君就以“个人身体原因”为由退出项目组,直到他离职前才私下告诉我“CORS 这么常识的事儿都如此争执,后面坑少不了”……
原生标准好不好?
随后,令我和 M 君更加意外的是,一起加入第一个正式项目后,遇到了更多没必要的争执……
需求 | 我们的方案 | 领导的要求 | 领导的评价 | 我们的看法 |
---|---|---|---|---|
全局异常捕获(后置拦截) | unhandledreject 事件(后置拦截) |
Axios 拦截器(前置拦截) | “你们怎么把代码改成这个鬼样子” | 对合适但不常见的用法有偏见 |
分行列展示几项数据 | <table /> (符合语义化规范,每列自动对齐) |
<div /> + flex 模拟表格列对齐 |
“table 太老了,我们的用户也没有盲人” | 看重“时髦”甚于无障碍规范 |
文字罗列多个名词 | Intl.ListFormat 依数量自适应中文标点、连词 |
array.join('、') |
“你这个我看不懂,我们没那么先进” | 对书面文书写规范不重视 |
处理 HTTP 请求 | async + await 解决冗长的“回调地狱” |
Redux Saga 生成器 + 自定义回调 | “Saga 唯一的缺点就是‘样板代码’多” | “重复代码多”违背编程消除重复的本质 |
一个 Web 国际标准通常历经三步走才发布 ——
- 一线开发者多年实践总结出标准提案
- 各大浏览器厂商尝试实现,提出改进意见
- W3C 标准委员会综合全球其它会员厂商意见
上述业界领袖们多年争执后推出的正式标准,没有理由再在团队内部争执“该不该用”。我写这块代码我先用了新标准,你写那块暂时没用,都无可厚非,不影响大局。
Code review 本是交流技术的契机,不是用来争执“看不看得顺眼”的。
开卡、关卡必须 BA、QA、UX、Dev 全到齐
多数故事卡的 UI 设计并无不清楚的细节,项目设计师又经常没时间,如不灵活变通,卡一直开不了或关不上,让 Dev 一直被阻塞,拖累了项目进度。
而当 Dev 想先尝试写一下新卡的代码,却被告知“必须先开卡,否则做了后面 BA 改需求就要返工”,但敏捷实践不就要求“较大需求变更本迭代不做,要放到下个迭代的新卡”吗?若真到开卡时大量返工,那是 BA 的错误,与 Dev 无关。
长此以往,对于 Dev 个人
主观上不能尽其所能地写代码,消磨工作积极性;客观上白白增加了其做卡的时长,对其本人评价不利。
技术会议一言堂
M 君离职前提议项目组前端要统一设计规范,后端主程便召集大家开会讨论,他提议全面封装出一套项目乃至公司的组件库,如 ——
<tw-button>
# shadow-root
<vant-button />
</tw-button>
我则补充道:
过于简单的组件不需再封装一层,直接用现有组件库的即可,否则对开发、运行都增加负担。
但双方争执不下,于是民主投票,其他人都赞同后端主程。
几日后正式开发,
S 君突然说:“我们还是每个组件都再封装一层吗?”
一个附和道:“没必要了吧?”
另一个也点头默许……
对于前文中项目伊始我和 M 君提出的“Saga 样板代码多”问题,S 君后来接触那一块代码时也私下向领导提出同样的疑问。
如此看来,我和 M 君有时并不是看起来“不好合作”,只是
多数人在众人和领导面前 —— 不敢讲真话!
Code review? Code rejected!
每天下午的代码回顾会的一般步骤是
- 该项目的前后端各自预定地点,集体开会
- 每人照着 Git 变更记录,轮流讲解自己一天所写代码的来龙去脉
- 其他人可随时提出意见,经探讨达成一致修改方案后记录在案
- 检查前一天的修改方案是否实施
但这个民主的议程,实际运行得似乎并不太民主 ——
- 组长的代码 组员有异议的,若组长不赞同,有时就一笔带过、不予记录
- 组员的代码 组长有异议的,即使组长没能有理有据地说服组员,组长也会记录在案
- 组长对组员一些变量/函数命名等有异议,组员问组长和大家,无人说得出更好的建议,但组长依然要求该组员修改
- 对于上述争议问题,组员事后没有修改,便被定性为“不重视 code review”
可话说回来,既然敏捷开发是代码集体所有制,相持不下之际,谁有异议谁去改就好了,追着组员去改一点都不敏捷……
沟多通少
敏捷重视沟通与反馈,但实践起来也有不尽如人意的地方 ——
问题 | 建议 |
---|---|
凡事都要开会商量 | 能用简洁代码、国际标准解决的就不开会 |
多人多次反复拉通上下文 | 简洁文档、自动化办公工具 |
大小会议经常严重超时 | 有人开始注意力不集中了说明要精简了 |
在入职不久后的“反馈文化”培训会上,一位人事小姐姐说:“看似很大的沟通成本,TW 认为这种民主的过程是值得的。”
但社会上大有人在的“保守派”就是一直揪着民主的效率问题为独裁统治辩护、站台的!民主人士必须用更好的方法论、更新的技术手段去解决 ——
太长不看,太久不听,太繁不做……
但凡有人对上述繁琐、低效的沟通表现出一丝不悦,可能就会被同僚视为 —— 态度不好,难以融入团队!
其实不限于交朋友、谈恋爱,人与人的沟通都可在短短几句话中判断“能否懂得起”。虽说所有问题在充足的时间内都可解决,但与其“你说东,我说西”迟迟不能共识,不如
先尝试做起来,用事实说话会更清楚、更高效~
用 Linux 和 Git 之父 Linus Torvalds 的名言就是 ——
Talk is cheap, show me the code!
俗话也说得好 ——
懂得起的人不用解释,懂不起的不必解释~
不敏捷的感受
如果每个员工都以“按点上下班,卖身领工资”的心态去工作,只要不加班,敏不敏捷、高不高效“与我何干”?才不着急上火呢!悠哉悠哉不好吗?
但凡希望在日复一日的“搬砖”之余做些更有意义的事的人,多半焦躁不堪、疲惫不已。写过代码的都知道,状态差时就是在“写 bug”……
于是,在第一个正式项目的迭代 1 结束时,M 君再次主动离开,并且是彻底的 —— 离职……
他走前的一句话我一时不解其意 ——
我之前创业时虽然练就了善于沟通的能力,但我现在很讨厌沟通……
那时前文所述的种种才经历了不到一半,当全部经历后,我才明白 ——
讨厌的不是沟通,而是不必要的低效沟通
在 M 君离职的同时,我和上司有次长谈,其间我提了个问题 ——
ThoughtWorks 有没有可能至少在某个局部,存在一定程度的表面和谐?
她坚定地给了我否定的答案……