敏捷思維- 架構設計中的方法學(3)
——源自需求
作者:林星 (iamlinx@21cn.com)
本文選自:IBM DW中國
2002年04月28日
我們說,和重型方法偏重于計劃、過程和中間產物不同,敏捷方法更加看重人和溝通。人和溝通永遠是第一位的,而計劃、過程和中間產物,那只是保證溝通、實現目標的手段。這并不是說計劃、過程、中間產物不重要,只是不能夠本末倒置
注:我們把中間產物定義為為了實現跨邊界的溝通而制定的文檔、模型、代碼。例如設計文檔、數據模型等。參考RUP的Artifact。
評判軟件成功的標準有很多,對于敏捷方法論來說,成功的標準首先在于交付可用的軟件。為了保證軟件的可用性,最重要的就是做好需求。做好需求的方法有很多(參見拙作需求的實踐),但這并不是我們討論的主題。對于我們要開始的架構設計的工作來說,從需求出發來設計架構,這就是保證軟件可用性的一個基本的保證。
Context
我們如何開始我們的架構設計工作?
Problem
我們在進行架構設計的時候,往往主要考慮的都是平臺、語言、開發環境、數據庫等一些基本問題,可是對于和客戶的具體情況密切相關的一些問題卻很少系統的考慮。甚至還存在一種誤區,認為架構設計無非就是寫一些空話,套話。這樣子做出來架構設計,如何用于指導軟件的實現呢?
IT界的技術層出不窮,面對著如此之多的技術、平臺、框架、函數庫,我們如何選擇一組適合軟件的技術?
每一個客戶的軟件都有自身的特點,如何才能夠設計出符合客戶利益的架構?
軟件中往往都充斥著眾多的問題,在一開始就把所有的問題都想清楚往往很難做到,但是如果不解決問題,風險又居高不下。
Solution
針對需求設計架構。
架構設計就是鋪設軟件的主管道(例1)。我們根據什么來制定主管道的粗細、路徑等因素呢?很明顯,是根據城市的人口、地理位置、水源等因素來決定的。對應到軟件設計也是一樣的。城市的各因素就是軟件中的各種需求:功能需求、非功能需求、變化案例等等。
一般來說,功能需求決定業務架構、非功能需求決定技術架構,變化案例決定架構的范圍。需求方面的知識告訴我們,功能需求定義了軟件能夠做些什么。我們需要根據業務上的需求來設計業務架構,以使得未來的軟件能夠滿足客戶的需要。非功能需求定義了一些性能、效率上的一些約束、規則。而我們的技術架構要能夠滿足這些約束和規則。變化案例是對未來可能發生的變化的一個估計,結合功能需求和非功能需求,我們就可以確定一個需求的范圍,進而確定一個架構的范圍。
從例2中,我們看到自已字處理軟件的幾種需求的范例。真正的字處理軟件要復雜的多。而我們最主要的就是必須認識到,架構是來自于需求的。有什么樣的需求就有什么樣的架構。試想一下,如果我們沒有對速度的要求,我們還需要考慮這方面的設計嗎?我們上面提到了幾種類型的需求對架構的影響,其實還有一個很重要的需求,就是環境的需求。這并不是一個很重要的需求,但是對于部署(deployment)架構設計來說就特別重要。畢竟,我們開發出的軟件是要上"戰場"的,充分的考慮部署問題是非常有必要的。
例1:城市中自來水管的架設是一項非常的復雜的工程。為了需要滿足每家每戶的需要,自來水管組成了一個龐大的網絡。在這樣一個復雜的網絡中,如何完成鋪設的任務呢。一般的做法是,先找出問題的根源,也就是水的源頭。從水源鋪設一條管道通至城市,然后根據城市的區域劃分,設計出主管道,剩下的就是使用的問題了,每家每戶的管道最終都是連到主管道上的。因此,雖然自來水網絡龐大復雜。但是真正的主管道的非常簡單的。
例2:我們打算開發一個字處理軟件,功能需求可以簡單概括為格式化用戶輸入的文字,非功能需求可能是格式化大小為1000K的一段文字的處理速度不能低于10S,變化案例可能是推出多種語言版本。那么我們在設計業務架構的時候,我們會集中于如何表示文字、圖象、媒體等要素,我們該需要有另外的技術架構來處理速度問題,比如緩沖技術,對于變化案例,我們也要考慮相應的架構,比如把字體獨立于程序包的設計。
從需求到架構
在需求階段,我們可以得到一些代表需求調研成果的中間產物。比如說,CRC卡片、基本用例模型、用戶素材、界面原型、界面原型流程圖、非功能需求、變化案例等。我們在架構設計階段的主要工作就是要把這些需求階段的中間產物轉換為架構設計階段的中間產物。
其實,架構設計就是要完成兩項工作,一是分析,二是設計。分析是分析需求,設計則是設計軟件的大致結構。很多的方法論把分析和設計兩種活動分開來,但其實這兩者是很難區分的,做分析的時候會想到如何設計,而思考如何設計反過來又會影響分析的效果?梢哉f,他們兩者之間是相互聯系和不斷迭代的。這種形態我們將會在后面的迭代設計模式中詳細的討論。
在敏捷方法論中,需求最好是迭代進行的,也就是說一點一點的作需求。這種做法在那些需求變化快的項目中尤其適用。由于我們采用的流程是一種迭代式的流程,這里我們將會面臨著如何對待上一次迭代的中間產物的問題。如果我們每一次迭代都需要修改已存在的中間產物,那么這種維護的成本未免過大。因此,敏捷方法論的基本做法是,扔掉那些已經沒有用處的中間產物。還記得在第一章的時候,我們強調說軟件要比文檔重要。我們生成中間產物的目的都是為了生成最終的程序,對于這些已經完成作用的模型,沒有必要付出額外的維護成本。
不要斷章取義的采用拋棄模型的做法。因為,拋棄模型的做法需要一個適合環境的支持。后面會針對這個話題開展大范圍的討論。這里我們簡單的做一個了解:
簡單化:簡單的模型和簡單的程序。模型和程序越復雜,就需要更多的精力來處理它們。因此,我們盡可能的簡化它們,為的是更容易的處理它們。
高效的溝通渠道:通過增強溝通的效果來減少對中間產物的需要。試想一下,如果我隨時能夠從客戶那里得到需求的細節資料,那前期的需求調研就沒有必要做的太細致。
角色的交叉輪換:開發人員之間建立起交換角色的機制,這樣,能夠盡量的避免各子系統諸侯割據的局面。
清晰的流程:或者我們可以稱之為明確的過程。過程在方法論中向來都是一個重點,敏捷方法論也不例外。開發人員能夠清楚的知道,今天做什么,明天做什么。過程不是給別人看的,而是給自己用的。
工具:好用的工具能夠節省大量的時間,這里的工具并不僅僅指CASE工具,還包括了版本控制工具、自動化測試工具、畫圖工具、文檔制作和管理工具。使用工具要注意成本和效益的問題。
標準和風格:語言不通是溝通的一個很大的障礙。語言從某個角度來看屬于一種標準、一種風格。因此,一個團隊如果采用同樣的編碼標準、文檔標準、注釋風格、制圖風格,那么這個團隊的溝通效率一定非常的高。
如果上述的環境你都不具備,或是欠缺好幾項,那你的文檔的模型還是留著的好。
僅針對需求設計架構
僅針對需求設計架構的含義就是說不要做未來才有用的事情。有時候,我們會把架構考慮的非常復雜,主要的原因就是我們把很多未來的因素放入到現在來考慮;蛘,我們在開發第一個產品的時候就視圖把它做成一個完美的框架。以上的這兩種思路有沒有錯呢?沒有錯,這只是如何看待投入的問題,有人希望開始的時候多投入一些,這樣后續的投入就會節省下來。但在現實中,由于需求的不確定性,希望通過增加開始階段的投入來將降低未來的投入往往是難以做到的,框架的設計也絕對不是能夠一蹴而就的,此這種做法并不是一個好的做法。所以我們在后頭會著重論述架構設計的簡單性和迭代過程,也就是因為這個理由。
模式
模式將可以幫助我們抓住重點。設計模式在書的一開始(第二章)就討論了一個設計一個文檔編輯器的問題。為了解決設計文檔編輯器引出的七個問題,一共使用了8種不同的模式。這8種模式的組合其實就是架構,因為它們解決的,都是系統中最高層的問題。
在實踐中,人們發現架構也是存在模式的。比如,對于系統結構設計,我們使用層模式;對于分布式系統,我們使用代理模式;對于交互系統,我們使用MVC(模型-視圖-控制器)模式。模式本來就是針對特定問題的解,因此,針對需求的特點,我們也可以采用相應的模式來設計架構。
在sun網站上提供的寵物商店的范例中,就把MVC模式的思想擴展成為架構的思想,用于提供不同的界面視圖:
MVC架構圖,這里提供原圖的概覽,查看其出處請點擊以下連接:
http://java.sun.com/blueprints/patterns/j2ee_patterns/model_view_controller/index.html

