二代水务系统架构设计分享——DDD+个性化
系统要求
C/S架构的单体桌面应用,可以满足客户个性化需求,易于升级和维护。相比于一代Winform,界面要求美观,控件丰富可定制。
解决方案
依托.Net6开发平台,采用模块化思想设计(即分而治之的策略),每个模块采用DDD分层设计。前端选用WPF + Prism 框架,后端选用ABP + EF框架,数据库选择SQL Server。
业务拆分
核心领域:包含用户管理、客户管理、表具管理、方案管理、抄表管理
通用领域:包含权限、菜单、个人中心、参数配置、审计日志、数据字典
支撑领域:包含数据查询、统计报表、消息管理、STS安全、工单、自动升级
业务建模
通过业务拆分,水务领域已经被划分为若干子领域(即模块)。每个模块可以看成是一个限界上下文,在此边界内可以进一步拆分更细粒度的单元(我们把最小的业务单元叫做聚合)。一个模块也可能只有一个聚合,如:数据字典。
先拿简单的用户管理来说,用户(User)、角色(Role)、组织(Organization)三者关系紧密、彼此协作。一个用户可以拥有多个角色,一个组织可以拥有多个用户,因此可以归属到用户界限上下文,它们既是实体又是聚合根。
再拿复杂一点的客户管理来说,客户可分为预付费和后付费两种。对于预付费客户来说,可以按量或按金额购水。对于后付费客户来说,每月会生成一笔月账单,客户需要及时充值,否则就会欠费。因此,在客户这个业务边界内,可以确定客户(Customer)、客户类型(CustomerType)、交易记录(Transactions)、月账单(MonthlyBilling)等领域对象。其中水费的计算是一个非常复杂的业务逻辑,涉及到阶梯价格、附加费、债务、当月历史售水交易等多个领域实体,所以需要借助领域服务来完成这笔交易。
系统设计
系统设计包含两部分:全局设计和局部设计。
全局设计是从框架角度来进行整体设计。系统框图如下:
虚线框部分为笔者设计的Lapis.Framework框架,文件组织结构如下:
其中,Laison.Lapis.XXX文件夹代表基础业务模块(Laison.Lapis.Shared除外),如:审计日志、消息管理等,每个模块就是一个独立的C#解决方案。Laison.Lapis是一个底层类库,封装各种通用基础功能,供上层调用。Laison.Lapis.Shared称之为共享模块,用于封装和业务无关,可以被业务模块共享使用的功能,如: 抽象基类、接口、虚方法等。因为是单体应用设计,所以模块之间少不了相互引用的关系。模块划分越多,引用关系也会变得越复杂。
局部设计是从业务角度来进行模块设计,每个模块按照DDD来分层:基础设施层、领域层、应用层和表现层。下面是用户管理模块(Laison.Lapis.Identity)的分层设计:
Laison.Lapis.Identity.UI:表现层,包含前端页面、控件和一些UI逻辑。
Laison.Lapis.Identity.Application.Contracts:应用接口层,负责定义应用接口和DTO。
Laison.Lapis.Identity.Application:应用层,用于实现应用接口,包含各种应用逻辑。
Laison.Lapis.Identity.Domain:领域层,负责业务逻辑处理,包含实体、值对象、仓储接口等领域模型。
Laison.Lapis.Identity.Domain.Shared:领域共享层,包含了一些枚举和常量的定义,可供其它任意层调用。
Laison.Lapis.Identity.EntityFramework:实体框架层(EF),包含实体的映射配置和仓储的实现。
Laison.Lapis.Identity.HttpApi.Host 和 Laison.Lapis.Identity.Shell:即宿主和壳,分别用来启动前/后端应用程序。
在ABP框架的世界里,每一分层就是一个模块单元,它是代码层面的模块,而Identity是业务层面的模块,后者包含前者,最终以DLL的形式来呈现。
系统如何运行
但随着系统不断迭代,模块数量也再随之增长。假设1个模块会生成6个DLL(采用DDD分层),那么20个模块就会有120个DLL,听上去有点吓人。每次模块发生变化,就要重新打包、发布、升级120个Nuget包,这显然不符合常理(非常耗时)。后来笔者采取了一种折中的处理方式:将通用稳定性强的模块保留在Lapis.Framework中,把易于变化的模块下沉到项目中管理,这样就能避免之前的尴尬,但却牺牲了模块代码的复用性。项目最终代码结构如下:
个性化定制
企业个性化功能定制是一个普遍而又绕不开的话题,假如能用一套代码把所有客户的需求全部覆盖,当然是最理想的状态(现实几乎不可能,除非通用标准化)。所以笔者从设计一开始就是围绕如何提高代码的复用,将差异化分散到项目中的思路来展开,这也是采用模块化设计的初衷。至于个性化如何来实施?根据笔者已知的做法有以下两种:1. 通过版本管理开分支的方式,2. 简单粗暴,每个项目都单独复制一套标准版,然后在上面做定制化修改。 除此之外,笔者似乎没有想到更好的办法。至于选择哪一种,就要根据项目实际情况来考量。
结束语
无论是模块化设计还是DDD,都是强调从业务领域角度出发,根据业务的发展,合理划分业务边界,采用分治策略,降低业务和软件开发的复杂度,持续调整现有架构,以保持架构和代码的生命力。 因此,世界上并不存在一劳永逸的架构,软件设计本身就是一个平衡取舍的过程,只有合适的才是最好的,这也许就是架构设计的魅力所在吧!如果你有好的建议或不同想法,欢迎评论区留言。
二代水务系统架构设计分享——DDD+个性化的更多相关文章
- 万级TPS亿级流水-中台账户系统架构设计
万级TPS亿级流水-中台账户系统架构设计 标签:高并发 万级TPS 亿级流水 账户系统 背景 业务模型 应用层设计 数据层设计 日切对账 背景 我们需要给所有前台业务提供统一的账户系统,用来支撑所有前 ...
- 基于Struts2,Spring4,Hibernate4框架的系统架构设计与示例系统实现
笔者在大学中迷迷糊糊地度过了四年的光景,心中有那么一点目标,但总感觉找不到发力的方向. 在四年间,尝试写过代码结构糟糕,没有意义的课程设计,尝试捣鼓过Android开发,尝试探索过软件工程在实际开发中 ...
- 新零售SaaS架构:多租户系统架构设计
什么是多租户? 多租户是SaaS领域的特有产物,在SaaS服务中,租户是指使用SaaS系统的客户,租户不同于用户,例如,B端SaaS产品,用户可能是某个组织下的员工,但整个企业组织是SaaS系统的租户 ...
- PetShop的系统架构设计
<解剖PetShop>系列 一.PetShop的系统架构设计 http://www.cnblogs.com/wayfarer/archive/2007/03/23/375382.html ...
- petshop4.0 具体解释之中的一个(系统架构设计)
前言:PetShop是一个范例,微软用它来展示.Net企业系统开发的能力.业界有很多.Net与J2EE之争,很多数据是从微软的PetShop和Sun的PetStore而来.这样的争论不可避免带有浓厚的 ...
- NET ERP系统架构设计
解析大型.NET ERP系统架构设计 Framework+ Application 设计模式 我对大型系统的理解,从数量上面来讲,源代码超过百万行以上,系统有超过300个以上的功能,从质量上来讲系统应 ...
- Unity3D手游开发日记(2) - 技能系统架构设计
我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活自由的技能系统架构设计,传统的技能设计,做法都是填excel表,技能需要什么,都填表里,很死板,比如有的技能只需要1个特效,有的要10 ...
- 图数据库 Nebula Graph 的数据模型和系统架构设计
Nebula Graph:一个开源的分布式图数据库.作为唯一能够存储万亿个带属性的节点和边的在线图数据库,Nebula Graph 不仅能够在高并发场景下满足毫秒级的低时延查询要求,而且能够提供极高的 ...
- 5G 融合计费系统架构设计与实现(一)
5G 融合计费系统架构设计与实现(一) 随着5G商用临近,5G的各个子系统也在加紧研发调试,本人有兴全程参与5G中的融合计费系统(CCS)的设计.开发.联调工作.接下来将用几篇文章介绍我们在CCS实现 ...
- [转]【转】大型高性能ASP.NET系统架构设计
大型高性能ASP.NET系统架构设计 大型动态应用系统平台主要是针对于大流量.高并发网站建立的底层系统架构.大型网站的运行需要一个可靠.安全.可扩展.易维护的应用系统平台做为支撑,以保证网站应用的平稳 ...
随机推荐
- Oracle 定时任务job实际应用
目录 一.Oracle定时任务简介 二.dbms_job涉及到的知识点 三.初始化相关参数job_queue_processes 四.实际创建一个定时任务(一分钟执行一次),实现定时一分钟往表中插入数 ...
- SDK日志上传性能优化
问题描述 在SDK初始化时,会在init方法中开启一个倒计时,在5s倒计时结束后使用子线程将本地保存的历史日志信息上传到后台. 因业务需要,在日志在发送上传前,对日志数据上传时需要对日志数据做编码和特 ...
- vue全家桶进阶之路17:组件与组件间的通信
在 Vue2 中,组件与组件之间的通信可以通过以下几种方式来实现: Props 和 Events 这是 Vue2 中最基础和常用的父子组件通信方式.父组件通过属性传递数据给子组件,子组件通过事件触发向 ...
- ping不通能curl通
今天发现一个域名或ip居然在ping不通的情况下能curl通,以前的思维定式直接给整破防了啊!!! 涨见识了,具体原因和原理后续补充~
- SqlServer 设置用户只能访问特定表、特定数据库
设置用户只能访问特定表.特定数据库 一.只能访问特定数据库 1.[安全性]-[登录名]右击用户.打开属性,选择用户映射,勾选特定数据库 2. 如果 服务器角色 勾选了 [查看任意数据库],那么登录后会 ...
- jQuery 添加水印
jQuery 添加水印 <script src="../../../../AJs/jquery.min.js"></script> <script t ...
- WPF 入门笔记 - 03 - 样式基础及控件模板
原学习路线是按照圣殿骑士的<WPF基础到企业应用系列>的路线走的,但是布局之后直接依赖属性学起来有些僵硬,不太好理解,尝试了文章的前部分内容后放弃,调整为本篇博文内容.笔记路线将按照痕迹g ...
- R 语言关于 SSL 证书异常处理笔记
一.关于 TCGAbiolinks TCGAbiolinks 是一个用于 TCGA 数据综合分析的 R/BioConductor 软件包,能够通过 GDC Application Programmin ...
- Hive执行计划之一文读懂Hive执行计划
目录 概述 1.hive执行计划的查看 2.学会查看Hive执行计划的基本信息 3.执行计划步骤操作过程 4.explain extended 概述 Hive的执行计划描述了一个hiveSQL语句的具 ...
- DosBox环境配置
DosBox环境配置 DOSBox 是一个基于 x86 架构的 PC 的模拟器,它允许用户在现代操作系统上运行 DOS 程序.DOSBox 是自由软件,可以在 Windows.Linux ,macOS ...