关于领域建模时考虑用户需求的出发点的理解

2024-03-11 21:48

本文主要是介绍关于领域建模时考虑用户需求的出发点的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘自http://www.jdon.com/42751

最近又重温了领域驱动设计的原著,有了一些新的理解。现在我觉得我能更好地理解jdon007之前说的下面这段话了。

“用 户需求”不能等同于“用户”,捕捉“用户心中的模型”也不能等同于“以用户为核心设计领域模型”。 《老子》书中有个观点:有之以为利,无之以为用。在这里,有之利,即建立领域模型;无之用,即包容用户需求。举些例子,一个杯子要装满一杯水,我们在制作 杯子时,制作的是空杯子,即要把水倒出来,之后才能装下水;再比如,一座房子要住人,我们在建造房子时,建造的房子是空的,唯有空的才能容纳人的居住。因 此,建立领域模型时也要将用户置于模型之外,这样才能包容用户的需求。

所以,我的理解是:我们设计领域模型时不能以用户为中心为出发点去思考问题,不能老是想着用户会对系统做什么;而应该从一个客观的角度,根据用户需求挖掘出领域内的相关事物,思考这些事物的本质关联及其变化规律为出发点去思考问题。

下面以Eric Evans(DDD之父)在他的书中的一个货物运输系统为例子简单说明一下。

在经过一些用户需求讨论之后,在用户需求相对明朗之后,Eric这样描述领域模型:
1. 一个Cargo(货物)涉及多个Customer(客户,如托运人、收货人、付款人),每个Customer承担不同的角色;
2. Cargo的运送目标已指定,即Cargo有一个运送目标;
3. 由一系列满足Specification(规格)的Carrier Movement(运输动作)来完成运输目标;

从 上面的描述我们可以看出,他完全没有从用户的角度去描述领域模型,而是以领域内的相关事物为出发点,考虑这些事物的本质关联及其变化规律的。比如第1点, 如果是以用户为中心的话,就变成了:一个托运人可以托运货物,即具有托运货物的行为,一个收货人可以收货物,一个付款人需要付款;而他的描述中完全以货物 为中心,把客户看成是货物在某个场景中可能会涉及到的关联“事物”,如货物会涉及多个客户,货物有一个确定的目标,货物会经过一系列列的运输动作到达目的 地;其实,我觉得以用户为中心来思考领域模型的思维只是停留在需求的表面,而没有挖掘出真正的需求的本质;我们在做领域建模时需要努力挖掘用户需求的本 质,这样才能真正实现用户需求;

这让我想到了我之前思考图书借阅系统时的出发点也是错误的,因为我之前总是在以用户为中心思考问题。比如借书者借书,借书者还书,管理员对书本入库,等等;经过上面的分析后,我觉得我应该以书本为核心出发点思考领域模型。如:
1. 一本书在某个时刻最多只能被一个人借,或者没有被借走留在图书馆;
2. 书本在被归还时需要检查归还时间,如果有超期则需要做罚款处理;
3. 一本书有库存信息,如书本存放位置,库存数量;
4. ……

没有从用户的角度去描述领域模型,而是以领域内的相关事物为出发点。



看来认识识分析需求有两种线索,一个是以人为核心的需求分析;还有一个与人无关,事物领域自身的内在规律,或者称为“道”。

至于以哪个为主要为侧重点,还是要看人和事物在不同场景中扮演戏份的多少与否,比如在货运系统中,从这个名字我们也可以看出以货为主的一个运输系统,因此,人应该处于次要地位。

但是图书馆借书这个案例中,我个人认为好像不是以书为主的自主运动,而是以人为主,书为辅助的这样一个系统,如果以书为主,就发生“书被借”这样奇幻事情发生,呵呵。

人 != 用户

比如,人口档案管理系统,系统中应有记录人的信息或者说存在关于人的模型,但这个人的模型并不表示用户。

图书馆管理系统,用户群若是“读者”,那么应该将“读者”(用户)至于模型之外;如果用户群是图书馆管理员,那么“读者”(不再是用户,哪怕命名为用户),可以置于模型之内(比如要挖掘用户兴趣模型,发现什么的人群喜欢阅读什么样的书)。

物流系统,如果用户群是“顾客”,那么应该将“顾客”至于模型之外;如果用户群是“管理者”,那么可以将“顾客”(此时已不是系统的用户)放在模型之内。

将“用户”至于“模型”之外,用户群单一时,比较容易做到;若存在多种性质截然不同的用户群时,要注意到不同用户群将有不同的心智模型,尽管它们之间可能有交集。

但是,即便将不同性质的用户群的心智模型聚集在一起,也应遵循这个原则,并需要清醒地意识到视角潜在的变化(这可能被忽略或遗忘, 从而引起混淆)。

从整体上而言,“书”、“账号”、“书库”是模型(包括其结构/状态与功能/行为上的特征),可理解为系统的结构组成;“借阅规则”是场景规约或业务规则,可理解为系统的运作规则。

用户(读者)的心智模型不仅仅包含书,还应包含账号(图书卡)、书库(图书馆)等,模型有状态有行为,但其在参与场景进行交互时的受到场景规约的约束。

