如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

2023-05-16

本系列所有文章

如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

如何一步一步用DDD设计一个电商网站(二)—— 项目架构

如何一步一步用DDD设计一个电商网站(三)—— 初涉核心域

如何一步一步用DDD设计一个电商网站(四)—— 把商品卖给用户

如何一步一步用DDD设计一个电商网站(五)—— 停下脚步,重新出发

如何一步一步用DDD设计一个电商网站(六)—— 给购物车加点料,集成售价上下文

如何一步一步用DDD设计一个电商网站(七)—— 实现售价上下文

如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成

如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

如何一步一步用DDD设计一个电商网站(十一)—— 最后的准备

如何一步一步用DDD设计一个电商网站(十二)—— 提交并生成订单

如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展

 

阅读目录

  • 前言
  • 名词解释
  • 实施DDD的关键
  • 如何构建一个领域的上下文映射图
  • 构建我们的上下文映射图
  • 结语

 

一、前言
    DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了。自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平台也算是对DDD的推广尽了一份绵薄之力。一开始接触这个东西是在2014年,真的觉得像是发现了一片新大陆一般,对我整个程序开发视野有了新的理解,但是像[Vaughn Vernon]《实现领域驱动设计》里写的那样,景色虽好,可是自己很长一段时间内很混乱,理不清眼前的陌生世界,因为它与传统的观念完全不同。我相信大部分同学刚接触DDD的时候也会有一样的感觉。
    这次开始写这系列,也希望有越来越多的人能够加入到DDD的队列中,在我之前,园子里的netfocus、dax.net、田园里的蟋蟀等园友都已经对推广DDD做了很多事情,再此感谢下各位,这些分享在我学习DDD的道路上给予了很多帮助。
    本次系列中多处引用[Vaughn Vernon]《实现领域驱动设计》一书里的语句,我认为此书可以作为各位进入DDD的敲门砖,希望大家能够去拜读一下此书。
 
二、名词解释
    首先我觉得有必要先把DDD中的常用名词做一个解释。
    界限上下文:代表一个系统、一个应用程序或者一种业务服务。限界上下文所包含的领域模型概念应该恰如其分,不多也不少。
    通用语言:作用于某个“限界上下文”,在一个特定的限界上下文中只使用一套通用语言,并且保证它的清晰性(避免一个概念在同一个界限上下文中的二义性)和简洁性。举个例子:像京东和天猫这样的B2C系统中会用到系统的人有2种,买家和卖家,对于系统来说都可以称为用户,但是这样破坏了清晰性的特点。如果使用一个类似Type的枚举来区分,破坏了简洁性。所以对于这种场景,就应该直接设计2个对象:买家和卖家。    
    领域:从大了看,领域代表整个公司的运作一切。从小了看,是每个组织运作中的一切。所以领域的概念必然与公司的组织架构所承担的职责有一定的关系。
    子域:一个领域内可以包含1个或者多个子域。理论上一个子域对应一个限界上下文是最优也是最理想的情况,但是有时又要考虑到业务关联度需要做出权衡。子域又分核心域、支撑子域、通用子域。
    核心域:它是整个业务领域的一部分,也是业务成功的主要促成因素。从战略层面上讲,企业应该在核心域上胜人一筹。我们应该给予核心域最高的优先级、最资深的领域专家和最优秀的开发团队。在实施DDD的过程中将主要关注核心域。
    支撑子域:对应着业务的某些重要方面,但却不是核心,那么它便是一个支撑子域。
    通用子域:某个支撑子域的运用范围是整个系统,那么这个子域便是通用子域。
    上下文映射图:由多个界限上下文和子域组成的表示当前单个领域或者多个领域之间的集成关系图。
 

三、实施DDD的关键
    我认为实施DDD最最最关键的东西有2样。
    一是“通用语言”,没有基于通用语言建立的所谓的聚合,实体,值对象,只能算是DDDLite,只是技术层面的一种设计方式。
    二是“建模”,建模又分为战略建模和战术建模,这2者相辅相成,来构建合理的上下文映射图。
    ①战略建模:战略建模是以一种最宏观的角度去审视整个项目对它进行拆分,来划分“界限上下文”,最终形成一个具有俯瞰视角的“上下文映射图”。
    ②战术建模:在我们战略建模划出的“界限上下文”中进行“聚合”、“实体”、“值对象”的建模,并且按模块分组。
 

