当前位置: 首页 > news >正文

小架构step系列24:功能模块

1 概述

开发一个业务系统的时候,功能可能非常多,需要对功能进行分组,这里引入“模块”的概念,它就代表着一组功能。对于程序员来说,“模块”这个概念可能容易混淆,比如python语言里也有Module这个概念,翻译为中文也是“模块”,在python中一个模块就是一个代码文件。所以为了有别于其他“模块”,这里专门指功能分组的“功能模块”。如果觉得“模块”这个词不好理解,也可以换成“应用”,本文采用“模块”来说明。

2 模块的规则

2.1 如何分模块

仅“功能模块”这个概念并不好理解,虽然把它定义为一组功能,但“功能”这个词也比较泛,不同人的理解不一样。这里讲几个分模块的原则,增进一点对模块的理解。

首先是业务分离。比如“物业”这个概念,在一个小区里物业管理包含安防巡逻、设备报修维护、清洁保洁等基础业务,即业内常说的“三保”业务。不同的业务不宜合并在一起,合并在一起就互相受影响,不好维护。

然后是角色分离。一般业务系统都至少有三类角色:服务提供方、服务使用方、系统管理员。既然是业务系统,那就需要提供服务,提供服务的那方就是服务提供方,使用系统所提供服务的那一方就是服务使用方。系统管理员负责系统的初始化配置和基础运维,通常代表系统的所有者(如系统的采购方)。当然角色可能还有更多,比如对于一个SAAS平台,可能还有个平台管理方,它管理着所有的服务提供方和服务使用方,系统也带了这方需要使用的功能。

对于同一类功能,如果涉及到这些角色的,建议按角色分成不同模块。比如物业报修,物业接受维修申请、提供维修服务等,属于服务提供方。看到走道的灯坏了向物业方提交一个说明灯坏了的信息(报修),并享受物业维修灯之后走道有灯光的服务,这方就是服务使用方。在物业方内可能还分两个角色,一个是提供维修服务的业务部门,一个是对维修功能进行授权或者初始配置的部门,前者对应前面说的服务提供方角色,后者则是管理员角色。这个时候可以分为“物业报修”、“报修管理”、“报修配置”三个模块,分别对应不同角色。

从这个角度看,模块之所以按功能分组,其实隐含着一个“权限”在后面,不同的功能使用者不一样,对应的权限不一样,分成不同的模块的好处之一是方便授权。如果上面物业报修例子中只有一个模块,那么分权限的时候就必须在模块下进行细化分配权限,当细化权限过多的时候分配起来就比较困难,而分模块设计后,实践中通常直接按模块分配权限即可。

2.2 统一模块

功能模块是针对整个系统的功能进行分组,天然地有一个“全局”统一的要求。模块最重要的信息有两个:ID和名称。ID是功能模块的唯一标识,这个标识需要全局唯一,需要在整个系统中统一分配。也就是模块的ID需要硬编码,在系统外部统一维护,ID需具备业务语义,能明确映射到具体业务域,在代码中可能需要拿来做逻辑的。

如果业务公司里有产品设计,最好是由产品统一维护,每设计一个功能,就需要明确这个功能属于什么模块。这样比较方便传递到后面的开发和测试,使得大家概念统一。

每个业务系统可以有自己的ID定义。这里建议模块ID用四位数字来表示,前1000个留给系统内部使用,主要是应用于一些不对外的模块,比如发短信发邮件,如果这个发短信或发邮件没有界面、也没有相关管理,就是发一下和记录一下,此时分一个模块感觉有点多余,不分模块可能又无法满足后面的一些权限、错误码等要用模块ID的要求,可以定义一个通用模块“通知服务”,这种模块产品也不关心,就由开发和产品商量使用前1000个ID来定义。

后面1001到9999还有将近9000个ID供业务使用,如果觉得系统足够大不够用,那么要么增加id位数,要么换其它方案。过大的系统就不符合本文“小系统”的范畴了,在此略过。选四位来表示ID,是因为后面会用模块ID来作为错误码的一部分,不宜过长。太短则不够用,所以选一个折中的长度。

