敏捷思維: 架構設計中的方法學(6)–迭代設計

來源:互聯網
上載者:User

簡介: 迭代是一種軟體開發的生命週期模型,在設計中應用迭代設計,我們可以得到很多的好處。

Context

在軟體生命週期中,我們如何對待架構設計的發展?

Problem

架構設計往往發生在細節需求尚未完成的時候進行的。因此,隨著項目的進行,需求還可能細化,可能變更。原先的架構肯定會有不足或錯誤的地方。那麼,我們應該如何對待原先的設計呢?

我們在簡單設計模式中簡單提到了"Planned Design"和"Evolutionary
Design"的區別。XP社團的人們推崇使用"Evolutionary
Design"的方式,在外人看來,似乎擁護者們從來不需要架構的設計,他們採用的方式是一開始就進入代碼的編寫,然後用Refactoring來改進代碼的品質,解決未經設計導致的代碼品質低下的功能。

從一定程度上來說,這個觀點並沒有錯,它強調了代碼對軟體的重要性,並通過一些技巧(如Refactoring)來解決缺乏設計的問題。但我並不認同"Evolutionary
Design"的方式,在我看來,一定程度上的"Planned Design"是必須的,至少在中國的軟體行業中,"Planned
Design"還沒有成為主要的設計方向。借用一句明言,"凡事預則立,不預則廢",在軟體設計初期,投入精力進行架構的設計是很有必要的,這個架構是你在後續的設計、編碼過程中依賴的基礎。但是,一開始我們提到的設計改進的問題依然存在,我們如何解決它呢?

在簡單設計模式中,我們提到了設計改進的必要性,但是,如果沒有一種方法去控制設計的改進的話,那麼設計改進本身就是一場噩夢。因此,何時改進,怎麼改進,
如何控制,這都是我們需要面對的問題。

Solution

為了實現不斷的改進,我們將在開發流程中引入迭代的概念。迭代的概念在我的另一篇文章--《需求的實踐》中已經提到,這裡我們假設讀者已經有了基本的迭代的概念。

軟體編碼之前的工作大致可以分為這樣一個工作流程:

 

中的流程隱含著一個資訊的損失的過程。來自於使用者的需求經過整理之後,開發人員就會從中去掉一些資訊,同樣的事情發生在後面的過程中,資訊丟失
或變形的情況不斷的發生。這裡發生了什麼問題?應該說,需求資訊的失真是非常普遍的,我們缺少的是一種有效辦法來抑止失真,換句話說,就是缺少反饋。

如果把眼睛蒙上,那我們肯定沒有辦法走出一條很長的直線。我們走路的時候都是針對目標不斷的調整自己的方向的。同樣的,漫長的軟體開發過程如果沒有一種反饋機制來調整方向,那最後的軟體真是難以想象。

所以我們引入了迭代周期。

初始設計和迭代設計

在團隊設計中,我們一直在強調,設計組最開始得到的設計一定只是一個原始架構,然後把這個原始架構傳播到每一位開發人員的手中,從而在Team Dev中形成
共同的願景。(願景(Vision):源自於管理學,表示未來的願望和景象。這裡借用來表示軟體在開發人員心中的樣子。在後面的文章中我們會有一個章節專
門的討論架構願景。)

迭代(Iterate)設計,或者我們稱之為增量(Incremental)設計的思想和XP提倡的Evolutionary
Design有異曲同工之妙。我們可以從XP、Crystal、RUP、ClearRoom等方法學中對比、體會迭代設計的精妙之處:每一次的迭代都是在
上一次迭代的基礎上進行的,迭代將致力於重用、修改、增強目前的架構,以使架構越來越強壯。在軟體生命週期的最後,我們除了得到軟體,還得到了一個非常穩
定的架構。對於一個軟體組織來說,這個架構很有可能就是下一個軟體的投入或參考。

