美文网首页Android技术知识Android开发Android开发经验谈
实战分析:项目业务模块划分与包名设计思想

实战分析:项目业务模块划分与包名设计思想

作者: 程序老秃子 | 来源:发表于2022-08-12 14:25 被阅读0次

前言

首先明确一下,这里所说的 业务模块 的划分,是针对 client,service,common 这样的技术划分,而不是针对具体业务的模块划分; 避免由于歧义,造成你的误解

直接原因

在公司内部某一技术团队,在引用我们系统的client包时,启动失败

失败原因是由于client下有一个cache相关的依赖,其注入失败导致的

然后,就发出了这样一个疑问:我只是希望使用一个hsf接口,为什么还要引入诸如缓存,web处理工具等不相关的东西?

这也就自然地引出了前辈对我的一句教导:对外的client需要尽可能地轻便

很明显,我们原有的client太重了,包含了对外的RPC接口,相关模型(如xxxDTO),工具包等等

可能有人就要提出,直接RPC+模型一个包,其它内容一个包不就OK了嘛?

问题真的就这么简单嘛?

根本原因

其实出现上述问题,是因为在 系统设计之初,并没有深入思考client包的定位,以及日后可能遇到的情况

这也就导致了今天这样的局面,所幸目前的外部引用并不多,更多是 内部引用;及时调整,推广新的依赖,与相关规范为时不晚

常见模块拆分

先说说我以前的模块拆分。最早的拆分是每个业务模块主要拆分为:

  • xxx-service:具体业务实现模块。
  • xxx-client:对外提供的RPC接口模块。
  • xxx-common:对外的工具,以及模型。

这种拆分方式,是我早期从一份微服务教程中看到的;优点是简单明了,调用方可选择性地选择需要的模块引入

至于一些通用的组件,如统一返回格式(如ServerResponse,RtObject),则放在了最早的核心(功能核心,但内容很少)模块上

后来,认为这样并不合适,不应该将通用组件放在一个业务模块上。所以建立了一个base模块,用来将通用的组件,如工具,统一返回格式等都放入其中

另外,将每个服务都有的xxx-common模块给取消了。将其中的模型,放入了xxx-client,毕竟是外部调用需要的; 将其中的工具,根据需要进行拆分:

  • base:多个服务都会使用的
  • xxx-service:只有这个服务本身使用
  • xxx-client:有限的服务使用,并且往往是服务提供方和服务调用方都要使用。但是往往这种情况,大多是由于接口设计存在问题导致的。所以多为过渡方案

上述这个方案,也就是我在负责某物联网项目时采用的最终模块划分方式

在当时的业务下,该方案的优点是模块清晰,较为简洁,并且尽可能满足了迪米特原则;缺点则是需要一定的技术水平,对组件的功能域认识清晰。并且需要有一定的设计思考与能力(如上述工具拆分的第三点-xxx-client,明白为什么这是设计缺陷导致,并能够解决)

新的问题

那么,既然上述的方案挺不错的,为什么不复用到现在的项目呢?

  • 因为业务变了,导致应用场景变了;而这也带来了新的问题,新的考虑角度

  • 原先的物联网业务规模并不大,所以依赖也较为简单,也并不需要进行依赖的封装等,所以针对主要是client的内/外这一维度考虑的。

但是现有的业务场景,由于规模较大,模块依赖层级较多,导致上层模块引入过多的依赖。如有一个缓存模块,依赖tair-starter(一个封装的key-value的存储),然后日志模块依赖该缓存模块(进行性能优化),紧接着日志模块作为一个通用模块,被放入了common模块中。依赖链路如下:

调用方 -> common模块 -> 日志模块 -> 缓存模块 -> tair-starter依赖

但是有的调用方表示,根本就不需要日志模块,却引入了tair-starter这一重依赖(starter作为封装,都比较重),甚至由于tair-starter的内部依赖与自身原有依赖冲突,得去排查依赖,进行exclude
但是同时,也有的调用方,系统通过rich客户端,达到性能优化等目标

所以,现有的业务场景除了需要考虑client的内/外这一维度,还需要考虑client的pool/rich这一维度

可能有的小伙伴,看到这里有点晕乎乎的,这两个维度考量的核心在哪里?

内/外,考虑的是按照内外这条线,尽量将client设计得简洁,避免给调用方引入无用依赖

而pool/rich,考虑的是性能,用户的使用成本(是否开箱即用)等

最终解决方案

