[如何學習寫程式] #7 - 一開始就訓練自己的抽象化與分層能力

抽象化 (abstraction) 能力在物件導向領域以及 Design Pattern 中是非常重要的一項專業能力,還可以衍生出一項重要的能力,即分層 (layer) 能力,這個能力可以進一步協助抽象化能力降低元件之間的耦合性,也可以協助將應用程式切割的更細,強化程式元件的內聚性,它亦是目前軟體工程鼓吹的領域知識設計 (domain design) 的基石。

抽象化 (abstraction) 能力在物件導向領域以及 Design Pattern 中是非常重要的一項專業能力,只要是學習 C++ 或 C# 等物件導向程式語言的話,一定會用到抽象化的技巧,而且如果物件導向的程式沒有用到抽象化能力的話,基本上是根本沒有發揮物件導向的優點,尤其是多型這一項,多型確保了在不同的物件下,使用相同的方法 (method/function) 可以得到不同的回應與行為,這樣就能進一步的深入到物件本身要解決的問題,而設計出具低耦合但高聚合性的物件架構,這對物件的延展性和彈性有相當大的幫助。

抽象化能力基本上是一種進階技術,但我仍然建議初學者在一開始學習時就嘗試去思考抽象化的程式設計,雖然初學者一開始會很不習慣 (因為抽象化是要使用腦力模擬的),但每次寫程式時一點一點的累積,很快就會反應到自己的程式架構上,而學習順序可以考慮:

 

  • 初級:專案內的抽象化。只在一個專案內練習抽象化的能力,像是在一個專案內放置不同的類別物件,這個部份的重點是在熟悉多型的能力以及概念,多型是抽象化能力的基礎,如果多型不夠了解的話,在後面進一步練習抽象化時可能會有很大的副作用。
  • 中級:跨專案的靜態抽象化。試著在多個專案間做抽象化,這個部份著重的是介面 (interface) 的使用,介面在物件導向中非常重要,在業界內重要系統的程式開發,很少不用到介面的,介面導向程式設計 (Interface-oriented Programming) 是未來進一步學習 Design Pattern 的重要基石,透過使用介面的訓練,可以讓你學到利用介面限制元件範圍以及訂定跨元件的合約 (contract) 機制。抽象類別在這個階段也可以一併訓練,最好是更進一步的學習如何將介面和抽象類別合併使用。
  • 高級:跨專案的動態抽象化。這是抽象化的高階應用,在中級所訓練到的介面與抽象類別的使用,在這個階段會進一步使用程式語言內的 RTTI (RunTime Type Information) 機制進行動態載入與產生物件的能力,這個能力在許多企業級 Framework 都有應用,像是 Entity Framework 或 Spring Framework 等,而業界所說的 Plug-in Framework 也是應用這個作法所實作的,到了這個階段,基本上開發一個具有彈性的基礎核心的必要能力已經具備了,將高級的應用發揮到淋漓盡致時,也表示你的物件導向能力已為個中翹楚。

 

抽象化能力還可以衍生出一項重要的能力,即分層 (layer) 能力,這個能力可以進一步協助抽象化能力降低元件之間的耦合性,也可以協助將應用程式切割的更細,強化程式元件的內聚性,它亦是目前軟體工程鼓吹的領域知識設計 (domain design) 的基石。分層最基本的概念可以分成幾種:

 

  • 以功能切割。像是 MVC (Model-View-Controller) 或是 n-tier 的分層架構,著重元件本身的功能,切割的標準是以元件是屬於什麼功能,像是與資料庫互動 (data model),商業邏輯 (business logic) 或是使用者介面的呈現 (presentation)。
  • 以行為切割。像是一個會計系統可以切分為不同的會計流程,或是財務系統切分為各種不同的財務處理功能,著重於元件應該做的功能或是領域知識等,切割的標準是以領域知識或功能為主。

 

分層能力會有助於將元件本身的程式碼更加的獨立,以提高重覆使用的能力,而抽象化可以更有效的輔助分層的能力,因為分層會需要透過像是介面或中介的 Framework (ex: Spring Framework ORM) 來支援系統的發展,若抽象化能力不夠的話,分層的程式在設計起來會比較吃力。

對初學者來說,如果自己的抽象化能力還不夠的話,建議不要勉強使用分層,因為會不知道哪些功能要切層哪些不要,或是歸納出一個共用的層次程式碼等等,但可以試著以領域知識的角度來模擬將功能切割成不同的方法,並且充實抽象化的能力,日後等抽象化能力有了較穩固的基礎時,再對程式碼進行元件或跨專案的切割,此時,就能真正發揮分層的威力了。