6

新项目模块不能拆拆拆,但怎么应对大型项目?

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzA4MTc4NTUxNQ%3D%3D&%3Bmid=2650523268&%3Bidx=1&%3Bsn=fe03d2370c95b8e7e8c04c156ea32444
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

e6JBVrU.gif!mobile

原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转载请保留出处。

很多同学创建一个项目之后,就迫不及待的上手开写了。项目代码不像一些框架代码一样可以随意的去写,但一般都是采用MVC的模式进行开发。很悲催的是,Java中Web开发的这些目录名称,到现在还是一团乱麻,你需要自己去规划。

什么Controller、Service、Dao等,但其实这种划分方式弊端很多!本文将先介绍两种典型的分层结构,然后稍微借鉴一下DDD的思想,谈一下我在项目中常用的目录结构。本篇文章非常的 实用 ,将探讨怎样做一个应对 大型项目 的目录划分。

naqyEnm.png!mobile

清晰的目录结构,能够辅助其他同学轻而易举的了解项目的功能模块,在项目中保持整体一致的约定也是一个非常好的习惯。如果再加上一个 扩展性 ,那目录划分就是重中之重。

有两种典型的分类方式,但也有很多细节。

1. 最简单的MVC

我们平常最熟悉的,就是MVC结构。这种结构很流行,写简单项目很方便,但是会产生严重的耦合问题、Service爆炸问题,数千、上万行的代码是家常便饭。

  1. Model(模型)表示应用程序核心(比如数据库记录字段)。

  2. View(视图)显示数据(数据库记录)。

  3. Controller(控制器)处理输入(写入数据库记录)。

在项目划分上,就类似下面的目录结构。

aIj2M32.png!mobile

1.1 模型

domain是DDD中一个非常宽泛的概念。不过,我们平常就当作数据库对应的Java 类使用了(没什么错)。在实际操作中,它还可能有下面几种名字,在 普通项目 中区别不大,你最好在项目中保持相同的意义来避免歧义。

  • entity 这个意义比较明显,就是实体的意思,最常用。比如JPA的 Entity 注解
  • model 模型的意思,一般用来在不同系统之间交互。但如果你的模型非常简单,直接用entity来表示也是可以的
  • domain 这个范围有点大,甚至会包含领域内service。如果你对DDD的概念不是很熟悉,那就玩上面几种

对于简单的项目,我通常在项目中使用entity来表示和数据库的交互。在JPA之类的ORM中,也是做相关处理的。比如 javax.persistence.Entity 注解。你要明白的是,Spring Data其实取了一个比较折衷的点,把很多东西揉在一起了。

1.2 Dao

dao 层叫数据访问层,全称为 data access object ,属于一种比较底层,比较基础的操作。在一些其他框架中,还会叫别的名字。

  • mapper 这个一般是Mybaits之类的框架所生成的目录,通常是一些接口。
  • repository 仓库的意思,在jpa中经常用。

Dao应该满足最小封装原则,理论上只涉及一句SQL的执行。如果有多个数据的存取动作,需要封装在Service中,并用事务进行管理(虽然这么说,但repository在DDD中,是不和具体的数据库打交道的)。

1.3 service和controller

这个没什么好说的,基本上所有重要的逻辑都在这里完成。service用于逻辑处理,controller用于接口暴露。

2. 根据功能组织

大多数情况下,我们使用上面的这种划分模式,能够很好的完成工作。比如,所有的数据处理,都放在Dao层,所有的逻辑处理,都放在Service层。

这在小项目中相安无事,但如果项目中,有成百上千个Entity,这些目录中的文件就会爆炸,以至于最后无法维护。

另外一个问题就是,仅仅一个简单的功能,就可能分散在多个package下的多个文件中,大型项目维护变得困难。

我们有另外一个思路,就是根据功能进行分组。比如下面的截图。

I7JnQnE.png!mobile

我们把相似功能,放在 modules 下的单个文件夹中。如果这个功能模块比较大,我么可以在功能模块下,再进行分层设计。

比如上图,有一个商品服务,我们单独给它分配了一个目录空间goods,然后在里面又划分了dao、entity等目录;但对于Service和Controller,我们简单的放在了外层,可以看到在模块内的分配是比较灵活的。

