新建项目,手指头是不是又条件反射地敲下 class 了?别装了,咱这帮写代码的,面向对象早就练成肌肉记忆了。封装能多套几层就多套,继承能拉关系就拉,最后甩两张UML图糊弄过去,完事。代码是能跑,功能也齐活。可你信不信,隔上几个月再回去看,那逻辑,啧,跟被拆过的毛线团有啥区别?越扯越死结。错哪儿了?真不怪语法。顺序反了。Haigh在《面向对象的分析与设计》里早就掰扯明白了:面向对象,不是让你把代码往类里硬塞。是敲键盘之前,先拿笔在纸上画清楚,现实里这摊子事儿,到底该归谁管。书里反反复复就这一句:别急着动手。先想明白权责。
听着是有点反直觉。上学那会儿,老师不都喊“先跑通,再优化”吗?可软件这东西,一旦往上堆,复杂度过了那道坎,反噬来得比翻书还快。书里点得很透。多少人把UML当打卡,把继承当炫技?全忘了分析阶段,本质是“做减法”。一层层剥开。拿电商订单系统举例。一个模块,既要管支付校验,又要扣库存,顺手还得发通知。全压在一块儿。上周同行跟我倒苦水,改个优惠券逻辑,硬塞了三十多个 if-else 进同一个服务类。改完直接崩盘,排查了一整天。这时候你狂补逻辑?纯属浪费时间。得拆。“校验”归校验,“扣减”归扣减,“通知”归通知。各自管一块,靠清晰的接口碰头。书里翻来覆去拆解的,就是这拨乱反正的功夫。先揪出领域里的关键角色,分派下去。最后,才琢磨怎么用多态,去替换那些一碰就碎的 if-else。这步真省不得。后期需求一改,你光掉头发都算轻的。
坑在哪?最扎眼的叫“贫血模型”。领域对象光秃秃的,就剩 getter 和 setter 杵在那儿干瞪眼。业务逻辑?全塞控制器或服务层里了。远看架构图,挺规整。实际呢?权力全扎堆在一个臃肿的调度中心。需求稍微变个脸,调度中心就得脱层皮,推倒重来。跳过分析、闷头敲代码的下场,就在这儿摆着。Haigh拿 UML v1.4 推演设计,真不是要把你培养成画工。是逼你在纸上,把“这活儿到底归谁干”给钉死。协作线理得清清楚楚,代码里的耦合,自然就一刀两断。面向对象能省多少维护的力气?根本不靠语言里那些花里胡哨的特性。是把脑子里的负担,分摊到好几个边界分明、各司其职的对象头上。画图,真不是为了交差。是为了提前踩雷,排雷。
但别误会。责任划分,不是包治百病的仙丹。硬往不合适的场景里套,代码只会越写越僵。写个轻量脚本,搭条数据管道,或者搞快速原型验证,非要死磕对象边界?纯粹给自己加戏。平白多出好几层抽象,图啥?书里那套能转得动,有个前提:业务地盘本身结构得稳。复杂度已经高到集中式管理玩不转了,才得上这招。要是碰那种天天变、纯靠瞎摸索的任务,还抱着“单一职责”当圣旨?节奏绝对拖死。问题压根不在面向对象行不行。在咱们是不是拿错了工具箱。把设计方法供上神坛当教条,跟完全不管设计瞎搞,半斤八两,都挺要命。这话听着可能反常识。但你真去线上改过几次屎山代码就懂了。有时候,“快”比“对”管用。一开始非得搞得多复杂,纯属瞎折腾。
说到底,面向对象不是啥语法糖。是管住复杂性的规矩。它就在耳边敲:写代码,不是搬砖垒墙。是在织一张责任网。下次再盯着空白编辑器发呆,干脆掐表停两分钟。别急着琢磨“这玩意儿该建个啥类”。先盘一问,“这事儿到底该谁牵头”。心里那本账算清了,代码的骨架,自己就长出来了。写软件是这路数。对付生活里那些剪不断理还乱的烂摊子,用的,也是同一套心法。