第十章 暗战

一

入职第四个月,王志远遇到了一个大机会。

公司拿下了一个重要客户——一家连锁零售企业,需要在现有系统上做一套"会员积分体系"。这个项目是季度重点,周旋经理亲自盯,做好了整个团队都有奖金。

赵北辰在 Sprint Planning 会上分配任务时,把积分体系的核心模块——"积分规则引擎"——交给了王志远。

"志远,这个模块有一定复杂度,但我觉得你现在可以独立搞定。"赵北辰说。"先出设计文档,我来 Review。"

王志远既兴奋又紧张。这是他入职以来接到的最重要的任务。

他花了三天时间做调研和设计。积分规则引擎的核心需求是:不同的消费场景(线上购物、线下门店、会员日活动等)有不同的积分计算规则,而且规则会经常变化——比如"双十一期间积分翻倍"、"新会员首单三倍积分"。

他设计了一个基于策略模式的规则引擎:每种积分规则是一个策略类,实现统一的 PointRule 接口;规则的配置存在数据库里,可以动态加载和切换,不需要改代码就能调整规则。

他把设计文档写好,发了邮件给赵北辰,抄送了周旋和李想。邮件标题是:

【设计文档】会员积分规则引擎 - 技术方案 v1.0 — 王志远

赵北辰 Review 后提了几条小意见,改完之后设计通过了。

二

接下来的一周,王志远埋头编码。他按照设计文档一步步实现,先写测试再写代码,进展顺利。

周三下午,他去茶水间倒水的时候,听到了一段对话。

是陈锐和周旋在小会议室里说话,门没关严。

"……周总,积分规则引擎这块,我有一些想法。"陈锐的声音。

"哦?说说看。"周旋的声音。

"我觉得可以用规则引擎框架来做,比如 Drools。比自己写策略模式灵活多了,规则可以用 DSL 配置,业务人员都能改,不需要开发介入。我画了一个方案……"

王志远端着杯子站在门外,心里咯噔了一下。

他没有偷听——他只是路过。但他听到的内容让他很不舒服。

陈锐在跟经理单独汇报积分规则引擎的"替代方案",而这个模块是分配给他的。陈锐没有在组内讨论,没有在设计评审上提出,而是私下找经理。

他端着水回到了工位上,心里很乱。

三

第二天的站会上,周旋突然说了一句:"积分规则引擎这块,陈锐提了一个用 Drools 的方案,我觉得挺有意思的。志远,你看看能不能结合一下?"

王志远愣了一下。

陈锐在旁边接话:"我昨天跟周总聊了一下,觉得 Drools 比纯策略模式更灵活。我写了一个简单的 POC,可以给大家看看。"

他打开笔记本电脑,展示了一个用 Drools 实现的积分规则 demo。规则用 DRL 文件配置,确实看起来很灵活——业务人员可以直接修改规则文件,不需要改 Java 代码。

周旋看了连连点头:"不错不错,这个方案好。志远,你觉得呢?"

王志远张了张嘴,想说"我的方案也能做到动态配置",但话到嘴边又咽了回去。他不想在站会上跟陈锐争论——那样显得他在争功。

"我回去看看。"他说。

站会结束后,他回到工位上,心里五味杂陈。

他花了三天做的设计,被陈锐用一个下午的 POC 抢了风头。更让他难受的是,陈锐的方案确实有亮点——Drools 的规则 DSL 确实比他的策略模式更灵活。但陈锐的做法让他很不舒服——不在组内讨论,私下找经理,用"我的方案"来包装一个替代方案。

这不是技术讨论,这是抢功。

四

中午吃饭的时候,林秀秀看出了他的心事。

"怎么了?脸色不太好。"

王志远犹豫了一下,把事情简单说了。他没有说陈锐的名字,只是说"有个同事提了一个替代方案,经理很认可"。

林秀秀听完,想了想说:"你觉得他的方案比你的好吗?"

"……有些地方确实更灵活。但他的做法不对。"

"做法不对是一回事,方案好不好是另一回事。"林秀秀说。"如果他的方案确实有可取之处,你可以吸收好的部分,让你的方案更完善。至于做法的问题……你的实力大家都看在眼里。"

王志远看着她,觉得这个行政部的姑娘有时候比他这个程序员看问题更清楚。

"但我还是很委屈。"他老实说。

"委屈是正常的。"林秀秀笑了笑。"但委屈不能当饭吃。你得想办法保护自己。"

五

下午,王志远去找了赵北辰。

赵北辰听完,沉默了一会儿,然后说:"陈锐这个人,技术不差,但做事的方式有问题。不过这件事,你也有需要反思的地方。"

"我哪里做得不对?"

"你的设计文档发邮件的时候,抄送了我和周旋、李想。但你有没有在组内做过正式的设计评审?"