这么做的好处是显而易见的。功能变的非常的集中,各个package之间的内容互不影响。

3. 还是不够优雅

其实,即使我们这样划分了,项目仍然会面临很大的挑战(很多DDD的书籍,会大量讨论各层的交互)。

下面分享一个我在平常使用的分层模式,兼顾高内聚和低耦合,有着良好的扩展性。

VZ7viey.png!mobile

  1. config ,最外层的一些全局配置,比如web配置,消息队列配置等
  2. system ,全局的工具和依赖功能,在DDD中叫做基础设施(但在非DDD实践的项目中名称太怪异了)
  3. auth
    JWT
    Spring Sercurity
    
  4. bc
    模块
    请求量
    crm
    images
    order
    

我们再来看一下每个模块之内的结构。

RvAnqeA.png!mobile

和传统的MVC类似。不过,为了屏蔽变化,兼顾扩展性,我们增加了更多的内容。

  1. persitence ,持久层,具体使用JPA还是Mybatis,这个是无关紧要的。我们的目标,就是尽量的弱化持久层的实现,将变化封装在Domain层中
  2. persitence/dao ,具体的持久层接口,比如MyBatis的Mapper文件,或者JPA的 Repository
  3. domain 层,具体的业务层,你可以认为是一堆Getter、Setter的Bean。我们尽量会把大多数验证类和变化封装在这里(可以大体认为是DDD中的充血模型)
  4. controller
    Request
    Response
    
  5. application ,应对传统的service层,除了在application能够调用 Dao ,其他层是没有权利调用Dao的
  6. api ,和application的功能是相同的。只不过,api的接口,指的是模块之间可以相互调用的接口。除了api暴露的这些接口,bc之间的类和接口,默认彼此是不可见的
  7. util ,不通用的util,会放在模块内部,而不是抽离出公共的util

除了要解决目录方面的问题,我们还要把数据的流向给规划清楚。

一个上层的应用,是可以通过API接口直接调用下层服务的。比如,订单系统访问商品基础信息的数据;反之却不可以,比如商品基础信息模块访问订单系统的接口。

低层想要对高层的数据产生变化,就只能通过消息模块,将变更发布出去,其他的模块就可以订阅这些变化。

小结

综上所述, xjjdog 认为,如果你的项目,可能会比较大,单纯的使用分层的package,并不是一个好的习惯。

你可能对这种后台管理类的项目驾轻就熟,有很多有用的模版,它们都是简单的MVC分层。这应付一些外包项目,干一些一锤子买卖的时活,或许没什么问题,但一旦是比较大的长期项目,这种分层的目录接口就显现出它的弊端。

这是因为:项目的短期风险,是工期问题;而长期风险,是扩展问题。随着访问量的增加,还有低耦合高内聚的需求增加,如何快速的应对需求,减少BUG,将会是制约项目发展的最主要因素。

作者简介: 小姐姐味道 (xjjdog),一个不允许程序员走弯路的公众号。聚焦基础架构和Linux。十年架构,日百亿流量,与你探讨高并发世界,给你不一样的味道。我的个人微信xjjdog0,欢迎添加好友,进一步交流。

推荐阅读:

一图解千愁,jvm内存从来没有这么简单过!

失联的架构师,只留下一段脚本

架构师写的BUG,非比寻常

nginx工程师,需要上承天命,下召九幽

实力解剖一枚挖矿脚本,风骚操作亮瞎双眼

又一P1故障,锅比脸圆

传统企业的人才们,先别忙着跳“互联网”!

面试官很牛,逼我尿遁

又一批长事务,P0故障谁来背锅?

一天有24个小时?别开玩笑了!

《程序人生》杀机!

可怕的“浏览器指纹”,让你在互联网上,无处可藏

2w字长文,让你瞬间拥有「调用链」开发经验

996的乐趣,你是无法想象的

作为高级Java,你应该了解的Linux知识(非广告)

必看!java后端,亮剑诛仙(最全知识点)

学完这100多技术,能当架构师么?(非广告)

Linux上,最常用的一批命令解析(10年精选)

数百篇「原创」文章,助你完成技术「体系化」

EnUneen.gif!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK