orderservice 膨胀主因是职责未按变更原因切分。应依“谁因何修改”拆为 inventorydeductionhandler、couponvalidator、paymentcallbackrouter 等单一职责组件,消除 private 方法,收敛入参,用事件解耦,避免伪拆分。

为什么 OrderService 一写就上千行?
不是业务复杂,是职责没切开。单一职责原则(SRP)不是教条,是为降低修改成本:改个优惠计算逻辑,不该牵扯到订单状态机或物流通知。真实项目里,OrderService 膨胀的主因是把「能放一起」当成「该放一起」——比如把库存扣减、优惠券核销、支付回调处理全塞进一个类,结果改支付渠道时得通读 800 行代码找钩子点。
按「变更原因」切分比按「功能模块」更可靠
别按「用户端」「管理端」「后台任务」这种横向切分,要盯住「谁会因为什么改它」:
-
InventoryDeductionHandler:只响应库存相关变更(如仓库切换、超卖策略调整),不碰订单字段 -
CouponValidator:只管优惠券有效性、叠加规则、黑名单校验,不触发任何外部调用 -
PaymentCallbackRouter:只解析支付平台回调参数、路由到对应处理器,不处理订单状态更新逻辑
关键区别:每个类只有一个「修改理由」。如果某次需求要求「微信支付回调加幂等日志」,你只动 PaymentCallbackRouter;换成「满减券支持跨品类」,只改 CouponValidator。
Spring @Service 类里藏 private 方法就是危险信号
看到 OrderService 里有 private void doInventoryCheck()、private void sendSmsNotification() 这类方法,说明职责已溢出。这些方法本该是独立组件:
- 把
doInventoryCheck()拆成InventoryCheckService,暴露check(Order order)接口,方便单元测试和 mock - 把
sendSmsNotification()提炼为SmsNotifier,接收NotificationContext而非整个Order对象 - 原
OrderService只保留协调逻辑:inventoryCheckService.check(order); couponValidator.apply(order); smsNotifier.send(order);
注意:拆分后别搞「服务链式调用」——A → B → C → D。用事件(如 OrderPaidEvent)解耦,让各处理器监听事件,避免强依赖和事务边界混乱。
警惕「伪拆分」:接口名变了但实现还耦合
常见翻车现场:
- 新建
OrderPaymentService,但内部仍 newOrderDao+LogDao+InventoryClient,没抽象依赖 - 所有新类都直接注入
OrderMapper,导致改数据库字段时十几个类全要改 - 用
Map<string object></string>在服务间传参,丢失类型约束,后续加个字段就得 grep 全局
真正有效的拆分,必须伴随接口抽象和入参收敛:InventoryDeductionHandler.deduct(InventoryDeductionRequest request) 的 request 应只含 skuId、quantity、warehouseCode,不含订单号、用户ID、创建时间等无关字段。
最易被忽略的一点:拆分后的类,其构造函数参数应能清晰反映它的协作边界。如果一个类同时需要 OrderMapper、InventoryFeignClient、RedisTemplate、MailSender,它大概率还没拆干净。










