免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
Martin Fowler:設(shè)計已死?
Martin Fowler:設(shè)計已死?
 

設(shè)計已死?
英文原文版權(quán)由Martin Fowler擁有
Original text is copyrighted by Martin Fowler

Martin Fowler
Chief Scientist, ThoughtWorks

原文出處| 繁體版 | 譯者:Daimler Huang

對很多粗略接觸到 Extreme Programming 的人來說,XP 似乎 宣告了軟件設(shè)計的死刑。不只很多的設(shè)計被嘲笑為 "BigUp Front Design"[譯注1],連很多技術(shù)像UML、富有彈性的程序架構(gòu) (framework),甚至連模式 (pattern)都不受重視,或是近似忽略了。事實上,XP內(nèi)含很多設(shè)計理念,但是它與現(xiàn)有的軟件流程有著不同的運作方式。XP藉由多種實務(wù)技巧 (practice)賦予演進式設(shè)計 (evolutionary design) 嶄新的風貌,讓演進變成一種實用的設(shè)計方法。它也讓設(shè)計者(designer[譯注2]) 面臨新的挑戰(zhàn)與技巧,學習如何使設(shè)計精簡,如何使用重構(gòu)來保持一個設(shè)計的清楚易懂,以及如何逐步地套用模式。

(這篇文章是我在 XP2000 研討會發(fā)表的演說,它會公布在研討會講義中。)

      Planned and Evolutionary Design (經(jīng)過規(guī)劃的設(shè)計與演進式的設(shè)計)

      The Enabling Practices of XP (XP有效的實作技巧)

      The value of Simplicity (簡單的價值)

      What on Earth is Simplicity Anyway (究竟什么是簡單)

      Does Refactoring Violate YAGNI? (重構(gòu)違反了YAGNI嗎?)

      Patterns and XP (模式與XP)

      Growing an Architecture (發(fā)展結(jié)構(gòu))

      UML and XP (UML與XP)

      On Metaphor (關(guān)于隱喻)

      Do you wanna be an Architect when you grow up? (你將來想成為一個軟件結(jié)構(gòu)師嗎?)

      Things that are difficult to refactor in (很難重構(gòu)的東西)

      So is Design Dead? (所以,設(shè)計死了嗎?)

      Acknowledgements (致謝)

     Revision History (修訂的記錄)

Extreme Programming (XP) 挑戰(zhàn)很多軟件開發(fā)常見的假設(shè)。其中最受爭議的就是極力排斥 up-frontdesign,而支持一種比較屬于演進的方式。批評者說這是退回到了 "code and fix"的開發(fā)方式,頂多只能算是一般急就章的程序設(shè)計罷了。支持者也??吹?XP 對于設(shè)計方法 (如UML)、principle(設(shè)計準則)、patterns 等的排斥。別擔心,仔細注意你的程序代碼,你就會看到好的 design 浮現(xiàn)出來。

我發(fā)現(xiàn)自己正陷于這個爭論當中。我的工作著重在圖形化設(shè)計語言 - UML 以及 patterns,事實上我也寫過 UML 和patterns 的書。我如此的擁抱 XP 是否表示我放棄了這些理論,或是將這些反漸進式 (counter-revolutionary)的概念從腦中清除了?

嗯... 我不想讓你的心懸蕩在這兩種情境中。簡單的說并不是;接下來的文章就讓我來詳細說明。

 

Planned and Evolutionary Design

 

我將在這篇文章中說明軟件開發(fā)的兩種設(shè)計方式是如何完成的?;蛟S最常見的是演進式設(shè)計。它的本質(zhì)是系統(tǒng)的設(shè)計隨著軟件開發(fā)的過程增長。設(shè)計 (design) 是撰寫程序代碼過程的一部份,隨著程序代碼的發(fā)展,設(shè)計也跟著調(diào)整。

在常見的使用中,演進式設(shè)計實在是徹底的失敗。設(shè)計的結(jié)果其實是一堆為了某些特殊條件而巧妙安排的決定所組成,每個條件都會讓程序代碼更難修改。從很多方面來看,你可能會批評這樣根本就沒有設(shè)計可言,無疑地這樣的方式常會導致很差勁的設(shè)計。根據(jù)Kent的陳述,所謂的設(shè)計 (design)是要能夠讓你可以長期很簡單地修改軟件。當設(shè)計 (design)不如預(yù)期時,你應(yīng)該能夠做有效的更改。一段時間之后,設(shè)計變得越來越糟,你也體會到這個軟件混亂的程度。這樣的情形不僅使得軟件本身難以修改,也容易產(chǎn)生難以追蹤和徹底解決的 bug。隨著計畫的進行,bug 的數(shù)量呈指數(shù)地成長而必須花更多成本去解決,這就是 "code and fix" 的惡夢。

Planned Design的做法正好相反,并且含有取自其它工程的概念。如果你打算做一間狗屋,你只需要找齊木料以及在心中有一個大略的形象。但是如果你想要建一棟摩天大樓,照同樣的做法,恐怕還不到一半的高度大樓就垮了。于是你先在一間像我太太在波士頓市區(qū)那樣的辦公室里完成工程圖。她在設(shè)計圖中確定所有的細節(jié),一部份使用數(shù)學分析,但是大部分都是使用建筑規(guī)范。所謂的建筑規(guī)范就是根據(jù)成功的經(jīng)驗 (有些是數(shù)學分析)制定出如何設(shè)計結(jié)構(gòu)體的法則。當設(shè)計圖完成,她們公司就可以將設(shè)計圖交給另一個施工的公司按圖施工。

Planned Design 將同樣的方式應(yīng)用在軟件開發(fā)。Designer先定出重要的部份,程序代碼不是由他們來撰寫,因為軟件并不是他們 "建造[譯注3]" 的,他們只負責設(shè)計。所以 designer 可以利用像UML 這樣的技術(shù),不需要太注重撰寫程序代碼的細節(jié)問題,而在一個比較屬于抽象的層次上工作。一旦設(shè)計的部份完成了,他們就可以將它交給另一個團隊(或甚至是另一家公司) 去 "建造"。因為 designer朝著大方向思考,所以他們能夠避免因為策略方面不斷的更改而導致軟件的失序。Programmer 就可以依循設(shè)計好的方向 (如果有遵循設(shè)計)寫出好的系統(tǒng)。