四、如何构建一个领域的上下文映射图
    对于如何构建一个上下文映射图,分为思想和操作2个层面。
    首先思想层面需要引入2个空间的概念:问题空间和解决方案空间。
    在问题空间中,我们思考的是业务所面临的挑战,而在解决方案空间中,我们思考如何实现软件以解决这些业务挑战。    
    评估问题空间和解决方案空间的问题:
    ①这个战略核心域的名字是什么,它的目标是什么?
    ②这个战略核心域中包含哪些概念?
    ③这个核心域的支撑子域和通用子域是什么?
    其次操作层面就是[Vaughn Vernon]《实现领域驱动设计》里提到的9种组织模式和集成模式。
    ①合作关系(Partnership):如果2个限界上下文的团队要么一起成功,要么一起失败,此时就是这种关系。应该为相互关联的软件功能制定好计划表,这样可以确保这些功能在同一个发布中完成。
    ②共享内核(Shared Kernel):对模型和代码的共享将产生一种紧密的依赖性,对于设计来说,这种依赖性可好可坏。我们需要为共享的部分模型指定一个显式边界,并保持共享内核的小型化。共享内核具有特殊的状态,在没有与另一个团队协商的情况下,这种状态是不能改变的。我们应该引入一种持续集成过程来保证共享内核与通用语言的一致性。【简单的说就是数据库共享】
    ③客户方——供应方(Customer-Supplier Development):当2个团队处于一种上游——下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。因此,在上游团队的计划中,我们应该顾及到下游团队的需求。
    ④遵奉者(Conformist):在存在上游——下游关系的2个团队中,如果上游团队已经没有动力提供下游团队之需,下游团队便孤军无助了。处于利他主义,上游团队可能向下游团队做出种种承诺,但是有很大的可能是:这些承诺是无法实现的。下游团队只能盲目地使用上游团队模型。
    ⑤防腐层(Anticorruption Layer):在集成2个设计良好的限界上下文时,翻译层可能很简单,甚至可以很优雅的实现。但是,当共享内核,合作关系或客户方——供应方关系无法顺利实现时,此时的翻译将变得复杂。对于下游客户来说,你需要根据自己的领域模型创建一个单独的层,该层作为上游系统的委派向你的系统提供功能。防腐层通过已有的接口与其他系统交互,而其他系统只需要做很小的修改,甚至无需修改。在防腐层内部,它在你自己的模型和他方模型之间进行翻译转换。【为每个防腐层定义相应的领域服务】
    ⑥开放主机服务(Open Host Service):定义一种协议,让你的子系统通过该协议来访问你的服务。并且需要将协议公开。
    ⑦发布语言(Published Language):在2个限界上下文之间翻译模型需要一种公用的语言。此时你应该使用一种发布出来的共享语言来完成集成交流。发布语言通常与开放主机服务一起使用。
    ⑧另谋他路(SeparateWay):在确定需求时,我们应该做到坚持彻底。如果2套功能没有显著的关系,那么它们是可以被完全解耦的。集成总是昂贵的,有时带给你的好处也不大。声明2个限界上下文之间不存在任何关系,这样使得开发者去另外寻找简单的、专门的方法来解决问题。
    ⑨大泥球(Big Ball of Mud):当我们检查已有系统时,经常会发现系统中存在混杂在一起的模型,它们之间的边界是非常模糊的。此时你应该为整个系统绘制一个边界,然后将其归纳在大泥球范围之列。在这个边界内,不要试图使用复杂的建模手段来化解问题。同时,这样的系统有可能会向其他系统蔓延,应该对此保持警觉。    
 
