軟體架構文件記錄大全 – @herbertograca

banq發表於2019-08-13

我們學習如何編寫程式碼並構建一些很酷的應用程式,然後我們瞭解架構以及如何使應用程式可維護多年......

但是,當我們需要向其他人(新開發人員,產品所有者,投資者......)解釋應用程式如何工作時,我們需要更多......我們需要文件。

但是我們有哪些文件選項可以表達整個應用程式構建塊及其工作原理?!

在這篇文章中,我將涉及:

  • UML
  • 4 + 1建築檢視模型
  • 架構決策記錄
  • C4模型
  • 依賴關係圖
  • 應用地圖Application Map

UML

我們可以使用UML建立幾個圖表,我們可以將它們分為兩類:

我不會詳細介紹每種型別的圖表,因為在這篇文章中要介紹的內容太多了,並且有很多資源可以記錄這些圖表型別。要了解有關這些型別的更多資訊,您可以檢視上面的每個連結。

總而言之,UML很酷,非常有趣,我們可以非常有表現力,我們可以輕鬆地用它描繪一些想法並與同事討論。

但是,要使用UML記錄整個應用程式體系結構,我們需要使用幾種型別的圖表。此外,如果我們嘗試使用單個類圖來表達整個應用程式,我們就會遇到麻煩。

良好使用UML類圖的一個示例是描述設計模式:

軟體架構文件記錄大全 – @herbertograca

可以表達類,介面,可用性和繼承關係,資料和行為。它既簡潔又易讀,而且因為它很小,所以建立起來也很快。

但是,下面的例子並不是那麼有用......它非常大,所以它讓人感到困惑和難以理解。此外,建立它需要花費很多時間,當我們完成時,它可能已經過時了,因為有人會在同一時間對程式碼進行更改。

軟體架構文件記錄大全 – @herbertograca

因此,我們可以而且應該使用UML,但是對於它應該使用的情況:詳細描述模式,應用程式的小部分或低細節的應用程式的高粒度檢視(不使用類圖)。

4 + 1架構檢視模型

4 + 1架構檢視模型由Philippe Kruchten建立,並於1995年在題為“ 架構藍圖 - 4 + 1”軟體架構檢視模型 “的論文中發表。

這種視覺化軟體應用程式體系結構的方式基於應用程式的5個檢視/視角,告訴我們可以使用哪些圖來記錄每個檢視。

軟體架構文件記錄大全 – @herbertograca

  1. 邏輯/結構檢視關注系統提供的功能以及程式碼如何設計以提供此類功能;
  2. Implementation / Developer檢視描述程式碼,元件,模組和包的靜態組織;
  3. 程式/行為檢視重點關注系統的執行時行為,系統程式的通訊方式,併發性,同步性,效能等;
  4. 部署/物理檢視說明應用程式的物理組織,它是關於“什麼程式碼在什麼硬體中執行”;
  5. 用例/場景檢視在一些用例的幫助下解釋了整個架構,這些用例只是互動的序列。部分架構從這些用例演變而來。

值得注意的是,4 + 1架構檢視模型並未強制要求我們使用所有提到的圖表,甚至不是所有檢視。我們總是需要了解這些工具,並且不再使用我們需要的工具。

架構決策記錄文件

架構決策記錄(ADR)實際上不是真正的記錄應用程式架構當狀態,而是記錄原因,可以告訴別人和我們未來,為什麼架構就是這樣。

ADR是一個關於已經做出的體系結構決策的日誌條目,它可以導致體系結構的狀態,就像它現在或將來一樣。它們包含了描述架構的圖表背後的原因。

首先,我們需要了解一些腳手架:

  • 架構重要性要求(ASR):對軟體系統架構具有可測量影響的要求;
  • 架構決策(AD):滿足重要需求的軟體設計選擇;
  • 架構決策記錄(ADR):一個文件,捕獲一個重要的架構決策及其背景和後果;
  • 架構決策日誌(ADL):為特定專案(或組織)建立和維護的所有ADR的集合;
  • 架構知識管理(AKM):所有先前概念的更高領域。

我已經看到了一些用於建立ADR的模板,我在其中幾個中看到了很好的東西,所以我建立了自己的模板。你也可以,也許應該創造你的,一個對你和你的團隊有意義的東西。

對我來說,模板最重要的是它很簡單,並且它有一些文件可以幫助填寫它,甚至可以幫助做出實用和公正的決策。