Planned design 方法從七○年代出現(xiàn),而且很多人都用過它了。在很多方面它比 code and fix漸進式設(shè)計要來的好,但是它也有一些缺點存在。第一個缺點是當你在撰寫程序代碼時,你不可能同時把所有必須處理的問題都想清楚。所以將無可避免的遇到一些讓人對原先設(shè)計產(chǎn)生質(zhì)疑的問題??墒侨绻?designer 在完成工作之后就轉(zhuǎn)移到其它項目,那怎么辦?Programmer開始遷就設(shè)計來寫程序,于是軟件開始趨于混亂。就算找到designer,花時間整理設(shè)計,變更設(shè)計圖,然后修改程序代碼。但是必須面臨更短的時程以及更大的壓力來修改問題,又是混亂的開端。

此外,通常還有軟件開發(fā)文化方面的問題。Designer 因為專精的技術(shù)和豐富的經(jīng)驗而成為一位designer。然而,他們忙于從事設(shè)計而沒有時間寫程序代碼。但是,開發(fā)軟件的工具發(fā)展迅速,當你不再撰寫程序代碼時,你不只是錯失了技術(shù)潮流所發(fā)生的改變,同時也失去了對于那些實際撰寫程序代碼的人的尊敬。

建造者 (builder[譯注3])和設(shè)計者之間這種微妙的關(guān)系在建筑界也看得到,只是在軟件界更加凸顯而已。之所以會如此強烈是因為一個關(guān)鍵性的差異。在建筑界,設(shè)計師和工程師的技術(shù)有清楚的分野;在軟件界就比較分不清楚了[譯注2]。任何在高度注重 design 的環(huán)境工作的 programmer都必須具備良好的技術(shù),他的能力足夠?qū)?designer 的設(shè)計提出質(zhì)疑,尤其是當 designer 對于新的發(fā)展工具或平臺越來越不熟悉的狀況下。

現(xiàn)在這些問題也許可以獲得解決。也許我們可以處理人與人之間的互動問題。也許我們可以加強 designer的技術(shù)來處理絕大部份的問題,并且訂出一個依照準則去做就足夠改變設(shè)計圖的流程。但是仍然有另外一個問題:變更需求。變更需求是軟件項目中最讓我感到頭痛的問題了。

處理變更需求的方式之一是做有彈性的設(shè)計,于是當需求有所更改,你就可以輕易的變更設(shè)計。然而,這是需要先見之明去猜測將來你可能會做怎樣的變更。一項預(yù)留處理易變性質(zhì)的設(shè)計可能對于將來的需求變更有所幫助,但是對于意外的變化卻沒有幫助(甚至有害)。所以你必須對于需求有足夠的了解以隔離易變的部份。照我的觀察,這是非常困難的。

部份有關(guān)需求的問題應(yīng)該歸咎于對需求的了解不夠清楚,所以有人專注于研究需求處理,希望得到適切的需求以避免后來對設(shè)計的修改。但是即使朝這個方向去做一樣無法對癥下藥。很多無法預(yù)料的變更起因于瞬息萬變的商場,你只有更加小心處理需求問題來應(yīng)付無法避免的情況。

這么說來,planned design 聽起來像是不可能的任務(wù)。這種做法當然是一種很大的挑戰(zhàn)。但是,跟演進式設(shè)計(evolutionary design) 普遍以 code and fix 方式實作比較起來,我不覺得 planned design會比較差。事實上,我也比較喜歡 planned design。因為我了解 planned design 的缺點,而且正在尋找更好的方法。

 

The Enabling Practices of XP

 

XP 因為許多原因而備受爭議,其中之一就是它主張演進式設(shè)計 (evolutionary design) 而不是 planned design。我們也知道,演進式設(shè)計可能因為特定的設(shè)計或是軟件開發(fā)趨于混亂而行不通。

想了解這些爭論的核心,就是軟件研發(fā)異動曲線。曲線的變化說明,隨著項目的進行,變更所需要的成本呈現(xiàn)指數(shù)的增加。這樣的曲線常以一句話來表示:在分析階段花一塊錢所作的變更,發(fā)行之后要花數(shù)千元來補救。諷刺的是大部分的計畫仍然沒有分析過程而以非標準的方式進行,但是這種成本上的指數(shù)關(guān)系還是存在著。這種指數(shù)曲線意味著演進式設(shè)計可能行不通,它同時也說明著為什么 planned design要小心翼翼地規(guī)劃,因為任何的錯誤還是會面對同樣的問題。

XP 的基本假設(shè)是它可以將這種指數(shù)曲線拉平,這樣演進式設(shè)計就行得通了。XP 使曲線更平緩并能運用這種優(yōu)勢。這是因為 XP實作技巧之間的耦合效果:換句話說,不使用那些能夠拉平軟件開發(fā)曲線的實作技巧來工作,這條曲線也不會趨向平緩。這也是爭論的來源,因為評論家不了解這其間的關(guān)系。通常這些批評是根據(jù)評論家自身的經(jīng)驗,他們并沒有實行那些有效的實作技巧,當他們看到結(jié)果不如預(yù)期,對于 XP 的印象也就是這樣了。

這些有效的實作技巧有幾個部份,主要是 Testing 和 Continuous Integration。如果沒有 testing提供保障,其它的 XP 實作技巧都不可行。Continuous Integration可以保持團隊成員信息同步,所以當你有改變的部份,不必擔心與其它成員資料整合會有問題。同時運用這些實作技巧能夠大大影響開發(fā)曲線。這讓我再次想起在ThoughtWorks 導入 testing 和 continuous integration之后,明顯的改善了研發(fā)成果。改善的程度好到令人懷疑是不是像 XP 所主張的,必須要用到所有的實作技巧才能大幅改善效率。[譯注4]