五、构建我们的上下文映射图
    本次的系列的主题是电商网站,那么现在开始构建一个电商网站的上下文映射图。
    ①这个战略核心域的名字是什么,它的目标是什么?
    销售核心域,目标是卖更多的商品,获取更多的利润。这点是整个组织的共同目标,所以应该很容易界定,并且应该是在整个组织中能最终够达成一致的某个观点。如图1。
 
                           【图1,点击图片查看大图】
    ②这个战略核心域中包含哪些概念?
    我一般会使用“划分”,“组合”,“梳理”的3步走方式去做。先根据我们对这个领域的理解进行划分出各个上下文,然后重新审视每个上下文在销售这个领域中的定位来“圈地(划分子域)”,最后再思考是否能够完全体现出每个子域的功能和职责。我的思路是这样的,先根据我自己的经验得出了图2。
                            【图2,点击图片查看大图】
    我思考了一下,整个销售过程中,订单只是一个结果,一旦到达这个环节,其实销售的工作已经结束了,那么订单的相关业务其实不应该属于销售的子域内,所以把它拿出去,变为图3这个样子。
                            【图3,点击图片查看大图】
    然后看了一下全图,销售上下文的概念太泛,无法得知其中应该干什么,怎么去销售,有哪些影响销售概念,我又做了拆分。如下图4。
                              【图4,点击图片查看大图】
    到这里几个核心域内包含的概念已经出来了:价格体系(促销、会员价)、销售方式(打包、捆绑赠品)、内容管理、购买。这其中最核心的又是购买。    
    ③这个核心域的支撑子域和通用子域是什么?
    这里开始我们需要对我们整理出的各个上下文和子域结合起来,并且根据9种组织模式和集成模式表达出各上下文之间的关系。如下图5。
                              【图5,点击图片查看大图】
    这里的U和D分别代表UpStream和DownStream,表达出上下游关系,并且图的位置也需要看出这点。另外OHS+PL = Open Host Service+Published Language,ACL = Anticorruption Layer。
 
    发现这里的5个子域中,订单和物流子域分别承担着2个子域的下游支撑作用,那么成为了通用子域。
    最终这个问题的结果为商品子域[支撑]、会员子域[支撑]、支付子域[支撑]、订单子域[通用]、物流子域[通用]。
    最后再考虑到一些非必须的辅助性概念,数据分析系统和预测系统,形成我们的最终上下文映射图。
                              【图6,点击图片查看大图】
 
六、结语
    以上的每个环节都应该尽可能有领域专家参与,这样才能得出最符合实际的上下文映射图。DDD之路不好走,并且从短期的表面来看,需要花费的时间和精力会比我们常规的数据驱动开发方式看上去多的多。但是从沟通的便捷性、理解的错误率、代码的可维护性来看,DDD能够让对项目的把控更上一个层级。并且为了应对互联网行业的快速变化,我们得到的远比我们付出的多的多。
    

作者:Zachary_Fan
出处:http://www.cnblogs.com/Zachary-Fan/p/5991674.html

 

 

▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描右侧的二维码~。

定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。

 

如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。

如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念 的相关文章

