2014年10月9日 星期四

[iThome 第七屆鐵人賽 17] 資料驗證 - 思路篇

在任意的Application裡面,都一定需要儲存資料。而這些資料的正確性是非常重要。舉例來說,以一篇部落格文章來說,這篇文章一定要有“標題”和“作者”,如果沒有這兩個資訊,這篇部落格文章更本就不算是文章。因此,確認進入資料庫的內容的資料是否正確(或者說符合領域裡面的規則),這就是資料正確性。

在Mvc裡面,有一個非常好的基本資料驗證服務,也就是用DataAnnotation定下欄位基本規則,讓Mvc在Model Binding的時候就會做基本的資料驗證。

但是那個只是單一的資料驗證,邏輯性的資料驗證呢?例如,需要和另外一個資料庫欄位做比對。這個光靠DataAnnotation是不夠的,只能夠在service層級來做這方面的資料驗證。

在來,當資料要實際儲存的時候Entity Framework這邊也會有實際DB欄位的資訊,有時候會和DataAnnotation設定的不一樣,導致儲存的時候炸掉。

上面提到3個層面,其實並沒有一個統一整合的東西把它們包在一起,導致在開發專案的時候,每一個人處理這三個層面的方式都不一樣。

因此,接下來要看的是,框架如何把這些驗證的地方整合在一起。

3個層面的驗證

雖然在開篇提到了關於3個層面的驗證,這裡用一張圖更好的解釋三個層面的驗證和不同之處:

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
Mvc 3 個層面的資料驗證

基本上,3個層面驗證的東西都不同:

  1. Controller - 般的基礎驗證,例如必填。
  2. Service - 複雜的商業邏輯驗證
  3. Reposit (DB) - 和最終DB Table Schema比對驗證

目前的問題在那裡?

現在最大問題在於3個層面的資料驗證沒有一個統一的處理方式。

舉例來說,第一層,會由Mvc的Controller透過ModeStateDictionary來記錄驗證結果。

第二層,複雜的商業邏輯驗證。因為每一個domain都不一樣,因此這邊的邏輯依專案而不同,但是問題是如何把驗證結果傳遞到前端給使用者看?

假設今天有多人在開發,開發者A或許自己定義Class來把錯誤訊息包起來並且傳遞給Controller去顯示,而開發者B則是用丟exception的方式傳到Controller。這個會造成維護的不方便。

第三層,當資料和實際DB Schema比對(更準確的說是和Entity Framework所記錄的DB Table Schema),如果不一致,會直接丟出Exception。如果開發者沒有把這個Exception好好處理並且轉成使用者可以看得懂的內容,整個網站就炸掉了。

因此,這些問題作答在於沒有統一的東西在傳遞這些訊息。

解決思路

上面提到了問題的所在,要解決這個問題,在框架裡面就需要有一個東西,能夠儲存三個層面的驗證資訊,並且統一由Controller來接住,並且顯示在前端。

而Service層,將會作於Controller端的驗證資訊,和Repository層級的驗證資訊,整合驗證之後,回傳一個共通看得懂的東西給Controller到View裡面。

結語

在這一篇相信已經瞭解到沒有透過一個東西整合三層驗證的資訊是不行的,只有有了統一的處理邏輯,開發者才不用去思考這一塊的內容。

這一篇是要解決問題的思路而已。因此,下一篇才會介紹如何實作這一篇的思路。

沒有留言 :

張貼留言