Refactoring 具有類似的成效。那些曾經(jīng)采用 XP 建議的原則來對程序代碼進行refactoring的人發(fā)現(xiàn),這么做要比無章法或是特殊方式的 restructuring 明顯的更有效率。那也曾經(jīng)是 Kent 指導我適當?shù)?refactor得到的難忘經(jīng)驗,也因為這么一次巨大的轉(zhuǎn)變促使我以這個主題寫了一本書。

Jim Highsmith 寫了一篇很棒的文章 "summary of XP",他把 planned design 和refactoring 放在天秤的兩端。大部份傳統(tǒng)的做法假設(shè)構(gòu)想不變,所以 planned design占優(yōu)勢。而當你的成本越來越不允許變更,你就越傾向于采用 refactoring。Planned design并不是完全消失,只是將這兩種做法互相搭配運用取得平衡。對我來說,在設(shè)計進行 refactoring 之前,總覺得這個設(shè)計不夠健全。

Continuous integration、testing 和 refactoring 這些有效的實作方法讓 evolutionarydesign 看似很有道理。但是我們尚未找出其間的平衡點。我相信,不論外界對 XP 存有什么印象,XP 不僅僅是 testing、coding和 refactoring。在 coding 之前還有 design 的必要。部份的 design 在 coding 之前準備,大部份的design 則發(fā)生在實作每一項詳列的功能之前??傊?up-front design 和 refactoring 之間可以找到新的平衡。

 

The value of Simplicity

 

XP 大聲疾呼的兩個口號是 "Do The Simplest Thing that Could PossiblyWork"(只做最簡單可以正常運作的設(shè)計) 和 "You Aren‘t Going to Need It"(就是 YAGNI -你將不會需要它)。兩項都是XP實務(wù)中簡單設(shè)計的表現(xiàn)形式。

YAGNI 一詞時常被討論,它的意思是現(xiàn)在不要為了將來可能用到的功能加入任何程序代碼。表面上聽起來好象很簡單,問題則出在像framework、重用組件、和彈性化設(shè)計,這些東西本來就很復雜。你事先付出額外的成本去打造它們,希望稍后將這些花費都賺回來。這個事先彈性設(shè)計的想法被認為是軟件設(shè)計有效率的關(guān)鍵部份。

但XP的建議是,在處理第一個問題時不要因為可能需要某項功能,就建造出彈性的組件組及框架出來。讓整體結(jié)構(gòu)隨著需要成長。假如我今天想要一個可以處理加法但是不用乘法的 Money 類別,我就只在 Money類別中建造加法的功能。就算我確定下一個階段也需要乘法的運算,而且我知道很簡單,也花不了多少時間,我還是會留到下一階段再去做它。

其中一個理由是效益。如果我要花時間在明天才需要的功能,那就表示我沒有將精神放在這個階段應(yīng)該完成的事情上。發(fā)表計畫詳列目前要完成的事項,現(xiàn)在做以后才需要的事情違背開發(fā)人員和顧客之間的協(xié)議。這種做法有讓現(xiàn)階段的目標無法達成的可能。而且這個階段的 stroies[譯注5]是否具有風險,或是需不需要做額外的工作,都是由顧客來決定的 - 還是可能不包括乘法功能。

這種經(jīng)濟效益上的限制是因為我們有可能出錯。就算是我們已經(jīng)確定這個功能應(yīng)該如何運作,都有可能出錯 - 尤其是這時候我們還沒有取得詳細需求。提前做一件錯誤的事情比提前做一件對的事情更浪費時間。而且XP專家們通常相信我們比較有可能會做錯而不是做對(我心有戚戚)。

第二個支持 simple design 的理由是復雜的設(shè)計違反光線行進的原理。復雜的設(shè)計比簡單的設(shè)計還要令人難懂。所以隨著漸增的系統(tǒng)復雜度,更加難以對系統(tǒng)做任何修改。如此,若系統(tǒng)必須加入更復雜的設(shè)計時,成本勢必增加。

現(xiàn)在很多人發(fā)現(xiàn)這樣的建議是無意義的,其實他們那樣想是對的。因為你所想象一般的研發(fā)并沒有被 XP 有效的技巧所取代。然而,當規(guī)劃式設(shè)計和漸進式設(shè)計之間的平衡點有了變化 (也只有當這樣的變化發(fā)生時),YAGNI 就會變成好的技巧。

所以結(jié)論是,除非到了往后的階段有所需要,否則你不會浪費精神去增加新的功能。即使不會多花成本,你也不會這樣做,因為就算現(xiàn)在加入這些功能并不增加成本,但是卻會增加將來做修改時的成本??傊?,你可以在套用 XP 時明智的遵守這樣的方法,或是采取一種能降低成本的類似的方法。

 

What on Earth is Simplicity Anyway

 

因此,我們希望程序代碼能夠越簡單越好,這聽起來沒什么好爭論的,畢竟有誰想要復雜呢?但問題來了,究竟 "什么才叫簡單呢?"

在 XPE 一書中,Kent 對簡單系統(tǒng)訂了四個評量標準,依序是 (最重要排最前面):

通過所有測試。

呈現(xiàn)所有的意圖。

避免重復。

