首页 编程语言 领域模型应用

领域模型应用

系统设计
任何系统设计都可以用schema表示,不管画什么设计图,其核心思路就是找层级和关系。所以任何系统都可以用树型结构表达!

用树型结构表达局限在于,树是个二维结构。系统可以有不同维度的树,有了不同维度的树后,单靠一颗树不足以描述复杂的业务形态。所以,就要找出哪些是维度是变的,哪些是不变的。

变的是什么
场景
在领域模型中叫context,对应spring里的也是context,context的核心思路是把各种概念划分出边界。

比如购物车与结算页

在购物车的计算优惠的逻辑与结算页几乎一样,但它们有差异,如果在代码中就描述这种差异,是否逻辑将会非常清楚

购物车context

购物车只计算商品与优惠券,优惠价,换购

结算页context

结算页还需要计算个人权益、用户选择优惠方案、口令等操作

两者计算核心逻辑用OrderContext来计算

为什么要用context来记录,用文档不行吗,最好的文档就是代码!

用context可以描述各种层级关系,也就是表达树模型!过度的context也会增加理解。所以,context也需要有层级归类来保证不过度熵增!当然给context一定的命名规则也可以减少理解难度。

流程
流程容易变,系统变化最大的就是流程,流程可以变顺序、变条件、变参数、变结构、变关系、变路径等。也正是因为流程的变动大,代码的实现以面向流程是最容易实现的。

面向流程最容易完成简单的工作,当面向非复杂的工程时,流程非常长且关系较为复杂时的流程变化时,就非常吃力。

就好比人吃饭这个需求时,面向流程的编程里,你还需要把饭怎么来的,怎么煮熟,饭有没有熟等许多条件都加进来判断,才能完成这个需求。

而面向对象编程,饭这个领域对象只要创建好就行了,至于饭是怎么来的,是蒸熟、煮熟、有没有熟都由饭这个领域对象自己判断,它有一套完整的流程来保证自己是熟的饭。在完成人吃饭的需求时,只需要关心吃饭这个流程即可!

定义
定义某个业务时,在某个时刻它是大家描述的样子,在业务发展到一定阶段后,它可能变了,这是对系统稳定性是非常大的挑战!

比如定义一品多供概念时

早期的定义是,一个商品由多个供应商供应,那么,定义这个商品时的价格,规格是不变的,变的只是供应商。

而现在的定义是,一品多供只是一个组ID,代表售卖时就按这个ID去售卖,其背后的价格与供应商本来就不一样。


语言的模糊性影响代码的实现
活动概念的模糊性

有效概念的模糊性

类型概念的模糊性

不容易变的是什么
领域模型
领域模型的定义是不容易变的。这里不变指概念不变,沟通时不变的概念。但是真的是不变的吗,不一定,比如活动的时间在某个阶段,它表示单纯的时间,在业务发展中,它需要表示动成态截单时间,会变成一个带id的对象

所以,不变的是时间概念不变,变的是随着业务的发展,它由属性变成了值对象或是领域,由领域拆成了系统等等。而活动的概念是不变的。

系统的成长自然就成了,领域对象的成长+新的领域对象的加入,系统这颗树也就长大了。

领域模型的层级关系不容易变

领域模型定义好了之后,各种层级关系也就定义好了,这是不容易变的,除非有重大的变动。否则,系统的稳定性就无从说起了。

营销工具定义好了之后,工具子类,如券、价、余额、换购等就定义好了。子类的层也就定好了,不允许再变了。

层级
层级不容易变。

代码层级不容易变,画的架构图不容易变,模板与实例的关系不容易变。

领域模型的层级不容易变,一般都是不停的增加层级关系,原来的关系一般不容易变。

场景的层级也不容易变,场景只会变多与变少,复用的场景不容易变。


为什么需要领域模型
领域模型的产生在某个阶段来说,是确定不变的,需求只是在各种场景用领域对象做组合完成它。

举例:我有一个工人施工队,可以提供建房的能力。那么工人就是这个领域的对象,建房所需要的所有资源就是场景上下文,建房这个动作就是建房场景中的功能。

当建完房子后,又接到一个修路的工程,那么工人还是领域对象,就有个修路的场景上下文来保证修路工程所需要的资源,修路这个动作就是修路场景中的功能。

