為什麼我要規範所有團隊用同樣的架構開發專案?

前陣子在上架構與框架設計的課程時候,提到幾件事情。我說...
  • 要設計出好的架構不難,但真正能夠實施(implement)在團隊中的卻很不容易。
  • 架構設計是一種取捨,沒有絕對完美的做法,有得,就有失,架構師除了要有足夠的技術能力,更重要的是,要有足夠的溝通能力。
  • 架構設計只有一件事情最重要,就是能夠實施(implement),無法實施的架構,再美也是枉然。(不能實施的因素有很多,除了設計的好壞,更多的時候是架構師是否能夠同理開發人員技術程度,以及能否在導入時突顯這個設計的優點)
  • 架構與框架的設計與導入,不僅僅是建構開發團隊的基礎,更是一種引導或限制,讓開發人員被框在某一個規範中,在有限制的狀況下自由發揮(我甚至補充,在軟體開發和專案管理的世界中,過度的自由是一種罪惡) 。

我無法在有限的課程時間中,解釋某些事情。因此,趁著有空且記憶猶新,我想來談談我們過去一兩年做的架構設計,以及為何我要求台灣和China幾個團隊中,所有的成員(PO/PM, SD/SM, Developers)都必須採用這樣的架構。

===================================

先講講背景...

最近這幾年,我們在Web開發上揚棄了從服務器端產生HTML的方式,而改採接近SPA(Single Page Application)的model來進行專案開發,也因此,整個ASP.NET MVC,嚴格說起來,我們只有用WebAPI,其他的部分都是透過我們自己開發的框架(Framework)來搭配與運行。

簡單的架構圖如下:

 
在這個架構底下,Framework 本身負責 Services Layer(中間橘色的那塊)、Client 端對服務器端 Server Components 的調用(呼叫)、以及 Cross-Cutting Components(左方豎著的那塊)。

採用此Framework 架構的開發人員,只focus 在底下2個部份的開發,而將其他部分交由這個Framework 處理,分別是:
  1. Server Components 開發
     
    Server Components 以.NET Assembly(.dll)的形式開發,開發人員可以建立標準 的.NET 4.5.x Class Library,透過引入 Framework Server Component Nuget Package 來建立 Visual Studio Project。開發後的.dll會被佈署到上圖中最底下藍色的那層Backend Application Service Layer中。
            
  2. Client 端 UI 開發
     
    Client 端 UI 有各種不同的形式,如果是網站可能是 HTML Pages,如果是 Windows Desktop application,則可採用 WPF 或 Windows Form 開發技術。如果是 Mobile Device,則可能是 Windows Store App, Windows Phone App, 或是 iOS/Android Apps…etc.。
     
    不論是何種形式的前端Project,均可透過引入相對應的 Nuget Package,取得 BackendServiceClient 這個共用 Component 來進行 Server Component 的調用,以及開發 Client 端所需要的各種 Helpers/Utilities。

透過這樣的開發方式,你會發現,這和你以前習慣的開發方式 -- 『開發人員直接打開Visual Studio 2013,用微軟內建的範本來寫程式…』會有著很大的不同。

首先,我們只讓開發人員寫兩個部分的Code,分別是:
  1. ServerComponent(.dll)
  2. Presentation(UI)
我們稱之為ServerComponent的部分,本質上就是Class Library,也就是.net的assembly(.dll),其中的具體內容就是一個一個的Method(我稱為ServerMethod)。

除此之外,其他的程式碼我們都已經透過framework所封裝,包含身分驗證、日誌(Log)的儲存、例外處理(exception Handling)、權限與安全性…等。都由Framework中的AOP機制來達成。

所以我們的開發人員在進行ServerComponent的撰寫時,毋須擔心或過度的處理cross-cutting concern部分的機制。撰寫程式碼時,只要繼承自我們提供的BaseClass,並專注在business logic的撰寫即可。cross-cutting concern部分的機制,有我們開發好的一整組Attributes可以用。(例如,只消在ServerMethod掛上WriteLog attribute,該Method即可具有log的功能,掛上Exception Handling attribute即可自動處理例外發生時的紀錄、retry、或alert...)

而前端UI(Presentation Layer)調用服務器端ServerComponent的部分,也是透過我們所建立的Services Layer與前端API。且不管前端用哪一種開發方式,是Web/Desktop/Mobile甚至是iOS或Android,都以同樣的一個Helper(BackendServiceClient)來調用服務器端ServerComnponent中的Server Method(via ExecuteCommand),也就是說,不論是開發哪一種前端,前端對於後端Business Logic調用的寫法幾乎完全相同。

如此一來,前端開發人員需要發揮的就是UI的處理與特性,後端開發人員需要撰寫與掌握的就是Business Logic。

簡單總結一下,透過這樣的架構:
  1. 後端開發人員需要會的技能是 C#, OOP, ORM(EF), 以及domain know-how
  2. Web前端開發人員需要會的技能是 HTML/JavaScript(or some js framework)
  3. Windows desktop開發人員需要會的技能是 XAML/C#
總的來說,我們盡可能地壓低開發人員所需要的skill set,這樣的目的是確保開發成本降低,並且讓交接與維護更為容易。

