1. 程式人生 > >MicrosoftNet企業級應用架構設計(下)

MicrosoftNet企業級應用架構設計(下)

事件溯源導論

簡單是可靠的先決條件。 ——Edsger Dijkstra

推動DDD發展的動力是填補軟體架構師和領域專家在業務領域上的見解差異。與關係型建模相比,DDD是一項突破,因為它促進領域建模代替資料建模。關係型建模著眼於資料實體和它們的關係。而領域建模則著眼於領域中可觀察的行為。
事件溯源(Event Sourcing,ES)並非只是使用事件對業務邏輯進行建模。在ES場景裡,你的資料來源只包含持久化事件。
ES並非全能獨立的架構,而是一個能讓領域模型和CQRS等架構進一步發揮所長的特性。當把ES新增到系統時,你只是改變了資料來源的結構和實現。

  1. 事件的突破
    1. 下一件大事
      總的來說,認為事件是軟體開發的下一件大事。繫結上下文以及領域事件和繼承事件共同為架構師指明瞭一條道路,使它們更有效地理解和實現需求。
      把可觀察的業務事件看做持久化資料為開發打開了新的視角。
    2. 現實世界不僅有模型,還有事件
      模型是現實的抽象,是架構師根據會面領域專家、利益相關者和終端使用者得到的結果建立的。
      最終,模型只是模型,而非我們在現實事件直接觀察到的東西。
    3. 拋棄“最近已知的正常狀態”
      當我們用觀察到的事件構建模型時,模型就是我們想要持久化的東西。一個模型通常是一組物件。
      ES的關注點主要在你觀察道德事件序列上。事件就是你想儲存到持久化儲存的東西。
      1. 最近已知的正常狀態:軟體正常執行時,某個物件的最近已知的正常狀態。
        一般而言,在實體的歷史裡也可能有事件改編實體的結構。“最近已知的正常狀態”方案是好的,但在業務領域裡展開時並非有效表示專案的生命週期的理想方案。
      2. 跟蹤剛才發生的事情
        從事件溯源的角度來看,事件是系統資料的主要來源。當一個事件觸發時,與之關聯的資料將被儲存。這樣,系統就能跟蹤正在發生的事情及其帶來的資訊。
    4. 事件對軟體架構的深刻影響
      1. 你不會錯過任何事情
        事件的主要好處是分析報告提到的任何領域事件都能在幾乎任何時候新增到系統並儲存到儲存。
        事件並沒有固定的格式或結構。事件只是一組屬性,將以某種方式持久化,但不一定持久化到關係型資料庫。
      2. 幾乎無限業務場景可擴充套件性
        事件會想你詳述某個特定領域裡的業務。
        處理事件持久化需要新的架構元素,如事件儲存,事件就是記錄在這裡的。
      3. 支援假設場景
        通過儲存和處理事件,可以再任何需要的時候構建內容的當前狀態。
        使用假設場景的可能性是使用ES的主要業務原因之一。
      4. 沒有強制要求的技術
        事件溯源並未顯式地繫結任何技術或產品。
        事件溯源需要某些軟體工具,主要是事件儲存。
        事件和事件溯源關乎架構;技術按照種類界定。
      5. 缺點:抵制改變
        如果你找到一個或多個領域專家需要你產生的事件序列,那麼事件許願就是一個進一步探索的方案。
  2. 事件溯源架構
    決定把事件用作你的分層系統的主要資料來源時你需要做什麼。有兩個基本方面要考慮:持久化事件以及為查詢奠定基礎。
    1. 持久化事件
      事件應被持久化成審計日誌,並記錄以發生的事情。
      事件儲存時普通資料庫,但它不是用來持久化資料模型的。它持久化的是一組事件物件。
      事件儲存有三個主要特徵:
      ①它儲存的事件物件包含了重建這個時間引用的物件狀態所需的任何資訊。
      ②它必須可以返回與給定鍵關聯的資料流。
      ③它只能新增儲存,不支援更新和刪除。
      事件物件必須通過某種方式引用業務物件。
      1. 事件和業務邏輯的整體流程
        事件溯源基本上是關於以時間序列的方式捕獲應用程式狀態的所有改變。但是,事件是源自資訊。每個事件都是事件儲存裡的一條記錄,但每個事件都記錄了已發生的某件事。
      2. 事件儲存的選擇
        事件儲存最終還是一個數據庫。
    2. 回放事件
      事件溯源的主要作用是持久化訊息,它使你可以跟蹤應用程式狀態的所有改變。
      1. 構建業務實體的狀態
      2. 回放事件意味著什麼
      3. 資料快照
  3. 總結
    事件促進基於任務的方案的分析和實現。
    構建一個保羅永珍的模型有時候很難,而命令和查詢之間的分離展示了更加高效地構建系統的方式。
    使用事件溯源時,每次重播事件都必須建立聚合狀態。

持久層

知識只是對事實的擁有,智慧則是對它們的活用。 ——Thomas Jefferson

從應用程式的角度來看,資料來源不再是物理資料庫,而是構建在業務領域之上的邏輯模型

  1. 持久層概覽
    在某種程度上,現在的軟體都需要訪問資料,然後將資料儲存或者以某種方式展示給客戶。持久層這個名字通常用來指代瞭解資料訪問那些繁雜細節的程式碼:字串連線、查詢語言、索引和JSON資料結構等。

    1. 持久層的職責
      持久層通常會建立成類庫、被領域層(特別是領域服務)和應用程式層引用。持久層可以引用任何用於訪問資料的技術。
      1. 永久儲存資料 :持久層提供一組類,它們知道如何永久儲存資料。永久資料是應用程式需要處理的資料,可以再將來任何時間繼續使用。
      2. 處理事務:持久層應該瞭解應用程式的事務需求,但是,持久層親自處理的應該只有與資料訪問有關的工作單元的事務。這意味著持久層應該負責在單個工作單元的某個聚合邊界內更新多個表。總之,持久層的事務職責不會超出資料聚合上下文裡的普通資料訪問的邊界。
      3. 讀取永久資料:持久層負責從任何永久儲存讀取資料。出於效能的考慮,更好的辦法是把讀取的工作放在單獨的伺服器列表上,並充分利用快取資料。持久層也是資料來源內容快取策略集中實現的理想地方
    2. 倉儲模式的設計
      倉儲是一個類,裡面的每個方法都表示一個針對資料來源的操作——無論是什麼操作。這就是說,倉儲類的實際結構在不同的場景和應用程式裡可能會有較大差別。

      1. 倉儲模式:倉儲式一個協調領域模型和資料對映層的元件,使用類似集合的介面訪問領域物件。倉儲在分層架構裡所處的位置:
        這裡寫圖片描述
        使用倉儲的好處:

        • 實現關注點分離
        • 減少重複資料訪問程式碼的可能
        • 把資料訪問程式碼用作可注入元件,增加應用程式層和領域層裡的可測試程式碼。

        此外,一組良好隔離的倉儲類能為一些應用程式的部署打下堅實的基礎,以便一些資料訪問層可以應對不同的資料庫。

      2. 工作單元模式:Uow被定義構成一個業務事務的一組操作。一個支援這個模式的元件,比如倉儲,可以協調在單個物理事務裡的寫入更改,其中包括解決併發問題。總而言之,支援工作單元一位置呼叫方可以通過把倉儲暴露的操作組合起來安排邏輯事務。
      3. 倉儲模式與CQRS:若選擇CQRS,通常只在命令棧裡建倉儲,每個聚合對應一個倉儲類。倉儲類只有寫入方法和一個根據ID返回聚合的Get方法。在CQRS場景裡,只讀棧通常不需要倉儲類。
      4. 倉儲模式與領域模型:在領域模型場景裡,每個聚合都有一個倉儲。這個倉儲類會處理查詢和命令。
      5. 命令倉儲的介面:無論使用領域模型還是CQRS,都需要一個倉儲為聚合執行寫入操作。倉儲基於泛型介面,這個介面通常定義在領域層。介面的實現則通常放在基礎設施層的一個單獨的程式集裡。
  2. 為何考慮非關係型儲存
    NoSQL,不僅僅是SQL。

    1. 哪些地方正在使用NoSQL:
      • 海量資料以及數百萬潛在使用者。
      • 每秒上千次查詢。
      • 非結構化/半結構化資料以不同形式出現,但仍需統一處理(多型資料)。
      • 使用雲端計算和虛擬化硬體滿足極端伸縮性需要
      • 資料庫是一個天然的事件源
    2. NoSQL型別:
      • 文件/物件儲存
      • 圖儲存
      • 鍵值儲存
      • 表格儲存
    3. 優缺點

      1. 關係型資料庫
        優點:

        • 支援標準資料訪問語言(SQL)
        • 表格模型易於理解,設計和規範流程定義明確。

        缺點:

        • 對通過SQL讀寫複雜型別僅提供有限支援
        • 需要資料庫結構的知識才能建立即席查詢。
        • 對大量記錄進行索引(數百萬行級別)會變得很慢。
      2. NoSQL
        優點:
        • 簡單的擴充套件
        • 快速讀寫
        • 低廉的成本
          缺點:
        • 不提供對SQL的支援
        • 支援的特性不夠豐富
        • 現有產品不夠成熟
  3. 總結
    • 無需讀寫資料的應用程式和繫結上下文是不存在的。
    • 讀寫不一定發生在相同的資料儲存。其次,資料儲存不一定是資料庫。
    • 瞭解系統的機制和資料的特徵,然後制定出最可行的架構。
    • 針對企業場景,應該使用不同的儲存技術來儲存不同型別的資料。
    • 沒有理由通過單個技術或產品來統一儲存。
    • 多元化持久化要求你學習不同的儲存技術和產品。