我們可以把早期的原始架構當作第一次迭代前的早期投入,也可以把它做為第一次迭代的重點,這些都是無所謂的。關鍵在於,原始架構對於後續的架構設計而言是非常重要的,我們討論過架構是來源於需求的,但是原始架構應該來源於那些比較穩定的需求。

TIP:現實中迭代設計退化為"Code and Fix"的設計的情況屢見不鮮("Code and
Fix"參見簡單設計)。從表面上看,兩者的做法並沒有太大的差別,都是針對原有的設計進行改進。但是,二者效果的差別是明顯的:"Code and
Fix"是混沌的,毫無方向感可言,每一次的改進只是給原先就已搖搖欲墜的積木上再加一塊積木而已。而迭代設計的每一次改進都朝著一個穩定的目標在前進,他給開發人員帶來信心,而不是打擊。在過程上,我們說迭代設計是在控制之下的。

從實踐的經驗中,我們發現,把原該在目前就該解決的問題退後是造成這一問題的主要原因之一。因此,請嚴格的對待每一次的迭代,確保計劃已經完成、確保軟體的品質、確保使用者的需求得到滿足,這樣才是正統的迭代之路。

單次的迭代

我們說,每一次的迭代其實是一個完整的小過程。也就是說,它同樣要經曆文章中討論的這些過程模式。只不過,這些模式的工作量都不大,你甚至可以在很短的時間內做完所有的事情。因此,我們好像又回到了文章的開頭,重新討論架構設計的過程。

單次迭代最令我們興奮的就是我們總是可以得到一個在當前迭代中相當穩定的結果,而不像普通的架構設計那樣,我們深怕架構會出現問題,但又不得不依賴
這個架構。從我們的心理上來分析,我們是在持續的建設架構中,我們不需要迴避需求的變更,因為我們相信,在需求相對應的迭代中,我們會繼續對架構進行改
進。大家不要認為這種心理的改變是無關緊要的,我起初並沒有意識到這個問題,但是我很快發現新的架構設計過程仍然籠罩在原先的懼怕改變的陰影之下的時候,
迭代設計很容易就退化為"Code
and Fix"的情形。開發人員難以接受新方法的主要原因還是在心理上。因此,我不得不花了很多的時間來和開發人員進行溝通,這就是我現實的經驗。

迭代的交錯

基於我們對運籌學的一點經驗,迭代設計之間肯定不是線性關係。這樣說的一個原因架構設計和後續的工作間還是時間差的。因此,我們不會傻到把時間浪費在等待其它工作上。一般而言,當下一次迭代的需求開始之後,詳細需求開始之前,我們就已經可以開始下一次迭代的架構設計了。

各次迭代之間的時間距離要視項目的具體情況而定。比如,人員比較緊張的項目中,主要的架構設計人員可能也要擔任編碼人員的角色,下一次迭代的架構設
計就可能要等到編碼工作的高峰期過了之後。可是,多次的交錯迭代就可能產生版本的問題。比如,本次的迭代的編碼中發現了架構的一個問題,反饋給架構設計
組,但是架構設計組已經根據偽修改的本次迭代的架構開始了下一次迭代的架構設計,這時候就會出現不同的設計之間的衝突問題。這種情況當然可以通過加強對設
計模型的管理和引入版本控制機制來解決,但肯定會隨之帶來管理成本上升的問題,而這是不符合敏捷的思想的。這時候,團隊設計就體現了他的威力了,這也是我
們在團隊設計中沒有提到的一個原因。團隊設計通過完全的溝通,可以解決架構設計中存在衝突的問題。

迭代頻率

XP提倡迭代周期越短越好(XP建議為一到兩周),這是個不錯的提議。在這麼短的一個迭代周期內,我們花在架構設計上的時間可能就只有一兩個小時到
半天的時間。這時候,會有一個很有意思的現象,你很難去區分架構設計和設計的概念了。因為在這麼短的一個周期之內,完成的需求數量是很少的,可能就只有一
兩個用例或使用者素材。因此,這幾項需求的設計是不是屬於架構設計呢?如果是的話,由於開發過程是由多次的迭代組成的,那麼開發過程中的設計不都屬於架構設
計了嗎?我們說,架構是一個相對的概念,是針對範圍而言的,在傳統的瀑布模型中,我們可以很容易的區分出架構設計和普通設計,如果我們把一次迭代看作是一
個單獨的生命週期,那麼,普通的設計在這樣一個範圍之內也就是架構設計,他們並沒有什麼兩樣。但是,迭代周期中的架構設計是要遵循一定的原則的,這我們在
下面還會提到。

我們希望迭代頻率越快越好,但是這還要根據現實的情況而定。比如資料倉儲項目,在項目的初期階段,我們不得不花費大量的時間來進行資料建模的工作,這其實也是一項專門針對資料的架構設計,建立中繼資料,制定維,整理資料,這樣子的過程很難分為多次的迭代周期來實現。

如何確定軟體的迭代周期

可以說,如果一支Team Dev沒有相關迭代的概念,那麼這支團隊要立刻實現時隔兩周迭代周期是非常困難的,,同時也是毫無意義的。就像我們在上面討論的,影響迭代周期的因素很多,以至於我們那無法對迭代周期進行量化的定義。因此我們只能從定性的角度分析迭代周期的發展。

另一個瞭解迭代的方法是閱讀XP的相關資料,我認為XP中關於迭代周期的使用是很不錯的一種方法,只是他強調的如此短的迭代周期對於很多的軟體團隊而言都是難以實現的。

迭代周期的引入一定是一個從粗糙到精確的過程。迭代的本質其實是短周期的計劃,因此這也是迭代周期越短對我們越有好處的一大原因,因為時間縮短了,
計劃的可預測性就增強了。我們知道,計劃的制定是依賴於已往的經驗,如果原先我們沒有制定計劃或細節計劃的經驗,那麼我們的計劃就一定是非常粗糙,最後的
誤差也一定很大。但是這沒有關係,每一次的計劃都會對下一次的計劃產生正面的影響,等到經驗足夠的時候,計劃將會非常的精確,最後的誤差也會很小。

迭代周期的確定需要依賴於單位工作量。單位工作量指的是一定時間內你可以量化的最小的績效。最簡單的單位工作量是每位程式員一天的編碼行數。可惜顯
示往往比較殘酷,團隊中不但有程式員的角色,還有設計師、測試人員、文檔製作人員等角色的存在,單純的編碼行數是不能夠作為唯一的統計依據的。同樣,只強
調編碼行數,也會導致其它的問題,例如代碼品質。為了保證統計的合理性,比較好的做法是一個團隊實現某個功能所花費的天數作為單位工作量。這裡討論的內容
實際是軟體測量技術,如果有機會的話,再和大家探討這個問題。

迭代周期和軟體架構的改進

我們應用迭代方法的最大的目的就是為了穩步的改進軟體架構。因此,我們需要瞭解架構是如何在軟體開發的過程中不斷演化的。在後面的文章中,我們會談
到用Refactoring的方法來改進軟體架構,但是Refactoring的定義中強調,Refactoring必須在不修改代碼的外部功能的情況下
進行。對於架構來說,我們可以近乎等價的認為就是在外部介面不變的情況下對架構進行改進。而在實際的開發中,除非非常有經驗,否則在軟體開發全過程中保持
所有的軟體介面不變是一件非常困難的事情。因此,我們這裡談的架構的改進雖然和Refactoring有類似之處,但還是有區別的。

軟體架構的改進在軟體開發過程會經曆一個振蕩期,這個振蕩期可能橫跨了數個迭代周期,其間架構的設計將會經曆劇烈的變化,但最後一定會取向於平
穩。(如果項目後期沒有出現設計平穩化的情況,那麼很不幸,你的項目註定要失敗了,要麼是時間的問題,要麼就是需求的問題)。關鍵的問題在於,我們有沒有
勇氣,在架構需要改變的時候就毅然做出變化,而不是眼睜睜的看著問題變得越來越嚴重。最後的例子中,我們討論三個迭代周期,假設我們在第二個周期的時候拒
絕對架構進行改變,那麼第三個周期一定是有如噩夢一般。變化,才有可能成功。

我們知道變化的重要性,但沒有辦法知道變化的確切時間。不過我們可以從開發過程中嗅到架構需要變化的氣味:當程式中重複的代碼逐漸層多的時候,當某些類變得格外的臃腫的時候,當編碼人員的編碼速度開始下降的時候,當需求出現大量的變動的時候。

例子

從這一周開始,我和我的小組將要負責對軟體項目中的展示層的設計。在這個迭代周期中,我們的任務是要為用戶端提供6到10個的視圖。由於視圖並不很多,展示層的架構設計非常的簡單:

 

準確的說,這裡談不上設計,只是簡單讓用戶端訪問不同的視圖而已。當然,在設計的中,我們並沒有必要畫出所有的視圖來,只要能夠表達用戶端和視圖的關聯性就可以了。

(架構設計需要和具體的實現綁定,但是在這個例子中,為了著重體現設計的演化,因此把不必要的資訊都刪掉。在實際的設計中,視圖可能是JSP頁面,也可能是一個視窗。)

第一個迭代周的任務很快的完成了,小組負責的展示層模組也很順利的和其它小組完成了對接,一個簡陋但能夠運轉的小系統順利的發布。客戶觀看了這個系統的示範,對系統提出了修改和補充。

第二個迭代周中,模組要處理的視圖增加到了30個,視圖之間存在相同的部分,並且,負責資料層的小組對我們說,由於客戶需求的改進,同一個視圖中將
會出現不同的資料來源。由於我們的視圖中直接使用了資料層小組提供給我們的資料來源的函數,這意味著我們的設計需要進行較大的調整。

考慮到系統的視圖的量大大的增加,我們有必要對視圖進行集中的管理。前端控制器(Front
Control)模式將會是一個不錯的技巧。對於視圖之間的普遍的重複部分,可以將視圖劃分為不同的子視圖,再把子視圖組合為各種各樣的視圖。這樣我們就可以使用組合(Composite)模式:

 

 

客戶的請求集中提交給控制器,控制器接受到客戶的請求之後,根據一定的規則,來提供不同的視圖來反饋給客戶。控制器是一個具有擴充能力的設計,目前
的視圖數量並不多,因此仍然可以使用控制器來直接分配視圖。如果視圖的處理規則比較複雜,我們還可以使用建立工廠(Create
Factory)模式來專門處理產生視圖的問題。對於視圖來說,使用組合模式,把多個不同資料來源的視圖組合為複雜的視圖。例如,一個JSP的頁面中,可能
需要分為頭頁面和尾頁面。

項目進入第三個迭代周期之後,展示層的需求進一步複雜化。我們需要處理許可權資訊、需要處理資料的合法性判斷、還需要面對更多的視圖帶來的複雜程度上升的問題。

展示層的許可權處理比較簡單,我們可以從前端控制器中增加許可權控制的模組。同時,為瞭解決合法性判斷問題,我們又增加了一個資料過濾鏈模組,來完成數
據的合法性判斷和轉換的工作。為了不使得控制器部分的功能過於複雜,我們把原先屬於控制器的視圖分發功能轉移到新的分發器模組,而控制器專門負責使用者請
求、視圖的控制。

 

我們來回顧這個例子,從迭代周期1中的需求最為簡單,其實,現實中的項目剛開始的需求雖然未必會像例子中的那麼簡單,但一定不會過於複雜,因此迭代
周期1的設計也非常的簡單。到了迭代周期2的時候,需求開始變得複雜,按照原先的架構繼續設計的話,必然會導致很多的問題,因此對架構進行改進是必要的。
我們看到,新的設計能夠滿足新的需求。同樣的,迭代周期3的需求更加的複雜,因此設計也隨之演化。這就是我們在文章的開始提到
的"Evolutionary
Design"的演化的思想。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.