DailyMart03:如何基于DDD设计商城的领域模型?

大家好,我是飘渺。既然有人催更那今天咱们就继续更新DDD&微服务系列!

在面向对象开发中,所有事物都可以看作是对象。然而,在日常开发中,我们通常从数据出发来设计对象的表现形式,这种做法侧重于数据属性的定义,而忽略了领域逻辑的处理过程。虽然这种做法很常见,但并不是DDD推荐的开发模式。在DDD中,我们关注的是领域数据对象,而非仅仅是数据本身。领域模型对象在本质上不同于数据,它包含了一系列的标识和行为定义,而不仅仅是数据属性的定义。

在DDD中,领域模型对象可以分为聚合、实体和值对象三种类型。实体和值对象是聚合的组成部分,而值对象同时也是实体的组成部分。它们之间的关系如下图所示:

3abce25c7c6619c3de36a66bff705f07.png

在上一篇文章[[DailyMart02:DDD领域分解与微服务划分]]中,我们已经对DailyMart进行了领域分解和限界上下文的拆分。在本文中,我们将从DDD战术的角度出发,对DaliyMart进行设计,分析各个限界上下文中的实体、值对象和聚合对象。

1. 领域模型对象

让我们首先了解一下这几个关键对象。

  1. 实体(Entity):实体是具有唯一标识符(ID) 的对象,它在整个生命周期中保持不变。实体的属性可以发生变化,但其ID始终保持不变。例如,在DailyMart系统中,用户可以是一个实体,因为每个用户都有一个唯一的ID,即使他们的姓名、昵称、密码等信息发生变化,这个ID也不会改变。

  2. 值对象(ValueObject):值对象与实体对象相反,它是一种不具有唯一标识符(ID) 的对象,它们是通过其属性值来定义的,它的一个重要特点是它们是不可变的,一旦创建,它们的属性就不能被修改。如果需要修改值对象的属性,我们需要创建一个新的值对象来替换旧的值对象。值对象通常表示一些简单的概念,如颜色、地址或者金额等。例如在跨境电商系统中,商品的价格通常会被设计成值对象,价格由货币类型和数值组成,我们关心的是这两个属性的组合,而不是价格对象本身的唯一性。

  3. 聚合(Aggregate):聚合是一组相关的实体和值对象的集合,它们共同组成一个整体。聚合有一个根实体,也称为聚合根,它是聚合中最重要的实体,负责维护聚合内部的完整性和一致性。聚合根可以包含其他实体和值对象,但是其他实体和值对象不能直接访问聚合根以外的实体和值对象。这种限制可以保证聚合内部的一致性和完整性,同时也可以简化聚合的设计和实现。

2. 领域建模

接下来,我们将进行领域模型分析,并从用户限界上下文开始。

2.1 用户限界上下文

为了完成限界上下文的领域建模,我们需深入分析业务场景和需求,以形成业务领域的通用语言。

通过与业务人员的深入沟通,我们总结出以下通用语言:

  • 商城用户首先需要注册,填写账号、密码、邮箱、手机号码等信息,注册成功后,系统赠送100积分。

  • 用户购买商品后,系统会赠送一定积分。这些积分在支付时可以抵扣现金,用户还可以查看自己的积分记录。

  • 用户登录系统后,可以维护自己的收货地址。每个用户可以维护多个地址,可以选择删除其中一个地址或将其中一个地址设置为默认收货地址。商品购买后,系统会将商品配送到默认地址。

根据这些业务需求,我们识别出了一些关键的领域模型:

  1. CustomerUser - 用户,显然是一个实体。它包含UsernamePasswordEmailPhoneNumber等属性,并拥有Points(积分)属性、DeliveryAddresses(收货地址列表)和PointsRecord(积分记录)。

  2. PointsRecord - 积分记录。由于我们需要追踪每次积分的变化,即使属性相同,每个积分记录也是独一无二的,因此它是一个实体。

  3. DeliveryAddress - 收货地址。用户可以删除某个地址或将其他地址设置为默认地址,这意味着我们需要对地址进行操作和管理。在这种情况下,将收货地址作为实体可能更合适。

  4. Points - 积分,即使只有一个属性,它也是一个值对象。将Points设计为值对象的原因是它代表了一个具有特定含义和行为的概念。例如,积分不能为负数,并且在某些操作时需要增加或减少特定的数量。通过将其设计为值对象,我们可以封装这些规则和行为,保证数据的完整性。

  5. 在用户限界上下文中,CustomerUser也是一个聚合,它封装了与用户相关的所有数据和行为,包括用户的基本信息、积分、收货地址和积分历史记录。