我們可以了解到在圖的背后隱藏著的需求:系統需要支持多種用戶界面,包括為普通用戶提供的HTML界面,為無線用戶提供的WML界面,為管理員提供的Swing界面,以及為B2B業務設計的WebService界面。這是系統最重要的需求,因此,系統的設計者就需要確定一個穩定的架構,以解決多界面的問題。相對于多界面的問題,后端的業務處理邏輯都是一致的。比如HTML界面和WML界面的功能并沒有太大的差別。把處理邏輯和界面分離開來還有額外的好處,可以在添加功能的同時,不涉及界面的改動,反之亦然。這就是我們在第二篇中提到的耦合度的問題。
MVC模式正可以適用于解決該問題。系統使用控制器來為業務邏輯選擇不同的界面,這就完成了MVC架構的設計思路。在架構設計的工作中,我們手頭上有模式這樣一張好牌,有什么理由不去使用它呢?
抓住重點
在架構設計一開始,我們就說架構是一種抽象,那就是說,架構設計摒棄了具體的細節,僅僅抓住軟件最高層的概念,也就是最上層、優先級最高、風險最大的那部分需求。
我們考慮、分析、解決一個問題,一定有一個漸進的過程。架構設計就是解決問題其中比較早期的一個階段,我們不會在架構設計這個階段投入過多的時間(具體的原因在下文會有討論),因此關鍵點在于我們要能夠在架構設計中把握住需求的重點。比如,我們在模式一節中提到了分布式系統和交互系統,分布和交互就是這兩個系統的重點。那么,如果說我們面對的是一個分布式的交互系統,那么,我們就需要把這兩種特性做為重點來考慮,并以此為基礎,設計架構。而我們提到的寵物商店的范例也是類似的,除了MVC的架構,還有很多的設計問題需要解決,例如用于數據庫訪問的數據對象,用于視圖管理的前端控制器,等等(具體使用到的架構模式可以訪問sun的網站)。但是這些相對于MVC模式來說,屬于局部的,優先級較低的部分,可以在架構確定后再來設計。
架構設計和領域專家
一個架構要設計的好,和對需求的理解是分不開的。因此在現實中,我們發現業務領域專家憑借著他對業務領域的了解,能夠幫助開發人員設計出優秀的架構來。架構是需要抽象的,它是現實社會活動的一個基本模型,而業務領域的模型僅僅憑開發人員是很難設計出來的。在ERP的發展史上,我們看到MRP發展為MRPII,在發展到閉環MRP,直到發展成為現在的ERP,主要的因素是管理思想的演化,也就是說,對業務領域的理解進步了,架構才有可能進步。
因此,敏捷型架構設計的過程中,我們也非常強調領域專家的作用。
例3:信貸系統
在一個銀行的信貸帳務處理系統中,我們應該如何把握最初的架構思路呢?從需求上來看,這個信貸帳務處理系統有幾個特點:
它不是一個單獨的系統,它需要和外部的其它系統交互,例如信貸業務系統、網上銀行、數據倉庫系統等。
在所有的需求中,最復雜的就是它的利息計算的需求,它要求能夠支持多種的利息算法。
因此,我們的架構設計首先是從系統的全局環境開始考慮。其它系統和該系統的關系如何,應該如何設計系統間的接口。通過需求的調研,系統的接口分為4類:
和企業外部系統的接口。信貸系統需要連接到人民銀行的系統。
和企業內部系統的接口。信貸系統需要能夠為數據倉庫系統和網上銀行系統提供數據。
和平級系統的接口。信貸系統需要從平級的帳戶、資金、財務系統中取數據,并向帳戶、押匯系統發送數據。
具體的實現策略并不在我們的討論范圍之內,但是可以看到,架構策略的制定是以需求為基礎的。我們可以把這部分的需求歸納為技術架構或平臺架構。
然后是利息算法的問題,我們經過統計,目前的利息計算方式有四種,可預見到的還有兩種。在一開始的階段,我們并不需要考慮具體算法的實現,但是我們需要考慮算法的實現框架,因此我們很自然的想到Strategy模式可以勝任這一工作,把不同的利息算法封裝起來。而我們的工作重點也就轉到定義利息算法的接口問題。通過分析、比較多種利息算法,我們定義了一個最初始的算法接口,然后由不同的利息算法來實現算法接口。雖然,這個接口目前還不是很完整,但是它會在接下去的開發過程中慢慢的完善起來。這部分的需求屬于業務架構的一部分。
考慮到系統的結構非常的復雜,因此在系統結構的處理上,我們采用了層模式做為系統的基本結構。此外,在每個層,我們還定義了幾個子模塊來處理特定的問題。這樣,我們就可以將復雜的功能有序的組織起來。
經過上述的分析,我們對系統的架構有了一個簡單的認識,但是還沒有結束,一個架構應該包括系統的各個基本部分,因此,我們還要考慮票據處理、報表、帳務處理等環節,但是一開始就考慮周詳,這要花費大量的時間,因此我們只是簡單的定義了一個原始的架構,然后在后續的開發過程中把這個架構完善起來。
文章來源于領測軟件測試網 http://www.kjueaiud.com/