2017/12/26 9:36:19

彩蛋

  1. 今天的程式設計是軟體工程師和老天之間的競賽,前者努力構建更大、更好、白痴也能用的程式,後者嘗試創造更大、更好的白痴。到目前為止,老天領先。
  2. 程式設計師的麻煩是你要等到一切都晚了才能搞清楚程式設計師在做什麼。
  3. 給人程式,毀人一天;教人程式設計,毀人一生。
  4. 你曾遇到的最大災難是你的第一門程式語言。
  5. 程式是寫給人讀的,寫給機器執行指示偶然。
  6. 面向物件的致富途徑是什麼?當然是繼承。
  7. 如有疑問,蠻力為之。
  8. 如果蠻力無法解決你的問題,那是你沒用力。
  9. 好的判斷源自經驗,而經驗源自壞的判斷。
  10. 電腦就像比基尼,避免人們過多猜測。
  11. 如果你只知道SQL,那麼所有資料看起來都是關係型的。
  12. 如果答案就是太多記錄,你可以改寫這句查詢嗎?
  13. 如果開發者可以再你設計的資料庫裡放入錯誤的資料,那麼最終會有某個開發者這樣做。

相關推薦

MicrosoftNet企業級應用架構設計()

事件溯源導論 簡單是可靠的先決條件。 ——Edsger Dijkstra 推動DDD發展的動力是填補軟體架構師和領域專家在業務領域上的見解差異。與關係型建模相比,DDD是一項突破,因為它促進領域建模代替資料建模。關係型建模著眼於資料實體和它們的關係

企業級應用架構設計》3.軟件設計原則

原則 包含 設計 高內聚低耦合 選擇 註意 soc cnblogs 說明 3.1.軟件設計通用原則 3.1.1 內聚和耦合 內聚:建議創建專註類,少量方法表示邏輯操作。 耦合:衡量兩個軟件模塊(如類)之間的依賴程度。例如A類和B類,A類改變,必須改變B,說明它們耦合。 3.

.Net企業級應用架構設計之UML

這篇部落格之所講UML出現在了《Microsoft.Net企業級應用架構設計》一書的第二章,從架構上講不應該出現這節知識點,但是從架構師的職責角度,UML知識點是一個基礎,因此作者獨立出了一個章節。大家

.Net企業級應用架構設計之當代的架構師和架構

前段時間剛剛看完了《Microsoft .Net企業級應用架構設計》一書,以後陸續的分享作者在書中的精華,簡明扼要的進行總結和概述。同時這本書推薦給有興趣的童鞋。軟體架構到底是什麼每次遇到軟體專案時,我

.Net企業級應用架構設計之業務層設計

業務層剖析任何複雜的任何軟體都可以通過層來組織,每一層表示系統中的一個邏輯部分,一般來說,業務邏輯層中的模組包含了系統所需要的所有功能上的演算法和計算過程,並於資料層和表現層互動。抽象的說,業務邏輯層是

.Net企業級應用架構設計之資料訪問層

綜述資料訪問層的設計很大程度上取決於專案干係人需求的影響。例如,資料訪問層應該持久化物件模型還是簡單的的值的集合?資料訪問層應該支援一種資料庫還是多種資料庫?下面仔細分析資料訪問層的常見功能需求。資料庫

.NET應用架構設計—重新認識分層架構(現代企業級應用分層架構核心設計要素)

閱讀目錄: 1.背景介紹 2.簡要回顧下傳統三層架構 3.企業級應用分層架構(現代分層架構的基本演變過程) 3.1.服務層中應用契約式設計來解決動態條件不匹配錯誤(通過契約式設計模式來將問題線上下暴露出來) 3.2.應用層中的應用控制器模式(通過控制器模式物件化應用層的職責) 3.

關於Django Web應用架構設計開發的幾個問題

依賴 實際應用 解決辦法 會有 簡單的 upd 嵌套 有用 缺點 1、關於分層,做過傳統JEE應用的同學肯定知道JEE應用會分很多個設計層。根據傳統Web應用架構設計一般從上到下分這麽幾個層(太懶了,不畫圖了):Web前端層、Web後端交互層、業務層、基礎數據設施層,Web

Web API應用架構設計分析(2)

最好 factor 狀態 是否 沒有 dot sel nal std Web API應用架構設計分析(2) 在上篇隨筆《Web API應用架構設計分析(1)》,我對Web API的各種應用架構進行了概括性的分析和設計,Web API 是一種應用接口框架,它能夠構建HTT

Web API應用架構設計分析(1)