最少數(shù)量的類別或方法。

 通過所有測試是一項很普通的評量標準,避免重復也很明確,盡管有些研發(fā)人員需要別人的指點才能做到。比較麻煩的是 "呈現(xiàn)所有的意圖"這一項,這到底指的是什么呢?

 這句話的本意就是簡單明了的程序代碼。XP 對程序代碼的易讀性有很高的標準。雖然在 XP 當中,"巧妙的程序代碼 (clevercode)" 這個字眼經(jīng)常被濫用,不過意圖清楚的程序代碼,對其他人來說真的是一種巧妙。Josh Kerievsky 在 XP 2000論文中舉了一個很好的例子,檢視在 XP 領(lǐng)域可能是大家最熟知的 JUnit 的程序代碼。JUnit 使用 decorators 在 testcases 中加入非必要的功能,像是同步機制及批次設(shè)定等,將這些程序代碼抽出成為 decorator,的確讓一般的程序代碼看起來清楚許多。

 但是你必須捫心自問,這樣做之后的程序代碼夠簡單嗎?我覺得是,因為我了解 Decorator 這個patterns。但是對于不了解的人來說還是相當復雜的。類似的情況,JUnit 使用 pluggablemethod,一種大部分的人剛開始接觸時都不會覺得簡單的技巧。所以,也許我們可以說 JUnit對有經(jīng)驗的人來說是比較簡單的,新手反而會覺得它很復雜。

 XP 的 "Once and Only Once" 以及 Pragmatic Programmer(書名) 的 DRY(Don‘tRepeat Yourself)都專注在去除重復的程序代碼。這些良好的建議都有很顯著而且驚人的效果。只要依照這個方式,項目就可以一路順利的運作。但是它也不能解決所有問題,簡單化還是不容易達成。

 最近我參與一個可能是過度設(shè)計的項目,系統(tǒng)經(jīng)過 refactor 之后去除部份彈性的設(shè)計。但是就像其中一位開發(fā)者所說的"重構(gòu)過度設(shè)計的系統(tǒng)要比重構(gòu)沒有設(shè)計的要來的容易多了" 做一個比你所需要簡單一點的設(shè)計是最好的,但是,稍微復雜一點點也不是什么嚴重的事情。

我聽過最好的建議來自 Bob 大叔 (Robert Martin)。他的建議是不要太在意什么是最簡單的設(shè)計。畢竟后來你可以,應(yīng)該,也會再重構(gòu)。愿意在最后重構(gòu),比知道如何做簡單的設(shè)計重要得多。

 

Does Refactoring Violate YAGNI?

 

這個主題最近出現(xiàn)在 XP 討論區(qū)上,當我們審視設(shè)計在 XP 扮演的角色時,我覺得很值得提出來討論。

基本上這個問題起因于重構(gòu)需要耗費時間卻沒有增加新的功能。而 YAGNI 的觀點是假設(shè)你為了眼前的需要做設(shè)計而不是未來,這樣算是互相抵觸嗎?

YAGNI 的觀點是不要增加一些現(xiàn)階段不需要的復雜功能,這也是簡單設(shè)計這項技巧的部份精神。重構(gòu)也是為了滿足盡可能保持系統(tǒng)的簡單性這個需要,所以當你覺得可以讓系統(tǒng)變得更簡單的時候,就進行重構(gòu)。

簡單設(shè)計不但利用了 XP的實務(wù)技巧,本身也是其中一項有用的實務(wù)技巧。唯有伴隨著測試,持續(xù)整合,及重構(gòu)的運用,才能有效地做出簡單設(shè)計。同時,讓研發(fā)異動曲線保持平緩的基礎(chǔ)也就是保持設(shè)計的簡單。任何不必要的復雜都會讓系統(tǒng)變得難于調(diào)整,除非這個復雜性是你為了所預(yù)測的彈性而加入的。不過,人們的預(yù)測通常都不太準確,所以最好還是努力地保持簡單性。

不管怎樣,人們不太可能第一次就能夠獲得最簡單的東西,因此你需要重構(gòu)來幫助你更接近這個目標。

 

Patterns and XP

 

JUnit 的例子讓我不得不想到 patterns。XP 和 patterns 之間的關(guān)系很微妙,也常常被問起。JoshuaKerievsky 認為 patterns 在 XP被過分輕視,而且他所提出的理由也相當令人信服,我不想再重提。不過值得一提的是,很多人都認為 patterns 似乎與 XP 是有沖突的。

 爭論的本質(zhì)在于 patterns 常被過度濫用。世上有太多傳奇性的 programmer,第一次讀到四人幫以 32 行程序代碼闡述16 種 patterns 這樣的事情還記憶猶新[譯注6]。我還記得有一晚與 Kent 喝著醇酒一起討論一篇文章 "Not Designpatterns: 23 cheap tricks (不要用設(shè)計模式-23 個簡單的訣竅)"。我們認為那不過是以 if 條件式來取代strategy 這個 pattern 罷了。這樣的笑話有個重點,patterns 被濫用了。但并不表示 patterns是不足取的,問題在于你要怎么運用它。

其中一項論點是簡單設(shè)計的力量自然會將項目導向patterns。很多重構(gòu)的例子明確地這么做,或者甚至不用重構(gòu),你只要遵從簡單設(shè)計的規(guī)則就會發(fā)現(xiàn) patterns,即使你還不知道patterns 是什么。這樣的說法也許是真的,不過它真的是最好的方式嗎?當然如果你先對于 patterns有個大略的了解,或者手邊有一本書可以參考,會比自己發(fā)明新的 patterns 要好些。當我覺得一個 pattern快浮現(xiàn)的時候,我必定會去翻翻 GOF 的書。對我來說,有效的設(shè)計告訴我們 pattern 值得付出代價去學習-那就是它特有的技術(shù)。同樣地就像Joshua 所建議的,我們需要更熟悉于如何逐步地運用 patterns。就這一點而言,XP 只是與一般使用 patterns的方式不同而已,并沒有抹煞它的價值。

但是從討論區(qū)一些文章看來,我覺得很多人明顯地認為 XP 并不鼓勵使用 patterns,盡管 XP 大部分的提倡者也都是之前patterns 運動的領(lǐng)導者。因為他們看到了不同于 patterns 的觀點嗎?或是他們已經(jīng)將 patterns融入思考而不必再去理解它?我不知道其它人的答案是什么,但是對我來說,patterns 仍然是非常重要的。XP 也許是開發(fā)的一種流程,但patterns 可是設(shè)計知識的骨干,不管是哪種流程這些知識都是很有用的。不同的流程使用 patterns 的方式也就不同,XP強調(diào)等到需要時才使用 patterns 以及透過簡單的實作逐步導入 patterns。所以 patterns 仍然是一種必須獲得的關(guān)鍵知識。

我對于采用 XP 的人使用 patterns 的建議:

花點時間學習 patterns。

留意使用 patterns 的時機 (但是別太早)。

留意如何先以最簡單的方式使用 patterns,然后再慢慢增加復雜度。

如果用了一種 pattern 卻覺得沒有多大幫助-不用怕,再次把它去掉。

