[譯]Chapter 1 – An Introduction to ASP.NET MVC(2)

來源:互聯網
上載者:User


原文地址:Chapter 1 - An Introduction to ASP.NET MVC
Avoiding Code Smells

如果你不是很小心,軟體程式很快就會變得很難對應變更。我們都曾經有這種經曆,從別人那裡接管一個應用程式,然後被要求對其進行改動。回想一下你心中在作出第一個改動前的擔心和恐懼。

在這個接力棒的遊戲中,你必須依次將接力棒從一堆接力棒中移除,而不能影響其他接力棒。一個很微小的錯誤對於一堆接力棒來說,可能是很巨大的。

改動一個現存的軟體應用程式和接力棒的遊戲很像。在你修正一個錯誤的同時,又引入了一個bug。

不好的軟體很難應對變化。Robert和Micah Martin將不好的軟體的特點描述為代碼味道。以下代碼味道表明了糟糕的軟體的代碼味道:

· 僵化 – 僵化的軟體是指當你改動一個地方時,同時還需要改動其他很多地方。

· 脆弱 – 脆弱的軟體是指你作出一個改動後,軟體會在多個地方崩潰。

· 沒有必要的複雜度 – 沒有必要的複雜度是指軟體被過度設計成可以解決任何可能的變更。

· 沒有必要的重複 – 沒有必要的重複是指軟體中包含重複代碼。

· 晦澀 – 晦澀的軟體很難被理解。

*** Begin Note ***

這些代碼味道在Micah 和 Robert Martin的著作《Agile Principles, Patterns, and
Practices in C#》的104頁被提及,強烈推薦這本著作。

*** End Note ***

請注意這些代碼味道都和變更相關,其中任何一個代碼味道都是橫在變更前的一個障礙。

Software Design Principles

軟體不必寫的很差,可以在一開始時,對軟體進行設計,使得它更好的應對後面的變更。

使得軟體容易應對變更的最好策略就是讓軟體的各個組件之間松耦合。在一個松耦合的應用程式中,你可以對程式的某一個組件進行改動,而不會影響其他組件。

多年來,為了編寫好的軟體,出現了一些原則。這些原則可以降低軟體不同部分相互依賴的程度。這些
原則被Robert Martin 收集到他的著作中。

Robert Martin並沒有發明這些原則,他是第一個人將這些原則收集整理到一個簡單的列表中。以下就是他關於軟體設計原則的列表:

· SRP – 單一職責原則

· OCP – 開-閉原則

· LSP – Liskov可替換原則

· ISP – 介面隔離原則

· DIP – 依賴倒置原則

這個由原則組成的集合被廣泛的稱為SOLID(沒錯,SOLID是每個原則的首字母的縮寫)。

例如,根據單一職責原則,一個類應該有且只有一個原因來引發變化。下面是一個對於這個原則如何應用的實際樣本:如果你知道你可能會更改程式的驗證邏輯,這些驗證邏輯是獨立於它的資料訪問邏輯的,那麼,你就不應該將驗證和資料訪問的邏輯放在一個類中。

*** Begin Note ***

關於軟體設計原則,還存在其他列表。例如《Head First Design Patterns》中也包含一個非常不錯的列表。

*** End Note ***

Software Design Patterns

軟體設計模式是應用軟體設計原則的體現,換言之,軟體設計原則是不錯的想法,設計模式是實現這個想法的工具(它是一個鼓)。

設計模式的思想最初是由《Design Patterns: Elements of Reusable Object-Oriented Software》書中提出的,這本書也被稱為“四人組”或“四人幫”,這本書影響了其他很多講述軟體設計模式的書籍。

和“四人幫”的書相比,《Head First Design Pattern》在設計模式方賣弄,提供了一個更加方便使用的介紹,這本書集中介紹了諸如觀察者、門面、單件以及適配器等14個模式。

另外一本在軟體設計模式領域有影響力的書籍是Martin Fowler 的《Patterns of Enterprise Application Architecture》。這本書有一個支援網站,在網站中提供了書中涉及的所有模式,網站地址:http://www.martinfowler.com/eaaCatalog/。

軟體設計模式可以使你的代碼更易於對應變更。例如,在這本書的很多地方,我們都會利用設計模式中的Repository模式。Eric Evans 在他的著作《Domain-Driven Design》中,對Repository 模式有以下描述:

一個Repository 代表了特定類型的所有對象,特定類型是一個概念上的集合(通常是類比的)。它在操作上很像一個集合,但是包含了更加複雜的查詢能力。特定類型的對象可以被添加和刪除,這些插入和刪除是通過操作資料庫來實現的(參考151頁)。
譯註:本段文字翻譯的可能不太準確,個人理解是Repository相當於在應用程式層和資料層之間的一層,嚮應用層提供持久化資料,向資料層負責管理持久化資料。附上原文:A REPOSITORY represents all objects of a certain
type as a conceptual set (usually emulated). It acts like a collection, except
with more elaborate querying capability. Objects of the appropriate type are
added and removed, and the machinery behind the REPOSITORY inserts them or
deletes them from the database. (see page 151),歡迎大家補充準確的含義。

按照Evans 的說法,使用Repository 模式的一個主要好處就是能夠讓你“將應用、領域設計和持久層技術、多資料庫策略或者多資料來源之間進行解耦合”(ibid),換言之,Repository
模式可以在資料庫訪問機制發生變化時,對你的應用程式進行保護,使應用程式獨立於資料庫訪問方式。