在实际操作中,实体与值对象的区别可能并不那么明显。例如,我们也可以把PointsRecord看作是值对象,因为系统只允许查看记录,不允许修改。从这个角度来看,积分记录就像用户积分变化的一个快照。然而,在这里,我们还是选择将其设计为实体,因为我们关心的是每一条独特的积分变化记录。


48a4f6068fe2a2eb96c3ef7952f6c5be.png

2.2 订单限界上下文

完成了用户限界上下文的设计后,现在我们进行订单限界上下文的领域模型设计。在“订单”限界上下文中,通过与业务人员深入沟通,我们总结出了以下通用语言:

  • 用户可以在DailyMart网站上下单购买书籍,每个订单可以包含多本书籍。

  • 订单需要包含收货人姓名、地址、联系电话等信息。

  • 订单需要记录订单状态,比如待支付、待发货、已发货、已完成等。

  • 用户可以在订单中查看每个书籍的详细信息,包括书名、价格、作者、ISBN号等。

  • 用户可以在订单中查看订单的配送状态,比如已发货、运输中、已签收等。

根据这些业务需求,我们确定了一些关键的领域模型:

  1. Order - 订单是一个聚合,因为它有其自己的生命周期,每个订单有唯一的订单ID作为标识。订单包含了RecipientInfo(收货人的信息,包括姓名、地址、联系电话),OrderStatus(订单的状态),以及订单中的书籍列表。

  2. OrderItem - 订单项是Order聚合中的一个实体,代表订单中的一本书。它包含了书籍的详细信息,例如书名、价格、作者、ISBN号等。由于每个订单项都是独一无二的,并且在订单中具有持久性,因此被设计为实体。

  3. RecipientInfo - 收货人信息是一个值对象,它没有自己的唯一标识,一旦订单创建就不能被修改,只能被替换。

  4. OrderStatus - 订单状态是一个值对象,可以被设计成枚举类型,表示订单的不同状态,例如待支付、待发货、已发货、已完成等。

  5. DeliveryStatus - 配送状态也是一个值对象,可以设计成枚举类型,表示配送的不同状态,例如已发货、运输中、已签收等。

6c975ce966374f0185fa9c1267b3cad8.png


2.3 商品限界上下文

接下来完成商品限界上下文的领域模型设计。在“商品”限界上下文中,通过与业务人员进行讨论和沟通,我们总结出了以下通用语言:

  • DailyMart主要是销售书籍(纸质版/电子版)。商品属性相对简单,只需要包含书名、价格、作者、ISBN号、简介、出版日期等几个重要属性。

  • 一本书会属于某一个分类,比如计算机类、设计类、心理学,管理员在另一个运营系统中可以配置分类。

  • 管理员可以对书籍进行推荐。

  • 用户登录后可以对书进行评论。

根据这些业务需求,我们识别出了一些关键的领域模型:

  1. Book - 书籍显然是一个实体,它需要一个唯一标识符。书籍包含ISBNtitleauthorprice、等属性,以及bookType(电子书或纸质书),这可以设计成一个枚举类型。此外,Book还有Category分类属性。

  2. Category - 分类,由于管理员在另一个运营系统中进行配置和维护,分类不需要有太多复杂的行为和属性。在此上下文中,我们可以将Category设计为值对象。

  3. Review - 评论,Review 具有持久性的唯一标识(评价ID),应该也是一个实体对象。

  4. 在商品限界上下文中,BookReview都设计成独立的聚合。Book作为核心实体设计为聚合是很自然的,因为它包含了书籍的所有重要属性。而Review则被设计为独立的聚合,使我们可以更方便地处理评论信息,包括添加、修改和查询等。