我認為XP應(yīng)該要更加強調(diào)學習 patterns。我不確定它要怎么和 XP 的實務(wù)技巧搭配,不過相信 Kent 會想出辦法來的。

 

Growing an Architecture

 

軟件架構(gòu)是指什么呢?對我來說,架構(gòu)這個字眼代表系統(tǒng)核心組件的概念,也就是難以改變的部份,剩下的都必須建造在這基礎(chǔ)上。

 那么當你使用演進式設(shè)計時,架構(gòu)又扮演著什么樣的角色呢?XP 的批評者再一次地聲稱 XP 忽視架構(gòu),因為 XP使用的方法是盡快地寫程序,然后相信重構(gòu)會解決所有設(shè)計的問題。很有趣地,他們說得沒錯,這有可能是 XP 的缺點。無疑地,最積極的 XP 專家-像Kent Beck, Ron Jeffries, 及 BobMartin-盡其所能地避免預(yù)先結(jié)構(gòu)性的設(shè)計。在你知道真的要用到數(shù)據(jù)庫之前,不要加入數(shù)據(jù)庫,先用檔案來代替,在之后的階段再用重構(gòu)加入數(shù)據(jù)庫。

 我常被認為是一個膽小的 XP 專家,這點我不同意。我認為一個概括性的初始架構(gòu)有它的用處在。像是一開始要怎么將應(yīng)用分層,如何與數(shù)據(jù)庫互動 (如果你需要的話),要使用哪種方式去處理網(wǎng)站服務(wù)器。

 基本上,我認為這些就是近年來我們所研究的 patterns。尤其當你對 patterns的認識越深,你就會越熟悉要怎么去善用它們。不過,關(guān)鍵性的差異是在于這些初期架構(gòu)的決定是可以更改的,只要團隊認為他們早期的判斷有誤時,就應(yīng)該要有勇氣去修正它們。有人跟我講了一個項目的故事,就在項目快要發(fā)表時,決定了不再需要EJB,并且要將它們從系統(tǒng)中移除。這是一個相當大規(guī)模的重構(gòu),不過最后還是完成了。這些有效的實務(wù)技巧不僅讓事情變得可能,而且很值得去做。

 如果以不同的方式來做這件事呢?如果你決定不采用 EJB,將來會難以加入嗎?你是否要在試過各種方式卻發(fā)現(xiàn)依然欠缺什么,然后才使用EJB?這是一個牽涉很多因素的問題。不使用復雜的組件當然可以增加系統(tǒng)的簡單度,而且可以讓事情進展比較快,但有時候從系統(tǒng)中抽掉某個部份會比加入它要容易多了。

 所以我建議從評估架構(gòu)可能的樣子開始。假如你看到將會有多個使用者使用到大量的資料,一開始就直接使用數(shù)據(jù)庫。若你看到很復雜的商業(yè)邏輯,就套用domain model。你會懷疑是否偏離簡單的特性,這當然不是 YAGNI的精神。所以你要有所準備,在發(fā)現(xiàn)所使用的結(jié)構(gòu)沒有幫助時盡快簡化你的結(jié)構(gòu)。

 

UML and XP

 