我要坦白說一句,這對於開發人員來說不一定100%是好事(但放心,我們並沒有苦待開發人員,我們有架構設計與RD單位,讓具有RD個性、特質、與能力的開發人員,反而更能夠有另一條更有挑戰也更有趣的升遷管道),但這對於專案管理來說,卻是一個很大的利基。當每一個案子都用這樣的方式和架構來開發時,你會發現每一個專案的程式碼寫法與架構都完全相同,在交接或維護時,立刻可以看到優點,管理效率提升到PM會偷笑的程度。

如果依照過去的作法,每一個案子(或產品)都由該案子的Architect來從頭設計架構,你會發現長期下來這根本是一個災難。

首先,先不管坊間framework的變化程度(你想想從ASP.NET WebForm到ASP.NET MVC才幾年? 再想想AngularJS從1.x到2.0的改變...),也不管架構師本身的素養和能力。當每一個案子的特性不同,架構師往往會很『盡責』的去設計出貼近這個案子的開發架構,並且『順手』就把最近學到的新技術給硬生生地塞進去。

你會發現很有趣的事情,在過度自由的開發環境中,同一個架構師(或同一個團隊),所經手的三個案子,可能會有五種不同的設計。每一次都有新的『改進』,而每一次『改進』,就意味著某些過去的作法被推翻與拋棄,然後架構師又會持續在新的案子中加入了新的元素(或技術、或pattern),企圖讓效能更好,讓開發更方便,或是讓XX更OO、讓ZZ更YY....總之架構師或SD會告訴你...加入這個...加入那個...各種好處不在話下。

如果案子不用維護,那當然沒有任何問題。但你有碰過不用維護的案子嗎? 是了,少到幾乎沒有,所以開發完成之後,往往才是災難的開始。

特定的開發技術,特定的前端框架,這對於開發來說都是機會,但也都是風險,對於維護來說則都是成本。即便用了某些框架,可以很快的完成某些功能,但,以後呢? 如果開發過程中碰到規格變更呢? 這些隱含的成本往往PM和開發團隊都不太關心,但這卻是日後無法結案或無法維護的主因。

也因此,最近這幾年,我們力求統一開發架構,讓每一個專案(甚至產品)的開發,都用完全一樣的Framework(我們自己開發的Framework),當有新的技術或是更好的作法,我們會邀請前線的開發人員,反饋給架構設計單位,並且每季定期釋出框架(framework)更新。由於開發工具的進步,現在我們將框架透過nuget package來導入,更新時開發人員只需要update package即可自動更新。

正如同我前面所說的,架構和框架設計是一種取捨,這樣做讓開發團隊自由發揮的空間減少,卻讓後續維護與交接的成本有效的降低。然而取捨,是一種需要智慧的決定。

有機會,我會再談談在企業和團隊中導入開發框架時,所會碰到的阻礙和因應方案。
-----------------------------
本篇將收錄到 - 『敏捷開發專案管理與架構設計實務
新版(精要版)SPA開發框架系列請參考 Here

留言

Kimxinfo寫道…
Dear 老師
看完此篇文件,有些疑問想請教,目前貴公司的自行開發的Framework,它的生命週期會跟著專案多長呢?例如:Framework 1.0版,給2個開發中的專案,1個維護專案(或結案)。若Framework更新或參考的nuget元件有更新,而變1.1版時,那3個專案都會更新Framework嗎?
David寫道…
不一定,每個案子不同,由PO決定。

因為Framework開發成nuget套件,所以對project來說升級或不升級原則上都不會有太大問題。每一版的nuget也都保持相容。

就原則上來說,除非開發中的案子需要新功能,否則我不會鼓勵升級,維護案可能就更沒有升級的必要了。

不過這部分,我們還是留給PO/PM決定。
匿名表示…
老師您好,
請問前端框架的選擇, 會選擇AngularJS而不用React的考量, 是取決於哪些面向呢? 感謝!!
David寫道…
Hi

其實並沒有特別選擇AngularJS, 甚至某些場合React可能是更適合SPA(Single Page Application)架構的前端框架,但最近這幾年前端技術變化太劇烈,不穩定性太高,對於企業應用來說,選擇一個熟悉和穩定的框架比較容易交接和維護,因此我們相望降低前端js框架的依賴性,只是圖上剛好畫了AngularJS而已。
Doris寫道…
老師您好,
Enterprise Library 6.0 在 Visual Studio 2015 似乎是不再支援是嗎? 是否微軟本身有提供其他的替代方案? 感謝!!
isDavid寫道…
Enterprise Library 6.0 嚴格說起來依舊可以使用,在nuget上也可以看到拆開輕量化的套件喔...

這個網誌中的熱門文章

原來使用 .net 寫個 MCP Server 如此簡單

使用LM Studio輕鬆在本地端以API呼叫大語言模型(LLM)

開啟 teams 中的『會議轉錄(謄寫)』與Copilot會議記錄、摘要功能

在VS Code當中使用 Azure DevOps MCP Server

原來使用 .net 寫個 MCP Client 也如此簡單