王志远想了想:"没有。你 Review 完我就开始写代码了。"

"这就是问题。"赵北辰说。"你的设计只有我看过,其他人不知道你的方案细节。陈锐提了一个替代方案,周旋没有对比的基础,自然觉得陈锐的方案'挺有意思'。如果你之前在组内做了设计评审,大家都了解你的方案,陈锐再提替代方案的时候,大家就能做出公正的比较。"

"另外,"赵北辰继续说,"技术人要学会保护自己的成果。邮件确认、文档留痕、版本记录——这些不是多余的,是必要的。你的设计文档有版本号吗?有修改记录吗?"

"有版本号,v1.0。但没有修改记录。"

"加上。每次修改都记录:谁改的、什么时候改的、改了什么。这样将来有争议的时候,版本记录就是证据。"

赵北辰看着他,语气认真了一些:"志远,吃一堑长一智。职场不是学校,不是你做得好就一定有人看到。你得学会让自己的成果摆在明面上——不是显摆,是让大家都知道。"

六

王志远回到工位上,做了几件事。

第一,他在设计文档里加了修改记录表:

版本 日期 修改人 修改内容
v1.0 3/15 王志远 初稿
v1.1 3/16 王志远 根据赵北辰 Review 意见修改

第二,他约了一个组内设计评审会,把自己的方案和陈锐的 Drools 方案放在一起做了一个对比分析:

维度 策略模式方案 Drools 方案
灵活性 中等,新规则需要写 Java 类 高,规则用 DRL 文件配置
学习成本 低,团队都熟悉 高,需要学习 Drools DSL
维护成本 低,纯 Java 代码 中等,DRL 文件调试困难
性能 高,直接 Java 调用 中等,规则引擎有解析开销
依赖 无外部依赖 引入 Drools 框架(~15MB)
适用场景 规则数量有限、变化不频繁 规则数量多、变化频繁

他在对比表下面写了自己的结论:

当前积分规则约 5-8 种,变化频率约每季度一次。策略模式方案足以满足需求,且学习成本和维护成本更低。建议采用策略模式方案,同时预留扩展点——如果将来规则数量超过 20 种或变化频率达到每周一次,再考虑引入 Drools。

第三,他把对比分析发了邮件,抄送全组。

七

设计评审会上,王志远把两个方案都讲了一遍。

他没有贬低陈锐的方案,而是客观地分析了两者的优缺点。他甚至主动说:"陈锐的 Drools 方案在规则灵活性上确实更强,如果将来业务复杂度上升,这是一个值得考虑的方向。"

陈锐坐在角落里,表情有点复杂。他大概没想到王志远会这么大度。

苏薇第一个发言:"我同意志远的分析。当前的业务场景用策略模式就够了,引入 Drools 是过度设计。而且 Drools 的 DRL 文件调试起来很痛苦,我之前在上一家公司用过,踩了不少坑。"

马德华说:"我也觉得策略模式简单,好维护。"

赵北辰总结:"两个方案都有道理,但要根据当前的实际需求来选择。志远的分析很到位——先用简单方案解决当前问题,预留扩展点应对未来变化。这就是 YAGNI 原则——You Aren't Gonna Need It,不要提前实现将来可能用到的功能。"

他看了一眼陈锐:"陈锐的 Drools 调研也有价值,可以作为技术储备。但下次有替代方案,建议先在组内讨论,不要直接找经理。技术决策应该在技术团队内部达成共识。"

陈锐的脸微微红了一下,点了点头,没说话。

周旋在旁边听着,若有所思。

八

评审会结束后,周旋把王志远叫到了办公室。

"志远,你那个对比分析写得不错。"周旋说。"以后重要的技术决策,都按这个标准来——有对比、有数据、有结论。"

"好的,周总。"

"另外,"周旋顿了一下,"积分规则引擎这个模块,还是你来负责。按你的方案来。"

王志远点了点头。

走出办公室的时候,他心里松了一口气。但他知道,这件事没有真正结束——陈锐不会因为一次评审就改变做事的方式。

九

转机来得比他预想的快。

一周后,周旋在周会上让陈锐汇报积分体系的另一个模块——"积分商城"的技术方案。陈锐之前主动请缨要做这个模块,周旋同意了。

陈锐打开 PPT,讲了十分钟。方案看起来很完整——架构图、流程图、技术选型,一应俱全。

周旋听完,问了一个问题:"积分兑换的时候,如果用户的积分余额不足,但同时有一笔积分正在入账(比如刚完成一笔订单),这种并发场景怎么处理?"

陈锐愣了一下:"这个……可以用数据库锁。"

"什么锁?行锁还是表锁?乐观锁还是悲观锁?"

"呃……悲观锁。"

"悲观锁在高并发场景下性能怎么样?如果双十一期间有几万人同时兑换积分呢?"

