愛流浪的小風

技術隨手寫

使用Asp.Net MVC打造Web Api (2) - 架構規劃

| Comments

在打造Api時,我們希望可以善用Asp.Net MVC易於擴充的特性來開發,讓所有開發的程式碼可以專注在實現自己的功能上,並能夠進行單元測試以及動態替換,為了實現這些目標,就必須妥善的思考並規劃整個Api的結構是否足以滿足這些需求,更甚者可以符合敏捷開發的需求,隨時能夠迎向變動,快速得到各種Feedback並可以馬上進行變更。

整體方向

整個Api的結構主要還是遵循N-Tier的架構設計,將UI層、商業邏輯層或資料存取層等分離,並透過預先定義好的介面來引用Class。Class的實作上盡可能的符合OO的原則,讓每一個Class可以專注在實現自己的功能,而不會擁有過於交錯複雜的邏輯。

介面的定義是十分重要的,在Class與Class之間的互相引用若是透過介面,可以讓我們更方便的動態抽換邏輯,而在進行單元測試的時候也可以透過Mock的方法來測試,讓Class與Class之間的耦合性降低,擴充性卻大大的增加。

撰寫完整的測試程式,讓我們的程式隨時都是在Stable的狀態,當一有需求變更的發生時,更可以確保任何快速更動的程式碼不會造成蝴蝶效應,同時也會讓測試的成本大大的降低,因為不再需要等到完整進行UI上的測試才能得知結果。

使用DI Framework - Autofac來組合系統

若說在Class與Class之間的互相引用透過介面可以讓Class的耦合性降低,擴充的彈性變高,那麼DI Framework可以說是讓Class與Class組合成整個應用程式的靈魂了。透過DI Framework,我們可以預先定義好所有介面所對應實現的Class是哪一個,更甚至可以將這些定義撰寫在config檔之中,方便我們隨時更動。

我們可以把Class當作一個一個的磚塊,而DI Framework則是房子的設計圖,說明了哪邊需要使用哪種磚塊,而最後透過兩者的結合我們可以得到一個完整的建築物。而若是我們臨時需要替換房子某一部分的磚塊樣式時,也只需要修改設計藍圖,準備好新的磚塊,就可以快速的得到我們所期待的新版建築物。

而在這系列的分享中我所使用的是AutoFac這套Framework,當然還有其他許多好用的DI Framework大家可以自己選擇使用 (Ex. Unity Application Block、NInject等)

延伸閱讀:

  1. [Software Architecture]IoC and DI
  2. Object Builder Application Block

使用ORM Framework - Entity Framework來連結資料庫

對於有經驗的開發者來說,與資料庫的互動幾乎是每天都在發生的,而在.Net Framework也提供了Ado.Net作為資料存取的媒介,但為什麼既然有了Ado.Net,還會再推出Entity Framework來同樣做為資料存取的媒介呢?

Entity Framework是微軟以Ado.Net為基礎所開發出來的O/R Mapping Solution,相較於以往直接使用Sql直接對資料庫進行操作的方式,現在則是直接面對實體的物件進行操作,而Entity Framework會再將我們所進行的操作轉換為SQL對資料庫進行查詢,這樣所帶來的好處是藉由Entity Framework作為中間的媒介,不論最後所接上的資料庫是什麼,我們對Entity Framework所進行的操作都會自動轉換為對應資料庫的查詢語法,就算是跨資料庫也不需要更改程式碼,讓程式碼對於資料庫的耦合性降低,工程師也不需要學會每一種資料庫的語法,甚至可以預先避免掉一定程度產生SQL Injection的風險!

註一: 使用Entity Framework可能會對效能造成些許風險,但有可能變快也有可能變慢,最終還是要觀察產生的程式碼
註二: 沒有號稱可以100%避免掉SQL Injection風險的Library,只有盡可能的提高安全程度,並且定期的更新Library至最新版本以降低風險

延伸閱讀:

  1. ORM VS SQL

物件之間的投射轉換 - AutoMapper

我們在撰寫程式時常會需要將物件進行一對一,或是多對一的轉換。最常發生的情境應該是從資料庫撈取資料後,不可能直接將資料庫欄位吐出至前端(避免不必要的危險),所以可能會另外的定義一個呈現用的ViewModel,當資料結構複雜時,若我們在每一個地方都寫一份資料轉換的邏輯,不僅當資料結構異動時維護起來困難,更會造成程式碼難以閱讀,也不方便測試資料轉換的邏輯是否正確,造成維護上的困擾。

而AutoMapper則很好的解決掉這個困擾,它可以將資料轉換的邏輯封裝成一個個Class,不但讓我們可以統一集中資料轉換的邏輯,也讓這些程式碼更容易測試和維護,萬一有邏輯變動的需求也可以一次處理掉所有的地方,因此我將在Api中使用這個Library來處理物件之間的投射轉換。

延伸閱讀:

  1. mrkt 的程式學習筆記 - AutoMapper系列

輸入資料的驗證 - FluentValidation

其實Asp.Net MVC就已經擁有非常好用的驗證功能,它可以透過使用DataAnnotation的方式來定義Model驗證的條件,不但清楚也容易閱讀,但在目前有時候會遇到驗證的邏輯較為複雜,不僅僅只是單純的字串長短,或是Regular Expression可以做完的驗證,很可能還會關係到商業邏輯,甚至和資料庫中的資料進行比對等等,所以我就希望可以真正的將驗證邏輯和Model兩者分離,更甚至可以讓前後台使用相同的Model,不同的驗證邏輯,而FluentValidation提供了一種不同於Asp.Net MVC的驗證方法,它更像是以條列式的方式將驗證邏輯一次撰寫完畢,但在開發時期時也是十分便於檢查是否正確,因此這次就改為使用FluentValidation作為Api的Validation Library。

註:當然它也是可以和Asp.Net MVC的驗證邏輯相容同時使用的,但為了避免程式過於分散本系列中還是以FluentValidation為主

延伸閱讀:

  1. 流暢的驗證組件:FluentValidation

其他好用的工具

除了以上提到的幾種Library之外,我們還會透過一些好用的Library來簡化我們的開發成本,讓我們可以快速的實現符合我們需求的程式碼,例如以下幾種

  1. 使用Elmah記錄異常狀況,並可以透過報表來即時查詢閱讀
  2. 透過Nlog來替程式加上Log,方便排除線上環境的異常
  3. 透過Json.Net來處理Json資料與Class之間的轉換

本日小結

隨著網路越來越發達,再加上現在有類似Github等好用的Open Source網站,讓Open Source開發者的協同工作較以往更加的方便,我們現在也可以透過類似Nuget等好用的套件管理工具來引用這些Open Source的程式碼,一但我們開發時遇到需要擴充或調整的地方,還可以修改並傳送Pull Request到Open Source社群,讓好用的Library更加的好用,也為這些工具提供一份自己的力量,關於今天的內容歡迎大家一起討論喔^_^

Comments

comments powered by Disqus