使用ADR的最佳方式不僅僅是在進行討論和做出決定後編寫的文件。最好的是將它作為討論的起點,作為RFC(徵求意見請求),這是我們提交給團隊/部門的其他成員的想法/提議,請求他們的意見/意見/批准。目的是使用它來開始討論,集體討論,做出最佳決策,並將提案文件本身用作決策日誌條目(ADR)。ADR事先編寫的事實並不意味著它是不可變的,它必須隨著討論的展開而更新/改進。我發現特別重要的是,所考慮的所有選項都要記下它們的優點和缺點,以激發討論和明確的決定。

這是我提出的模板:

軟體架構文件記錄大全 – @herbertograca

隨意從谷歌文件中複製它

如果您想更多地探討這個主題,我建議前往Joel Parker Henderson github儲存庫瞭解ADR

C4模型

C4模型是由Simon Brown引入的,它是迄今為止我遇到的關於軟體架構文件的最佳想法。儘管使用他自己的示例圖表,我會用自己的語言快速解釋主要想法。

我們的想法是使用4種不同的粒度(或縮放)級別來記錄軟體架構:

  • 第1級:系統上下文圖
  • 第2級:容器圖
  • 第3級:元件圖
  • 第4級:程式碼圖

第1級:系統上下文圖

這是最高的粒度圖。它沒有什麼細節,但其主要目標是描述應用程式的上下文。因此,它將由整個應用程式的一個單獨的框組成,並且它將被其他框所包圍,這些框指的是外部系統和應用程式與之互動的使用者。

軟體架構文件記錄大全 – @herbertograca第2級:容器圖

現在,我們放大我們的應用程式,上圖中的藍色方塊對映到下圖中的虛線方塊。

在此粒度級別,我們將看到應用程式的容器,其中容器是應用程式的任何獨立技術部分,例如移動應用程式,API或資料庫。它還記錄了所使用的主要技術以及容器的通訊方式。

軟體架構文件記錄大全 – @herbertograca第3級:元件圖

元件圖顯示了一個容器內的元件。在此上下文中,每個元件是應用程式的模組,不限於域智慧模組(即計費,使用者......),還包括純功能模組(即電子郵件,簡訊,......)。因此,該圖顯示了容器的主要齒輪以及這些齒輪之間的關係。

軟體架構文件記錄大全 – @herbertograca第4級:程式碼

最細粒度的圖,旨在描述元件內部的程式碼結構。對於這個級別,我們使用具有類級別人工製品的UML圖。

軟體架構文件記錄大全 – @herbertograca

要了解更多資訊,你可以在這裡這裡閱讀Simon Brown自己的解釋,甚至可以看到他在這裡談論它。

我認為C4模型是記錄應用程式架構的一種很好的方式,很高興將應用程式的架構理解到一定程度,但我仍覺得它不夠用,雖然我花了一些時間把手指放在缺少的東西上。

我在這些圖中看到了三個限制:

  1. 儲存一些例外,比如Simon Brown的結構,它們需要手動製作,不能自動化,也不能直接從程式碼中提取,這意味著它們可能無法反映實際程式碼,而是反映我們當前對它的理解;
  2. 它們並不能幫助我們看到我們的應用程式程式碼庫中出現的問題,即混雜的程式碼關係和糟糕的結構,這會影響模組化和封裝,這對任何工程產品都是必不可少的;
  3. 它們無法幫助我們理解整個程式碼庫,應用程式齒輪可以做什麼以及它們如何相互作用。

我發現了兩類可以幫助我們的圖表:

1. 依賴關係圖:有助於告訴我們程式碼庫中不同型別程式碼中存在的依賴關係。這裡至關重要的是這些圖表是直接從程式碼中自動生成的,否則圖表將僅反映我們認為程式碼的樣子,如果這是準確的,我們真的不需要這種型別的文件。

此外,可能比圖表本身更重要的是能夠使用這些依賴關係分析在我們預定義的依賴關係規則中斷的情況下停止構建。因此,用於生成這些圖表的工具也應該可以用作測試工具幷包含在我們的CI管道中,就像單元測試一樣,防止不必要的依賴關係到達生產,從而維護和實施模組化,從而有助於實現高可變性速率和特徵發展的高速度。

