ASP.NET MVC論壇應(yīng)用程序(下)
6、 軟件設(shè)計(jì)模式
軟件設(shè)計(jì)模式描述的是應(yīng)用軟件設(shè)計(jì)原則所遵循的策略的問題。換句話說,一個(gè)軟件設(shè)計(jì)原則是一個(gè)好的思想,而一個(gè)軟件設(shè)計(jì)模式是你用于實(shí)現(xiàn)這種好的思想的工具。
軟件設(shè)計(jì)模式的思想最初源于書籍《Design Patterns: Elements of Reusable Object-Oriented Software》。正是這本書為其它許多描述軟件設(shè)計(jì)模式書的創(chuàng)作帶去靈感。
例如,另一本書《The Head First Design Pattern》就以一種更易于理解的方式向人們介紹了GOF所著的書(即上面的那本《Design Patterns: Elements of Reusable Object-Oriented Software》)中所引入的設(shè)計(jì)模式。這本書中總共詳細(xì)介紹了下列14種軟件設(shè)計(jì)模式:
◆Strategy
◆Observer
◆Decorator
◆Factory
◆Singleton
◆Command
◆Adaptor
◆Façade
◆Template
◆Iterator
◆Composite
◆State
◆Proxy
◆Compound
另一本在軟件設(shè)計(jì)模式方面較有影響的書是Martin Fowler的《Patterns of Enterprise Application Architecture》。這本書還擁有一個(gè)公司網(wǎng)站,其中列舉了本書中所介紹的模式。此網(wǎng)站的網(wǎng)址是:http://www.martinfowler.com/eaaCatalog/。
軟件設(shè)計(jì)模式提供給你按照模式的方式構(gòu)建你的代碼,從而使之更富于適應(yīng)未來的彈性修改。例如,當(dāng)構(gòu)建本文中的論壇應(yīng)用程序時(shí),我們就使用了一種名字為 Repository的軟件設(shè)計(jì)模式進(jìn)行設(shè)計(jì)。Eric Evans,在他的著作《Domain-Driven Design》中這樣描述Repository模式:
一個(gè)REPOSITORY把某種類型的所有對象描述為一個(gè)概念的集合(通常是模擬的)。其行為類似于一個(gè)集合,但是具有更細(xì)致的支持查詢的能力。于是,符合相應(yīng)類型的對象可以被添加或刪除,而位于此REPOSITORY背后的系統(tǒng)則可以從數(shù)據(jù)庫中添加或刪除它們。
根據(jù)Evans的解釋,Repository模式的一個(gè)主要的優(yōu)點(diǎn)是,它能夠幫助你實(shí)現(xiàn)“應(yīng)用程序和域設(shè)計(jì)與存儲(chǔ)技術(shù),多種數(shù)據(jù)庫策略,甚至是多個(gè)數(shù)據(jù)源之間的解耦?!睋Q句話說,Repository模式能夠使你的應(yīng)用程序免于因數(shù)據(jù)庫訪問方式的不同而重新加以改變。
為了使我們的論壇應(yīng)用程序從某一種特定的存儲(chǔ)技術(shù)中獨(dú)立出去,我們將在系統(tǒng)中引入上述Repository模式。因此,最終的此論壇應(yīng)用程序的設(shè)計(jì)將能夠支持我們可以在不同的數(shù)據(jù)訪問技術(shù)(例如LINQ to SQL,Entity Framework或NHibernate)之間切換。
7、 測試驅(qū)動(dòng)開發(fā)
我打算使用測試驅(qū)動(dòng)開發(fā)原則構(gòu)建本文中的MVC論壇應(yīng)用程序。更具體地說是,在我編寫任何應(yīng)用程序代碼之前,我將首先編寫一個(gè)應(yīng)用程序代碼的單元測試。
測試驅(qū)動(dòng)開發(fā)將會(huì)基于下列原因?yàn)槟銕砀哔|(zhì)量的代碼:
(1)為你的代碼編寫測試能夠提供給你一個(gè)適應(yīng)于未來可能改變的安全網(wǎng)。
(2)為你的代碼編寫測試迫使你書寫松耦合的代碼。
(3)在正式書寫你的代碼前為你的代碼編寫測試將迫使你從一個(gè)用戶的角度來觀察自己書寫的代碼。
讓我們更細(xì)致地分析上述每種特征的優(yōu)點(diǎn)。
首先,單元測試提供你一個(gè)適應(yīng)于未來可能改變的安全網(wǎng)。這是Michael Feathers在他的著作《Working Effectively with Legacy Code》一再強(qiáng)調(diào)的一個(gè)觀點(diǎn)。事實(shí)上,他把遺留代碼定義為“簡單地編碼而不進(jìn)行測試”。
當(dāng)你的應(yīng)用程序代碼被單元測試所覆蓋時(shí),你可以修改該代碼而不必?fù)?dān)心此改動(dòng)會(huì)你的代碼既有的功能。單元測試有助于使你的代碼進(jìn)行更安全的重構(gòu)。如果你能夠重構(gòu),那么,你可以使用軟件設(shè)計(jì)模式修改你的代碼,這將產(chǎn)生更好的適應(yīng)未來修改的代碼。
其次,遵循測試驅(qū)動(dòng)開發(fā)將迫使你使用一種特定的方式書寫代碼??蓽y試的代碼將趨于導(dǎo)致松耦合的代碼。單元測試能夠在各自孤立的代碼單元中執(zhí)行一個(gè)測試。為了構(gòu)建你的應(yīng)用程序以便使之可測試,你需要使用一種可孤立的組件方式來構(gòu)建應(yīng)用程序。
一個(gè)類與另一個(gè)類之間是松耦合的是指,當(dāng)你改變第一個(gè)類時(shí)不必改變另一個(gè)類。測試驅(qū)動(dòng)開發(fā)經(jīng)常迫使你編寫松耦合的代碼,因?yàn)樗神詈洗a是經(jīng)得起改變的。
最后,按照測試先行的方式書寫代碼將迫使你從一個(gè)用戶的角度來觀察自己書寫的代碼。通過首先編寫測試的方式書寫代碼,會(huì)使你站在一個(gè)未來的有可能使用你的代碼的開發(fā)者的角度進(jìn)行工作。既然編寫測試迫使你考慮另一個(gè)開發(fā)者(也許是未來的你自己)如何使用你的代碼,那么,你最終編寫的代碼應(yīng)該是設(shè)計(jì)得更好的代碼。
8、 莫圖眼前之利益更宜立足于長遠(yuǎn)
使用測試驅(qū)動(dòng)開發(fā)原則構(gòu)建軟件在軟件開發(fā)之初要求開發(fā)者付出更多的努力。盡管編寫測試需要花費(fèi)一定的時(shí)間;然而,其思想是,最初構(gòu)建單元測試所要求付出的努力將會(huì)在未來獲得豐厚的回報(bào)。
存在兩種方式可以使你成為一名開發(fā)者。你可以成長為一個(gè)牛仔,也有可能成長為一個(gè)工匠。一個(gè)牛仔能夠立即開始編碼。也就是說,一個(gè)牛仔可以以很快的速度構(gòu)建一個(gè)軟件應(yīng)用程序。然而,作為一個(gè)牛仔,其問題在于軟件必須要進(jìn)行長期的維護(hù)。
一個(gè)工匠則是很有忍耐性的。一個(gè)工匠總會(huì)精雕細(xì)琢地開發(fā)一款軟件。一個(gè)工匠總是非常仔細(xì)地構(gòu)建單元測試,并使之涵蓋一個(gè)應(yīng)用程序中所有的代碼。因此,一個(gè)工匠要花費(fèi)更長的時(shí)間才能創(chuàng)建成功一款應(yīng)用程序。然而,此應(yīng)用程序在創(chuàng)建后,卻是易于后期的維護(hù)—更易于修改錯(cuò)誤且更易于把新特征添加到應(yīng)用程序中。
9、 總結(jié)
總之,我們的最終目標(biāo)是構(gòu)建一個(gè)MVC論壇應(yīng)用程序,此程序能夠經(jīng)得起長時(shí)間的測試。它應(yīng)該是不僅現(xiàn)在良好地工作,還應(yīng)該在未來繼續(xù)工作—即使是當(dāng)有人需要對該應(yīng)用程序進(jìn)行更改之時(shí)。
我想利用微軟ASP.NET MVC框架開發(fā)此論壇應(yīng)用程序。原因在于,這個(gè)框架可以使我更容易地編寫程序的測試代碼。而另一方面,ASP.NET MVC框架本身就從設(shè)計(jì)之初提供了對測試驅(qū)動(dòng)開發(fā)的最忠誠的支持。
【編輯推薦】