865342ebd964907c9b64b7522d462de9.png

2.4 购物车上下文

最后,完成购物车限界上下文的领域模型设计。

在“购物车”限界上下文中,通过与业务人员进行深入沟通,我们总结出了以下通用语言:

  • 用户登录后可以将商品添加到自己的购物车中,每个商品可以添加多个,同时可以添加多个商品

  • 在购物车界面需要显示购物车所有商品的数量,以及每个商品的部分信息,如书名、作者、简介等。

  • 在购物车中可以对商品进行选中,选中商品后自动计算商品的价格合计。

  • 选中购物车的商品可以进行结算,但具体的订单生成和管理在另一个“订单”限界上下文中处理。

根据这些业务需求,我们识别出了一些关键的领域模型:

  1. CartItem - 购物车项,代表了用户添加到购物车的商品以及数量。由于购物车项有其自身的生命周期,可以单独创建、更新和删除,所以它应该被设计成一个实体。购物车项需要包含商品的部分信息,如书名、作者、简介等,以便在购物车界面中显示。

  2. Cart - 购物车,这也是一个实体,购物车包含了多个购物车项,每个购物车项代表了用户添加到购物车的商品以及数量。

在购物车限界上下文中,Cart被设计为核心聚合。它代表了用户的购物车状态,包含了用户希望购买的所有商品的信息。这样,我们可以更方便地处理购物车信息,包括添加商品、移除商品、计算总价等。

9e121716cb6be764a5f29c47e2d1155e.png

...

同样地,我们还可以分析出库存限界上下文和物流限界上下文的领域模型。下面是最终完整的领域模型:

937d9e13997aa7ef681ee2d7eb400068.png

3. 构建领域模型

完成领域建模后,我们可以根据领域模型生成关键领域对象的代码,以便更加准确地实现业务需求。例如,在订单上下文中,几个重要的对象包括:

@Data
public class RecipientInfo {private String name;private String address;private String phoneNumber;
}public enum OrderStatus {AWAITING_PAYMENT, AWAITING_SHIPMENT, SHIPPED, COMPLETED
}public enum DeliveryStatus {SHIPPED, IN_TRANSIT, DELIVERED
}@Data
public class Order {private Long orderId;private Long userId;private LocalDateTime createdTime;private double totalAmount;private OrderStatus orderStatus;private DeliveryStatus deliveryStatus;private RecipientInfo recipientInfo;private List<OrderItem> orderItems;
}@Data
public class OrderItem {private Long itemId;private String bookTitle;private String author;private String ISBN;private double price;
}

4. 设计数据库

同样的,还可以根据领域模型设计数据库表结构,以确保数据库能够准确地反映业务领域中的实体、值对象和聚合等概念。例如,下面是订单表的数据表设计:

create table order
(order_id               bigint         ,user_id                bigint         ,created_time           datetime       ,total_amount           decimal(10, 4) ,order_status           varchar(10)    ,deliveryStatus     varchar(10)    ,recipient_name         varchar(50)    ,recipient_address      varchar(255)   ,recipient_phone_number varchar(255)   ,constraint order_pk primary key (order_id)
);create table order_item (item_id bigint,orderId bigint,bookTitle VARCHAR(255),author VARCHAR(255),ISBN VARCHAR(255),price decimal(10, 4),constraint order_item_pk primary key (item_id)
);

5. 小结

本文采用DDD战术,对 DailyMart 进行领域模型设计。通过识别出实体、值对象和聚合等概念,我们得到了 DailyMart 的完整领域模型,并根据该模型完成了关键领域对象的代码构建和关键表设计。

需要注意的是,领域模型并不是一成不变的,它会随着业务需求的变化而不断调整和优化,随着DailyMart商城系统的开发深入,我也会不断优化和补充它的领域模型。