所以,当你建好了领域模型后,能完成的场景业务就非常多了。各种场景对于领域模型来说,你只要保证场景所需要的资源到位,就保证能完成场景的功能。

找到这个规律后,所有的系统逻辑都可以按这个不变的模型去套!本质上就是找共性。


一切皆对象
当一切皆对象时,业务全是对象,各种层级的对象建立好后,本质上就是领域建模了,只需要完成模型与模型之间的关系。

过去总结的经验,任何业务流程拆解下来,只分为几步,适用于所有业务模型!

创建领域对象
创建业务场景
在场景中给领域对象建关系
在关系中做计算
在场景中组装计算结果
虽然许多简单流程可能不用这么多步骤,但无论多么简单的流程都可以用这几个步骤来走通!

关系
建关系时,领域对象自身有效性判断,能不能建关系又涉及到有效性校验等,建了关系是不是有效的关系等。关系建好时,业务都已经计算好了,只需要从场景对象的有效关系中获得结果就行了

所有的关系都可以用1对1来表示。

1对多的关系时,这就是系统领域拆分点。

商品与导购 1对N

营销工具与优惠券

关系有效性

场景 我们常说业务复杂,本质上就是场景多。如果场景全都梳理清楚了,所谓的复杂只是关系多!多不复杂,乱才复杂。


充血模型带来思考方式的转变!
思考角度 传统贫血模型(事务脚本) 充血模型(领域模型)
模型视角 实体只是数据容器(DTO) 实体拥有行为和业务逻辑
业务行为 写在 Service 里 写在 Entity 或 Domain Object 中
代码职责 Service 肥大、Entity 无脑 Entity 主动、Service 变薄
封装性 数据和行为分离,易出 bug 数据与行为绑定,增强一致性
过程驱动 谁来调用?怎么调用? 对象该做什么?它职责是什么?
可维护性 易失控、缺乏内聚性 高内聚、变化局部化
建模方式 结构导向:建表→写增删改查 语义导向:动词行为→建对象
充血模型改变的,不只是代码位置,而是建模哲学!


不破不立
继承会增加复杂性
继承的形态比组合的形态复杂

父类是不知道子类的类型

继承的引入一定会带来泛型,泛型是复杂代码的原罪之一

没有继承就没有父类,自然就没有抽象类,抽象类的实现只有在运行时才知道具体的实现类

不用map结构作为领域对象
对象比map有更明确的结构,也更容易扩展

数据表的设计没有map类型的表

领域的定义是明确的这点矛盾,map表达是模糊的,不确定性太强!

redis缓存只是缓存,减少依赖缓存数据结构。

现在许多系统都滥用redis,其本质redis数据结构简单,容易完成某些业务功能。而从设计的角度出发,redis数据结构不具备表达领域特性。

如需要redis表达领域特性,需要把对象序列化后保存到redis中,这样,redis就具备领域特性了。

当系统成长到一定规模时,不得不依赖redis的高性能数据结构时,才引入redis数据结构。

要明白redis定位是缓存,不是数据库。

领域模型的一个好处是带来思维方式的转换。你不用关心用哪种数据库,用哪个redis版本,用什么orm框架!在设计阶段,只需要关心设计的领域模型是否能满足业务。

只有模型设计好了,后续考虑如何存,如何缓存等真正技术上的事。软件工程容易做复杂的原因之一是过早的技术介入会限制系统设计。


技术上大胆突破,做大量减法
避免继承

没有泛型

不用map数据结构表示对象

避免引入设计模式(大量context来抽象表达)

避免复杂算法。算法可以用AI帮忙生成和用大量测试用例保证

缓存就是缓存,避免把缓存当数据库

使用轻量级ORM JPA

指标系统全新设计,去掉redis的lua脚本

避免分布式事务,避免分布式锁,依赖数据库事务

领域模型都是充血模型,所有context都是充血对象,保证各自完成自己领域内的事!

service层只做流程,不做领域层业务逻辑

做减法
忘记中间件,专注于领域模型。只有缓存,存储,事件概念

不执着于技术的先进性,业务才是技术发展的唯一源动力。效率才是解决成本的关键

业务体量对于系统设计的影响

系统以领域模型划分模块,不再以技术角度或流程拆分系统!

