在這篇文章中,我將寫:
- 統一語言
- 4 1 架構視圖模型
- 架構決策記錄
- C4模型
- 依賴關系圖
- 應用地圖
統一語言
我們可以使用 UML 創建幾個圖表,我們可以將它們分為兩類:
- 行為 UML 圖活動圖用例圖交互概覽圖時序圖狀態機圖通訊圖時序圖
- 結構 UML 圖類圖對象圖組件圖復合結構圖部署圖封裝圖剖面圖
我不會詳細介紹每種圖表類型,因為在這篇文章中涵蓋的內容太多了,而且有大量資源記錄了這些圖表類型。要了解有關每種類型的更多信息,您可以查看上面指向某些Visual Paradigm 指南的每個鏈接,或查看此博客文章。
總而言之,UML 很酷,很有趣,我們可以很好地表達它,我們可以很容易地用它勾勒出一些想法并與同事討論。
然而,要使用 UML 記錄整個應用程序架構,我們需要使用多種類型的圖表。此外,如果我們試圖用一個單一的類圖來表達整個應用程序,我們就是在自找麻煩。
UML 類圖的良好用法示例是記錄設計模式:
來源: https: //java-design-patterns.com/patterns/strategy
這很好,這實際上很棒!它可以表達類、接口、可用性和繼承關系、數據和行為。它還簡潔易讀,而且因為它很小,所以創建速度也很快。
然而,下面的例子不是很有用……它太大了,所以會讓人感到困惑和難以理解。此外,創建它會花費很多時間,以至于當我們完成時,它可能已經過時了,因為在此期間有人會對代碼進行更改。
來源: https: //knowhow.visual-paradigm.com
因此,我們可以而且應該使用 UML,但對于應該使用它的情況:描述模式、應用程序的小部分的詳細信息,或應用程序的高粒度視圖(不使用類圖)的低細節。
但問題仍然存在,我們如何記錄完整的應用程序?!
4 1 架構視圖模型
4 1 架構視圖模型由 Philippe Kruchten 創建并于 1995 年發表在他題為“架構藍圖——軟件架構的“4 1”視圖模型”的論文中。
這種可視化軟件應用程序架構的方式基于應用程序的 5 個視圖/視角,告訴我們可以使用哪些圖表來記錄每個視圖。
- 邏輯/結構視圖
關注系統提供的功能以及代碼如何設計以提供此類功能; - 實現/開發人員視圖
描繪代碼、組件、模塊和包的靜態組織; - 流程/行為視圖
關注系統的運行時行為,系統進程如何通信、并發、同步、性能等; - 部署/物理視圖
說明應用程序的物理組織,它是關于“什么代碼在什么硬件上運行”; - 用例/場景視圖
整個體系結構在一些用例的幫助下進行了解釋,這些用例只是交互序列。部分架構是從此類用例演變而來的。
重要的是要注意4 1 架構視圖模型并不強制我們使用所有提到的圖表,甚至不是所有視圖。我們總是需要了解工具,并根據需要使用不多不少。
架構決策記錄
架構決策記錄 (ADR)實際上并不是記錄應用程序架構的當前或未來狀態,而是記錄導致它的原因。它們特別重要,因為它們打算告訴其他人,以及我們未來的自己,為什么這個架構是現在的樣子。
ADR 是有關已做出的架構決策的日志條目,這些決策導致架構現在或將來的狀態。它們包含描述體系結構的圖表背后的原因。
首先,我們需要了解一些人工制品:
- 架構上重要的需求(ASR):對軟件系統架構有可衡量影響的需求;
- 架構決策(AD):解決重要需求的軟件設計選擇;
- Architecture Decision Record ( ADR ):一份記錄重要架構決策及其上下文和結果的文檔;
- 架構決策日志(ADL):為特定項目(或組織)創建和維護的所有 ADR 的集合;
- 架構知識管理(AKM):所有先前概念的更高領域。
我看過一些用于創建 ADR 的模板,我在其中看到了一些不錯的東西,所以我創建了自己的模板。您可以,也許也應該創建您自己的,對您和您的團隊有意義的。
對我來說,模板最重要的是它很簡單,而且里面有一些文檔可以幫助填寫,甚至可以幫助做出務實和公正的決定。
使用 ADR 的最佳方式不僅僅是在討論和做出決定后編寫的文件。最好的辦法是將其用作討論的起點,作為 RFC(征求意見稿),這是我們提交給團隊/部門其他成員的想法/提案,以征求他們的意見/意見/批準。真正的目的是用它來開始討論、集思廣益、做出可能的最佳決策,并將提案文件本身用作決策日志條目 (ADR)。事實上,ADR 是事先寫好的,并不意味著它是不可變的,它必須隨著討論的展開而更新/改進。我發現特別重要的是,將所有正在考慮的選項都寫下來,并附上它們的優缺點,以引發討論和做出明確的決定。
C4模型
C4 模型是由 Simon Brown 引入的,它是迄今為止我遇到的關于軟件架構文檔的最佳想法。我會用自己的話快速解釋主要思想,盡管使用他自己的示例圖。
這個想法是使用 4 種不同的粒度(或縮放)級別來記錄軟件架構:
- 第 1 級:系統上下文圖
- 第 2 級:容器圖
- 第 3 級:組件圖
- 第 4 級:代碼圖
級別 1:系統上下文圖
這是最高粒度的圖表。它沒有什么細節,但其主要目標是描述應用程序所在的環境。因此,它將由一個用于整個應用程序的盒子組成,并且將被其他盒子包圍,這些盒子指的是應用程序與之交互的外部系統和用戶。
第二層:容器圖
現在,我們放大我們的應用程序,上圖中的藍色方塊映射到下圖中的虛線方塊。
在此粒度級別,我們將看到應用程序的容器,其中容器是應用程序的任何獨立技術部分,例如移動應用程序、API 或數據庫。它還記錄了使用的主要技術以及容器如何通信。
第 3 級:組件圖
組件圖向我們展示了一個容器內的組件。在這種情況下,每個組件都是應用程序的一個模塊,不僅限于領域模塊(即計費、用戶……),還包括純功能模塊(即電子郵件、短信……)。所以這張圖向我們展示了容器的主要齒輪以及這些齒輪之間的關系。
第 4 級:代碼
最細粒度的圖表,旨在描述組件內部的代碼結構。對于這個級別,我們使用帶有類級別工件的 UML 圖。
要了解更多信息,您可以在此處和此處閱讀 Simon Brown 自己對此的解釋,甚至可以在此處觀看他的討論。
還缺什么
我認為 C4 模型是記錄應用程序架構的好方法,在一定程度上理解應用程序的架構很棒,但我仍然覺得它不夠,雖然我花了一些時間來指出缺少的東西.
我在這些圖中看到了三個限制:
- 除了一些例外,比如 Simon Brown 的structurizr,它們需要手動制作,而不是自動制作,也不是直接從代碼中提取,這意味著它們可能不會反映實際代碼,而是我們當前對它的理解;
- 它們并不能完全幫助我們了解我們的應用程序代碼庫中的錯誤,關于混雜的代碼關系和糟糕的結構,這會影響模塊化和封裝,這對任何工程產品都是必不可少的;
- 它們無助于我們從整體上理解我們的代碼庫、應用程序齒輪可以做什么以及它們如何相互交互。
我發現了兩類圖表可以幫助我們解決這個問題。
依賴關系圖
依賴關系圖有助于告訴我們代碼庫中不同類型代碼中存在的依賴關系。
這里至關重要的是,這些圖表是直接從代碼自動生成的,否則圖表只會反映我們認為代碼的樣子,如果那是準確的,我們就不會真的需要這種類型的文檔。
此外,也許比圖表本身更重要的是,在我們預定義的依賴性規則發生中斷的情況下,使用這些依賴性分析來停止構建的能力。因此,用于生成這些圖表的工具也應該可用作測試工具并包含在我們的 CI 管道中,就像單元測試一樣,防止不需要的依賴關系到達生產環境,從而維護和強制模塊化,這反過來有助于實現高可變性率,因此功能開發速度很快。
層依賴關系圖
該圖的目的是可視化并確保每一層中的代碼只能依賴于它內部或下面的層。
因此,在下圖中我們可以看到,例如,基礎設施層作為最上面的外層之一,可以依賴于任何其他層。另一方面,Domain 層作為最上層的中心層,只能依賴于下面的層,即 SharedKernel-Domain(它也是 Domain 的一部分)和 PhpExtension(其代碼被用作語言本身的一部分)。
deptrac為https://github.com/hgraca/explicit-architecture-php生成的層依賴圖
類依賴關系圖
Layer dependency diagram 分析層與層之間的依賴關系,但在一個層內仍然存在不能發生的依賴關系。
類依賴關系圖有助于分析我們代碼庫中不同類型類之間的依賴關系,特別是當它們位于同一層時。
例如,如果我們希望我們的事件是可序列化的,以便我們可以將它們放入隊列中,我們可能不希望它們包含實體,因為反序列化它并使用 ORM 持久化它會有問題。事件依賴于服務也是沒有意義的。使用這種類型的圖表,或者更準確地說,使用測試依賴關系的工具,我們可以輕松檢測到此類情況并防止它們進入生產環境。
組件依賴圖
組件是一個領域模塊,一個包含應用層和領域層的模塊。例如,組件可以是包含所有用例和領域邏輯的“計費”。
組件可以映射到 DDD 有界上下文和/或微服務,這意味著它們必須在物理上和時間上與其他組件完全解耦。如果我們有一個具有完全解耦組件的單體應用程序,那么將它轉換為微服務架構將相當容易(代碼方面)。
此外,將相同的解耦要求應用于其他非領域明智的模塊,我們可以保證我們可以輕松替換任何模塊。
組件依賴關系圖旨在確保應用程序組件和模塊是解耦的。
請注意,在下圖中,同一層中的模塊(具有相同顏色的節點)是如何相互不知曉的,至少是直接的。
特別重要的是這兩個組件(用戶和博客,中藍色)是分離的。如果這個應用程序有一個微服務架構,這兩個組件就是微服務。
deptrac為https://github.com/hgraca/explicit-architecture-php生成的組件依賴圖
應用地圖
大約一年前,我意識到我在這些文檔選項中還遺漏了一些其他東西:所有這些圖表,它們告訴我們應用程序的構建塊是什么,哪些塊相互交互以及它們是如何相關的,但它們并沒有不要告訴我們他們做什么,也不要告訴我們他們如何以及何時彼此互動。為此,我們需要從用戶的角度非常了解應用程序,或者從開發人員的角度了解代碼庫。前面的圖并沒有告訴我們應用程序中有哪些用例,也沒有告訴我們哪些用例觸發了哪些事件,也沒有告訴我們這些事件的后果是什么。如果我們向產品負責人展示這些圖表,他會發現它們對他的角色幾乎毫無用處。
所以我想出了一個新的文檔圖的想法,我稱之為Application Map,它可以取代 C4 模型組件圖。
應用地圖旨在成為真正的應用地圖,定義其“城市”(組件)、“地方道路”(用例)、“高速公路”(事件)等。
模塊和組件之間的區別在于,模塊是應用程序的任何模塊化部分,而組件是應用程序的領域模塊。因此,雖然 ORM 是應用程序的一個模塊,但它不是一個組件,因為它只處理技術問題。另一方面,“計費”模塊是一個組件,因為它處理領域問題。
Application Map 首先定義應用程序的組件,領域模塊,如“Billing”、“User”、“Company”、“Orders”、“Products”等。對于一個簡單的博客應用程序,我們可以有兩個組件,“用戶”和“博客”組件:
在每個組件中,我們定義了可以向它們發出的命令。“User”組件可以創建和刪除用戶,而“Blog”組件可以創建和刪除帖子,以及對帖子創建評論。
接下來,在每個組件中,我們列出所有相關服務。這些服務是相關的,因為,例如,它們觸發事件或直接由另一個組件使用。這很重要,因為應用程序映射應該使組件之間的連接以及它們的含義和任何后續副作用可見,為此我們需要公開連接到其他組件的服務及其名稱(應該表達它們的作用).
在服務之后,我們列出了每個組件中的所有事件偵聽器,即使它們實際上沒有被使用,這很方便,因為我們可以檢測到它并修復任何需要修復的內容或刪除未使用的代碼。
我所說的偵聽器是指一個類,其公共方法全部僅由一種類型的事件獨立觸發,它們專注于事件。
我們還將列出每個組件中的事件訂閱者,原因與列出偵聽器的原因完全相同。
事件訂閱者類似于事件監聽器,只是它的公共方法由不同的事件觸發,它們專注于一個復合任務,訂閱者的一個例子可以是一個監聽不同框架事件的類,以控制何時開始,提交或回滾請求事務。
此時,我們在地圖中擁有所有組件及其功能。這是非常有價值的,因為它告訴我們,或者任何非技術人員,每個組件可以做什么。
然而,它仍然沒有告訴我們所有這些功能是如何相互關聯的,例如“用戶創建博客文章會發生什么?”。
為了實現這一點,第一步是列出觸發特定功能時組件中發生的情況。
在下圖中,我們可以看到刪除帖子(“DeletePost”)會觸發 PostService 中的 deletePost() 方法,該方法也是由偵聽通知用戶已刪除的事件的偵聽器觸發的。這告訴我們,我們的應用程序刪除帖子是由于用戶的直接命令或帖子作者已被刪除。
在 User 組件中,我們可以看到創建帖子時,其作者會自動訂閱該帖子主題(標簽)。
現在我們有了組件內流的信息,但是我們還缺少跨組件流的信息,所以讓我們添加被觸發和監聽的事件:
例如,我們可以看到:
- 刪除用戶將觸發一個事件,該事件將刪除用戶的帖子;
- 創建帖子將觸發事件,該事件將導致作者訂閱帖子主題并提高作者評級;
- 從任何用例中刪除帖子都會觸發一個事件,該事件將導致降低該作者的評級。
有了我們地圖中的所有這些信息,我們就可以對其進行導航。任何技術人員或非技術人員都可以清楚地看到當應用程序的任何用例被觸發時會發生什么。這可以幫助我們澄清我們的代碼,以及我們對應用程序行為的想法。
但是,在大型應用程序中使用時,此圖仍然會存在與前面提到的圖相同的問題:
- 這是一個人工制品,需要花費大量的精力和時間才能完成,而且還需要保持更新;
- 我們最終仍然會得到一個包含很多線條的大圖,這不是最易讀的。
要解決第一個問題,我們需要能夠按需從代碼生成圖表。這將使創建這樣的圖表變得毫不費力,消除了維護它的需要,并且幾乎可以立即創建它。
為了解決第二個問題,我們需要能夠有選擇地只生成圖表的一部分。例如,通過提供我們想要分析的用例的名稱,這將導致只生成圖表中與給定用例以某種方式相關的部分。
前段時間我開始創建它,我到了只缺少組件內部流程的地步,但它列出了所有命令、服務、偵聽器、訂閱者和事件。由于缺少信息,它仍然處于 alpha 階段,還因為它在需要分析的代碼庫方面不靈活,但是,從我目前工作的公司的代碼庫來看,它可以生成如下內容:
如果您對該項目感到好奇,可以在此處查看,但請注意,它仍處于 alpha 階段,它只是一個概念證明,我已經幾個月沒有研究它了。如果您覺得這是一個有價值的項目并且您有空閑時間來貢獻,請告訴我,我會盡力讓您跟上進度并創建您可以接手的任務以將其提升到一個新的水平。
版權聲明:本文內容由互聯網用戶自發貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如發現本站有涉嫌抄襲侵權/違法違規的內容, 請發送郵件至 舉報,一經查實,本站將立刻刪除。