• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    敏捷思維(5)—簡單設計

    發布: 2008-2-02 16:57 | 作者: 林星 | 來源: 不詳 | 查看: 36次 | 進入軟件測試論壇討論

    領測軟件測試網

    XP非常強調簡單的設計原則:能夠用數組實現的功能決不用鏈表。在其它Agile方法中,簡單的原則也被反復的強調。在這一章,我們就對簡單性做一個全面的了解。
    Context
    架構應該設計到什么程度?
    Problem
    軟件的架構都是非常的復雜的,帶有大量的文檔和圖表。開發人員花在理解架構本身上的時間甚至超出了實現架構的時間。在前面的文章中,我們提到了一些反對象牙塔式架構的一個原因,而其中的一個原因就是象牙塔式架構的設計者往往在設計時參雜進過多的自身經驗,而不是嚴格的按照需求來進行設計。
    在軟件開發領域,最為常見的設計就是"Code and Fix"方式的設計,設計隨著軟件開發過程而增長;蛘,我們可以認為這種方式根本就不能算是設計,它抱著一種船到橋頭自然直的態度,可是在設計不斷改動之后,代碼變得臃腫且難以理解,到處充滿著重復的代碼。這樣的情形下,架構的設計也就無從談起,軟件就像是在風雨中的破屋,瀕臨倒塌。
    針對于這種情形,新的設計方式又出現了,Martin Fowler稱這種方式為"Planned Design"。和建筑的設計類似,它強調在編碼之前進行嚴格的設計。這也就是我們在團隊設計中談到的架構設計師的典型做法。設計師們通常不會去編程,理由是在土木工程中,你不可能看到一位設計師還要砌磚頭。
    "Planned Design"較之"Code and Fix"進步了許多,但是還是會存在很多問題。除了在團隊設計中我們談的問題之外,需求變更將會導致更大的麻煩。因此,我們理所當然的想到進行"彈性設計":彈性的設計能夠滿足需求的變更。而彈性的設計所付出的代價就是復雜的設計。
    題外話:
    這里我們談論"Planned Design"引出的一些問題,并沒有任何排斥這種方式的意思。"Planned Design"還是有很多可取之處的,但也有很多需要改進的地方。事實上,本文中我們討論的架構設計方式,本質上也是屬于"Planned Design"方式。和"Planned Design"相對應的方式是XP所主張的"Evolutionary Design"方式,但是這種方式還有待于實踐的檢驗,并不能簡單的說他就一定要比"Planned Design"先進或落后。但可以肯定的一點是:"Evolutionary Design"方式中有很多的思想和技巧是值得"Planned Design"借鑒的。
    Solution
    XP中有兩個非常響亮的口號:"Do The Simplest Thing that Could Possibly Work"和"You Aren't Going to Need It"(通常稱之為YAGNI)。他們的核心思想就是不要為了考慮將來,把目前并不需要的功能加到軟件中來。
    粗看之下,會有很多開發人員認為這是不切實際的口號。我能理解這種想法,其實,在我熱衷于模式、可重用組件技術的時候,我對XP提倡的簡單的口號嗤之以鼻。但在實際中,我的一些軟件因為復雜設計導致開發成本上升的時候,我重新思考這個問題,發現簡單的設計是有道理的。
    降低開發的成本
    不論是模式,可重用組件,或是框架技術,目的都是為了降低開發的成本。但是他們的方式是先進行大量的投入,然后再節省后續的開發成本。因此,架構設計方面的很多思路都是圍繞著這種想法展開的,這可能也是導致開發人員普遍認為架構設計高不可攀的原因。
    XP的方式恰恰相反,在處理第一個問題的時候,不必要也不可能就設計出具有彈性、近乎完美的架構來。這項工作應該是隨著開發的演進,慢慢成熟起來的。我不敢說這種方式肯定正確,但是如果我們把生物的結構視同為架構,這種方式不是很類似于自然界中生物的進化方式嗎?
    在一開始就制作出完美的架構的設想并沒有錯,關鍵是很難做到這一點?偸菚泻芏嗟膯栴}是你在做設計時沒有考慮到的。這樣,當一開始花費大量精力設計出的"完美無缺"的架構必然會遇到意想不到的問題,這時候,復雜的架構反而會影響到設計的改進,導致開發成本的上升。這就好比如果方向錯了,交通工具再快,反而導致錯誤的快速擴大。Martin Fowler在他的論文中說,"Working on the wrong solution early is even more wasteful than working on the right solution early"(提前做一件錯事要比提前做一件對的事更浪費時間),相信也是這個道理。
    更有意思的是,通常我們更有可能做錯。在我們進行架構設計的時候,我們不可能完全取得詳細的需求。事實上,就算你已經取得了完整的需求,也有可能發生變化。這種情況下做出的架構設計是不可能不出錯的。這樣,浪費大量的時間在初始階段設計不可能達到的"完美架構",倒不如把時間花在后續的改進上。
    提升溝通的效率
    我們在團隊設計中已經談過了團隊設計的目標之一就是為了降低溝通的成本,以期讓所有人都能夠理解架構。但是如果架構如果過于復雜,將會重新導致溝通成本的上升,而且,這個成本并不會隨著項目進行而降低,反而會因為上面我們提到的遇到新的問題導致溝通成本的持續上升。
    簡單的架構設計可以加快開發團隊理解架構的速度。我們可以通過兩種方式來理解簡單的含義。首先,簡單意味著問題的解不會非常的復雜,架構是解決需求的關鍵,無論需求再怎么復雜多變,總是可以找出簡單穩定的部分,我們可以把這個簡單穩定的部分做為基礎,再根據需要進行改進擴展,以解決復雜的問題。在示例中,我們提到了measurement pattern,它就是按照這種想法來進行設計的。
    其次,簡單性還體現在表示的簡單上。一份5頁的文檔就能夠表達清楚的架構設計為什么要花費50頁呢?同樣的道理,能夠用一副簡單的圖形就能夠表示的架構設計也沒有必要使用文檔。畢竟,面對面的溝通才是最有效率的溝通,文檔不論如何的復雜,都不能被完全理解,而且,復雜的文檔,維護起來也需要花費大量的時間。只有在兩種情況下,我們提倡使用復雜的文檔:一是開發團隊沒有辦法做到面對面溝通;二是開發成果要作為團隊的知識積累起來,為下一次開發所用。
    考慮未來
    我們之所以考慮未來,主要的原因就是需求的不穩定。因此,我們如果考慮未來可能發生的需求變化,就會不知覺的在架構設計中增加復雜的成分。這違背的簡單的精神。但是,如果你不考慮可能出現的情況,那些和目前設計格格不入的改變,將會導致大量的返工。
    還記得YAGNI嗎?原則上,我們仍然堅持不要在現有的系統中為將來可能的情況進行設計。但是,我們必須思考,必須要為將來可能出現的情況做一些準備。其實,軟件中了不起的接口的思想,不就是源于此嗎?因此,思考未來,但等到需要時再實現。
    變更案例有助于我們思考未來,變更案例就是你在將來可能要(或可能不要)滿足的,但現在不需要滿足的需求。當我們在做架構設計的時候,變更案例也將會成為設計的考慮因素之一,但它不可能成為進行決策的唯一考慮因素。很多的時候,我們沉迷于設計通用系統給我們帶來的挑戰之中,其實,我們所做的工作對用戶而言是毫無意義的。
    架構的穩定
    架構簡單化和架構的穩定性有什么關系嗎?我們說,架構越簡單,其穩定性就越好。理由很簡單,1個擁有4個方法和3個屬性的類,和1個擁有20個方法和30屬性的類相比,哪一個更穩定?當然是前者。而架構最終都是要映射到代碼級別上的,因此架構的簡單將會帶來架構的穩定。盡可能的讓你的類小一些,盡可能的讓你的方法短一些,盡可能的讓類之間的關系少一些。這并不是我的忠告,很多的設計類的文章都是這么說的。在這個話題上,我們可以進一步的閱讀同類的文章(關于 refactoring 的思考)。
    辨正的簡單
    因此,對我們來說,簡單的意義就是不要把未來的、或不需要實現的功能加入到目前的軟件中,相應的架構設計也不需要考慮這些額外的需求,只要剛好能夠滿足當前的需求就好了。這就是簡單的定義?墒窃诂F實之中,總是有這樣或者那樣的原因,使得設計趨向復雜。一般來說,如果一個設計對團隊而言是有價值的,那么,付出一定的成本來研究、驗證、發展、文檔化這個設計是有意義的。反之,如果一個設計沒有很大的價值或是發展它的成本超過了其能夠提供的價值,那就不需要去考慮這個設計。
    價值對不同的團隊來說具有不同的含義。有時候可能是時間,有時候可能是用戶價值,有時候可能是為了團隊的設計積累和代碼重用,有時候是為了獲得經驗,有時候是為了研究出可重用的框架(FrameWork)。這些也可以稱為目的,因此,你在設計架構時,請注意先確定好你的目的,對實現目的有幫助的事情才考慮。
    Scott W.Ambler在他的文章中提到一個他親身經歷的故事,在軟件開發的架構設計過程中,花了很多的時間來設計數據庫到業務邏輯的映射架構,雖然這是一件任何開發人員都樂意專研的事情(因為它很酷)。但他不得不承認,對用戶來說,這種設計先進的架構是沒有太大的意義的,因為用戶并不關心具體的技術。當看到這個故事的時候,我的觸動很大。一個開發人員總是熱衷于新奇的技術,但是如果這個新奇技術的成本由用戶來承擔,是不是合理呢?雖然新技術的采用能夠為用戶帶來效益,但是沒有人計算過效益背后的成本。就我開發過的項目而言,這個成本往往是大于效益的。這個問題可能并沒有確定的答案,只能是見仁見智了。

    例1.Java的IO系統
    從Java的IO系統設計中,我們可以感受到簡單設計的困難。
    IO系統設計的困難性向來是公認的。Java的IO設計的一個目的就是使IO的使用簡單化。在Java的1.0中,Java的IO系統主要是把IO系統分為輸入輸出兩個大部分,并分別定義了抽象類InputStream和OutputStream。從這兩個的抽象類出發,實現了一系列不同功能的輸入輸出類,同時,Java的IO系統還在輸入輸出中實現了FilterInputStream和FilterOutputStream的抽象類以及相關的一系列實現,從而把不同的功能的輸入輸出函數連接在一起,實現復雜的功能。這個實現其實是Decorator模式(由于沒有看過源碼和相關的資料,這里僅僅是根據功能和使用技巧推測,如果大家有不同的意見,歡迎來信討論)。
    因此,我們可以把多個對象疊加在一起,提供復雜的功能:
    DataInpuStream in =
    new DataInputStream(
    new BufferedInputStream(
    new FileInputStream("test.txt");

    上面的代碼使用了兩個FilterInputStream:DataInpuStream和BufferedInputStream,以實現讀數據和緩沖的功能,同時使用了一個InputStream:FileInputStream,從文件中讀取流數據。雖然使用起來不是很方便,但是應該還是非常清晰的設計。
    令設計混亂的是既不屬于InputStream,也不屬于OutputStream的類,例如RandomAccessFile,這正表明,由于功能的復雜化,使得原先基于輸入輸出分類的設計變得混亂,根據我們的經驗,我們說設計需要Refactoring了。因此,在Java1.1中,IO系統被重新設計,采用了Reader和Writer位基礎的設計,并增加了新的特性。但是目前的設計似乎更加混亂了,因為我們需要同時使用1.0和1.1兩種不同的IO設計。

    簡單并不等于實現簡單
    說到這里,如果大家有一個誤解,認為一個簡單的架構也一定是容易設計的,那就錯了。簡單的架構并不等于實現起來也簡單。簡單的架構需要設計者花費大量的心血,也要求設計者對技術有很深的造詣。在我們正在進行的一個項目中,一開始設計的基礎架構在實現中被修改了幾次,但每修改一次,代碼量都減少一分,代碼的可讀性也就增強一分。從心理的角度上來說,對自己的架構進行不斷的修改,確實是需要一定的勇氣的。因為不論是設計還是代碼,都是開發人員的心血。但跨出這一步是值得的。
    右側的例子討論了Java的IO設計,Java類庫的設計應該來說是非常優秀的,但是仍然避免不了重新的修改。實際上,在軟件開發領域,由于原先的設計失誤而導致后來設計過于復雜的情況比比皆是(例如微軟的OLE)。同樣的,我們在設計軟件的時候,也需要對設計進行不斷的修改。能夠實現復雜功能,同時自身又簡單的設計并不是一件容易的事情。
    簡單設計需要什么樣的設計師
    簡單的架構需要全面的設計師。什么才是全面的設計師,我的定義是既能夠設計,又能夠編碼。我們在團隊設計模式中就已經談過象牙塔式架構和象牙塔式架構設計師。他們最容易犯的一個毛病就是設計和代碼的脫離。從我們自己的經驗來看,即使在設計階段考慮的非常完美的架構,在編碼階段也會出現這樣或那樣的問題。從而導致架構實現變得復雜。最明顯的特征就是在編碼時出現了有大量方法的類,或是方法很長的類。這表明架構和代碼脫鉤了。在我們的開發過程中,不只一次出現這種現象,或者說,出現了壞味道(Bad Smell)。Refactoring的技巧也同樣有助于識別壞味道。
    一次的架構設計完成后,開發人員可以按照設計,快速的編程?稍谝欢螘r間之后,新的特色不斷的加入,我們發現代碼開始混亂,代碼量增大,可讀性下降,調試變得困難,代碼不可控制的征兆開始出現。我們就知道,架構的設計需要調整了。這屬于我們在后面所提到的Refactoring模式。而我們在這里要說的是,如果架構的設計師不參與編碼,它是無法感受到壞味道的,因此也就不會主動的對設計進行改進。要解決這個問題,最好的辦法是讓設計師參與代碼的編寫,尤其是重要架構的現實部分需要設計師的參與。如果設計師沒有辦法參與編碼,那就需要一種機制,能夠把代碼反饋給設計師,讓他在適當的時候,重新考慮改進架構。一個可能的辦法是Code Review。讓設計師審核代碼,以確保編碼者真正了解了架構設計的意圖。
    例1.Java的IO系統
    從Java的IO系統設計中,我們可以感受到簡單設計的困難。
    IO系統設計的困難性向來是公認的。Java的IO設計的一個目的就是使IO的使用簡單化。在Java的1.0中,Java的IO系統主要是把IO系統分為輸入輸出兩個大部分,并分別定義了抽象類InputStream和OutputStream。從這兩個的抽象類出發,實現了一系列不同功能的輸入輸出類,同時,Java的IO系統還在輸入輸出中實現了FilterInputStream和FilterOutputStream的抽象類以及相關的一系列實現,從而把不同的功能的輸入輸出函數連接在一起,實現復雜的功能。這個實現其實是Decorator模式(由于沒有看過源碼和相關的資料,這里僅僅是根據功能和使用技巧推測,如果大家有不同的意見,歡迎來信討論)。
    因此,我們可以把多個對象疊加在一起,提供復雜的功能:
    DataInpuStream in =
    new DataInputStream(
    new BufferedInputStream(
    new FileInputStream("test.txt");
    上面的代碼使用了兩個FilterInputStream:DataInpuStream和BufferedInputStream,以實現讀數據和緩沖的功能,同時使用了一個InputStream:FileInputStream,從文件中讀取流數據。雖然使用起來不是很方便,但是應該還是非常清晰的設計。
    令設計混亂的是既不屬于InputStream,也不屬于OutputStream的類,例如RandomAccessFile,這正表明,由于功能的復雜化,使得原先基于輸入輸出分類的設計變得混亂,根據我們的經驗,我們說設計需要Refactoring了。因此,在Java1.1中,IO系統被重新設計,采用了Reader和Writer位基礎的設計,并增加了新的特性。但是目前的設計似乎更加混亂了,因為我們需要同時使用1.0和1.1兩種不同的IO設計。
    例2. measurement pattern
    在分析模式一書中有一個measurement pattern(測量模式),原來它是為了要解決現實中各種各樣紛繁復雜的可測量的屬性。例如,一個醫療系統中,可能會有身高多高,體重多種,血壓多少等上千種可測量的屬性。如果分別表示它們,必然導致系統復雜性的上升。因此measurement pattern就從這些屬性的可測量的共性出發,研究新的解決方法,提出了measurement pattern的想法:
    如圖所示,把可測量的屬性(Measurement)做為Phenomenon Type的實例,此外,每一個的Person可以擁有多個的Measurement,同時,Measurement還對應處理的屬性,例如圖中的Quantity,就表示了Measurement的數量和單位。比如,一個人的體重是65公斤,那么,Phenomenon Type就是體重,Quantity的amount是65,units是公斤。


    圖 5.牋 measurement pattern 的類圖
    這其實是一個很簡單的設計,但它清楚的表示了屬性之間的關系,簡化了數千種的屬性帶來的復雜性。此外,我們進一步思考,就會發現,這種架構只是針對目前出現屬性眾多的問題的基本解決方法,它還可以根據具體的需要進行擴展,例如,實現動態添加單位,或實現不同單位的轉化等問題。
    因此,我們這里展示的其實是一種思考的方法,假想一下,當你在面對一個復雜的醫療系統時,大量的屬性和不同的處理方式,你是不是可以從這樣復雜的需求中找出簡單的部分來呢?在我們架構設計的第一篇中,我們談到架構設計的本質在于抽象,這里例子就是最典型的一個例子,在我們傳統的想法中,我們都會把身高、體重等概念做為屬性或是類,但是為了滿足這里的需求,我們對這些具體的概念做一個抽象,提出可測量類別的概念,并把它設計為類(Phenomenon Type),而把具體的概念做為實例。這種抽象的思想在軟件設計中無處不在,例如元類的概念。
    更深入的理解
    下一章中我們將會討論迭代設計,其中還會涉及到簡單設計的相關知識。建議可以將兩章的內容結合起來看。

    (待續)
    作者簡介:
    林星,辰訊軟件工作室項目管理組資深項目經理,有多年項目實施經驗。辰訊軟件工作室致力于先進軟件思想、軟件技術的應用,主要的研究方向在于軟件過程思想、Linux集群技術、OO技術和軟件工廠模式。您可以通過電子郵件 iamlinx@21cn.com 和他聯系。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/

    TAG: 敏捷思維


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>