相关文章推荐
耍酷的枕头  ·  Dou Jie Home ...·  3 年前    · 
道上混的创口贴  ·  为DataFrame中的一列数据添加前/后缀 ...·  3 年前    · 
英俊的遥控器  ·  如何设置MediaWiki用户权限_百度知道·  3 年前    · 
任性的凉面  ·  Android ...·  3 年前    · 
急躁的围巾  ·  语言模型困惑度的两种形式及python实现 ...·  3 年前    · 
Code  ›  java - 按业务拆分模块的疑惑 -
https://segmentfault.com/q/1010000021706282
飘逸的萝卜
3 年前
segmentfault segmentfault
注册登录
问答 博客 标签 活动
发现
✓ 使用“Bing”搜本站 使用“Google”搜本站 使用“百度”搜本站 站内搜索
注册登录
  1. 首页
  2. 问答
  3. java
  4. 问答详情

按业务拆分模块的疑惑

头像
xxinyue
7 5
发布于
2020-02-08
更新于
2020-02-24
打算做一个 Java admin 快速开发框架;将常用的库、权限管理、用户管理...啥的集成,方便平时做点小项目。
  • xinyue-platform 是 parent 项目,类型是 pom
  • xinyue-admin 是 Web 项目,用来最后打包运行的后台管理服务
  • xinyue-business 是所有的业务逻辑模块,模块内按照业务分包(业务包内分层),如图:
  • xinyue-core 是项目核心模块,包含一些 base 基类等等
  • xinyue-common 作为公共模块,放一些常量、工具类、枚举啥的
  • xinyue-generator/xinyue-task 暂时可以忽略,还没设计 ?
  • xinyue-admin 依赖 xinyue-business
  • xinyue-business 依赖 xinyue-core
  • xinyue-core 依赖 xinyue-common
  • 因为未来比如用这个 platform 做电商项目,可能还需要对外提供 xinyue-api-h5/xinyue-api-appliet 一类的服务;所以希望可以将业务逻辑下沉到单独的模块,可以供 admin(后台管理系统)和各个终端 API 调用

    这也是为什么 xinyue-business 模块内部,分层的时候只有 entity、repository、service 层的原因了,因为具体这些服务对外提供的接口;可能路径不同,也可能需要在不同的 Web 层在进行一些业务逻辑

    所以 controller 层被单独拿到了 xinyue-admin 模块(也有可能是未来的 xinyue-api-xxx 模块),如图:
    3.png

    目前的设计存在哪些问题?

  • 由于自己还在上学,没接触过过大型项目,都是在 Google 和开源项目中学习了一些思路
  • 自己根据自己的业务特点设计了如上的结构,不知道是否标准,或者说存在着哪些问题呢
  • 之前参考的项目多是按业务模块划分,模块内 entity、repository、service、controller 分层,有些疑惑:

  • 比如分为 user 模块和 order 模块,不采用微服务,那么最终还是要打包到某个 Web 服务中发布运行的
  • 可是如果 order 模块某些逻辑需要依赖 user 模块,直接在 order.pom 中添加 user 的依赖会不会有点怪怪的
  • 并且,这样岂不是 maven 会有重复依赖的问题,比如 order 和 user 都有 springBoot-starer-web/data--jpa 的依赖,order 再依赖 user,那么 springBoot-starer-web/data--jpa 不就重复依赖了么?
  • business 按业务分包是否可以直接拆分为 xxx 模块

    有的时候在想,目前的 business 内按照业务分包,会不会导致未来各个业务包之间边界越来越模糊的问题(同在一个模块,可以直接互相调用其他包)

  • 比如同上的情况;order 的某些逻辑依赖 user ,那么可以直接在 orderService 中调用 user 提供的 service/repository,没有任何壁垒
  • 那么各个业务包是否丧失了高内聚、低耦合的核心
  • 若拆分为各个业务模块,又是否能解决这些问题
  • 项目中的依赖关系如何管理

    参考、分析了 4、5 个 GitHub 上高分的类似快速开发平台,发现这些项目被 Idea 的 Maven 提示 omitted for duplicate ,其实也是我第一个问题里面提到的重复以来的问题;看提示 maven 应该会自动处理,主要就是心里面有点想不通,这样会不会有隐患

    希望各位可以给一些参考意见,小弟不胜感激

    maven spring java
    阅读 7.1k
    2 个回答
    得票 最新
    头像
    imango
    3k 3 14 14
    发布于
    2020-02-10
    更新于
    2020-02-10
    ✓ 已被采纳

    题主你好
    首先说哈,我这边确实看不到图哈,没骗你,可能你的图是其他网站的链接,我这边没有权限
    image.png

    F12看了哈,403的报错,貌似是这个网站的 https://img.hacpai.com ,这是一个三级域名,二级应该是 hacpai.com ,没见过这个域名,搜了哈,是叫 黑客派 这个网站,也是一个程序员网站
    image.png

    好吧,按照题主的问题名称搜索了哈,终于找到对应的 提问 ,也终于可以看到题主的贴图。。。
    image.png

    言归正传,针对你的问题,由于是设计类问题,其实是没有绝对答案的,所以我根据自己的经验做一些回答,仅供参考,但是回答之前要说一个我自己理解的设计理念

    最好的设计 = 符合需求 + 截至时间 + 最低物理资源成本 + 最低人力成本

    换句话说就是:在有限资源和有限人力的情况下,截至日期内做出符合需求的产品,则此产品的设计就是最好的设计

    所以设计的好坏,其实没有绝对的标准,在满足上诉4个条件下的设计,那就是最好的设计

    由于题主是自己写的,看起来也不是商用版,现在也不会部署,所以没有截至时间,也谈不上物理资源,自己一个人写,也没有人力成本,最后对于题主来说,只有 符合需求 了,符合需求的设计那就是好设计了

    而从下面这句话可以看到,以后不同的 web 项目,但是是基于相同的业务,也就是相同的 business
    image.png

    如果题主的需求如此,那我可以说题主现在设计很合理了啊

    那简单画图就是这样
    image.png

    因此把 controller 单独放到一个 web 工程里就没毛病啊

    但是题主提到,别人是按业务模块划分,模块内 entity 、 repository 、 service 、 controller 分层,那题主你确定别人这样做,是符合你的需求么?因为别人这么做,也许有别人自己的需求支撑啊...

    先不说题主提到的若是这么做会有以下怪怪的问题
    image.png

    光是这么做之后,有个严重问题就是,我之前画的图,可能变成这个样子了
    image.png

    从题主你的 web 项目划分来看,你一个 User 模块,或者 Order 模块里的 controller 已经耦合了其他项目的 controller 了,尤其是对于前端更不友好,假设业务模块更多,他们要到处去找自己要的接口,毕竟每一个模块的接口地址开头都不一样,更不说类似功能但是是不同 web 项目使用的情况下可能造成接口调用错误

    当然题主说的依赖起来会有点怪怪的感觉,其实就是 controller 这层, controller 对下连接了业务,对上也连接了不同的项目,一个业务是可以在不同项目中使用的,但是完全不相关的项目是不可以在其他项目中使用的,这就是怪怪的感觉,去掉 controller ,就算 user 和 order 单独拆成两个模块, order 模块依赖 user 模块,可能题主也不会觉得怪怪的了

    再说说题主说的重复依赖,我个人觉得这个问题不大,只要不是相同包不同版本(这样可能有版本冲突),但只是重复依赖,还算好,毕竟都是分了父子模块,有父 pom 管理所有的版本,因此不同子模块引用相同的包也只会有相同的版本
    image.png

    如果确实觉得别扭,比如题主提到的情况,若 order 和 user 模块在去掉 controller 层下, order 和 user 都依赖了 jpa , order 再依赖 user ,那我觉得 order 不依赖 jpa 也是可以的

    最后题主提到有没有必要business模块按照业务拆分成子模块
    image.png

    这个就像刚才说一样,看你怎么拆,若是现在这样,一个 business 有不同的业务,业务之间有依赖,我觉得可行啊,因为在外看来, business 模块本身就是一个业务高内聚的模块,至于题主说觉得业务互相依赖,降低了 business 内每个业务的内聚性,但看你从哪个角度出发来看业务,如果整个 business 模块就是一个完整的大业务,那我觉得就是没有问题,很高内聚了,从需求来看, order 业务就是依赖 user 业务,真想要从这个粒度进行划分开,形成各自高内聚,那只能拆分不同服务,走微服务了,就算走子模块,你还是免不了模块的依赖(除非模块与模块之间本就变成了服务化),

    但是如果需求变成,假设后续新出一个 web 项目,但是只是会用到 user 业务,那此时可以看到 business 模块的方式就不是很好,因为依赖了 business 模块,就会依赖到不会使用的 order 业务,但若按照业务拆分成 order 和 user 两个子模块,新的 web 项目就可以只依赖它需要的业务模块了,所以得看需求

    综上,题主现在的设计基于现在的需求是可以的,没啥大问题,你要想去了解其他系统的设计,那你不光要看别人怎么做的,关键要看,它这样做到底是为了解决什么问题,单单看最终的做法然后借鉴到自己的项目上是不可取的,就像看一大堆设计模式,但是实际自己的代码根本就用不上,或者使用起来特别麻烦,还有一问题,那就是为了设计而设计,那就是过度设计了

    当然肯想是很好的,这点题主还在上学就有这样的思考,已经很强了,要给个赞,不过以后实际工作开发还是要考虑我之前提到的几个条件,在几个条件的基础上再来好好设计,不能无脑一把梭。。。就像
    image.png

    头像
    xxinyue
    7 5
    发布于
    2020-02-24
    更新于
    2020-02-24

    首先,非常感谢您回答了我的问题,且由于我的一时偷懒(直接从了另一个社群复制了问题导致看不到图片),增加了您的时间成本,实在抱歉了哈 ღ( ´・ᴗ・` )比心

    一些思路的重整

    距离抛出这个问题已经过去两周多了,对于原文中提到的部分问题,这段时间也做了新一轮的思考,具体如下:

    原文中的打算是在 xinyue-platform 这个项目完成后,可以基于这个项目落地一些需求,并复用一部分代码,比如基于此搭建 xinyue-mall 、 xinyue-mooc 等等, 最初的设想是在一套项目下实现多个业务项目 ;想了想,觉得不是很合理,所以更正为: 不同的业务项目都重新基于 xinyue-platform 搭建

    关于 xinyue-business 按业务分包是否可以直接拆分为 xxx 模块的问题: 的确,将所有的业务放在business模块中,从整个项目的角度来看实现了高内聚;

    不过这段时间想了一下,这种情况还会存在一些冗余;比如在后台管理系统中需要数据分析的功能,那么在 business 模块内就要相应的存在 dataanalysis 这个业务包(当然不一定非要按照某种粒度分出这个包,这里只是举例哈),那么对小程序提供服务的web项目 xinyue-api-applet 依赖 xinyue-business 时,就出现了所谓的冗余(虽然可能对项目来说,无非是增加了一些空间,可以忽略,不过心里还是觉得怪怪的?)

    故还是决定将 xinyue-business 下面的业务包拆分成具体的业务模块 ,同时也引入一些问题:

    其实也是原文提到的问题,拆分之后模块间的依赖关系会不会很"怪",比如订单模块依赖了支付模块,支付模块又依赖了订单模块(假设哈)

    对于这个问题, 参考微服务的远程过程调用,想了个折中办法

    即:将本模块被其他模块依赖的部分,单独提取作为一个 provider 模块(这个模块仅仅是一组接口),让本模块依赖这个 provider 模块并实现定义的接口,让原来依赖本模块的模块,也依赖 provider 模块,直接调用定义的接口

    这么设计的原因是,我们最终打包还是一个web项目,所以被打包到web项目后,接口的方法调用就会找到具体实现;当然缺点是引入了更多的复杂度,优点就是不同模块之间的界限变得清晰了,哪些是模块内应该内聚的,哪些是对外暴露的(实现了 provider 接口的)

    最终的模块结构如图:

    依赖关系举例:

    A -> B 表示A依赖B
  • xinyue-system -> xinyue-system-provider(并实现了provider中定义的接口)
  • xinyue-xxx -> xinyue-system-provider(调用了定义的接口)
  • xinyue-manger(web管理端项目) -> xinyue-system
  • xinyue-manger(web管理端项目) -> xinyue-xxx
  • 故在xinyue-manger中实际xinyue-xxx调用的是具体的实现
  • 关于Maven的重复依赖,经过这几天的学习,这个确实问题不大的,且可以在引入某依赖的时候,排除掉不需要的依赖

    关于Controller是否下沉到业务模块的问题,目前的做法是基本的CRUD还是放在业务模块(代码生成的时候更方便),通过在不同的web项目中添加项目前缀来区分;如果需要对特定终端提供API的时候,再跟进情况在web层编写需要的Controller

    最好的设计 = 符合需求 + 截至时间 + 最低物理资源成本 + 最低人力成本
     
    推荐文章
    耍酷的枕头  ·  Dou Jie Home 中国地质大学(武汉)教师个人主页系统
    3 年前
    道上混的创口贴  ·  为DataFrame中的一列数据添加前/后缀_给dafaframe某一列添加字符串_DL路人甲的博客-CSDN博客
    3 年前
    英俊的遥控器  ·  如何设置MediaWiki用户权限_百度知道
    3 年前
    任性的凉面  ·  Android 自定义View(四)实现股票自选列表滑动效果 - 掘金
    3 年前
    急躁的围巾  ·  语言模型困惑度的两种形式及python实现 - 知乎
    3 年前
    今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
    删除内容请联系邮箱 2879853325@qq.com
    Code - 代码工具平台
    © 2024 ~ 沪ICP备11025650号