例如,當我們在本書的最後編寫論壇應用程式時,我們利用Repository 模式來隔離論壇應用程式和特定的持久層技術。通過這種設計方式,論壇應用程式可以在不同的訪問救贖之間進行切換,例如從LINQ切換到SQL、Entity架構甚至是NHibernate 。

Writing Unit Tests for Your Code

通過利用軟體設計原則和模式,你可以建立更易應對變更的軟體。設計模式是架構層次的模式,它們著眼於應用程式總的結構。

如果你想在更細的粒度層次上表明你的程式可以應對變更,你可以為你的應用程式構建單元測試。單元測試能夠讓你確定程式中的方法是否按照你的意圖運行。

你可以從為你的代碼編寫單元測試中得到很多好處:

1) 為你的代碼編寫測試可以向你提供一個應對變更的安全環境。

2) 為你的代碼編寫測試可以迫使你編寫松耦合的代碼。

3) 為你的代碼編寫測試可以迫使你站在使用者的立場上看待代碼。

首先,單元測試為你提供了一個應對變更的安全環境,這是Michael Feathers 在他的著作《Working Effectively with Legacy Code》中反覆強調的,事實上,他將遺留代碼定義為“沒有帶測試的簡單代碼”(參看xvi)。

當你的應用程式被單元測試所覆蓋時,你可以改動代碼而不用擔心改動會破壞代碼的功能。單元測試使得你的代碼可以很安全的進行重構,如果你可以重構,那麼你可以利用設計模式對代碼進行改動,從而使得程式更易於應對變更。

*** Begin Note ***

重構是這樣一個過程,它改動了代碼,但是沒有改變代碼的功能。

*** End Note ***

第二,為你的代碼編寫單元測試可以迫使你以一種特別的方式編寫代碼。可測試的代碼一般是松耦合的代碼,單元測試是對一塊代碼進行隔離測試。為了使得你的程式是可測試的,你不得不以隔離組件的方式構建你的應用程式。

當一個類和另外一個類是松耦合時,你對第一個類進行改動時,不用影響到第二個類。測試驅動開發經常迫使你編寫非常松耦合的代碼,這種代碼非常易於應對變更。

最後,編寫單元測試可以迫使你站在使用者的立場來看待代碼。當編寫一個單元測試時,你會採取和將來使用你的代碼的人一樣的立場,既然編寫測試會迫使你思考將來開發人員(可能就是將來的你自己)如何使用你的代碼,代碼自然會被更好的設計。

Test Driven Development

在上一個章節中,我們討論了為你的代碼編寫單元測試的重要性,測試驅動開發是一種軟體設計方法學,它認為單元測試在整個軟體開發過程中出於中心地位,當你實踐測試區鄂東開發時,你首先編寫測試,然後針對測試編寫代碼。

更細的說,當你實踐測試驅動開發時,在你編寫代碼時,需要3個步驟(紅/綠/重構):

· 編寫一個失敗的單元測試(紅)。

· 編寫代碼,已通過單元測試(綠)。

· 重構你的代碼(重構)。

首先,編寫單元測試,單元測試應該表達你期望代碼應該是如何啟動並執行。當你第一次建立單元測試時,它是應該運行不通過的,之所以失敗,是因為你還沒有編寫任何可以滿足測試的代碼。

接下來,你需要編寫必要的代碼來使得單元測試可以通過,要是以最懶、最草率、最快的方式來編寫代碼。你不應該浪費時間來思考程式的架構,你應該關注的是編寫最小數量的代碼來滿足單元測試中表達的意圖。

最後,在編寫了足夠的代碼後,你可以退回去思考程式的整個架構,在這個階段,你應該利用設計模式來重寫(重構)你的代碼--例如Repository 模式-- ,這樣你的代碼會變的更易於維護。在這個過程中你可以放心的重寫代碼,因為代碼已經被單元測試覆蓋了。

實踐測試驅動開發可以帶來很多好處。首先,測試驅動開發迫使你關注那些實際中確實需要的代碼,因為你持續的關注只編寫能夠通過特定測試的代碼,就可以避免編寫那些龐大的、你永遠都不會用到的代碼。

其次,“測試優先”的設計方法學可以迫使你站在使用你的代碼如何被使用的角度來編碼。換言之,在實踐測試驅動開發的時候,你是一直的站在使用者的角度編寫你測試,這樣,測試驅動開發可以帶來更加整潔和可理解的API。

最後,測試驅動開發迫使你將編寫單元測試作為整個軟體開發過程的一部分。在著眼於項目到期日的方法論中,測試經常是第一個被取消的,但是在實踐測試驅動開發時,由於單元測試出於整個開發過程的中心地位,你在編寫單元測試時,可能會更加從容不迫。

Short Term Pain, Long Term Gain

構建用於應對變更的軟體需要更多前期的努力,實現設計原則和模式需要思考和努力,編寫測試需要時間。然而,與前期讓軟體以正確的方式進行構建所花費的力氣相比,在將來會得到巨大的回報。

開發人員有兩條路。你可以做一個牛仔,或者你可以做一個工匠。牛仔接到任務後馬上跳進去開始編碼,他可以迅速的構建一個軟體應用程式,問題是隨著時間遷移,軟體必須要進行維護。

工匠就很有耐心。工匠在構建軟體時很小心。他會很小心的構建單元測試來覆蓋應用程式中的所有代碼,這樣他需要花費更長時間來完成一個應用程式。但是,在應用程式被建立後,修改bug和添加新特性都會變得很容易。

大部分開發人員都是以牛仔的方式開始他們的編程生涯,然而,在某個時候,你必須掛起你的馬鞍,來構建那些能夠經得起時間考驗的軟體。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.