系统成长
用领域建模的关键点是对业务足够了解,如果是新业务,在不足够了解业务的前提下建模,容易推翻。个人经验会在建模时,最好走1步想3步,多考虑以后的业务发展。这就是系统成长带来的必然之痛,好的抽象归类是系统建模关键一步。

传统的系统很依赖数据的关联查询,因为有了数据库的关联查询,几乎不再考虑领域与领域之间的关系是如何连接的。自然而然,很多的重逻辑都用sql写完,本质上用sql写逻辑是屏蔽了领域之间的关联关系。当业务做大时,数据库不堪重负。当把业务剥离出数据库后,才有机会做缓存,做分布式!

引入领域模型后,做缓存与做业务会非常清晰,你只将需求拆解成领域模型的各种任务,然后用对应的context组织起来,用service层串流程就好了。

领域模型本质是将管理学应用到工程
领域对象一般指有唯一id的对象称之为领域对象。一切设计从领域对象定义好后开始。

领域对象就如同一个大型项目,需要把参与这个项目的人分成各种工种的人。大家协调合作来完成一个大型项目。领域对象就是来完成大型项目的人的抽象!

小项目是一个人就能全做了,当遇到庞大复杂的大型工程,一个人的能力是有限的,就需要多人协助完成。而人多了就需要分工,就涉及到对象职责、工作边界的问题。工程大了就涉及到各种场景应用问题,各种工具和各种工程承包等问题。这种问题也同样存在领域模型的设计中,所以就引入了各种领域对象,边界上下文,各种工具,各种拆分领域等概念来规范!

领域模型的本质是将管理学应用到工程项目中。而将管理学应用到工程中的典型就是spring。

站星网

系统设计任何系统设计都可以用schema表示,不管画什么设计图,其核心思路就是找层级和关系。所以任何系统都..

为您推荐

DDD领域驱动设计的理解

前言领域驱动设计(DDD,Domain-Driven Design)是一套以业务领域知识为中心、以统一语言和模型为驱动的复杂软件系统设计方法学。它的核心思想是:把技术实现与业务知识深度融合,让代码成为业务概念的忠实映射,从..

大/小模型在视频分析领域中的联合应用

CV领域小模型发展自2012年AlexNet在ImageNet大规模视觉识别挑战赛(ILSVRC)中以显著优势夺冠以来,计算机视觉(CV)领域进入了深度学习驱动的新纪元。AlexNet首次大规模使用卷积神经网络(CNN)进行图像分类,其成..

权限系统:6个权限概念模型设计

大家好,我是汤师爷~今天来来聊聊权限的概念模型设计。权限的概念模型用户在权限模型中,用户是系统权限控制的核心对象,也是所有操作行为的直接主体。用户的权限决定了他们在系统中能够访问哪些资源,以及能执行哪..

大数据领域面临的挑战与未来的演进趋势

序有群友提了一个关于大数据行业当前发展状况的问题。暂时先用GPT帮我们对此问题,搜罗和总结一二。其一,此问题较为宏大,需要结合个人实践、对行业的综合认知做深度思考,较为耗时。短时间内,懒于再一一总结和思..

领域驱动的事实与谬误 一 DDD 与 MVC

本文有以下几个目的:让新手少交智商税,少浪费时间看一些软文。普及一个基本概念:了解一项观点的提出年代和最初初衷,才能更好地掌握其精粹。我想指出市场上一些误人子弟的软文。首先说明:文中所说的谬误并非原书..

从零实现富文本编辑器#3-基于Delta的线性数据结构模型

数据模型的设计是编辑器的核心基础,其直接影响了选区模型、DOM模型、状态管理等模块的设计。例如在quill中的选区模型是index + len的表达,而slate中则是anchor + focus的表达,这些都是基于数据模型的设计而来的。..

交易系统:退款单模型设计详解

大家好,我是汤师爷~和退款单作为整个交易逆向系统的核心,支撑着售后管理环节。售后域核心概念模型1、退款单退款单是记录和跟踪退款处理过程的核心业务单据,包含以下关键信息:租户ID:标识所属商户或组织退款单ID..

领域驱动设计,让程序员心中有码(七)

-设计原则和设计模式,互联网开发者们共同的追求 前言多年来,笔者一直从事传统软件企业的软件开发和项目管理工作。笔者发现在众多的传统软件企业中,评判优秀开发者的标准往往是技能的熟练程度,基本上都是以梭代码..