2.3 功能粒度

可以认为模块是在代码层面,系统管理功能的最小粒度。比如服务A看到服务B的时候,看到的是服务B里的模块,这个在微服务体系里更加明显。有了这个关联关系,就比较容易识别一些信息,比如某操作来源于某模块等。以发短信为例,发短信需要定义一个模板,这个模板属于什么业务的,应该有个模块对应;短信最终是由什么业务发的,应该对应一个模块。

上面说“代码层面”,这个是站在写代码如何组织功能对应代码来说的。如果是从运行层面,还有可能一套代码对应多种业务的情况,比如有些业务的流程太像了,如列一些课程供选择,选择后提交申请,这个流程和列一些活动供选择然后提交申请的流程几乎是一样的,如果把代码写成一套,那么模块应该就只有一个,但在功能上应该是两个功能,此时需要在模块的基础上再分一下,此时功能管理的最小单位不再是模块,需进一步拆分为子模块或功能点。这种情况不多,也不建议用这种方式,上面两种功能虽然初始的时候看起来好像“流程”一样,但如果它们真的是一种服务,就随着时间的延长,很可能会发展出更多独特的功能,到那个时候可能就“后悔”把这么小的“相似”抽象成一类功能,在扩展和维护上都非常困难。在这个角度上,更偏向分开,虽然初始的代码“拷贝”了一遍多了一点代价,但后续维护和扩展的成本显著降低。

2.4 模块实现

功能模块类是一个不变类,一经初始化就不能再修改,只提供getter,不提供setter。

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Value;@Value
@Schema(description = "功能模块")
public class FunModule {@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED, minimum = "1")Long id;@Schema(description = "模块默认名称", requiredMode = Schema.RequiredMode.REQUIRED)String name;public FunModule(Long id, String name) {this.id = id;this.name = name;}
}

3 架构一小步

统一概念“功能模块”,统一维护,统一分配唯一标识。

http://www.dtcms.com/a/296993.html

相关文章:

  • 【ResizeObserver】【页面布局】监听一个 div 元素的动态高度变化并同步设置另一个元素的高度
  • Windows环境下 Go项目迁移至Ubuntu(WSL) 以部署filebeat为例
  • 【数组的定义与使用】
  • 保障工业核心命脉:深度解读工业交换机QoS的“智能流量治理”之道
  • CMake ARGV变量使用指南
  • Python桌面版数独(五版)-优化选择模式触发新棋盘生成
  • OSPF 实验
  • RuoYi-Vue 项目 Docker 全流程部署实战教程
  • 中国、美国、欧盟、日本、英国临床试验API数据接口
  • Ⅹ—6.计算机二级综合题7---10套
  • Mac系统机能连接操控别的平台设备吗?能被远程操作吗?
  • Nginx快速入门及案例
  • 【安卓笔记】解决livedata粘性事件
  • 《Java语言程序设计》第2章复习题(2)
  • RePlugin 坑位使用原理与指南
  • 多源信息融合智能投资【“图神经网络+强化学习“的融合架构】【低配显卡正常运行】
  • 模拟退火算法 (Simulated Annealing, SA)简介
  • JavaWeb学习打卡14(JSP内置对象及作用域)
  • ARM汇编常见伪指令及其用法示例
  • IntelliJ IDEA中管理多版本Git子模块的完整指南
  • 智慧工厂网络升级:新型 SD-WAN 技术架构与应用解析
  • 商场导航软件:3D+AI 基于Deepseek 模型的意图识别技术解析
  • BacNet 是什么?跟 LoRaWAN 的关系是什么?
  • 将JS字节流转化为对象
  • 西安交通大学XJTU 通信/信息工程大三和部分大四 实验和课程答案
  • C++哪些运算符不能被重载?
  • kubernetes集群中部署CoreDNS服务
  • day46day47 通道注意力
  • 一种基于单片机控制的太阳能电池板系统设计
  • 集训Demo6