把业务从三张表拆到十张表:Java领域建模的心路历程

阿乐
阿乐 管理员 黑卡会员
发布于 2026-09-06 07:50 ·5 浏览 ·0 回复

刚接手这个项目时,业务逻辑其实并不复杂:一个订单、一个客户、一张流水表,满打满算三张核心表就能跑通所有接口。心里还暗自得意——表少,意味着联查简单、逻辑直观、性能也好调优。

当时我就想,这大概就是所谓的“大道至简”吧。

但好景不长。随着业务方接二连三地提需求,三张表的架构开始变得力不从心。先是订单表里塞了十几种状态:待支付、已支付、待发货、已发货、已完成、已取消、退款中……每一种状态对应着一套截然不同的业务规则。为了满足这些规则,那张订单表膨胀到了四十多个字段——有冗余的冗余,没冗余的也在硬加。

紧接着是“越权”问题。客户、运营、财务、仓储,各角色对同一笔业务的读权限完全不同,还有一整套审批流和三方对账逻辑。所有逻辑都堆在Service层,哪怕是一个小小的状态变更,也要牵扯七八个if-else分支。

有一次,为了修改一个优惠金额分摊的bug,我翻了三层Service、四张表、五段注释模糊的历史代码。那晚我盯着屏幕,忽然意识到自己不是在“维护”代码,而是在考古。

于是,我决定重构。把业务从三张表拆到十张表。

说出来容易,做起来却像是把自己辛苦搭建的茅草屋推倒重盖。第一步要做的,就是把那个无所不能的订单表“解剖”掉。

原本一张订单表里的信息被拆分成了订单主表、明细表、支付表、物流表、售后表、优惠表、操作日志表……表面上表多了,联查多了,前期开发量上去了,但这之后,每个领域边界的职责清晰了:订单只关心自己的生命周期,支付只管流水,物流只管轨迹。那根纠缠不清的“上帝对象”逻辑,终于被切开。

数据表拆分本身并不难,真正触动我的是建模思维的转变。表不再是“存数据的盒子”,而是领域模型的投影。

举个很小的例子:以前订单状态我直接用一个`status`字段去扛,一遇到各种组合条件,代码里飞满了魔法数字。后来领域建模时,我把状态抽出来,做成状态机,每个状态变更都有明确的入口、合法的迁移路径、对应的事件与动作。刚开始觉得很繁琐,后来才体会到,设计上的“约束”其实是在为未来的“扩展”托底。而那些曾经“灵活”的if-else,最后都变成了无从下手的泥沼。

这让我想到Eric Evans在《领域驱动设计》里反复强调的一个观点:模型不是画出来的,而是不断重构出来的。真正的领域建模,是让代码结构与业务语义对齐,让每个概念在代码中有明确的归属。

回头再审视“三张表与十张表”的对比,我发现关键不在于表数量的多少,而在于对业务复杂度的尊重

三张表在业务初期,或在一个边界清晰的子域中,依然可能是最优解。拆到十张表,并不意味着表结构高级,而是因为业务本身已经在长成一颗大树,再用花盆去装,迟早会枯死。

我见过很多同事抱怨:“表拆这么细,查询要join七八张表,性能肯定不行。”这话没有全错,但更多时候,性能问题可以通过缓存、读写分离、冗余查询字段来兜底——而复杂的业务逻辑如果一开始揉成一团,后面就再也没有兜底的机会了。那一堆难以理解的代码和混乱的字段之间的耦合,才是真正的技术债。

领域建模是慢功夫,也是内功。它不会让你这个迭代的KPI立刻变好看,也不会成为你简历上闪亮的一笔。但它决定了系统在五年后,是依然能稳如磐石地交付需求,还是成为每一任新人都恨不得推翻重写的黑盒。

这段从三张表到十张表的历程,说到底是让我学会了一件事:先思考清楚业务的语言,再决定表的形状。表结构,从来不只是存储设计的产物,它承载着你对一个业务领域最本质的理解。理解得越深,表分割得也会越巧——不是为了多而多,而是让每个概念都有其应许之地。

至今我的数据库里依然保留着那张最初的订单总表,不过它的字段少了许多,功能也瘦身成了一个单纯的聚合根入口。每次看到它,都能提醒自己:**业务的复杂度永远在不远处等着你,早建模早超生,技术上的图省事,最终都会由维护者加倍偿还。**

全部回复 0

还没有回复,来抢沙发~