随机推荐

  • 面试感悟----一名3年工作经验的程序员应该具备的技能

    原文地址http www cnblogs com xrq730 p 5260294 html xff0c 转载请注明出处 xff0c 谢谢 xff01 前言 因为和同事有约定再加上LZ自己也喜欢做完一件事之后进行总结 xff0c 因此有了这
  • c语言菜单经典实例

    include lt conio h gt include lt dos h gt include lt graphics h gt include lt stdio h gt include lt stdlib h gt 定义一些常数 d
  • Mac 必备工具之 brew

    brew 是 Mac 下的一个包管理工具 xff0c 类似于 centos 下的 yum xff0c 可以很方便地进行安装 卸载 更新各种软件包 xff0c 例如 xff1a nodejs elasticsearch kibana mysq
  • ps:图像尺寸

    在课程 01中我们知道了显示器上的图像是由许多点构成的 xff0c 这些点称为像素 xff0c 意思就是 构成图像的元素 但是要明白一点 xff1a 像素作为图像的一种尺寸 xff0c 只存在于电脑中 xff0c 如同RGB色彩模式一样只存
  • WSL+cmder+oh-my-zsh美化win10命令工具(terminal)

    最近在win10下面搭建了一个 WSL 43 cmder 43 oh my zsh 的程序员命令行环境 xff0c 为什么呢 xff1f 还不是买不起mac xff0c 加上自己的黑苹果瘫了 xff0c 所有又回到了win10上面 不过上面
  • 计算机专业总人数所占比例公式,excel统计数据所占比例的教程详解

    Excel中经常需要统计数据所占的比例 xff0c 统计数据所占比例具体该如何操作呢 下面是学习啦小编带来的关于excel统计数据所占比例的方法 xff0c 希望阅读过后对你有所启发 excel统计数据所占比例的方法 统计数据所占比例步骤1
  • Android包管理机制(五)APK是如何被解析的

    本文首发于微信公众号 刘望舒 原文链接 xff1a APK是如何被解析的 xff1f 相关文章 包管理机制系列 前言 在本系列的前面文章中 xff0c 我介绍了PackageInstaller的初始化和安装APK过程 PMS处理APK的安装
  • 银河麒麟系统开机自动运行

    制作了一个deb安装包 xff0c 实现应用软件开机自启动 将Desktop文件放到 etc xdg autostart目录下 xff0c Desktop中Exec指向一个脚本文件 同样的脚本文件桌面菜单和开始菜单点击都是可以执行的 xff
  • SpringMvc+ajax 实现json格式数据传递

    传JSON对象 前端 function test var param 61 username 34 yitop 34 ajax timeout 20000 type 34 POST 34 dataType 34 JSON 34 url 34
  • 教你一招:windows批处理中实现延时的办法

    五种方法可以实现批出里的延时 xff0c 推荐使用方法一 xff0c 该方法也是使用最多的 方法一 用ping命令延迟 这是最简单而且是最常见的 xff1a 64 echo off echo 34 use ping to delay 34
  • 计算机与我的生活英语作文,描写一天的生活英语作文(通用7篇)

    描写一天的生活英语作文 通用7篇 在平凡的学习 工作 生活中 xff0c 大家都不可避免地要接触到作文吧 xff0c 作文要求篇章结构完整 xff0c 一定要避免无结尾作文的出现 相信很多朋友都对写作文感到非常苦恼吧 xff0c 下面是小编
  • Ubuntu通过LDAP集成AD域账号登录(libnss-ldap方式)

    Ubuntu通过LDAP集成AD域账号登录 xff08 libnss ldap方式 xff09 xff1a apt get install libnss ldap xff08 中间直接回车 xff0c 忽略 xff09 vi etc nss
  • 优秀的程序员需要擅长数学吗?

    天有很多年轻人或经验不足的程序员 在 论坛发帖 在 Stack Exchange 网站问 xff1a 为了成为优秀的程序员 xff0c 我需要擅长数学吗 xff1f xff0c 在我还年轻的时候 xff0c 我也问自己同样的问题 最近 xf
  • 阅读作业:大泥球、敏捷、人件

    34 大泥球 34 我了解到的就是这几点 xff1a 第一 xff0c 有很多条件促使大泥球产生 xff0c 包括 34 一次性代码 34 xff0c 时间紧缺 xff0c 急于完成最小集 xff0c 初期尝试 xff0c 功利主义等等 第
  • lubuntu自动登录(lxde)

    lubuntu 是个轻量级的发行版本 xff0c 非常简洁 xff01 值得一试 xff01 好吧 xff0c 上主题 xff0c 设置自动登录 xff08 两步 xff09 xff1a 1 etc lxdm default conf su
  • 常用照片尺寸

    照片规格 英寸 xff08 厘米 xff09 像素 数码相机类型 1寸 2 5 3 5cm 413 295 身份证大头照 3 3 2 2 390 260 2寸 3 5 5 3cm 626 413 小2寸 xff08 护照 xff09 4 8
  • spring boot application.properties 属性详解

    2019年3月21日17 09 59 英文原版 xff1a https docs spring io spring boot docs current reference html common application properties
  • linode中文社区 linodeclub

    Linode Manager管理后台的功能简介 xff01 Linode中文文档 xff08 原创或翻译 xff09 Linode中文社区 Linode讨论 Linode代购 Powered by Discuz 基本操作 Linode Ma
  • 关闭线程池:shutdown()方法与isTerminated()和awaitTermination()配合使用

    今天在项目中使用了线程池 xff0c 发现不会把线程关闭掉 xff0c 所以就看了这方面 xff0c 并作个记录 1 shutdown 和isTerminated 配合使用 目前项目中使用的shutdown 和isTerminated 配合
  • 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    本系列所有文章 如何一步一步用DDD设计一个电商网站 xff08 一 xff09 先理解核心概念 如何一步一步用DDD设计一个电商网站 xff08 二 xff09 项目架构 如何一步一步用DDD设计一个电商网站 xff08 三 xff09