ASP.NET MVC 實戰經驗分享 - 長日網路多媒體股份有限公司 ...

94 downloads 433 Views 634KB Size Report
多奇數位創意有限公司. 技術總監WILL 保哥. ASP.NET MVC 實戰經驗分享 ... 何謂「 實戰經驗」?  弄砸了4 個網站以上.  因為玩Preview, Beta, RC而重構5次以上.
ASP.NET MVC 實戰經驗分享 多奇數位創意有限公司 技術總監 WILL 保哥

何謂「實戰經驗」?  弄砸了4 個網站以上  因為玩Preview, Beta, RC而重構5次以上  寫出有 Bug 的程式 20 次以上

 寫過至少 50 個Controller  寫過至少200個Action  套過至少200個View  有網站同時線上人數達3,000人  有網站每日上線人數達30,000人次

 ASP.NET MVC 開發經驗一年

有什麼實戰經驗可分享?  快速上手、學習方法  協同開發、團隊分工  高效能的ASP.NET MVC網站  高執行效能  高開發效率  安全的ASP.NET MVC網站  單元測試的經驗分享  開發人員應注意的事  常見問題解答

 QA Time

ASP.NET Web Form 與 ASP.NET MVC 的差異

ASP.NET Web Form 與 ASP.NET MVC 的差異 ASP.NET Web Form

ASP.NET MVC 1.0/2.0

ViewState





ASP.NET 頁面追蹤機制 (Page Trace)





ASP.NET 事件驅動模型 (Event Model)





伺服器控制項 (Server Control)



部分支援

System.Web.SiteMapProvider 類別





ASP.NET Provider Model





System.Web.Caching 命名空間





System.Web.SessionState 命名空間





System.Web.Security 命名空間





Profile, Membership, SiteMap





其他 System.Web.* 功能





支援功能

ASP.NET Web Form 與 ASP.NET MVC 的差異  相同之處  都是 IHttpHandler 的產物  共享 ASP.NET Framework 的所有功能  IL 指令集差很多  System.Web.Mvc.*: 16,902 IL instructions 雖然 ASP.NET MVC 的 WebFormView 用到許多原本 WebForm 的 東西,但是還是很多控制項不會去用他!  ASP.NET MVC 的 ViewPage 繼承 System.Web.UI.Page (非常邪惡) 



System.Web.UI.*: 238,179 IL instructions

快速上手、學習方法

簡化版的 ASP.NET MVC 執行生命週期 HTTP 要求

• GET /Product/Detail/1

Controller

• ProductController.Detail(1)

Model View HTTP 回應

• ProductRepository.GetProduct(1)

• ~/Views/Product/Detail.aspx

• HTML, XML, RSS, Text, CSS, File (Binary), …

簡化版的 ASP.NET MVC 執行生命週期 HTTP 要求

• POST /Product/Edit/1

Controller