一种可以尝试的思路,是从业务规则(感知场景,从中提炼出的场景规约)中发现模型,并将业务规则与模型进行整体上的分离,让模型更自由,从而可能复用于不同的业务规则,或适应业务规则的变化。

至于模型的组织可以借鉴四色 原型的PPT , 如图书馆的例子:Place(Library)、Party(Account)、Thing(Book), 或借鉴OO 的message-based的思路,将模型分类为object+message或event+handler/dispatcher; 当然,还有别的分类或组织模型的方法。

模型的使用者不应该被包含在模型内部。 ...



当你确定书是核心领域模型了,那么模型的使用者是不应该包含进来进行分析,通过借书这样一个事件 或场景的发生,模型的使用者与模型发生了关系,这时模型书还是需要一个使用者的记录的。
模型:
Class Book{
String id;
String name;
}

用户操作借书事件 激活借书服务,从而发生借书场景:
Class BookContext{

boolean borrow(Book book);

}

当borrow(Book book)事件被调用以后,拉了一泡屎,留下状态,这个书被借了,借阅者是某个用户,在数据表中我们可能有这样的记录:
book{
String id;
String borrowedUserId;
}

至于,这个borrowedUserId字段是否应该出现在Book模型中,则是另外一种设计考虑,比如我们认为borrowedUserId字段应该属于Book的状态,那么出现在BookState中比较合适,那么Book类有了一个新引用BookState:

Class Book{
String id;
String name;
BookState bookState;
}

Class BookState{
Book book;
User borrowedUser;
Date returnDate;//归还日期等
}

完毕。

我把整个过程列出来,是为了理清我们的思绪,不要让模型的状态去影响我们的分析。

以上这个分析的唯一前提是:假设这个系统是以书为核心,跟踪围绕书发生的各种事件

所以,我们在描述时不能以“书被借”这样去描述需求,会产生误导,因为“借书”是一个事件 ,而“书被借”是一个状态,状态是事件 的结果,事件是状态的因,而模型是事件 的核心,没有模型,事件就无法发生,就象没有电话,就没有电话铃这个事件 ,没有书,就不会有借书这样的事件

由以上倒退,我们知道,分析一个需求,核心模型是第一步,这一步是不应该考虑用户,前提是如果这个用户是在事件 发生时介入的话;但是如果这个用户不是事件 介入发生,而是属于模型一部分,如书的作者,那么就应该考虑用户。

我的观点是:天地不仁,以万物为刍狗。

千万不要以为是人就扔掉:驱动者和参与者的区别。在领域当中的“人”,与“刍狗”等同,没有特殊地位。在整个领域世界中,应该全是逻辑描述,即使是人,也应该以简单对象来理解,构成事实离不开万事万物。

试想一个互动功能,交朋友,没有任何独立于人的实物,把人扔掉会是什么样的效果呢?

理解驱动者与参与者区别,就可以走出误区,account很容易让人想到使用者,分开Passport和Reader不就行了?Reader是人吗?是,但他完全和Book的地位一样,“刍狗”一只而已。

“以用户为中心”的思想主要来自于登录系统——认为系统事件 参 与者就是现实世界中的用户。虽然这样的观点在一定程度上可行,但这种关联只是一个潜在的认为而已——经过登录后,认为某个现实用户(或者电脑,或者仪器, 或者IP)所发出的所有命令是系统中与这个登录所绑定的“人”发出的。这种关联是通过登录后获得,也就是说,若果没有登录,这两者应该是分离的,是两个独 立的个体。

这篇关于关于领域建模时考虑用户需求的出发点的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799183

相关文章

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念

如何通俗理解注意力机制?

1、注意力机制(Attention Mechanism)是机器学习和深度学习中一种模拟人类注意力的方法,用于提高模型在处理大量信息时的效率和效果。通俗地理解,它就像是在一堆信息中找到最重要的部分,把注意力集中在这些关键点上,从而更好地完成任务。以下是几个简单的比喻来帮助理解注意力机制: 2、寻找重点:想象一下,你在阅读一篇文章的时候,有些段落特别重要,你会特别注意这些段落,反复阅读,而对其他部分

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。

分布式系统的主要考虑

异构性:分布式系统由于基于不同的网路、操作系统、计算机硬件和编程语言来构造,必须要考虑一种通用的网络通讯协议来屏蔽异构系统之间的禅意。一般交由中间件来处理这些差异。缺乏全球时钟:在程序需要协作时,它们通过交换消息来协调它们的动作。紧密的协调经常依赖于对程序动作发生时间的共识,但是,实际上网络上计算机同步时钟的准确性受到极大的限制,即没有一个正确时间的全局概念。这是通过网络发送消息作为唯一的通信方式

Java IO 操作——个人理解

之前一直Java的IO操作一知半解。今天看到一个便文章觉得很有道理( 原文章),记录一下。 首先,理解Java的IO操作到底操作的什么内容,过程又是怎么样子。          数据来源的操作: 来源有文件,网络数据。使用File类和Sockets等。这里操作的是数据本身,1,0结构。    File file = new File("path");   字