很多Java后端的项目都会采用这种后缀分包的方式。但这种分包方式很违反常理。

这里类名的前缀表示主体,后缀表示组件。比如ModuleService,Module表示这个类是属于模块这个主体的,Service表示这个类是一个处理业务逻辑的组件。后缀分包的方式就会像这样把所有名称中以Service结尾的类都放到service这个包下面。

我们平时开发时对这种分包方式已经司空见惯了,但我这里做个类比,你马上就会发现事情并不对劲。

我们把主体Module看作一个人,起个名字叫Bob,把Service、Controller这些换成随身物品,比如衣服鞋子之类,这样Bob的衣服鞋子就可以称为BobClothes,BobShoes等等,再把package比作一个行李箱,用于装Bob的个人物品。然后就有这样一组场景。

场景1:
我们的Bob拎着装满自己物品的行李箱参加了一个旅行团,这个旅行团有一个规定,就是要求你将衣服放进装衣服的箱子里,鞋子放进装鞋子的箱子里,以此类推。如果你是Bob,你遇到这样的规定会不会觉得很奇葩?
这就跟我们写新业务的时候一样,XxxService放在service包下,XxxController放在controller包下,但是大家都默认了。

场景2:
当Bob某天想换洗衣服的时候,尴尬事来了,Bob需要去不同的箱子去翻找自己的东西。
这就好比我们开发一个业务的时候,需要去不同包下去修改这个业务相关的组件的代码。

场景3:
当Bob准备离开这个旅行团的时候,麻烦的事情又来了,Bob需要一个一个箱子去找出他自己的东西再装回他自己的箱子。
对应的开发场景就是当进行微服务拆分的时候,我们需要一个包一个包里面找到对应的类,然后拷贝的新项目上。

还有一些其他的场景就不再一一列举了。通过这些场景我们可以看出这种后缀分包的方式是多么违反生活常识,正常人在生活中肯定都不会做的事情我们在做项目开发时却习以为常,见怪不怪。

后缀分包带来的问题解决起来也很简单,那就是依据前缀来进行分包。Menu的归menu,User的归user,Bob的东西就放在Bob的箱子里好了。一切自然而然,一个重要原因就是前缀分包的方案符合高内聚这一原则,而后缀分包下的类,互相之间基本不会有依赖关系。

那么后缀分包就一无是处吗?当然不是。当一个主体下的某个组件特别多时,就可以适当依据后缀来进行分包。比如说业务功能多了之后就会有很多DTO,VO这样的类,这时再在该业务的包下创建dto,vo的包来存放这些类,以保持主包下类的整洁和可读性。

这就是我在项目中组织包结构的一项工程实践,好处多多,欢迎讨论和落地。