2014年11月22日 星期六

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

前陣子在上架構與框架設計的課程時候,提到幾件事情。我說...
  • 要設計出好的架構不難,但真正能夠實施(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

6 則留言:

Hsu Kim 提到...

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上也可以看到拆開輕量化的套件喔...