• ProductController.Edit(1, FormCollection c) • TryUpdateModel(product, new string[] { “Name"})

Model View HTTP 回應

• var product = ProductRepository.GetProduct(1) • ProductRepository.UpdateProduct(1, product)

• N/A

• HTTP 重導向(Redirection)

瞭解 ASP.NET MVC 執行生命週期 Request

Controller Factory

Controller

URL Routing

Http Handler

View Factory

Route

Route Handler

View

Response

快速上手

先強調不傷身體再講求效果  先建立正確觀念  瞭解 ASP.NET MVC 執行生命週期  以 System.Web 命名空間為基礎,所有功能都還在  關注點分離 (Separate of Concerns; SoC)  要簡單、要複雜,決定權在 “你”  瞭解現階段的限制  需處理更多的 HTML, CSS, JavaScript  缺乏元件化技術與視覺化開發工具支援  理解 ASP.NET Web Form 有哪些成分不見了

關注點分離 (Separate of Concerns; SoC)  簡化複雜度  將複雜的問題拆解成數個容易解決的單元  一次僅關注於一個較容易理解與解決的部分  可維護性大幅提昇  不止可區分Model、View、Controller  還可以再切割成更多層次,讓專案更易於維護

 更容易測試  僅測試需要關注的點  測試導向先行 (Test-Driven Development; TDD)

瞭解現階段的限制  需處理更多的 HTML, CSS, JavaScript  對於負責處理 View 的開發人員來說 HTML, CSS, JavaScript 是必備技能  學會使用 jQuery 能有效提升開發速度 



建議讓 HTML, CSS 的責任切割出去 聘請專業的網頁設計人員專心處理 HTML, CSS  讓開發人員調整網頁版面是很沒效率 



熟悉 JavaScript 是開發人員的天命 請當成一個「程式語言」來看,而非「小工具」  推薦書籍:JavaScript 大全 (第五版) JavaScript: The Definitive Guide, 5/e 

 缺乏元件化技術與視覺化開發工具支援

母雞帶小雞的學習模式  開發經理擔當 Pilot  研究抽象概念並與專案成員分享  找幾個小案子做實驗性開發  不斷的 Code Review 與 Code Refactoring 累積經驗

 不同技術不同人研究  Design Pattern  TDD  LINQ to SQL , LINQ to Entities  AutoMapper  Moq  …

協同開發、團隊分工

開發方法論  透過 MVC 分階段開發  Model  Controller  View  Model  Repository  Controller  View  Model  Repository  Service  Controller  View  IoC / DI / AutoMapper / Unit Test / Integration Test  透過關注點分離簡化複雜度  漸進式擴充各 ASP.NET MVC 擴充點  HTML Helper, AtionFilter, Model Binder, Model Validation, …  定時做 Code Refactoring  推薦書籍:重構-向範式前進 (Refactoring to Patterns)

團體合作的ASP.NET MVC開發策略  架構師專注 Model  設計資料結構、資料驗證規則、商業邏輯(Business Logic)  LINQ to SQL, Repository, Service, DAL  Model Validation, Model Binder, DataAnnotation  分析師專注 Controller  設計網頁與後端的互動關係  URL Routing, Controller, Actions, Action Filter  開發人員專注 View  決定前端呈現的細節、實做Action的程式碼、利用Service物件  開發人員千萬不要自己承攬 HTML, CSS 的編修工作  撰寫單元測試程式 (非整合測試)

高效能的ASP.NET MVC網站

寫出高效能的程式碼  善用 ASP.NET 快取機制與用戶端快取機制  OutputCache  Cache API  Client-side Cache  適當的透過 HTML Helper 產生 URL 的方式  Strong-Typed HTML Helper  Template HTML Helper ( ASP.NET MVC 2.0 )  適度的使用 CDN (Content Delivery Network)  最小化與合併 Scripts、CSS 與 Images (CSS Spirit)  部署時  用 Release 模式建置網站  移除不要的 HttpModule  關閉 web.config 中的 debug 模式  HTTP 壓縮 ( 要小心 CPU 問題 )

縮短開發時間‧提升開發速度  累積經驗,撰寫程式碼產生器  專注於解決問題,而非程式碼  透過關注點分離簡化複雜度進而減少維護時間  將問題釐清,並適度分離物件責任,以達到權責分工的目的  一個物件僅負責一件事,一個 ViewModel 只給一個 View用  撰寫可靠的單元測試程式  每個人都要能寫出可讓你們自己信任的測試程式  撰寫可靠的整合測試程式  透過專職的測試人員撰寫整合測試案例程式  確保程式的執行結果與需求一致,保證軟體品質不會退化

安全的ASP.NET MVC網站

 適當的選擇 Action Selector  讓 Action 不要這麼容易曝光在網路上  有限制的允許 HTML 輸入  [ValidateInput(false)] ( 預設為true)  所有輸出的資料都要做 HTML.Encode  ( ASP.NET 4.0 )  瞭解 Model Binder 與 Model Validation 的風險  Under-Post  Over-Post  Non-null data type  適當的處理錯誤  [HandleError]  Views\Shared\Error.aspx  原始碼檢測工具  至今沒有任何一家源碼檢測軟體能夠檢測 ASP.NET MVC 專案,因為他們連入口 點(Entry Point)都找不到

單元測試的經驗分享

何謂「單元測試」?  測試的最小單位,必須是可信任的、可重複執行的。 

例如: 測試某一個類別(Class)的某一個方法(Method)

 必須與「整合測試」做非常清楚的切割,兩者個概念完全

不同 

DAL (Data Access Layer) 的程式不建議撰寫「單元測試」,因為 DAL 的程式會與資料庫直接產生關聯,而資料庫中可能還會有 Trigger, Stored Procedure, 表格關聯, … 等,這些東西都會打破「單元測試」 的原則,所以建議放入「整合測試」來進行。

 單元測試程式不應該接觸到任何與任何 外部資源

(External Resources) 或 靜態物件 (Statics)。 

例如: File I/O, 資料庫操作, 網路連線, … 等等,且由於靜態方法會牽 扯到狀態,所以不建議在單元測試中存取任何靜態物件。

 只能確保程序如你預期的執行(不保證結果)

何謂「整合測試」?  針對軟體專案的一部份或全部進行測試,可以跨越不

同的類別與方法,並可直接存取的外部資源。 

例如: File I/O, 資料庫操作, 網路連線, … 等等。

 通常做「整合測試」都會需要先設置(Configure)測試

所需的環境,測試完畢後通常要清除測試所產生的殘 留資料,以利下次測試或避免影響其他整合測試的結 果。  確保軟體執行後的結果與需求相符合!

成功導入 TDD 的三個成功要素  信任你的測試結果 ( Trustworthiness )  

你是否能信任你的測試結果? 如果你不斷的對測試結果失去信心,那麼你也不會繼續堅持撰寫單元 測試

 測試程式的可維護性 ( Maintainability )  

你是否能夠持續的維護你的測試程式? 如何有效的降低維護測試程式的成本?

 測試程式的可讀性 ( Readability )   

你的測試程式的命名是否易於理解? 當你測試失敗時是否能從測試失敗的測試方法(TestMethod)明確看出 實際失敗的原因? 當讀取測試數據的人看不懂你的測試,人們就不會執行這些測試、也 不會去維護這些測試,久而久之就會越來越惡化。

「整合測試」與「單元測試」的差異  Storage 類別  Run 方法 

呼叫 Service Layer 中的 Logger 物件的 Log 方法

 單元測試  確保 Storage.Run() 執行時有確實執行 Logger 物件的 Log 方法  驗證輸入的參數格式符合基本要求  整合測試  確保 Storage.Run() 執行完後,Logger物件的 Log 方法確實有 將 Log 寫入資料庫或檔案!(確認外部資源)  確保 Storage 類別與客戶的需求一致!

如何聞出「單元測試程式」的壞味道  每個 TestMethod 之間不能有任何關聯  每個 TestMethod 之間不能有任何執行順序的要求  不要使用 Setup 或 Teardown

 一個 TestMethod 不要同時間驗證(Assert)兩件事以上  一個 TestMethod 中如果有兩個以上的 Assert 命令,通常 90% 的情況都是有問題的,但如果這兩個以上的 Assert 命令是為了 驗證同一件事,那就可以接受。  重點在於你所定義的 TestMethod 是不是一個完整的「邏輯測試 單位」,如果你測試的是「一件事」但有多個可以驗證的目標, 那就可以擁有多的 Assert 驗證。

單元測試中的 TestMethod 的命名規則    

方法名稱會切割成三段,每段以底線 ( _ ) 分隔 第 1 段:被測試的 Method 名稱 第 2 段:測試的情境(Scenario) 第 3 段:預期測試的結果

 不以「單字」作為分段的依據,而是以這三段的分別來分

隔  例如:    

第 1 段:我們要測試 ChangePassword 方法 第 2 段:情境是透過 HTTP GET 取得頁面時 第 3 段:預期會回傳一個 ViewResult 這時該測試方法的命名就可以為: 

ChangePassword_Get_ReturnViewResult

對測試專案的組織方法  假設你原本專案名稱為:ProjectX  單元測試專案可命名為:ProjectX.Tests  整合測試專案可命名為:ProjectX.IntegratedTests  剛開始導入單元測試建議一個專案對應一個單元測試

專案,先不要多個專案共用一個單元測試專案

單元測試到底要寫多少才夠?  寫到你相信你的測試結果 ( Trustworthiness ) !  先弄清楚「單元測試」與「整合測試」的差異!  錯誤的觀念會讓你不信任你的測試程式。  錯誤的假設會導致無止境的測試迴圈!(因為不信任而導致無止 盡的撰寫測試程式)  正向測試 v.s 負面測試  先測試合理的輸入值,確認功能與架構符合需求  再測試無理的輸入值,確認超出範圍的輸入值可否被正確處理

開發人員應注意的事 我的最佳實務 MY BEST PRACTICES

通則  關注點分離 (Separate of Concerns; SoC)  不要讓一個物件處理兩件事!  慣例優於組態(Convention over Configuration)  命名規則、目錄結構  多學習一些設計樣式(Design Pattern)的知識  GRASP (Object Oriented Design)  Single responsibility principle  Factory method pattern  ……

 Model 要肥、Controller 要輕、View 要夠笨

開發人員應注意的事 (Model)  DomainModel != ViewModel  有時後並非所有 DomainModel 都適合傳給 View 顯示  有時後畫面要顯示的欄位不見得在 DomainModel 會有 

例如:註冊會員畫面有兩個 Password 欄位

 善加利用開發工具可有效加速開發流程  可考慮導入 LINQ to SQL 或其他 ORM 技術  實做 Repository Pattern  負責存取資料(類似Data Access Layer; DAL)  實做 Service Pattern  負責商業邏輯(類似Business Logic Layer; BLL)

開發人員應注意的事 (View)  千萬不要用義大利麵式的寫法(早期ASP 的開發模式)  千萬不要用 Code Behind 的寫法  如果可以的話,盡量少用 HTML Helper ,能用

HTML 表達的就用 HTML 撰寫  

便於閱讀 效率

 如果View的邏輯過於複雜,還是可以考慮撰寫 HTML

Helper

Response.Write(“義大利麵”)

注意不可為 Null 的實質型別參數  public ActionResult Index(int page)  public ActionResult Index(int? page)

開發人員應注意的事 (Controller)  謹慎的使用 BaseController,過多的程式會影響效能  可將 ActionFilter 視為「共享」資料的管道  善用 ViewModel ,少量的資料可使用 ViewData  注意實值型別參數不能為null的特性(可轉成 Nullable 型別)  善用 PRG Pattern  

[HttpPost] 、 [HttpGet] 屬性 Post  Redirect  Get

 利用 RouteDebugger 測試 URL Routing  不要在 Controller 指派 ViewName,養成習慣

(Convension)才能有效提升開發效率  一個 Action 僅搭配一個 ViewModel

ASP.NET MVC常見問題解答

ASP.NET MVC常見問題解答  ASP.NET MVC 的 View 是不是回歸早期 ASP 的寫法?  ASP.NET MVC 與ASP.NET Web Form的差別?  以 System.Web 命名空間為基礎  除了 Page Framework 之外,所有功能都能用  ASP.NET Web Form 與 ASP.NET MVC 比較表  ASP.NET Web Form 與 ASP.NET MVC 可否並存?

 ASP.NET MVC 可否以 WebSite 專案形式執行?  ASP.NET MVC 常見問題解答 Part 1

聯絡資訊 THE WILL WILL WEB 記載著 WILL 在網路世界的學習心得與技術分享

http://blog.miniasp.com/ ★ ★ ★ WILL 保哥的噗浪 ★ ★ ★

http://www.plurk.com/willh/invite MY TWITTER

http://twitter.com/Will_Huang