最后,欢迎关注公众号和加入知识星球,获取最新的文章和源码更新。现在加入知识星球,您还可以享受30元优惠券,每天仅需不到3毛钱。

- End-

公众号回复关键词 知识星球 获取限量30元优惠券加入,每天不到3毛钱。目前更新了SpringCloud alibaba开发实战、Kubernetes云原生实战、分库分表实战、设计模式实战、架构实战、一起学DDD 、SpringBoot 老鸟等,还有每周的送书活动等着你....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/256466.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

哈萨比斯的人类补完计划

在著名动漫《新世纪福音战士》里&#xff0c;碇源堂和他背后的SEELE组织始终在执行一项叫做“人类补完计划”的神秘行动。 这个计划到底是什么意思&#xff0c;粉丝们已经争吵了很多年。但大体上应该是说利用“神性”来补完人类族群&#xff0c;从而消除人类社会中的种种问题。…

阿基里斯之踵

阿基里斯是古希腊神话中最伟大的英雄之一。相传&#xff0c;他的母亲是一位女神&#xff0c;在他降生之初&#xff0c;女神为了使他长生不死&#xff0c;将他浸入冥河洗礼。阿基里斯从此刀枪不入&#xff0c;百毒不侵&#xff0c;只有一点除外———他的脚踵当时被女神提在手中…

麦比乌斯带

数学家们吐露&#xff0c;麦比乌斯带只有单面&#xff0c;如果你要将它分成两半&#xff0c;你将会感到十分可笑&#xff0c;因为分开后还是一条带。 莫比乌斯环的奇妙之处有三&#xff1a; 一、莫比乌斯环只存在一个面。 二、如果沿着莫比乌斯环的中间剪开&#xff0c;将会形成…

数字与能源,交织成新基建的摩比斯环

提到新基建&#xff0c;大家可能会首先想起大数据、AI、云计算组成的数字产业&#xff0c;以及高铁、城轨、新能源汽车构成的交通产业。但如果你留心分析&#xff0c;会发现新基建的体系里还有一条“暗线”——那就是能源。 无论直接指向能源升级的特高压、充电桩&#xff0c;还…

塞尔希奥·阿奎罗和 The Sandbox 携手合作,激活元宇宙足球迷!

五次英超联赛冠军兼创纪录的得分球员选择了 The Sandbox 平台来创建他的第一个虚拟世界。 简要介绍 阿根廷在串流媒体和游戏领域上的足球传奇人物和全球典范将继续建立新的数字社区&#xff0c;这一次是与 The Sandbox 中的独特空间 Kuniverse。 来自世界各地的球迷将能够关注阿…

莫比乌斯详细介绍

莫比乌斯反演 莫比乌斯反演是数论数学中很重要的内容&#xff0c;可以用于解决很多组合数学的问题。 莫比乌斯函数 莫比乌斯函数&#xff0c;数论函数&#xff0c;由德国数学家和天文学家莫比乌斯提出。梅滕斯首先使用μ(n)作为莫比乌斯函数的记号。 莫比乌斯函数是指以下的…

无主之地kill ajax,阿克斯顿 - 无主之地中文维基 - 灰机wiki