一文搞懂SaaS架构建设流程:业务战略设计、架构蓝图设计、领域系统架构设计、架构治理与实施

大家好,我是汤师爷~SaaS架构建设是一项复杂的系统工程,不仅需要技术层面的实现,更要从业务战略、架构设计、治理与实施等多个维度进行全面规划。一个成功的SaaS架构可以帮助企业降低IT成本、提升业务灵活性、加快..

领域驱动设计,让程序员心中有码(六)

领域驱动设计-聚合,一种极简的思维模式引言 作为IT技术产业飞速发展的产物,软件工程学已经成为当今时代非常重要的一个学科。作为一名资深的软件开发从业者,我们需要学习的东西实际上已经远远超出了原本在大学教育..

微软发布VS Code AI工具包,集成多模型AI能力

微软发布了VS Code AI工具包,增强了代码编辑器的AI功能!微软推出了VS Code AI工具包,这是一个全新的扩展,旨在将AI功能集成到Visual Studio Code中。该工具包支持多种AI模型,包括本地和远程模型,用户可以配置自..

.NET Core 管道模型中间件及管道模拟实现

管道,PipelineASP.NET Core 路由,认证,绘画,缓存,都是由管道来处理的中间件。MVC WEB API,都是建立在某个特殊的中间件之上。MVC,路由的中间件,请求地址和控制器之间的映射,在此基础上实现了实例化控制器,..

vercel发布免费AI工具 支持GPT3.5 GPT-4 和claude等模型

vercel 免费playground地址:https://play.vercel.ai/无需登录,无需翻墙就可以免费使用vercel AI工具,支持GPT3.5,GPT-4 和 claude 等20多个模型,下面是我是用的截图。速度也很快,国内可以直接使用。..

开源中文LLaMA2模型 Chinese-Llama-2-7b

Meta开源了LLaMA2模型,但是官方的LLaMA2对中文的支持度不是特别充分,Chinese Llama 2 7B号称是开源社区第一个能下载、能运行的中文 LLaMA2 模型。Chinese Llama 2 7B全部开源,完全可商用的中文版 Llama2 模型及中..

《实现领域驱动设计》笔记——上下文映射图

一个项目的上下文映射图可以用方式来表示。比较容易的一种是画一个简单的框图表示两个或多个限界上下文之间的映射关系。该框图表示了不同的限界上下文在解决方案空间中是如何通过集成相互关联的。另一种更详细的方式..

LangChain开发环境部署AI大模型

当下在AI应用开发领域,LangChain框架可以说是唯一选择。然而,上手学习的小伙伴们大多被拦在了第一步,没有可供使用的AI大模型底座,没有可供实验的环境进行实操。而各大厂商比如OpenAI提供的API需要付费不说,从注..

清华启动ChatGLM对话模型内测

清华大学计算机系技术成果转化公司智谱AI于近日开源了General Language Model (通用语言模型,GLM)系列模型的新成员——中英双语对话模型ChatGLM-6B,支持在单张消费级显卡上进行推理使用。这是继此前开源..

腾讯混元大模型官网发布 价格每1000 token收费0.14元

在发布会上,腾讯宣布混元大模型今日起对外开放,用户可通过腾讯云进行体验,支持直接调用 API 接口,或者将混元作为基底模型,在公有云上进行精调。腾讯混元大模型官网:https://cloud.tencent.com/product/hunyuan..

使用Ollama在本地安装Google轻量级开源大模型Gemma

Google轻量级开源大模型Gemma在个人电脑上也可以部署体验了!以下是详细部署步骤:一、安装 Ollama1.访问 Ollama 官方网站(https://ollama.com/)。2.下载适合操作系统的 Ollama 版本。3.在 Windows 上,下载后直接..

.NET 高级程序员面试题和答案

在.NET高级程序员的面试中,通常会涉及到一系列深入的技术问题,这些问题旨在评估候选人的编程能力、系统设计理解以及对.NET平台和相关技术的掌握程度。以下是一些可能的面试问题及其简要答案:如何在Controller中注..

发表回复

返回顶部

微信分享

微信分享二维码

扫描二维码分享到微信或朋友圈

链接已复制