在說什么是領域驅動設計之前,我覺得需要先說一下我們為什么需要領域驅動,我個人認為領域驅動設計對于研發來說改進點主要有下面三個:
領域驅動設計(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小時內與您取得聯系。