在我投身于 XP 領(lǐng)域之后,由于我與 UML 的關(guān)系讓我遇到一個揮之不去最大的問題:這兩者不是不兼容嗎?

 當然有些不兼容。XP 顯然不重視 diagram。雖然臺面上大家對 "好用就用" 有共識,但是實際上卻是 "實際上采用 XP的人不畫藍圖"。這種印象因為如 Kent 這些人不習慣作圖的現(xiàn)象而強化了。事實上我也從來沒看過 Kent 主動使用固定的標記法畫下軟件藍圖。

 我覺得這種情形來自兩個因素,其一是有人覺得軟件藍圖有用,而有人不覺得有用。難就難在覺得藍圖有用的人不是真正必須動手做的人,而必須動手做的人卻不覺得有其必要性。事實上我們應(yīng)該接受有人喜歡用,而有人不喜歡用。

 另一種情形是軟件藍圖常引人進入繁重的流程中,這些流程耗時費力卻不見得有用,甚至還會產(chǎn)生壞處。我認為應(yīng)該教導人們?nèi)绾问褂盟{圖卻不落入這樣的陷阱,而不是像那些提倡者僅僅消極的說 "必要時才用"。

 所以,我對于有效使用藍圖的建議是:

 首先別忘了你畫這些圖的目的,主要的價值在于溝通。有效的溝通意味著選擇重要的部份而忽略不重要的部份。這樣的選擇也是有效運用 UML的關(guān)鍵。不必把全部的 class 都畫出來,畫出重要的就好。對于每個 class 也只顯示關(guān)鍵的 attribute 和operation,而不是全部顯示出來。也不要為所有的 use case 和步驟畫循序圖...除非你已經(jīng)有完整的想象。有一個使用藍圖的通病就是人們通常希望詳細完整的把圖表現(xiàn)出來。其實程序代碼就是提供完整信息的最佳來源,同時程序代碼本身也是保持信息同步最簡單的方式。因為圖形的巨細靡遺就是一目了然的敵人。

 藍圖的用途是在開始撰寫程序代碼之前探討設(shè)計內(nèi)容。印象中總是覺得這樣的動作在 XP 是不合法的,但并不是這樣。很多人都說如果你遇到棘手的問題,就值得先做些設(shè)計。但是當你進行設(shè)計時:

保持簡短。

不要做得太詳細(只挑重要的做)。

把結(jié)果當作是草圖,而不是定案。

最后一點值得深入探討。當你做預(yù)先式設(shè)計,無可避免的會發(fā)現(xiàn)一些錯誤,而且是在撰寫程序代碼的時候才發(fā)現(xiàn)。如果你適時變更設(shè)計,它就不是問題。麻煩的是如果你認定設(shè)計已經(jīng)定案,沒有從 coding 過程學到經(jīng)驗而跟著先前的設(shè)計將錯就錯。

 變更設(shè)計不代表一定要更改藍圖。畫這些藍圖來幫助你了解設(shè)計,然后就把圖扔開,這么做是非常合理的。這些圖能夠幫上忙就有它的價值了。它們不必永遠存在,最有用的 UML 圖形也不會是收藏品。

 不少實行 XP 的人使用 CRC 卡,這與 UML 并不沖突。我常常交互運用 CRC 卡和UML,我也總是依照手上的工作選擇最有用的技巧。UML 圖形的另一個用途是持續(xù)修訂的文件。它一般的形式,就是在 case tool中看到的模型。最初的想法是留著這樣的資料有助于建構(gòu)系統(tǒng)。事實上卻常常沒什么用。

保持圖形的更新太花時間,最后常無法與程序代碼同步。

它們隱含在 CASE tool 或 thick binder,讓人忽略它。

所以要希望這種持續(xù)修訂的文件有用,就從這些看到的問題下手:

只用一些改起來不至于讓人覺得痛苦的圖。

把圖放在顯眼的地方。我喜歡畫在墻上,鼓勵大家一起動手修改。

檢討這些圖是不是有人在用,沒用的就擦掉。

使用 UML 的最后一個問題是文件的交接,像是不同團隊的接手。XP 的想法是文件就像說故事,所以文件的價值由顧客來決定。于是 UML 又派上用場,所提供的圖形可以幫助溝通。別忘了程序代碼本身就蘊含了所有詳細的信息,圖形的作用只是提供概觀以及標示重要的部份。

 

On Metaphor

 

好吧,我也許該坦承 - 我一直沒有抓住 metaphor 的精神。它有用,而且在 C3 項目中運用得很好,但是并不表示我知道怎么用它,更不用說要解釋怎么用了。

 XP 實務(wù)技巧中的 Metaphor 是建立在 Ward Cunningham‘s 為系統(tǒng)命名的做法上。重點是想出一個眾所周知的詞匯,以這樣一個字來比喻整個范疇。這個代表系統(tǒng)的名字會套用在 class 和 method 的命名上。

 我以不同領(lǐng)域的觀念性模型,利用 UML和它的前身與領(lǐng)域?qū)<乙黄鸾⒘艘粋€命名系統(tǒng)。我發(fā)現(xiàn)你必須很小心,你要保持最精簡的注釋,而且要當心別讓技術(shù)性的問題不知不覺的影響這個模型。但是一旦你完成這個工作,你就可以為各種領(lǐng)域建立一組詞匯,這些詞匯是大家都能了解并且可用來與研發(fā)人員溝通的。這種模型無法與 class設(shè)計完美的吻合,但是足夠給整個領(lǐng)域一個通用的代名詞。

 目前我找不到任何理由說明為何這樣的一個字匯無法成為一個比喻,就像 C3 這個成功的例子;我也不覺得以系統(tǒng)為主找到在該專業(yè)領(lǐng)域的一個詞匯有什么壞處。同時我也不會放棄可以運作自如的為系統(tǒng)命名的技巧。

 人們常批評 XP 乃是基于覺得一個系統(tǒng)實在是至少需要一個大概的設(shè)計。XP 專家則以 "就是 metaphor ??!" 來響應(yīng)。但是我還是沒有看到一個對于 metaphor 令人信服的解釋。這是 XP 的缺憾,必須由 XP 專家來理出頭緒。

 

Do you wanna be an Architect when you grow up?

 

近幾年來 "software architect (軟件設(shè)計師)"越來越熱門,這是一個就我個人而言難以接受的名詞。我太太是結(jié)構(gòu)工程師,工程師和建筑師之間的關(guān)系是... 有趣的。我最喜歡的一句話是:建筑師對三種B 是好的,燈泡、灌木叢、和鳥。因為建筑師畫出這些美麗的圖畫,但卻要工程師保證能做出來。結(jié)論是我避免 software architect一詞,畢竟如果連我的太太都不能尊重我的專業(yè),我又怎么能對其他人有所期望呢?

對軟件來說,architect 一詞可以代表很多事情。(軟件界很多詞都可以代表很多事。)這通常符合一句話:我不僅是一個程序員,我還是一個設(shè)計師[譯注2]。還可以進一步解譯成:我現(xiàn)在是一個設(shè)計師 -我對于完成所有程序來說太重要了。然后這個問題就變成,當你要展現(xiàn)技術(shù)領(lǐng)導的時候,你是不是該把自己與煩瑣的程序撰寫分清楚?

這個問題引起眾多的不滿。我看到人們對于再也無法擔任設(shè)計角色這樣的想法感到生氣。我最常聽到:在 XP 沒有設(shè)計師的揮灑空間。

就設(shè)計本身的角色來說,我不覺得 XP 不重視經(jīng)驗或好的設(shè)計。事實上多位 XP 的提倡者 - Kent Back、BobMartin、當然還有 Ward Cunningham -都是我從而學習設(shè)計的對象。然而這也代表著他們的角色從大家既有的印象中開始轉(zhuǎn)變成為技術(shù)領(lǐng)導者。

我將以一位 ThoughtWorks 的技術(shù)領(lǐng)導者 Dave Rice 為例。Dave 參與了很多個研發(fā)周期,并且非正式的指導一個 50人的項目。他擔任指導的角色意味著要花很長的時間與程序員為伍。當程序員需要幫助,他就介入,否則就留意著看誰需要協(xié)助。他的座位有一個明顯的特征,擔任一位長期的思考工作者,他可以在任何形式的辦公環(huán)境適應(yīng)良好。他曾經(jīng)與發(fā)行部經(jīng)理 Cara共享辦公室一段時間。而在最后幾個月,他更是搬到工程師們工作的開放式空間 (就像 XP 小組喜歡的開放式"戰(zhàn)斗空間")。這么做對他很重要,他可以知道事情的進展,并適時伸出援手。

知道 XP 的人就能夠了解我描述的是 XP "教練" 的清楚角色。的確,在 XP 玩的文字游戲中提到領(lǐng)導技術(shù)就是在描繪 "教練"這個角色。其意義是很清楚的:在 XP 技術(shù)的領(lǐng)導特質(zhì)是透過教導程序員和幫助他們做決定而呈現(xiàn)。這是一種需要良好人際管理和技術(shù)并重的技巧。JackBolles 在 XP2000 說:孤單的大師有點機會了,合作和教導是成功的關(guān)鍵。