在這個類別的圖表中,我發現有3種不同型別的圖表來斷言,以斷言不同的依賴型別。

在我下面的示例中,它們都是由deptrac為我的寵物專案(explicit-architecture-php)生成的,我用它來進行實驗。您可以在儲存庫根目錄中找到用於生成它們的配置。

但請注意,我自己新增了顏色,以便在本博文中更容易閱讀。顏色代表應用程式中的不同層,根據我在之前的部落格文章中寫到的層次:

軟體架構文件記錄大全 – @herbertograca

2. 層依賴關係圖

此圖的目的是視覺化並確保每個層中的程式碼只能依賴於其內部或下方的層。

因此,在下圖中,我們可以看到,例如,作為頂層外層之一的Infrastructure層可以依賴於任何其他層。另一方面,作為頂層中心層的Domain層只能依賴於下面的層,即SharedKernel-Domain(也是Domain的一部分)和PhpExtension(其程式碼的使用就像它是語言本身的一部分)。

軟體架構文件記錄大全 – @herbertograca

3. 類依賴關係圖

層依賴關係圖分析了層之間的依賴關係,但是在一個層中仍然存在必須不會發生的依賴關係。

類依賴關係圖對於分析我們在程式碼庫中具有的不同型別類之間的依賴關係非常有用,特別是如果它們位於同一層中。

例如,如果我們希望我們的事件可序列化,以便我們可以將它們放入佇列中,我們可能不希望它們包含實體,因為將它反序列化並使用ORM將其保留是有問題的。事件依賴於服務也沒有意義。使用這種型別的圖表,或者更準確地說使用工具來測試依賴關係,我們可以輕鬆地檢測到這種情況並防止它們到達生產階段。

軟體架構文件記錄大全 – @herbertograca4. 元件依賴關係圖

元件是域智慧模組,包含應用程式和域層的模組。例如,元件可以是包含其所有用例和域邏輯的“計費”。

元件可以對映到DDD有界上下文和/或微服務,這意味著它們必須在物理上和時間上與其他元件完全解耦。如果我們有一個具有完全解耦元件的單片應用程式,那麼將它轉換為微服務架構將非常容易(程式碼方面)。

此外,將相同的解耦要求應用於其他非域模組,我們可以保證我們可以輕鬆更換任何模組。

元件依賴關係圖旨在確保應用程式元件和模組分離。

請注意,在下圖中,同一層中的模組(具有相同顏色的節點)如何彼此都不知道,至少是直接的。

特別重要的是兩個元件(使用者和部落格,中藍色)是分離的。如果此應用程式具有微服務架構,則這兩個元件將是微服務。

deptrachttps://github.com/hgraca/explicit-architecture-php生成的元件依賴關係圖:

軟體架構文件記錄大全 – @herbertograca

應用地圖

大約一年前,我意識到我在這些文件選項中也缺少了一些東西:所有這些圖表,它們告訴我們應用程式的構建塊是什麼,它們阻止彼此之間的互動以及它們如何相關,但它們不是告訴我們他們做了什麼,以及他們如何以及何時互相交流。為此,我們需要從使用者的角度非常瞭解應用程式,或者從開發人員的角度來看程式碼庫。前面的圖表沒有告訴我們在應用程式中有哪些用例,也沒有告訴我們哪些事件由什麼用例觸發,以及這些事件的後果是什麼。如果我們向產品負責人展示這些圖表,他會發現它們對於他的角色來說幾乎沒用。

所以我提出了一個新的文件圖表的想法,我稱之為應用程式圖,它可以取代C4模型元件圖。

應用地圖的目的是為真正的地圖應用程式,確定其“城市”(元件),其“地方道路”(用例),“高速公路”(事件),等等。

模組和元件之間的區別在於模組是應用程式的任何模組化部分,而元件是應用程式的領域智慧模組。

因此,雖然ORM是應用程式的一個模組,但它不是一個元件,因為它只處理技術問題。另一方面,“結算”模組是一個元件,因為它處理領域關注。

應用程式對映首先定義應用程式的元件,即領域模組,如“Billing”,“User”,“Company”,“Orders”,“Products”等。在簡單的部落格應用程式的情況下,我們可以有兩個元件,“使用者”和“部落格”元件。

在每個元件中,我們定義了可以向它們發出的命令。“使用者”元件可以建立和刪除使用者,而“部落格”元件可以建立和刪除帖子,併為帖子建立評論。