阿克斯顿 艾克斯顿和军刀枪塔 角色类型可选角色(无主之地2) NPC(无主之地&#xff1a;前奏) 性别男性 种族人类 Axton is the playable Commando class character in Borderlands 2 Launch Date Trailer. 背景 Originally from Hieronymous, Axton spent ten years with the Da…

Mahalanobis(马哈拉诺比斯)距离

马氏距离(Mahalanobis Distance)是一种距离的度量&#xff0c;可以看作是欧氏距离的一种修正&#xff0c;修正了欧式距离中各个维度尺度不一致且相关的问题。 马氏距离&#xff08;Mahalanobis Distance&#xff09;是由马哈拉诺比斯&#xff08;P. C. Mahalanobis&#xff09;…

通用寄存器-汇编复习(1)

弄清寄存器表达,原理和配件及汇编实验验证。 往期文章: 汇编语言基础-汇编复习(0)_luozhonghua2000的博客-CSDN博客 一个典型的 CPU(此处讨论的不是某一具体的 CPU)由运算器、控制器、寄存器(CPU工作原理)等器件构成,这些器件靠内部总线相连。前一章所说的总线,相对于 CP…

想把手机内容投屏到电脑 并且可以用电脑控制手机怎么办,很简单

首先打开设置&#xff0c;点击应用》可选功能 点击 查看功能 搜索 无线显示器点击下一步 点击安装 等待安装完成 完成后我们打开 系统》投影到此电脑 把设置改为以下选项&#xff0c;然后单击启动两家应用以投影到此电脑 出现这个画面就对了&#xff0c;接下来我们开始调试手…

发现了一个很好用的电脑上用电脑控制安卓手机的软件

2019独角兽企业重金招聘Python工程师标准>>> 发现了一个很好用的电脑上用电脑控制安卓手机的软件scrcpy&#xff0c; 还是开源的 地址&#xff1a; https://github.com/Genymobile/scrcpy windows,mac os,linux都支持。 基本上没有延迟&#xff0c;电脑屏幕显示安卓…

图解:手机控制电脑的软件的使用教程

在使用IP软件时总是掉线&#xff0c;有时又要出去&#xff0c;不能总呆在电脑旁&#xff0c;所以使用了一个手机控制电脑的软件 使用方法&#xff1a;电脑下载一个这个软件&#xff0c;手机下载一个 下载地址官网&#xff1b;https://www.teamviewer.com/en/download/windows…

手机可以控制电脑?

当你在外时&#xff0c;老师一个电话打过来要文件。 当你躺在床上时&#xff0c;想看看书房的电脑下载学习资料是否掉线。 当你把电脑借给别人用&#xff0c;想偷偷观察他有没有干坏事&#xff0c;电脑不在身边&#xff0c;手机尚在。 用手机控制电脑是一种怎样的体验&#…

怎么用手机控制电脑?手机控制手机如何实现?

随着远程控制技术的发展&#xff0c;怎么用手机控制电脑是很多人的疑问。用手机远程控制电脑&#xff0c;通过手机实现对电脑的实时操作&#xff0c;实现手机与电脑同时兼得的效果。本文小编教您怎么用手机控制电脑&#xff0c;希望可以帮助到大家。 怎么用手机控制电脑? 工具…

神器!亲自教大家一键用手机远程控制电脑,让手机秒变高配电脑!

软件介绍 今天Aliwen要给大家伙介绍的东西是微软远程桌面&#xff01;这个东西可是神器啊&#xff01;远程使用你的电脑&#xff0c;延迟低&#xff0c;画质好。感觉就像用平板&#xff01;想用电脑却不想下床&#xff1f;想玩一些奇怪的游戏不想被别人看见&#xff1f;那就来…

如何实现用手机远程控制电脑?

这个问题不由得让我想起了多年前传的神乎其神的肉机操作&#xff0c;上大学的时候我还不幸中过招&#xff0c;最后以重装系统结束战斗。 但现在我们完全没必要一碰到这个词就战战兢兢&#xff0c;QQ不是早就实现了这个功能嘛&#xff0c;我还帮媳妇远程修电脑&#xff0c;嘿嘿…

手机远程控制电脑+手机显示器

远程控制电脑操作步骤: CSDN (免积分)下载地址: http://download.csdn.net/detail/liduanw/5436649 1. 运行附件中的 RemoteControlServer.exe,因电脑端程序使用 Java 编写,所以需要 jre 环境支持,如果没有请先搜索下载安装, 控制台会出现: Listening... 表示电脑正在监听中..…

电脑控制手机/手机控制手机/手机控制电脑

一、TeamViewer 1. 电脑版&#xff0c;使用360软件管家下载的&#xff0c;安装TeamViewer_15.0.8397.exe&#xff0c;或者到官网下载&#xff1a;https://www.teamviewer.cn/。 2. 手机版 直接在豌豆荚或者应用市场下载安装就好了&#xff0c;TeamViewer.apk&#xff0c;这个…