在说什么是领域驱动设计之前,我觉得需要先说一下我们为什么需要领域驱动,我个人认为领域驱动设计对于研发来说改进点主要有下面三个:
领域驱动设计(DDD)是一种软件设计思路,领域指的是业务领域,比如银行业务领域,医药销售领域;不同于传统以数据表为中心的建模方式,它以业务领域为中心来建模,能促使我们以正确的方式使用面向对象,建立饱满的领域对象。
在进行领域建模和开发时我们主要需要关注以下几点:
下面的思维导图是领域驱动设计需要掌握的一些点:
Tips:
1.领域驱动设计是2004年Eric Evans在《领域驱动设计:软件核心复杂性应对之道》这本书中提到的,DDD的出现是为了应对复杂业务场景下软件越来越复杂问题;也就是说通过DDD可以将软件的复杂度控制在合理的范围内。
2.领域驱动设计主要解决的是业务复杂度问题(避免大泥球风格:大泥球风格就是没有任何清楚的结构,例如随意共享的数据,随意全局化的数据结构。这样风格的系统可维护性(maintainability)和可扩展性(extensibility)都很差,最终导致整个系统难以改动,维护不下去),如果业务不复杂,则不需要使用DDD方式来处理(推荐用三层架构)。
领域驱动设计的优缺点很明显,我这边整理了几个优缺点,供参考。
优点:
缺点:
按照实现领域驱动设计一书中描述的DDD步骤主要有4步:
软件开发实际作用就是为客户解决问题或者软件升级变革,所以在领域中我们划分了问题空间和解空间两个纬度空间,用于描述客户的问题(需求)和如何解决问题(解决方案)。
问题的来源:
首先我们需要对问题域进行拆分,拆分的理念就是由大化小,逐个击破。拆分完毕问题空间,我们需要做到逐一击破,为每一个问题形成一套落地解决方案。一个问题对应一个答案,解空间与问题空间基本上应该是一一对应的。
我们给出的解方案是一个个限界上下文,一个限界上下文负责应对其对应的问题进行解决,承载了该问题中的业务知识及规则。限界上下文是解决某一类问题的单一功能模块,例如订单限界上下文,处理开单、通知订单状态等一切与订单关联的功能。
随着问题的划分,将领域拆分成了不同的子域,每个子域有其独有的业务知识,而这些知识需要靠一门统一语言来描述。而不同限界上下文间的统一语言是相互独立的。可能在不同的限界上下文有同样的名词,但同样的名词在不同的限界上下文中可能表示的不是同一事物,即使是同一事物可能其在不同上下文中的关注点也不一致。
限界上下文之间的映射关系:
核心域是一款软件的所能获得的竞争优势的根本所在。所以在核心的建模和开发主要投入大量的时间和人力。
通用域是许多大型软件系统都有的子域。通用域例如像电子邮件和短信发送、OSS、MQ等。
系统中的其他域被称为支撑域。支撑域的主要作用就是有助于支撑核心域的业务。比如:用户的注册等。
DDD分析建模主要有两种方法可以使用:用例分析法、四色建模法、事件风暴、领域驱动建模。
通过对需求进行分析构建出用例图如下所示(举例子不一定正确):
这里列一下标准的四色建模法(https://www.infoq.cn/article/xh-four-color-modeling/),其实还是需要多联系才行。
时标型(Moment-Interval)对象:具有可追溯性的记录运营或管理数据的时刻或时段对象,用红色表示 -> 操作
PPT(Party/Place/Thing)对象:代表参与到流程中的参与方/地点/物,用绿色表示 -> 名词
角色(Role)对象:在时标型对象与 PPT 对象(通常是参与方)之间参与的角色,用黄色表示 -> 操作角色
描述(Description)对象:对 PPT 对象的一种补充描述,用蓝色表示 -> 表述备注
领域建模并不是没有方法,而是选择太多,有用例法、四色建模、领域驱动建模、事件风暴等,人有一个特点是喜欢找最简单、最易用的方法,每个方法都有自己的特点,并没有好坏优劣之分,只有适不适合。听到一个方法就去尝试,尝试到一半就放弃,一种种方法尝试,最终就会迷失在方法选择上。
对于DDD而言领域建模完成后,我们就需要对照模型进行开发,在开发之间我们需要知道领域战略设计中的几种架构风格。
DDD四层架构是一个松散分层架构(任意上层可以调用下层,但是下层不能调用上层),DDD四层架构的含义如下:
如下是DDD四层架构图:
依赖倒置原则:我们要依赖不变或稳定的元素(类、模块或层),抽象不应该依赖于细节,细节应该依赖于抽象。依赖倒置原则可以改进分层架构,即底层服务应该依赖于高层组件所提供的接口。
?采用了依赖注入方式后,其实可以发现事实上已经没有分层概念了。无论高层还是底层,实际只依赖于抽象,整个分层好像被推平了,这就引入下一个架构六边形架构。
六边形架构是Alistair Cockburn在2005年提出的,在这种架构中,不同的客户通过“平等”的方式与系统交互。在《实现领域驱动设计》一书中,作者将六边形架构应用到领域驱动设计的实现,六边形的内部代表了application和domain层。外部代表应用的驱动逻辑、基础设施或其他应用。内部通过端口和外部系统通信,端口代表了一定协议,以API呈现。个人理解其实就是变成内层、适配层&外部资源,内层是应用层和领域层;适配层是之前的接口层和基础设施层;外部资源就是对外接口、缓存、MQ、数据库等等。六边形架构图如下所示:
?下面是对六边型架构的一个落地实践示例:
?
四层架构、DIP、六边形架构可以参考:
https://www.jianshu.com/p/c405aa19a049
http://it.hzqiuxm.com/ddd%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E6%88%98%E7%95%A5%E7%AF%87%EF%BC%884%EF%BC%89/#DDD-2
在DDD设计思路中,DDD 通过领域对象之间的交互实现业务逻辑与流程,并通过分层的方式将业务逻辑剥离出来,单独进行维护,从而控制业务本身的复杂度。但是作为一个业务系统,查询的相关功能也是不可或缺的。在实现各式各样的查询功能时,往往会发现很难用领域模型来实现。假设在用户需要一个订单相关信息的查询功能,展现的是查询结果的列表。列表中的数据来自于订单、商品、品类、送货地址等多个领域对象中的某几个字段。这样的场景如果还是通过领域对象来封装就显的很麻烦,其次与领域知识也没有太紧密的关系。所以命令查询职责分离的设计架构(CQRS)是可以很好的解决上述的问题。
CQRS将系统分为两类操作:命令(command)、查询(Query)。命令则是对会引起数据发生变化操作的总称,即我们常说的新增,更新,删除这些操作,都是命令。而查询则和字面意思一样,即不会对数据产生变化的操作,只是按照某些条件查找数据。CQRS 的核心思想是将这两类不同的操作进行分离,然后在两个独立的服务中实现。这种独立服务可以是两个不同的应用或者同一个应用中不同的包进行隔离。同时理论上命令和查询的数据源也是不同的(实现读写分离)。
当然读写分离模式,肯定会遇到事务的问题,事务问题主要的包含两种情况:
所以从事务的角度来看 CQRS,你需要面对的是问题从根本来说是个最终一致性的问题。对于团队处理这种最终一致性问题需要有对应的方案。
CQRS架构如下所示:
了解了战略设计后,我们主要做具体的实施,具体实施时我们需要了解实体、值对象和聚合这几个领域对象。
我们先看一下他们的定义:
实体:许多对象不是由它们的属性来定义,而是通过一系列的连续性(continuity)和标识(identity)来从根本上定义的。只要一个对象在生命周期中能够保持连续性,并且独立于它的属性(即使这些属性对系统用户非常重要),那它就是一个实体。
值对象:当你只关心某个对象的属性时,该对象便可作为一个值对象。为其添加有意义的属性,并赋予它相应的行为。我们需要将值对象看成不变对象,不要给它任何身份标识,还应该尽量避免像实体对象一样的复杂性。
对于实体Entity,实体核心是用唯一的标识符来定义,而不是通过属性来定义。即即使属性完全相同也可能是两个不同的对象。同时实体本身有状态的,实体又演进的生命周期,实体本身会体现出相关的业务行为,业务行为会实体属性或状态造成影响和改变。
如果从值对象本身无状态,不可变,并且不分配具体的标识层面来看。那么值对象可以仅仅理解为实际的Entity对象的一个属性结合而已。该值对象附属在一个实际的实体对象上面。值对象本身不存在一个独立的生命周期,也一般不会产生独立的行为。
对于实体和值对象详细说明可以参考:https://www.jianshu.com/p/da51d16dbdc4
聚合是业务和逻辑紧密关联的实体和值对象组合而成,聚合是数据修改和持久化的基本单元,一个聚合对应一个数据的持久化;同时将选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制。
https://www.cnblogs.com/laozhang-is-phi/p/9916785.html
在所有的DDD项目中,通常存在多个限界上下文,这意味着我们需要找到合适的方法对这些上下文进行集成。当模型概念从上游上下文流入下游上下文中时, 尽量使用值对象来表示这些概念。这样的好处是可以达到最小化集成,即可以最小化下游模型中用于管理职责的属性数目。使用不变的值对象使得我们做更少的职责假设。
贫血模型:指使用的领域对象中只有setter和getter方法(POJO),所有的业务逻辑都不包含在领域对象中而是放在业务逻辑层。贫血模型中领域对象只有属性没有丰富的操作,使用时需要单独的Dao层配合使用,风格比较面向过程。
充血模型:将大多数业务逻辑和持久化放在领域对象中,业务逻辑只是完成对业务逻辑的封装、事务和权限等的处理。充血模型更加倾向于面向对象的设计风格(可以参考:https://www.jianshu.com/p/fae3da337ebc)。
模块(Module)是DDD中明确提到的一种控制限界上下文的手段,在我们的工程中,一般尽量用一个模块来表示一个领域的限界上下文。一般的工程中包的组织方式为{com.公司名.组织架构.业务.上下文.*},这样的组织结构能够明确的将一个上下文限定在包的内部。
领域服务:领域中的服务表示一个无状态的操作,它用于实现特定于某个领域的任务。
工厂:在DDD中有可能存在复杂对象的创建,如果使用对象本身进行创建有可能会破坏单一责任原则,所以需要工厂进行对象创建。
TML 或超文本标记语言 允许 Web 用户使用元素、标签和属性创建和构造部分、段落和链接。然而,值得注意的是,HTML 不能被视为一种编程语言,因为它不能创建动态功能。
HTML有很多用例,即:
本文将介绍 HTML 的基础知识,包括它的工作原理、优缺点以及它与 CSS 和 JavaScript 的关系。
HTML(代表超文本标记语言)是构成大多数网页和在线应用程序的计算机语言。超文本是用于引用其他文本片段的文本,而标记语言是告诉 Web 服务器文档的样式和结构的一系列标记。
在国内的网站上找了一圈,这应该是介绍历史最细致的,长按保存手机里翻译
平均每个网站包含几个不同的信息 HTML 页面。例如,主页、关于页面和联系页面都将具有单独的 HTML 文件。
HTML 文档是以 .html 或 .htm 扩展名结尾的文件。Web 浏览器读取 HTML 文件并呈现其内容,以便互联网用户可以查看它。
所有 HTML 页面都有一系列 HTML 元素,由一组标签和属性组成。HTML 元素是网页的构建块。标签告诉 Web 浏览器元素在哪里开始和结束,而属性描述元素的特征。
元素的三个主要部分是:
这三个部分的组合将创建一个 HTML 元素:
<p>这是在HTML中添加段落的方法。</p>
HTML 元素的另一个关键部分是它的属性,它有两个部分——名称和属性值。名称标识用户想要添加的附加信息,并且属性值给出进一步的说明。
例如,添加紫色和 font-family verdana 的样式元素将如下所示:
< p style="color:purple;font-family:verdana" >这是在HTML中添加段落的方法。< /p >
另一个属性,HTML 类,对于开发和编程来说是最重要的。class 属性添加了可以作用于具有相同类值的不同元素的样式信息。 例如,我们将对标题 <h1> 和段落 <p> 使用相同的样式。样式包括背景颜色、文本颜色、边框、边距和填充,在 .important 类下。要在 <h1> 和 <p> 之间实现相同的样式,请在每个开始标记后添加 class=”important”:
<html>
<head>
<style>
.important {
background-color: blue;
color: white;
border: 2px solid black;
margin: 2px;
padding: 2px;
}
</style>
</head>
<body>
<h1 class="important">This is a heading</h1>
<p class="important">This is a paragraph.</p>
</body>
</html>
大多数元素都有一个开始标签和一个结束标签,但有些元素不需要结束标签即可工作,例如空元素。这些元素不使用结束标签,因为它们没有内容:
< img src="/" alt="图像" >
这个图像标签有两个属性——一个src属性,图像路径,和一个alt属性,描述性文本。但是,它没有内容,也没有结束标签。
最后,每个 HTML 文档都必须以 <!DOCTYPE> 声明开头,以告知 Web 浏览器文档类型。使用 HTML5,doctype HTML public 声明将是:
< !DOCTYPE html >
目前,有 142 个 HTML 标签可以用于创建各种元素。尽管现代浏览器不再支持其中一些标签,但学习所有可用的不同元素仍然是有益的。
第二节将讨论最常用的 HTML 标签和两个主要元素——块级元素和内联元素。
块级元素占据页面的整个宽度。它总是在文档中开始一个新行。例如,标题元素将位于与段落元素不同的行中。
每个 HTML 页面都使用这三个标签:
<html>
<head>
<!-- META INFORMATION -->
</head>
<body>
<!-- PAGE CONTENT -->
</body>
</html>
其他流行的块级标签包括:
内联元素格式化块级元素的内部内容,例如添加链接和强调的字符串。内联元素最常用于在不破坏内容流的情况下格式化文本。
例如,一个 <strong> 标签会以粗体呈现一个元素,而 <em> 标签会以斜体显示它。超链接也是使用 <a> 标记和 href 属性来指示链接目标的内联元素:
<a href="https://www.icodingdeu.com/" >点我!</a>
HTML 的第一个版本由 18 个标签组成。从那时起,每个新版本都带有添加到标记中的新标签和属性。迄今为止,该语言最重大的升级是 2014 年引入的 HTML5。
HTML 和 HTML5的主要区别在于HTML5 支持新类型的表单控件。HTML5 还引入了几个语义标签,可以清楚地描述内容,例如 <article>、<header> 和 <footer>。
就像任何其他计算机语言一样,HTML 有其优点和局限性。以下是 HTML 的优缺点:
优点:
就像任何其他计算机语言一样,HTML 有其优点和局限性。以下是 HTML 的优缺点:
缺点:
HTML 用于添加文本元素并创建内容结构。然而,仅仅建立一个专业的和完全响应的网站是不够的。因此,HTML 需要借助层级样式表 (CSS)和JavaScript来创建绝大多数网站内容。
HTML 是 Internet 上的主要标记语言。每个 HTML 页面都有一系列创建网页或应用程序内容结构的元素。
HTML 是一种对初学者友好的语言,有很多支持,主要用于静态网站页面。HTML 与用于样式的 CSS 和用于功能的 JavaScript 一起使用效果最好。
我们还向您展示了一些在线教学课程,它们将有助于提高您的 HTML 知识或提供对 HTML 的基本理解。
如果您有任何其他喜欢的资源来学习 HTML,请在评论部分告诉我们。
<html>
<head>
标题 ---此处放置标题、导航、登录等内容
<!此处放置标题、导航、登录等内容--->
</head>
<body>
<!此处放置页面主要内容--->
<! :空格
<: 小于号
>: 大于号
": 引号--->
<p>第一段 世界大势,合久必分,分久必合。</p>
<hr/> <!表示单行横线显示--->
<br/> <!表示换行--->
<h1> hello world, html is easy</h1>
<h2> hello world, html is easy</h2>
<h3> hello world, html is easy</h3>
<h4> hello world, html is easy</h4>
<h5> hello world, html is easy</h5>
<h6> hello world, html is easy</h6>
<p>普通字体</p>
<b>粗体</b> <i>斜体</i> <del>本文字已被删除,请忽略</del>
<p> hello world</p> <!段落标记--->
<a href="http://www.baidu.com" target="_self"> 点击进入百度</a>
<br/>
<img src="http://mysite.com/mypic.png" alt="网站作者照片">
<h3> 普通无边框表格:</h3>
<table>
<tr>
<td>row 1 cell 1</td> <td>row 1 cell 2</td> <td>row 1 cell 3</td>
</tr>
<tr>
<td>row 2 cell 1</td> <td>row 2 cell 2</td> <td>row 2 cell 3</td>
</tr>
</table>
<h3>带表头,有边框,有跨列单元:</h3>
<table border="1">
<tr>
<th>head1</th> <th>head2</th> <th>head3</th>
</tr>
<tr>
<td>row 1 cell 1</td> <td>row 1 cell 2</td> <td>row 1 cell 3</td>
</tr>
<tr>
<td>row 2 cell 1</td> <td>row 2 cell 2</td> <td>row 2 cell 3</td>
</tr>
</table>
<h3>三种列表的表达方式:</h3>
<table cellpadding="2" cellspacing="2">
<tr>
<td>
<ul><li>python</li> <li>c++</li> <li>java</li> <li>golang</li></ul>
</td>
<td>
<ol><li>python</li> <li>c++</li> <li>java</li> <li>golang</li></ol>
</td>
</tr>
</table>
<dl>
<dt>CPU</dt><dd>处理器</dd>
<dt>MEM</dt><dd>内存</dd>
</dl>
<body bgcolor="#FF0000">
<body bgcolor="RGB(255,0,0)">
<body bgcolor="RED">
<p>视频</p>
<object
classid="clsid:d27sfsfstqwetsasasdfsdfs"
codebase="http://fpdownload.macromedia.com/pub/shckwave/cabs/flash/swflash.cab">
<embed src="flashfile.swf" width="300" height="200"></embed>
</object>
<br/>
<p>音频</p>
<audio controls="crontrols">
<source src="sample_song.mp3" type="audio/mp3" />
</audio>
<br/>
<p>视频</p>
<video controls="controls"/>
<source src="sample_video.mp4" type="video/mp4">
</video>
<p>html表单---文本输入</p>
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="name"></td>
<td>密码:</td>
<td><input type="password" name="pass"></td>
</tr>
<tr>
<tdcolspan="4"> <textarea name="comment" rows="5" cols="60"> </textarea></td>
</tr>
</table>
<table>
<tr>
<td>性别:</td>
<td>用户名:</td>
<td>男性<input type="radio" checked='checked' name="sex" value="male" /></td>
<td>女性<input type="radio" checked='checked' value="female" /></td>
</tr>
<tr>
<tdcolspan="4"> <textarea name="comment" rows="5" cols="60"> </textarea></td>
</tr>
</table>
</body>
</html>
*请认真填写需求信息,我们会在24小时内与您取得联系。