軟體架構文件記錄大全 – @herbertograca接下來,在每個元件中,我們列出任何相關服務。這些服務是相關的,因為,例如,它們觸發事件或由另一個元件直接使用。這很重要,因為應用程式對映應該使元件之間的連線以及它們的含義和任何後續副作用可見,為此我們需要公開連線到其他元件及其名稱的服務(應該表達它們的作用) )。

軟體架構文件記錄大全 – @herbertograca在服務之後,我們列出了每個元件中的所有事件監聽器,即使它們實際上並未使用,這很方便,因為我們可以檢測它並修復需要修復的任何內容或刪除未使用的程式碼。

事件監聽器是一個類,其公共方法都是由一種型別的事件獨立觸發,它們專注於事件。

軟體架構文件記錄大全 – @herbertograca我們還將列出每個元件中的事件訂閱者,原因與我們列出偵聽器的原因完全相同。

事件訂閱者類似於事件偵聽器,除了它的公共方法由不同的事件觸發,它們關注於複合任務,訂閱者的示例可以是監聽不同框架事件的類,以便控制何時啟動,提交或回滾Request事務。

軟體架構文件記錄大全 – @herbertograca此時,我們在地圖中擁有所有元件及其功能。這非常有價值,因為它告訴我們或任何非技術人員,每個元件可以做什麼。

但是,它仍然沒有告訴我們所有這些功能如何相互關聯,例如“使用者建立部落格文章後會發生什麼?”。

為了實現這一點,第一步是列出觸發特定功能時元件中發生的情況。

在下圖中,我們可以看到刪除帖子(“DeletePost”)將觸發PostService中的deletePost()方法,該方法也是由偵聽通知使用者已被刪除的事件的偵聽器觸發的。這告訴我們,我們的應用程式會刪除來自使用者的直接命令或刪除帖子作者的帖子。

在使用者元件中,我們可以看到,當建立帖子時,其作者會自動訂閱該帖子主題(標籤)。

軟體架構文件記錄大全 – @herbertograca

現在我們獲得了有關元件內流的資訊,但是我們仍然缺乏有關跨元件流的資訊,因此我們新增被觸發和監聽的事件:

軟體架構文件記錄大全 – @herbertograca

例如,我們可以看到:

  • 刪除使用者將觸發將刪除使用者帖子的事件;
  • 建立帖子將觸發事件,這將導致訂閱作者到帖子的主題並提高作者評級;
  • 從任何用例中刪除帖子會觸發一個事件,導致該作者的評分降低。

有了我們地圖中的所有這些資訊,我們就可以瀏覽它。任何技術人員或非技術人員都可以清楚地看到觸發應用程式的任何用例時會發生什麼。這可以幫助我們澄清我們的程式碼,以及我們對應用程式行為的想法。

但是,當在大型應用程式中使用時,此圖仍將存在前面提到的圖表中常見的問題:

  1. 這是一件人工製品,需要付出很多努力和時間才能完成,並且只是讓它保持最新狀態;
  2. 我們最終會得到一個包含很多行的大圖,這不是最具可讀性的。

要解決第一個問題,我們需要能夠按需從程式碼生成圖表。這樣可以輕鬆建立這樣的圖表,無需維護它,並使其立即建立。

為了解決第二個問題,我們需要能夠有選擇地僅生成圖的一部分。例如,通過提供我們想要分析的用例的名稱,這將導致僅生成以某種方式與給定用例相關的圖的部分。

所以我們需要一個......不存在的工具......

前段時間我開始建立它,我到了只缺少元件內部流程的點,但它列出了所有命令,服務,監聽器,訂閱者和事件。由於缺少資訊,它仍然是非常alpha的,但也因為它需要分析的程式碼庫不靈活,但是,從我目前工作的公司的程式碼庫,它可以生成如下內容:

https://gitlab.com/hgraca/app-mapper生成的(不完整)應用程式對映示例

軟體架構文件記錄大全 – @herbertograca如果你對這個專案感到好奇,你可以在這裡檢視,但是請注意它仍然是非常alpha,它只是一個概念證明,我已經幾個月沒有工作了。如果您認為這是一個有價值的專案,並且您有空閒時間做出貢獻,請告訴我,我會嘗試讓您加快速度並建立可以將其提升到更高階別的任務。

相關文章