陈锐的额头开始冒汗:"可以……可以用 Redis 做分布式锁。"

"Redis 锁的过期时间怎么设?如果持有锁的进程崩溃了怎么办?"

陈锐答不上来了。

会议室里安静了几秒。苏薇在旁边冷冷地说了一句:"内部设计文档的版本记录里写得很清楚,这个方案的初始版本是上周三创建的,只有一个版本,没有任何修改记录。也就是说,这个方案没有经过任何 Review 和迭代。"

她的意思很明显——陈锐的方案是赶工出来的,没有经过深入思考。

周旋的脸色不太好看。他没有当众批评陈锐,但说了一句:"方案回去再想想,下周重新评审。技术方案不是 PPT,要经得起追问。"

十

会后,王志远在走廊里遇到了陈锐。

陈锐的表情很难看。他看了王志远一眼,欲言又止,最后什么都没说,转身走了。

王志远看着他的背影,心里没有幸灾乐祸的感觉。他想起自己第一次 Sprint Review 上被陈锐追问线程池配置的场景——那种答不上来的窘迫,他太熟悉了。

他回到工位上,打开邮箱,给陈锐发了一封邮件:

标题:关于积分商城的并发处理方案

陈锐,

关于周总问的并发场景,我之前在做通知中心的时候研究过类似的问题。积分余额的并发控制,可以考虑用"乐观锁 + 重试"的方案——在积分表加一个 version 字段,更新时带上 version 条件,如果更新失败说明有并发冲突,自动重试。这种方案在中等并发场景下性能比悲观锁好很多。

如果并发量特别大(比如双十一),可以考虑用 Redis 做预扣减——先在 Redis 里扣积分,成功后再异步更新数据库。这样数据库的压力会小很多。

这只是我的一些想法,供参考。如果需要讨论,随时找我。

王志远

他发完邮件,犹豫了一下,又抄送给了赵北辰。

赵北辰的话在他脑子里回响:"邮件确认、文档留痕。"

不是为了邀功,是为了留痕。

十一

那天晚上,王志远在笔记本上写下:

Day 120

吃一堑长一智。这一堑吃得值。

职场不是象牙塔,做得好不一定会被看到。邮件确认、文档留痕、设计评审公开做——这些不是多余的,是必要的自我保护。以前觉得"酒香不怕巷子深",现在觉得这话害人不浅。

给陈锐发了那封邮件,承认他的方案里有可取之处。不知道他会怎么想,但我觉得这是对的。技术人之间,应该用技术说话,不是用手段。

格局比技术重要。这话说起来容易,做起来真难。

他合上笔记本,想起林秀秀说的那句话:"你的实力大家都看在眼里。"

他不确定"大家"是不是真的都看在眼里。但他确定,自己的实力在一天天增长。

而实力,是别人抢不走的东西。


:::{admonition} 小胖的笔记 :class: tip

本章知识卡片:职场沟通与文档化习惯

1. 保护技术成果的方法

方法 具体做法 作用
邮件确认 重要决策发邮件,抄送相关人 留下书面记录
文档版本记录 每次修改记录:谁、何时、改了什么 证明原创性和迭代过程
公开评审 设计方案在组内公开评审 提高透明度,减少信息不对称
Git 提交记录 规范的 commit 信息 代码归属可追溯
会议纪要 重要会议后发纪要邮件 确认共识,避免事后扯皮

2. 技术方案对比分析模板

做技术选型时,用表格对比多个方案:

维度 方案 A 方案 B
功能满足度
学习成本
维护成本
性能
外部依赖
社区活跃度
团队熟悉度
适用场景

结论:基于以上对比,推荐方案 X,理由是……

3. YAGNI 原则

You Aren't Gonna Need It — 不要提前实现将来可能用到的功能。

做: - ✅ 解决当前已知的问题 - ✅ 预留扩展点(接口、配置) - ✅ 记录未来可能的演进方向

不做: - ❌ 为"将来可能需要"的场景写代码 - ❌ 引入当前不需要的框架 - ❌ 过度设计(Over-engineering)

4. 积分系统并发控制方案

方案 原理 适用场景 优缺点
悲观锁 SELECT ... FOR UPDATE 低并发 简单但性能差
乐观锁 version 字段 + 重试 中等并发 性能好,需处理重试
Redis 预扣减 先扣 Redis,异步更新 DB 高并发 性能最好,需保证最终一致性

5. 职场沟通原则

  • 对事不对人:讨论方案优劣,不攻击提出方案的人
  • 用数据说话:对比分析要有具体的维度和依据
  • 大方承认:对手的方案有可取之处,要公开认可
  • 透明沟通:技术决策在团队内公开讨论,不搞小动作
  • 留有余地:给对方台阶下,不要赶尽杀绝

:::