最终的解决方案是对外提供3+n

  • xxx-client(1个):所有外部系统引用都需要的内容,如统一返回格式等
  • xxx-yyy-client(n个):对具体业务依赖的引用,进行了二次拆分。如xxx-order-client(这里是用订单提花那你一下,大家理解意思就OK)
  • xxx-pool-client(1个):系统引用所需要的基本依赖,如Lindorm的依赖等
  • xxx-rich-client(1个):系统引用所需要的依赖与对应starter,如一些自定义的自动装载starter(不需要用户进行配置)

这个方案,换个思路,理解也简单
我们提供相关的能力,具体如何选择,交给调用方决定

其实,讨论中还提到了BOM方案(通过DependentManagement进行jar包版本管理); 不过分析后,我们认为BOM方案更适合那些依赖集比较稳定的client,如一些中间件。而我们目前的业务系统,还在快速发展,所以并不适用。

总结

简单来说,直接从用户需求考虑(这里的用户就是调用方):

  • 外部依赖:
    • 额外引入的依赖尽可能地少,最好只引入二方依赖(我们提供的jar),不引入第三方依赖
    • 引入的二方依赖不“夹带”私货(如二方jar引入了一堆大第三方依赖)
  • 自动配置:
    • 可以傻瓜式使用。如引入对应的starter依赖,就可以自动装配对应默认配置
    • 也可以自定义配置。用户可以在自定义配置,并不用引入无效的配置(因为starter经常引入不需要的依赖)
  • 性能:
    • 可以通过starter,提供一定的封装,保证一定的性能(如接口缓存,请求合并等)
    • 可以自定义实现基础功能。因为有些人并不放心功能封装(虽然只是少数,但是稳定性前辈提出的)

补充

这里补充一点,我对讨论中一个问题的回答,这里提一下

有人提到工具类,应该如何划分;因为有的工具类,是不依赖于服务状态的,如CookieUtil进行Cookie处理。有的工具类,是依赖于服务状态的,如RedisUtil包含RedisPool状态,直连Redis,处理Redis请求与响应

其实这里有两个细节:

  • 工具应该按照上面的方式进行划分为两种。单一模块系统,不依赖服务状态的工具往往置于util包,依赖服务状态的工具往往置于common包中。这里还有一个明显的区分点:前者的方法可以设为static,而后者并不能(因为依赖于new出来的状态)。
  • 依赖于状态的工具类,其实是一种拆分不完全的体现。如RedisUtil,可以拆分为连接状态管理的RedisPool与请求响应处理的RedisUitl。两者的组合方式有很多,取决于使用者的需要,以后有机会写一篇相关的博客。不过,我希望大家记住 面向接口编程的原则

最后我想说:

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,愿与诸君共进步

相关文章

  • 实战分析:项目业务模块划分与包名设计思想

    前言 首先明确一下,这里所说的 业务模块 的划分,是针对 client,service,common 这样的技术划...

  • 模块的设计

    模块的设计 包的划分应该按照业务来划分,而不是职责 职责越具体的类/模块,应该放在越具体的包内部 严格控制类的可见...

  • 【滴滴打车-杭州】 服务器端高级 Java 开发工程师/ Jav

    职位描述: 1. 参与产品设计,完成系统需求分析设计; 2. 参与服务器端业务架构设计, 模块划分和模块开发; 3...

  • 测试开发笔记一(测试流程与理论)

    01 | 软件开发流程与项目管理 软件开发步骤 需求分析 概要设计:描述系统的处理流程、组织结构、模块划分、功能分...

  • Android 组件化方案对比

    为什么要组件化 在项目中,主要按包进行业务逻辑划分,并不存在模块组件的概念,各业务模块存在直接回调(如图2所示),...

  • 定制项目规则 ,科学实施计划

    找关键组员,如客户业务专家、系统分析员等,做项目模块划分工作 项目分成几块去做,每一块完成什么,模块之间的信息如何...

  • 概要设计与详细设计

    概要设计主要就是在需求分析之上,进行合理的模块划分。在这一阶段,划分模块是关键。具体的步骤:1.根据框架划分模块(...

  • 项目实际开发手册

    1,需求分析: 2,系统分析: 1>确定项目的技术框架,开发工具。 2>模块划分,各模块功能分析。 3>模块之间的...

  • 当MVP遇上Dagger2

    一、mvp+dagger2的包结构划分 1.直接从mvp+dagger2在app中的业务模块包划分开始: 系统中的...

  • 包 模块

    项目的组织结构包(文件夹)==》模块(文件)==》 类(class 包含函数 变量) 命名空间包名.模块名 包的概...

网友评论

    本文标题:实战分析:项目业务模块划分与包名设计思想

    本文链接:https://www.haomeiwen.com/subject/gygxgrtx.html