qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          對話馬丁·福勒(Martin Fowler)——第三部分:進(jìn)化型設(shè)計(jì)

          第一部分:重構(gòu)
            第二部分:設(shè)計(jì)原則與代碼所有權(quán)
            第三部分:進(jìn)化型設(shè)計(jì)
            第四部分:靈活性與復(fù)雜性
            第五部分:測試驅(qū)動(dòng)開發(fā)
            第六部分:性能與過程調(diào)優(yōu)

            第三部分:進(jìn)化型設(shè)計(jì)

            在連載的第三部分,福勒討論了計(jì)劃型設(shè)計(jì)和進(jìn)化型設(shè)計(jì)的區(qū)別,揭示了著眼于解決表象問題可以使開發(fā)者發(fā)現(xiàn)本質(zhì)問題,并主張好的設(shè)計(jì)工作不會(huì)降低工作效率。

            計(jì)劃型設(shè)計(jì)和進(jìn)化型設(shè)計(jì)

            比爾:在你的論文《設(shè)計(jì)是否已死》(Is Design Dead)一文中,談到了計(jì)劃型設(shè)計(jì)。那么什么是計(jì)劃型設(shè)計(jì)?

            馬丁:我將設(shè)計(jì)區(qū)分為計(jì)劃型設(shè)計(jì)和進(jìn)化型設(shè)計(jì)。當(dāng)開發(fā)者著手實(shí)施一個(gè)軟件時(shí),他首先需要做設(shè)計(jì),然后再按照這個(gè)設(shè)計(jì)進(jìn)行編 碼實(shí)現(xiàn)軟件,這就是我所說的計(jì)劃型設(shè)計(jì)。計(jì)劃型設(shè)計(jì)可能借助 UML;或者把整個(gè)系統(tǒng)分為若干子系統(tǒng),定義這些子系統(tǒng)間的接口。在計(jì)劃型設(shè)計(jì)中,在設(shè)計(jì)和代碼實(shí)現(xiàn)這二者之間存在明確的切換。而這二者又往往由不同的人 來完成。架構(gòu)師構(gòu)思設(shè)計(jì),開發(fā)者編碼實(shí)現(xiàn)。做好的設(shè)計(jì)并不是說一點(diǎn)都不能改變,但基本上是固定的。你可能會(huì)說,設(shè)計(jì)做得越好,在編碼的時(shí)候,就會(huì)越少對設(shè) 計(jì)做出改動(dòng)。

            而在進(jìn)化型設(shè)計(jì)中,開發(fā)者在編程實(shí)踐的過程中逐漸完善設(shè)計(jì)。剛開始的時(shí)候并沒有設(shè)計(jì),而是先實(shí)現(xiàn)一些小的功能。隨著實(shí)現(xiàn)的功能越來越多,設(shè)計(jì)才逐漸成型。

            我在《設(shè)計(jì)是否已死》一文中想要強(qiáng)調(diào)的是,很多人在嘗試進(jìn)化型設(shè)計(jì)時(shí),往往是在一種無約束無原則的環(huán)境里,最終的設(shè)計(jì)必然很蹩腳。這是人們之所以傾向于計(jì)劃型設(shè)計(jì)的原因之一。

            但是,在我看來,極限編程實(shí)踐中,通過持續(xù)不斷的集成、測試和重構(gòu),進(jìn)化型設(shè)計(jì)能夠做到比計(jì)劃型設(shè)計(jì)更有效。計(jì)劃型設(shè)計(jì)的弱點(diǎn)就是,要想做出一個(gè)好的設(shè)計(jì)非常難。

            比爾:為什么?

            馬丁:我解釋不清楚。這就跟解釋不清楚為什么譜一曲交響樂會(huì)如此困難一樣。世界上能把這些工作做好的人可以說是鳳毛麟角。我想,我認(rèn)為預(yù)先設(shè)計(jì)(upfront design)就屬于這類工作。要做好這類工作實(shí)在是太難了。

            有趣的是,很多進(jìn)化型設(shè)計(jì)的倡導(dǎo)者,比如肯特·貝克和沃德·坎寧安,都是非常出色的設(shè)計(jì)師。但正是他們,最后認(rèn)識(shí)到自己所做的預(yù)先設(shè)計(jì)往 往不夠好。他們?nèi)菀装岩恍┦虑檫^于工程化,在不需要靈活性的地方設(shè)計(jì)靈活性,而在需要靈活性的地方又未予以考慮。因此,他們最終采用了進(jìn)化型設(shè)計(jì),并通過 運(yùn)用一套規(guī)則,保證了設(shè)計(jì)效果。其結(jié)果是,不但最終的設(shè)計(jì)更加出色,并且速度也加快了。拿我自己來說,80%左右的時(shí)間里,進(jìn)化型設(shè)計(jì)會(huì)得到不錯(cuò)的結(jié)果。 而不客氣地說一句,我認(rèn)為我的設(shè)計(jì)水平要比一般人高。因此,我認(rèn)為進(jìn)化型設(shè)計(jì)應(yīng)該可以適用于更廣泛的人群。

            重構(gòu)與預(yù)先設(shè)計(jì)

            比爾:重構(gòu)如何改變了預(yù)先設(shè)計(jì)的地位?

            馬丁:人們之所以采用計(jì)劃型設(shè)計(jì),是因?yàn)樗麄冋J(rèn)為改動(dòng)代碼是件很麻煩的事情。因?yàn)楫?dāng)你改變代碼時(shí),有可能破壞了一些東西并造成許多漏洞。可是,如果你既有單元測試,又有在測試基礎(chǔ)上建立起來的有條理的重構(gòu)技術(shù),那么你就能十分快速有效地改動(dòng)代碼,并且不太會(huì)引起什么問題。

            比爾:預(yù)先設(shè)計(jì)在重構(gòu)和其他可行的實(shí)踐中有什么作用?你現(xiàn)在還會(huì)做一些預(yù)先設(shè)計(jì)嗎?

            馬丁:我認(rèn)為一些地方還是可以用到預(yù)先設(shè)計(jì)的,不過不會(huì)很多。一些人——像肯特·貝克和羅恩·杰弗里斯——認(rèn)為預(yù)先設(shè)計(jì)已 經(jīng)消亡了。從某種意義上來說,他們是對的,因?yàn)槟憧梢越柚M(jìn)化型設(shè)計(jì)搭建更復(fù)雜的系統(tǒng)。但在某些情況下,預(yù)先設(shè)計(jì)可能讓你的進(jìn)度加快一些。比如說,我不贊 同在架設(shè)數(shù)據(jù)庫之前就討論數(shù)據(jù)庫的進(jìn)化問題。我可能會(huì)對數(shù)據(jù)庫的存在有一個(gè)初步的判斷,然后以此作為起點(diǎn)。當(dāng)然,我仍會(huì)用進(jìn)化的方式完成大部分設(shè)計(jì)。

            比爾:構(gòu)造良好的(well-factored)程序和設(shè)計(jì)良好的(well-designed)程序之間有區(qū)別嗎?

            馬丁:它們在本質(zhì)上并沒有什么區(qū)別,但側(cè)重點(diǎn)有所不同。設(shè)計(jì)強(qiáng)調(diào)的是構(gòu)造——將程序劃分為若干分割清晰的部分。對我來說,“構(gòu)造良好的”一詞表達(dá)了更多對于設(shè)計(jì)的感覺,也即當(dāng)你審視或使用這個(gè)設(shè)計(jì)時(shí)的感覺。代碼中的“壞味道”

            比爾:在你的《重構(gòu)》一書中,關(guān)于何時(shí)應(yīng)用重構(gòu),你是這樣闡述的:“與其去追求一些很模棱兩可的編程美學(xué)原則(坦率地說,這是我們咨詢師們最喜歡做的事情),還不如來點(diǎn)兒更實(shí)際的。”

            我很好奇,你是怎么看待美學(xué)的?我的經(jīng)歷中有很多次都是跟已有的代碼打交道。這些代碼的設(shè)計(jì)很爛,因此處理起來非常痛苦。如果這些設(shè)計(jì)能做得好些,讓我不那么痛苦的話,我會(huì)非常感激。所以,對我來說,美學(xué)至少還是有些意義的,它可以使我的工作輕松些。

            馬丁:嗯,在討論何時(shí)應(yīng)用重構(gòu)時(shí),我的確是這樣談?wù)撁缹W(xué)的。從某種意義上說,我在重構(gòu)準(zhǔn)則中所給的那些條條框框也是一種模 棱兩可的美學(xué)原則。不過,我試著給出更多的說明,而不是僅僅說“當(dāng)你的代碼看上去很丑陋的時(shí)候就需要做重構(gòu)。”比如說,重復(fù)的代碼是一種“壞味道”,再比如 說,很長的方法是一種“壞味道”,或者很臃腫的類也是一種“壞味道”。

            很多“壞味道”是很容易嗅出來的。令人驚奇的是,當(dāng)你審視你的程序時(shí),往往一些很明顯的現(xiàn)象,像是某個(gè)方法長達(dá)100行,就能引導(dǎo)你改進(jìn)你的設(shè)計(jì)。

            在重構(gòu)這個(gè)長達(dá)100行的方法時(shí),你可能會(huì)發(fā)現(xiàn)一些諸如責(zé)任分配(responsibility allocation)不合理這樣的設(shè)計(jì)問題。像這樣的問題,你是不可能光憑掃一眼代碼就發(fā)現(xiàn)的;但是,一個(gè)長達(dá)100行的方法,卻是一眼就能看出來的。 所以說,很表象的問題能夠把你帶向更深層的問題。

            比爾:我參與過的一個(gè)項(xiàng)目竟然有一個(gè)長達(dá)11頁的 while 循環(huán)。

            馬丁:這太不可思議了。

            比爾:我們苦干了六個(gè)月試圖讓這個(gè)軟件穩(wěn)定運(yùn)行,可是我們不敢動(dòng)這個(gè)11頁的循環(huán)。

            馬丁:這恰恰從另一個(gè)側(cè)面說明了這個(gè)長達(dá)11頁的循環(huán)是個(gè)糟糕的設(shè)計(jì)。如果你對改動(dòng)某處代碼心存顧慮的話,那它顯然是一個(gè)蹩腳的設(shè)計(jì)。

            良好的設(shè)計(jì)與效率

            比爾:我想,人們不注重設(shè)計(jì)的一個(gè)原因是由于工作的流動(dòng)性。那個(gè)最初編寫11頁 while 循環(huán)的程序員在我們接手項(xiàng)目的時(shí)候已經(jīng)離開了公司。我認(rèn)為,程序員因?yàn)樽约旱脑愀庠O(shè)計(jì)而自食其果的情況很少發(fā)生,因此他們沒有足夠的動(dòng)因去注重設(shè)計(jì)。此 外,即便他們注重,但設(shè)計(jì)畢竟是一項(xiàng)費(fèi)力不討好的工作,好的設(shè)計(jì)需要時(shí)間,而開發(fā)中的時(shí)間壓力往往很大。

            馬丁:我不同意“好的設(shè)計(jì)需要更長的時(shí)間”這樣的說法。

            比爾:為什么?

            馬丁:這是很有意思的一件事。在軟件業(yè),我們似乎普遍認(rèn)為,慢工出細(xì)活。但當(dāng)我回顧我自己的經(jīng)歷時(shí),卻發(fā)現(xiàn)保持代碼的良好構(gòu)造以及編寫測試反而使我的工作加快了。

            我想,人們把改進(jìn)設(shè)計(jì)所花的時(shí)間看作是“失去”的時(shí)間,但卻沒有看到將來對代碼的改動(dòng)會(huì)容易得多,往往只需要幾分鐘的時(shí)間,否則可能要花上兩三個(gè)小時(shí)。

            人們往往還低估了在調(diào)試上所花的時(shí)間,低估了他們用來追蹤一個(gè)“潛伏”很久的漏洞所花的時(shí)間。我在寫代碼的時(shí)候可以立即察覺產(chǎn)生的漏洞,這使得我能在它潛伏下來之前就解決它。沒有幾件事比調(diào)試更花時(shí)間和更令人沮喪的了。假如我們一開始就能避免產(chǎn)生漏洞,那效率豈不是要提高很多?

          posted on 2012-05-25 09:46 順其自然EVO 閱讀(193) 評論(0)  編輯  收藏 所屬分類: 測試學(xué)習(xí)專欄

          <2012年5月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 务川| 揭阳市| 酒泉市| 二连浩特市| 博湖县| 奉节县| 民权县| 顺义区| 平远县| 开化县| 柳州市| 衡山县| 平武县| 喜德县| 丹棱县| 布拖县| 灵宝市| 平舆县| 玉环县| 丰镇市| 察隅县| 汤阴县| 鹰潭市| 库伦旗| 会泽县| 博爱县| 台北县| 桂东县| 芷江| 白河县| 牡丹江市| 个旧市| 垣曲县| 益阳市| 海晏县| 鸡泽县| 枣强县| 万安县| 鱼台县| 鹤峰县| 龙州县|