在研討會的晚餐會上,我和 Dave 在談話時對 XP 有了些對立的意見。當我們討論到以前的經(jīng)驗,我們的方法有相當?shù)念愃?。我們都偏好adaptive,iterative development,也認為測試是重要的。所以我們都對他反對的立場感到疑惑。然而他提到"最后我要的是程序員照著設(shè)計忙于重構(gòu)"。事情一下子明朗起來。后來 Dave 又對我說"如果我不信任我的程序員,我何必要用他們呢?",觀念上的隔閡就更加清楚了。在 XP里頭,有經(jīng)驗的研發(fā)人員所能做的最重要的一件事就是盡量將所有技術(shù)傳繼給新手。不同于一個決定所有重要事情的建筑師,你有一個能夠教導研發(fā)人員如何做重大決定的教練。就像 Ward Cunningham 指出,這么做不只是增進了新手的能力,對項目的好處更大于一個孤立無援的超人所能做的。[ 譯注7]

 

Things that are difficult to refactor in

 

我們能用 refactoring 來處理所有設(shè)計方面的決定嗎?或者,有些問題太普遍而且難以在將來加入設(shè)計中?此時,XP的正統(tǒng)做法是所有需求都可以輕易的在需要的時候增加,所以 YAGNI總是能夠適用。我猜是不是有例外?有一個不錯的,被討論到的例子是軟件的國際化。這是不是一種現(xiàn)在應(yīng)該立即進行,否則以后再加入時會覺得痛苦的事情?

我能輕易的想象一些事情就是這種情形。事實上我們?nèi)匀徽莆仗俚男畔ⅰH绻惚仨氷懤m(xù)加入一些功能,如國際化,而你知道那需要多少工夫。你比較不容易意識到在你真正需要他之前,你要花多少時間加入它,并且要長時間的維護它。你也比較不容易察覺到也許你可能做錯了,所以到頭來還是需要做些refactoring。

有一部份能夠為 YAGNI 辯護的理由是有些預(yù)先做的功能可能最后并不需要,或者它并不如預(yù)期的結(jié)果。不做這些所省下的力氣比用 refactoring 來更改成為符合需要所用的力氣要少。

另外一個要想的問題是你是否真的知道怎么做。如果你有很多次做軟件國際化的經(jīng)驗,你會知道該用什么模式來作。那樣的情形下你應(yīng)該會把它作好。這時你所加入的預(yù)留的結(jié)構(gòu)可能會比你頭一次處理這種問題要好。所以我的想法是,如果你知道怎么做,你就要考慮現(xiàn)在做和將來做,兩種情形之間不同的成本。反過來說,如果你沒有處理過那樣的問題,不僅是你無法正確判斷需要的成本,你也比較不可能把事情作好。這種情形,你就要選擇將來再做。如果你還是執(zhí)意做了,而且嘗到苦果,可能會比不做的情況更糟。當你的組員更有經(jīng)驗,你對相關(guān)領(lǐng)域有更多認識,你對需求也會更了解。通常到這時你回頭看才會發(fā)現(xiàn)事情有多簡單。提早加入的設(shè)計比你想象中要難多了。

這個問題也跟 stories 的順序密切相關(guān)。在 Planning XP 一書中,Kent 和我公開的指出我們的歧見。Kent偏向于只讓商業(yè)價值這一個因素影響 stories 的順序。在短暫的意見不合之后 Ron Jeffries也同意這種想法。我仍保持懷疑。我相信在商業(yè)價值和技術(shù)風險之間能找到平衡點?;谶@樣的理由讓我提早為軟件國際化做準備以降低風險。但是這種做法也只有當?shù)谝浑A段發(fā)行就需要將軟件國際化才能成立。盡快達到一個階段的發(fā)行是非常重要的。任何原來不需要而后來必須增加的復雜性都值得在第一階段發(fā)行之后才開始。發(fā)行之后運作中的程序有強大的力量,它抓住顧客的注意,增加信任感并且是一個學習的好機會。就算是在初次發(fā)行之后會有更多的事情要做,還是要盡所有努力將第一階段日期往前推。

 

So is Design Dead?

 

沒什么原因,只是設(shè)計的本質(zhì)已經(jīng)改變。XP 的設(shè)計追求以下的技巧:

持續(xù)保持清爽的程序代碼,越簡單越好。

重構(gòu)的技巧,所以當你覺得必要的時候都可以有信心的動手。

具有 patterns 的知識:不只是照它的解法,更要感覺何時可以應(yīng)用,或是如何導入 patterns。

知道如何將設(shè)計說給必要的人了解[譯注8],用程序代碼、或是圖形、或上述所有的工具:交談。

以上挑出來的技巧看來都挺嚇人,但是要成為一個優(yōu)秀的設(shè)計師本來就很難。XP 也不是要讓它變得簡單,至少我就不覺得。但是我想 XP 讓我們對有效率的設(shè)計有全新的看法,因為它讓漸進式設(shè)計聽起來是可行的方式。而且我也很支持演進 - 否則誰知道我會變成什么呢?

 

Acknowledgements[譯注9]

 

過去這些年我從很多好朋友身上偷學到不少好的想法,很多都已經(jīng)記不起來。但是我記得從 Joshua Kerievski那里偷到的好東西。我也記得 Fred George 和 Ron Jeffries 給我很好的建議。我當然也不能忘記 Ward 和 Kent不斷有好的想法。

我也感謝曾經(jīng)提出問題和指出打字錯誤的朋友。同時感謝 Craig Jones 提醒我好幾個漏掉的 “a”。

 

Revision History

以下是這篇文章重大的修改記錄:

      2001 年 2 月:對 growing an architecture、the role of anarchitect、和 where things that are difficult to add with refactoring等段落做修改。

      2000 年 7 月:原始文件在 XP 2000 發(fā)表,并刊載于 MartinFowler.com 網(wǎng)頁。

 

[譯注1] 一種在著手進行程序代碼的撰寫之前,就先按照既定的程序分析、設(shè)計、制圖、撰寫文件等等耗時費力的工作方式。