人員管理 門面 guid orm 和平 ide 額外 簡化 響應 Web API應用架構設計分析(1) Web API 是一種應用接口框架,它能夠構建HTTP服務以支撐更廣泛的客戶端(包括瀏覽器,手機和平板電腦等移動設備)的框架, ASP.NET Web API 是一種

React Native App應用架構設計

在上一篇介紹了React Native開發環境搭建,我們已經可以在本地成功執行一個helloword應用了,本節將開始詳細分析如何搭建一個React Native App應用架構,並支援完整本地執行預覽。前言現在已經有很多腳手架工具,如ignite,支援一鍵建立一個React

Unity應用架構設計(11)——一個網路層的構建

對於客戶端應用程式,免不了和遠端服務打交道。設計一個良好的『服務層』能幫我們規範和分離業務程式碼,提高生產效率。服務層最核心的模組一定是怎樣傳送請求,雖然Mono提供了很多C#網路請求類,諸如WebClient,HttpWebRequest,但考慮到跨平臺,這些類不一定適用。不過不用擔心,Unity 5.x

Unity應用架構設計(6)——設計動態資料集合ObservableList

什麼是 『動態資料集合』 ?簡而言之,就是當集合新增、刪除專案或者重置時,能提供一種通知機制,告訴UI動態更新介面。有經驗的程式設計師腦海裡迸出的第一個詞就是 ObservableCollection。沒錯,它在WPF中盛行其道,通過它開發者可以很方便的達到動態更新介面。要在Unity 3D中使用Obser

Unity應用架構設計(9)——構建統一的 Repository

談到 『Repository』 倉儲模式,第一映像就是封裝了對資料的訪問和持久化。Repository 模式的理念核心是定義了一個規範,即介面『Interface』,在這個規範裡面定義了訪問以及持久化資料的行為。開發者只要對介面進行特定的實現就可以滿足對不同儲存介質的訪問,比如儲存在Database,Fil

.NET應用架構設計—面向查詢服務的引數化查詢設計(分解業務點,單獨配置各自的資料查詢契約)

閱讀目錄: 1.背景介紹 2.對業務功能點進行邏輯劃分(如:A、B、C分別三個業務點) 2.1.配置對映關係,對業務點配置查詢契約(構造VS外掛方便生成查詢契約) 2.2.將配置好的對映策略檔案放在呼叫端,與服務不耦合 3.Dynamic、Dom動態構造服務端物件(Dynamic、D

.NET應用架構設計—適當使用活動記錄模式代替領域模型模式

閱讀目錄: 1.背景介紹 2.簡單介紹領域模型模式、活動記錄模式 3.活動記錄模式的簡單示例及要點 4.總結 1.背景介紹 對軟體開發方法論有興趣的博友應該發現最近“領域驅動設計”慢慢的被人發現被人實踐起來,園子裡也慢慢有了DDD的學習氣氛和寶貴實戰經驗的分享。其實之前我也痴迷於DD

Unity應用架構設計(10)——繞不開的協程和多執行緒(Part 2)

在上一回合談到,客戶端應用程式的所有操作都在主執行緒上進行,所以一些比較耗時的操作可以在非同步執行緒上去進行,充分利用CPU的效能來達到程式的最佳效能。對於Unity而言,又提供了另外一種『非同步』的概念,就是協程(Coroutine),通過反編譯,它本質上還是在主執行緒上的優化手段,並不屬於真正的多執行緒

Unity應用架構設計(12)——AOP思想的實踐

想象一下,當程式所有的業務邏輯都完成的時候,你可能還來不及喘口氣,緊張的測試即將來臨。你的Boss告訴你,雖然程式沒問題,但某些方法為什麼執行這麼慢,效能堪憂。領會了Boss的意圖之後,漫長的排查問題開始了。你會寫日誌,或者是其他工具來追蹤原因。那麼如何以一種優雅的形式,並且不侵入業務程式碼的形式來跟蹤呢?

Unity應用架構設計(4)——設計可複用的SubView和SubViewModel(Part 1)

『可複用』這個詞相信大家都熟悉,通過『可複用』的元件,可以大大提高軟體開發效率。 值得注意的事,當我們設計一個可複用的面向物件元件時,需要保證其獨立性,也就是我們熟知的『高內聚,低耦合』原則。 元件化設計的思路 不管是開發客戶端應用程式還是開發伺服器端應用程式,『元件』這個詞我們並不陌生。不管是在iOS中

Unity應用架構設計(3)——構建View和ViewModel的生命週期

對於一個View而言,本質上是一個MonoBehaviour。它本身就具備生命週期這個概念,比如,Awake,Start,Update,OnDestory等。這些是非常好的方法,可以讓開發者在各個階段去執行自定義的程式碼。但唯一遺憾的事,這些方法是有引擎呼叫,並且顆粒度不夠細。本文將談談怎樣構建View和V