后端开发十年,我重新理解了“简单”
十年前我拿着刚学会的Spring Boot脚手架兴奋地往项目里堆砌各种“高级”技术。Redis缓存、消息队列、微服务拆分、容器化部署一个都不能少。每当引入一个新框架我就觉得自己离“资深工程师”更近了一步。当时的我笃信复杂的系统需要复杂的技术来支撑代码写得让人看不懂才显得有水平。直到最近几年当我回头审视自己写过的那些“杰作”才惊觉自己一直在用战术上的勤奋掩盖战略上的懒惰。真正的“简单”从来不是自然而然发生的它是一场与自我和惯性思维的漫长战争。第一个五年我以“复杂”为荣刚入行的头几年我沉迷于“高并发”“分布式”这些听起来很酷的词。为了展示能力我把一个简单的用户查询接口硬是接入了缓存、加了一层消息队列、再放了个熔断器。同事问我为什么这么设计我滔滔不绝地讲了一堆“未来扩展”和“容灾备份”的道理内心却清楚只是想把简历写得更漂亮些。那种“复杂”带来的快感本质上是一种技术幻觉——我们误以为用了更重的工具就解决了更深的问题。实际上系统的性能瓶颈根本不在那个查询上而在于数据库的糟糕索引和缺失的分页。我用复杂的架构掩盖了基础的疏漏还沾沾自喜。更糟的是这种复杂成为了团队的负担。新同事接手项目时面对一长串依赖和层层抽象光理清调用链就要花一周。代码里充斥着设计模式却没人能说清它们到底解决了哪个具体问题。那段时间我的代码评审总是充满火药味。我批评别人“不够工程化”别人吐槽我“过度设计”。现在回想起来当时的“复杂”不是能力的勋章而是对问题理解肤浅的挡箭牌。因为没看透业务本质就只能靠堆技术来壮胆因为害怕承担“设计简单”的责任就把复杂性推给未来的维护者。第一次“断舍离”删掉那层“万能抽象”转机出现在一个风雨交加的下午。我们当时的支付系统有一个“通用支付流程”为了适配所有渠道我设计了一个极其复杂的策略工厂加模板方法。每当新增渠道开发人员要写三个类、改两处配置、还要理解抽象基类的生命周期。有一次线上问题为了定位到底是哪个渠道的哪种异常转换出了错我和同事排查了整整六个小时。最后我愤怒地打开IDE删掉了那层“万能抽象”把每个渠道的处理逻辑平铺开来。代码量从一千行变成了两千行但每个渠道的处理路径一目了然。诡异的是那是我职业生涯中第一次感受到“代码变多但系统变简单”。原先的抽象试图用统一的模型去理解所有差异结果把差异藏进了晦涩的钩子函数里。平铺之后差异被显式地命名和隔离维护难度骤降。这次经历让我意识到简单的核心不是“代码行数少”而是“认知负担低”。一个能让你在五分钟内理解全部流程的系统即使有一万行代码也比一个只有三千行但需要三天才能理清结构的系统更简单。从此我不再迷信“复用”而是开始信任“直白”。当然直白不是粗暴而是把该暴露的复杂性暴露在明面上而不是用一层层封装把它们缝进阴影里。重新定义“简单”不是做减法而是找准“核”后来我参与了公司核心订单系统的重构。旧系统经过三任团队的手像一团打了无数死结的毛线。每一任开发都往里加了“自己的理解”有些是业务规则有些是临时补丁有些纯属个人偏好。重构开始时我们差点沿袭老路继续用“更先进”的架构去替换旧架构。但这次我踩了刹车问了所有同事一个直击灵魂的问题这个系统最本质的“核”是什么讨论一周后我们达成共识订单系统的核心只有三个动作——创建、修改、查询。至于优惠计算、库存扣减、通知推送全部是围绕这三个动作的外围流程。于是我们以“订单状态机”为唯一主干把所有业务流程都显式地写成状态流转的条件和副作用。没有AOP切面没有事件总线甚至没有复杂的并发锁——因为状态机保证了每个状态只有一个合法入口。那次重构让我刻骨铭心地认识到简单不是功能少而是功能的组织方式恰好匹配业务的心智模型。当整个系统可以像讲故事一样被描述“用户下订单→订单待支付→支付成功→订单待发货→发货→完成”所有代码结构都围绕这个叙事展开时简单就自然涌现了。相反如果叙事是“在OrderService里调用PaymentProcessor同时通过EventPublisher触发InventoryAdjustment”你就需要额外记住这套不属于业务本身的“编导逻辑”。简单需要“残酷”的主动设计很多人以为简单等于“懒得设计”随随便便写写就好。恰恰相反简单是最高强度的设计活动它要求你对每个接口、每个字段、每个依赖都保持神经质的警觉。比如当有人提议“为了以后可能有用的功能先把这个参数加上”现在我会毫不犹豫地拒绝。YAGNI你怎么知道你需要它不是一句口号而是对抗复杂性的第一道防线。我见过太多“以后可能用得上”的代码最后变成了永远没人调用的死代码。它们像赘肉一样附着在系统上每次重构都要小心翼翼地绕过它们。每一个“先留着”的看似无害的扩展点都是交付给未来的债务。它们不是免费的期权而是需要持续付息的贷款——利息就是你的认知带宽。当团队花费精力去理解一段从不执行的分支逻辑时这笔债就在加速吞噬团队的生产力。我还学会了在评审中问“能不能删掉这个类”而不是“要不要加个接口”。删掉永远比增加需要更大的勇气和更深的洞察。但正是这种“删的勇气”才让系统长期保持呼吸畅通。一个没有勇气删除的团队注定会被自己制造的复杂性埋葬。简单不是一次重构的结果而是每天持续进行的小规模拆弹行动。从“技术视角”转向“人类视角”真正让我对“简单”开窍的不是任何一本技术书而是有一次我坐在一位业务运营旁边看她是如何用我们的后台操作系统完成日常工作的。她打开订单查询页面屏幕上跳出一个带六个筛选条件、三个图标的“高级搜索”面板。她茫然地看了几秒钟然后告诉我“我只想知道昨天团购的那批货到了没有。”那一刻我突然明白复杂不光存在于代码之间更存在于使用者与系统之间那条无形的鸿沟里。后端开发常常只盯着数据模型、接口性能、服务稳定性却忘了我们构建的每一样东西最终都会变成另一个人屏幕上的一个按钮、一段提示或一个错误码。当我们为了“后端设计整洁”而坚持返回一个结构复杂的JSON时前端的同事不得不写更多防御性代码当我们为了“系统解耦”而强行引入异步消息时排查问题的同事就得多跳两次上下文。后端的“简单”必须以前端、运维、测试以及未来的自己的“轻松”为度量衡。后来我在设计接口时会反复问自己如果我是一个第一次接触这个接口的人看到这个名字和参数我能立刻明白我要做什么吗如果不行说明我的抽象还不够贴合业务语言。于是我越来越多地使用动词和业务名词而不是“QueryDTO”“ResultModel”这类技术行话。简单是面向“变化”的生存策略有人会说系统越来越复杂不正是为了应对业务的变化吗这是一个巨大的误区。复杂恰恰是变化的敌人简单才是变化的朋友。当业务需要调整时一个简单的系统让你能快速定位修改点然后像手术刀般精准地切割。一个复杂的系统你经常要花三分之一的时间在“搞清楚这段逻辑到底干什么用”上面剩下三分之一时间在“会不会影响别的地方”最后三分之一时间才真正动手。我经历过一次版本大升级业务规则几乎全部改写。那个代码简洁的系统只用了两天就完成了改造而另一个“设计精良”的微服务群整整花了两周还要协调四个团队的排期。因为业务变化的速率永远大于技术演进的速率你的系统每多一层间接就多一道拖慢变化的枷锁。简单不是静态的状态而是一种让系统保持可塑性的能力——在需要改变时你能以最小的代价扭动它。当然简单不意味着不设计。恰恰相反最深的简单往往是最强的抽象。比如HTTP协议它只有几个方法、几个状态码但它支撑了全球互联网。那种简单是建立在深刻理解之上的“本质抽取”就像物理学中的Emc²公式很短却涵盖了宇宙的规律。我们追求的后端简单应该是找到了那条最短的、最能描述业务的公式而不是东拼西凑的“伪简洁”。这种公式往往藏在业务的故事线里需要耐心倾听、反复提炼。简单是一场终身的修行写代码的第十年我终于不再把“简单”当作一个形容词而是当成一个动词——我无时无刻不在“化简”。每一次重构我都在问自己这个类能拆得更小吗这个命名能更准确吗这个依赖能去掉吗这个分支能合并吗这种反复的修剪就像给大树修剪枝丫不是让它枯萎而是让养分集中流向主干。人与人的沟通同样如此。以前我在设计文档里写“基于CQRS架构的领域事件驱动模式”现在我会写“用户下了单订单状态变成已支付然后通知仓库发货。如果通知失败系统会在十分钟后重试三次。”这种转变是十年后端生涯给我最珍贵的礼物。它让我明白所谓资深工程师不是能搞定最复杂问题的人而是能把最复杂问题化简到所有人都能理解的人。简单不是低级而是高级的智慧结晶——就像好的作家能把深刻的思想用大白话讲出来好的后端也能让复杂的流程在代码里一目了然。这不是妥协而是一种更严苛的自我要求在所有的方案中选那条最让队友省心的路。未来的路还很长我知道自己还会无数次面对“复杂”的诱惑。每当这时我就会闭上眼睛想象新加入的同事第一次打开代码库时是感到如沐春风还是陷入迷宫。我希望他们看到的不是闪闪发光的架构圣经而是一排清晰的路标这里有订单那里有支付你此刻正站在这里。这大概就是我所理解的属于后端的“简单”——它不炫技却充满力量它不言说却胜过千言万语。

相关新闻

最新新闻

日新闻

周新闻

月新闻