[譯注2] 在臺灣你覺得 “程序設(shè)計師”、“軟件設(shè)計師” 和 “軟件工程師”有什么不同嗎?相信大部分的人覺得都是同一種角色。但是從英文字意就比較容易區(qū)別“programmer”、”designer”、”architect”等等不同的角色。這樣的語言文化差異性,也是我在內(nèi)文中留下不少原文的原因。在部份字句中,留下原文并不影響閱讀的順暢,但是可以避免文意因為翻譯所造成的模糊或扭曲。

[譯注3] 在建筑業(yè)應(yīng)該是稱呼 “施工人員” 比較順耳,而在軟件業(yè)應(yīng)該是 “programmer” 比較恰當。但是這兩者都是 “builder”。

[譯注4] 關(guān)于這一點,譯者也提供一個實際的經(jīng)驗,也就是翻譯這篇文章的過程。我和一位朋友一起翻譯這篇文章,而且因為都先看過 XPDistilled 一文,所以決定采用 XP 12 個有效的實務(wù)技巧其中的 Continuous Integration、PairProgramming、Small Releases、Refactoring、Coding Standards、Collective CodeOwnership 等等技巧。因為 XP Distilled 一文的經(jīng)驗我們首先對于部份翻譯名詞提出彼此的統(tǒng)一版本,這就是一種 CodingStandards。我們同時都對這篇文章進行翻譯,不同的人進行同一項工作進度就不會相同,每翻譯幾個段落就將進度寄給對方,這就是 SmallReleases。當我收到朋友寄來的部份,我就對照兩方的差異將文章針對譯意的正確性和辭句的通暢做初步的整理和修正,這就是 ContinuousIntegration。我整理過的部份再寄回給朋友進行檢查,如果發(fā)現(xiàn)不妥的部份,就進行討論或修改,這就是Refactoring。從頭到尾的過程中,我們都收到彼此的翻譯版本,也擁有整理過的版本,對于每個部份也都清楚了解,符合 CollectiveCode Ownership 的精神。最后,因為我們剛好是兩個人,不巧又可以冠上另一個技巧Pair Programming。所以,我們使用了XP 一半的方法,對于工作上有幫助的方法。但并不是非得每一項技巧都利用到。我想,更重要的一點是,XP并不是只能用在軟件研發(fā),我們的翻譯過程不也借來用了!

[譯注5] Story 是一種類似 use case 的描述。

[譯注6] 按照原文的意思就是以 32 行的程序代碼而能夠表現(xiàn)出 16 種 patterns!這樣的傳奇性功力實在不是經(jīng)驗及見識淺薄的譯者所能想象,所以我們只能按照原文翻譯,而無法對這句話提出左證。如果讀者見過作者提到的例子,很感謝您提供相關(guān)資料給我。

[譯注7] 這一點也是譯者對于臺灣軟件環(huán)境非常憂心的問題,大家都能體會中國人的一種不知道能不能說是重大缺點的民族習性“藏私”。我在不同的機會從文章中以及朋友的口中聽到一種想法,要提升團隊的整理效率,一種最簡單的方法就是將技術(shù)落后的成員教育提升到與技術(shù)領(lǐng)先的成員相同的水平。這樣的想法實在是一種非常有用而且深刻的體認,更是一種感嘆。在臺灣能夠在口頭上同意這種做法,而實際上更能夠進而實踐這種精神的人有多少??有些人都擔心自己的技術(shù)被人窺透之后,個人地位恐將遭到取代,更遭的是可能有老板真的會 “狡兔死走狗烹”的在榨取經(jīng)驗的傳承之后,將有貢獻卻成本高的成員以各種方式逼走,這實在是讓人憂心又灰心的現(xiàn)象啊!譯者相信,再困難的技術(shù)只要是你能了解,就已經(jīng)存在了競爭對手,如果不能將身邊成員的技術(shù)水平同時迅速提升,只有等著被快速超越,更可能被淘汰。譯者也實踐著 XP這方面的精神,雖然譯者所擁有的技術(shù)知識非常粗淺,但是只要同事朋友需要我的協(xié)助,我總是知無不言,言無不盡。譯者要向流星許愿,希望能夠找到越來越多的同類。

[譯注8]有效的溝通也是譯者常遭遇的問題之一,有些人無法以不同的方式為事情下批注,有些人對于門外漢還是滿口專業(yè)術(shù)語,有些人不能觀察顧慮到聽者是不是已經(jīng)了解所闡述的精髓。這些都不是有效的溝通。我們似乎還不夠重視人際溝通這門學問,如何以對方能懂的方式說給對方聽,真是不容易呢!譯者只是發(fā)出感嘆,卻也亟需要培養(yǎng)溝通能力,才不會讓共事的同事?lián)u頭。

[譯注9] 譯者之一的我 (Daimler) 也要搭個順風車,感謝朋友 (S.H.Chen)在百忙之中抽空與我完成這篇文章的翻譯,這位朋友在軟件工程方面的知識給我的幫助非常關(guān)鍵。翻譯本身就存在不少爭議,應(yīng)該按照句子逐字翻譯,還是要考慮依據(jù)本國文字的用語習慣做適當?shù)恼{(diào)整,以求字句的通順,真的讓人難以取舍抉擇。我 (Daimler)是比較傾向于在不扭曲原著作文意的原則下,對句子做適當?shù)闹亟M和調(diào)整。但是這個動作本身就存在著非常大的危險,我對于原文是否有足夠的認識?我對于本國文字的造詣是否及格?希望這篇文章對于國內(nèi)讀者能有所幫助,至少是效率上的幫助。更期盼來自各方的指教。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
步步為營 .NET 代碼重構(gòu)學習筆記 一、為何要代碼重構(gòu)
極限編程
軟件設(shè)計經(jīng)典書籍推薦
敏捷思維: 架構(gòu)設(shè)計中的方法學(6)
重構(gòu)
軟件工程師必讀技術(shù)書籍推薦<1>
更多類似文章 >>
生活服務(wù)
分享 收藏 導長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服