940 likes | 1.22k Views
軟體工程第六版 第九章 設計工程. 設計工程簡介. 設計工程含括一組 原則、概念和實務 ,以導引高品質系統或產品的發展。 設計原則 ( 在第 5 章中討論 ) 建立置換 (overriding) 的哲學,在所執行的工作中指導設計者。 當應用設計實務機制之前,必須要先瞭解設計概念,並且設計實務本身也導致軟體某些不同的表示法,做為隨後建構活動的指導。. 軟體設計宣言. 設計是核心的工程活動 。 在 1990 年代早期 Mitch Kapor , Lotus 1-2-3 的創造者,於 Dr. Dobbs 雜誌中發表一篇「軟體設計宣言」。他說:
E N D
設計工程簡介 • 設計工程含括一組原則、概念和實務,以導引高品質系統或產品的發展。 • 設計原則(在第5章中討論)建立置換(overriding)的哲學,在所執行的工作中指導設計者。 • 當應用設計實務機制之前,必須要先瞭解設計概念,並且設計實務本身也導致軟體某些不同的表示法,做為隨後建構活動的指導。
軟體設計宣言 • 設計是核心的工程活動。 • 在1990年代早期Mitch Kapor,Lotus 1-2-3的創造者,於Dr. Dobbs雜誌中發表一篇「軟體設計宣言」。他說: • 什麼是設計?它是你的一隻腳站在二個世界中 科技的世界和人的世界與人的目的 且你嘗試著將二者合在一起……
設計良好的軟體所具有的特性 • 羅馬的建築評論家Vitruvius的想法: • 設計良好的建築物就是展現堅固(firmness)、實用(commodity)和愉悅(delight)的那一些。 • 設計良好的建築物可以用來述說優良的軟體。 • 堅固:一個程式應該沒有任何的臭蟲(bug)約束到它的功能。 • 實用:一個程式應該適合於它所設計意圖的目的。 • 愉悅:使用程式的經驗應該是很愉悅的一種。這裡我們已開始軟體設計的理論。
快速瀏覽 • 它是什麼? • 事實上設計是每位工程師想要做的。它是創造力規則所在的地方 • 顧客需求、商務需要和技術考慮,全部都聚集在產品或系統的規劃中。 • 設計創造出軟體的表示或模型,但不像分析模型(聚焦在描述所需要的資料、功能和行為),設計模型提供有關實作系統所必需要的軟體資料結構、架構、介面和元件的細節。 • 誰完成它? • 軟體設計師帶領每個設計任務。
快速瀏覽 • 它為何重要? • 設計讓軟體工程師模塑所要建構的系統或產品。 • 此模型可以評估其品質,並且在產生程式碼、導入測試和大量的終端使用者涉入前先行改進。 • 設計是軟體品質建立的地方。
快速瀏覽 • 步驟為何? • 設計可以用許多不同的方式描繪軟體。 • 系統或產品的架構必須要呈現。 • 連結軟體到終端使用者、軟體到其他系統與裝置,和軟體對本身構成元件介面的塑模。 • 設計用來建構系統的軟體元件。 • 這些觀點的每一個都表示一種不同的設計行動,但所有的設計行動必須要遵照一組指導所有軟體設計工作的基本設計觀念。
快速瀏覽 • 工作產品為何? • 含括架構、介面,元件層級和部署表示的設計模型是軟體設計期間所產生的主要工作產品。 • 我如何確定我所做的是正確的? • 設計模型由軟體團隊評估,以盡力決定它是否有錯誤、不一致性或疏忽; • 是否有更好的替代選擇存在;和 • 此模型是否可於執行的侷限、時程和成本內建立。
設計工程的目的 • 設計工程的目的是製作一個模型或表示法,以展現其為堅固、實用和愉悅的。 • 設計者必須要實踐多樣性(diversification),接著收斂(convergence)。 • Belady陳述: • 「多樣性是獲得全部可供選擇的替代方案、設計的原始材料:元件、元件解決方案和知識,全部包含在型錄(catalog)、教科書和心中。」一旦資訊發散的集合被組成,設計者必須藉由需求工程(第7章)從全部所需要的定義與分析模型(第8章)中挑選元素。當此發生時,替代的選擇會被考慮或剔除,並且設計工程師收斂於「一個特定的元件組態,並因此產生最終的產品。 」
設計工程的發散與收斂 • 發散與收斂需要直覺與判斷。 • 這些的品質是基於建構相似實體的經驗、指導模型演進方式的一組原則或經驗法則(heuristics)、一組判斷品質的標準和一個最終導致最後設計呈現的反覆流程方法。 • 當新的方法、更好的分析和更廣泛地瞭解演進時,電腦軟體的設計工程將不斷地改變。
9.1軟體工程環境中的設計 • 軟體設計位在軟體工程技術的核心,並且它不管其使用的任何軟體流程模型而被應用。 • 一旦軟體需求被分析與塑模後就開始,軟體設計是塑模活動中最後的軟體工程活動,並設定建構的階段(產生程式碼與測試)。 • 「軟體工程最普通的奇蹟是由分析到設計、由設計到編碼的轉換。」Richard Due
分析模型轉換成為設計規格 • 分析模型的每個元素對所必要的完整設計規格提供創造四個設計模型所需要的資訊。 • 在軟體設計期間的資訊流向(information flow) 說明如圖9.1。 • 藉由以情境為基礎、以類別為基礎、以流向為導向和行為元素所顯露出的分析模型提供給設計任務。 • 使用設計記號與設計方法,產生資料/類別的設計、架構的設計、介面設計和元件設計。 • 資料/類別設計轉換分析類別(analysis class)模型成為設計類別的實現(realizations),和需要實作軟體所必要的資料結構。 • 由CRC索引卡片所定義的類別與關係、由類別所描述的詳細資料內容和其他提供資料設計活動基礎的記號。 • 部分的類別設計可能發生在與軟體架構設計相連接的地方。 • 當每個軟體元件被設計時,更多詳述的類別設計將會發生。
架構的設計 • 架構的設計定義軟體主要結構元素間的關係、可以使用來達成由系統所定義需求的結構型態與設計模式,和影響架構實作方法的侷限。 • 架構設計表示法-以電腦為基礎的系統框架-可由系統規格、分析模型和定義於分析模型中的子系統互動。
介面設計 • 介面設計描述軟體如何與相互操作的系統與使用它的人之間的溝通。 • 一個介面隱含著一個資訊的流向(例如,資料及/或控制)與特定的行為型態。 • 使用情境與行為模型提供許多介面設計所必要的資訊。
元件層級的設計 • 元件層級的設計轉換軟體架構的結構化元素成為軟體元件的程序描述。 • 從以類別為基礎的模型、流向模型和行為模型中所獲得的資訊,可做為元件設計的基礎。 • 設計期間我們所決定的最終將會影響軟體建構的成功,而同樣重要的是軟體能容易的維護。
為什麼軟體設計如此重要? • 軟體設計的重要性可以用一個字來說明 - 品質。 • 設計是軟體工程中品質養育的所在。 • 設計提供我們可以評估軟體品質的表示。 • 設計是我們可以準確地將顧客的需求轉換成為完成的軟體產品或系統的唯一方法。 • 軟體設計作為所有的軟體工程和接續的軟體支援活動的基礎。 • 當在時間不夠且已經花費許多經費,若沒有設計,我們就是在冒險建立一個不穩定的系統 • 當小的改變產生時它將會失敗;它可能難以測試;它的品質直到軟體流程的晚期之前都無法被評估。
9.2 設計流程與設計品質 • 軟體設計是一個反覆的流程,使需求得以轉化成為所建構軟體的「藍圖(blueprint)」。 • 藍圖描述軟體全部的觀點。 • 設計是高度抽象層級的表示一個可對特定系統目標和更為詳細的資料、功能與行為需求直接追蹤的層級。 • 當設計反覆發生時,隨後的改進導致在更低抽象層級的設計表示。 • 這些仍能被追溯到需求,但其間的連接則更難以捉摸。
評估良好設計的指導 • 整個設計流程中,演進的設計品質與一系列的正規技術檢視或將於設計排練時一起被評估。 • McGlaughlin建議三種特性,它們可以做為評估良好設計的指導: • 設計必須實作所有包含於分析模型中的明顯需求,並且必須要適應顧客想要的所有隱含的需求。 • 對那些產生程式碼和那些測試與隨後支援軟體的人,設計必須是可讀的、可瞭解的指導。 • 設計應該從實作的觀點針對資料、功能和行為的領域,提供一張軟體的完整圖像。 • 這些特性的每一個實際上都是設計流程的目標。但如何達成這些目標? 撰寫一段聰明的程式碼是一回事;設計能支援持久的商業運作則是一件相當不同的事。」 C. Ferguson
品質指導方針(Quality guidelines) • 為評估設計所表示的品質,我們必須要建立良好設計的技術準則。先說明下列的指導方針: • 一個設計應該展現如下的架構: • 使用已認可的架構型態或模式, • 由展現良好設計特性(將於本章稍後討論)的元件所組成,和 • 能以演進的形式1實作,藉此促進實作與測試。 • 一個設計應該是模組化的;即軟體應該合乎邏輯的分割而成為元素或子系統。 • 一個設計應該含括資料、結構、介面和元件等明顯的表示。 • 一個設計應該引導出資料結構,其適合於所要實作的類別,並從可辨識的資料模式中選取出。
品質指導方針(Quality guidelines) • 一個設計應該引導出展現獨立功能特性的元件。 • 一個設計應該引導出介面,它降低元件與外部環境間相連結的複雜度。 • 一個設計應該得自於使用可重複的方法,它藉由軟體需求分析期間獲得的資訊所驅動。 • 一個設計應該使用一種能有效溝通其意義的記號來表示。 • 這些設計指導方針的達成不是偶然的。 • 設計工程鼓勵經由基本設計原則的應用、系統化的方法學和徹底地檢視所構成的良好設計。
評估設計品質-正規的技術檢視 • 設計是重要的,因為它允許一個軟體團隊在實作前評估軟體的品質 • 每當錯誤、疏忽或不一致時,可以很容易且便宜地修正。但是我們如何在設計期間評估品質呢?軟體不能被測試,因為沒有可執行的軟體做為測試。那該做些什麼呢? • 在設計期間,品質是由導入一系列的正規技術檢視(formal technical reviews, FTRs)來評估。 • FTR是一個由軟體團隊成員所主導的會議。 • 通常視所需檢視的設計資訊範圍,由二至四人參與討論。 • 每個人扮演一個角色:檢視領導者(review leader)計畫會議、設定會議程序,然後進行會議;記錄者(recorder)做筆記以避免任何的遺漏;生產者(producer)是工作產品(例如,某個軟體元件的設計)正被檢視的人。
品質屬性(Quality attributes) • 惠普公司(Hewlett-Packard)[GRA87]發展出一組軟體品質屬性,並以字母首字縮寫成FURPS • 功能性(functionality) • 可使用性(usability) • 可靠性(reliability) • 效能(performance) • 可支援性(supportability)。
FURPS品質屬性 • FURPS品質屬性代表所有軟體設計的一個目標: • 功能性 • 藉由評估其性能組(feature set)與程式的能力、所遞交功能的主要部分和整體系統的安全性而進行評估。 • 可使用性 • 藉由考慮人為因素(human factors)(第12章)、整體美學、一致性和文件編寫來評估。 • 可靠性 • 藉由測量故障的頻率與嚴重程度、輸出結果的準確度、平均失敗時間(MTTF)、失敗恢復能力和程式的可預測性來評估。
FURPS品質屬性 • 效能 • 是藉由處理速度、回應時間、資源消耗、貫通率(throughput)和效率來測量。 • 可支援性 • 結合擴展程式的能力(擴充性)、適應性、可服務性(serviceability) • 這三種屬性表示一種更為普通的術語 - 可維護性(maintainability) • 可測試性、相容性、組態(configuration) • 軟體組態元素的組織與控制能力、系統安裝的容易性,和使問題可被局部化的容易性。
設計的一般任務組 • 檢查資訊領域模型,並為資料物件與其屬性設計適當的資料結構。 • 使用分析模型,選擇一個適合軟體架構的型態(模式)。 • 切割分析模型成為設計子系統,並配置這些子系統到結構中。確定每個子系統在功能上是凝聚的(cohesive)。 • 設計子系統介面。 • 配置分析類別或功能到每個子系統。
設計的一般任務組 • 創造一組設計類別或元件。 • 轉換每個分析類別描述成為設計類別。 • 依照設計標準檢查每個設計類別,並考慮繼承議題。 • 定義結合每個設計類別的方法與訊息。 • 為設計類別或子系統評估與選擇設計模式。 • 檢視設計類別,並於有必要時修訂。
設計的一般任務組 • 設計任何外部系統或裝置所需要的介面。 • 設計使用者介面。 • 檢視任務分析的結果。 • 基於使用者情境指定動作的順序。 • 創造介面的行為模型。 • 定義介面物件與控制機制。 • 檢視介面設計,並於有必要時修訂。
設計的一般任務組 • 導入元件層級的設計。 • 在相對低的抽象化層級上指明所有的演算法。 • 改善每個元件的介面。 • 定義元件層級的資料結構。 • 檢視每個元件並修正所有發現的錯誤。 • 發展部署模型。
9.3 設計概念 • 一組基本的軟體設計概念已經在軟體工程的歷史上演進。 • 雖然對每項概念有興趣的程度近年來有些變化,但每個都歷經時間的考驗。 • 它們提供軟體設計者一項基礎,因而更為精細的方法可以被應用。 • M. A. Jackson曾經說道:「[軟體工程師]智慧的開端是就分辨出拿程式去執行與拿對的程式之間的差異」。基礎的軟體設計概念提供「將它做對」所需要的框架。
9.3.1 抽象化 • 當我們對任何問題考慮模組化的解決方案時,會造成許多抽象化(abstraction)的層級。 • 在抽象化的最高層級,解決方案是使用問題環境的語言以大範圍的角度陳述。 • 在抽象化較低的層級,解決方案提供較為詳細的描述。 「抽象化是我們人類對付複雜的基本方法之一。」Grady Booch
程序與資料的抽象化 • 當我們移動經過不同的抽象化層級,我們著手創造程序的(procedural)與資料的抽象化。 • 程序的抽象化(procedural abstraction)參考具特定與限制功能的指令順序。 • 程序抽象化的名稱隱含著這些功能,但是特定的細節還是被抑制的。 • 程序抽象化的例子將會如一扇門的開啟(open)這個字。 • 開啟隱含著程序步驟很長的順序(例如:走到門前、伸出並握住門把、扭轉門把並拉開門、跨出門等) 。
程序與資料的抽象化 • 資料抽象化(data abstraction)是一個被稱為描述某個資料物件的資料集合。 • 在開啟(open)這個程序抽象的環境中,我們可以定義稱為door (門)的抽象化資料。 • 如同其他的資料物件,door的資料抽象化將包括描述門的一組屬性(例如:door type(門的型態)、swing direction(擺動的方向)、opening mechanism(開啟的機制)、weight(重量)、dimensions(尺寸))。 • 它遵循開啟(open)這個程序抽象化所要利用而包含在門(door)這個資料抽象化中的屬性。
9.3.2 架構 • 軟體架構(software architecture)約略提到「軟體的整體架構,和其內結構所提供系統概念整合的方式。」 • 在最簡單的形式中,架構是結構或程式元件(模組)的組織、這些元件互動的方法和由元件所使用的資料結構。 • 元件可被歸納以表示主要的系統元素和它們的互動。 「軟體架構是發展工作的產品,它給投資於品質、時程和成本最高的回饋報酬。」 Len Bass等人
軟體設計的目標 • 軟體設計的一個目標是獲得一個系統架構的演繹(rendering)。 • 此演繹提供一個框架,並將更為詳細的設計活動導入此框架中。 • 一組架構的模式讓軟體工程師重複使用設計層級的概念。
架構設計的模型 • 架構設計可以使用許多不同模型中的一種或多種來表示。 • 結構模型(structural models)表示一個組織程式元件集合的架構。 • 框架模型(framework models)藉由嘗試在所碰到類似型態的應用程式中,辨識可重複的架構設計框架,以增進設計抽象化的程度。 • 動態模型(dynamic models)針對程式架構的行為面向,指出結構或系統組態可能如何改變作為外部事件的功能。 • 處理模型(process models)聚焦於系統所必須調適的商業或系統流程的設計。 • 功能模型(functional models)可使用於表示系統功能的階層。
9.3.3 模式 • Brad Appleton以下列的方法定義設計模式(design pattern): • 「模式被稱為具有洞察力的珍品,它對於某個特定環境中不斷發生的問題傳達已經證明過的解決方案的本質[APP98]。」 • 設計模式描述設計結構,以解決特定環境中的特定設計問題,和對模式應用與使用的方法中帶來衝擊的「支配力」。 「每個模式描述一個在我們的環境中一再地發生的問題,然後描述對此問題的解決方案核心,用這種方式你可以使用此一解決方案超過百萬次以上,而不必用相同的方法做兩次。」Christopher Alexander
設計模式的意圖 • 每個設計模式的意圖是提供描述,使設計者能決定: • 模式是否可應用於目前的工作 • 模式是否能重複使用(因此節省設計時間) • 模式是否可以做為發展類似、但功能上或結構上不同的模式指導。
9.3.4 模組性 • 軟體架構與設計模式使模組性(modularity)更為具體化;即軟體被區分為個別的命名與可定址的元件,有時稱為模組(modules),以整合滿足問題的需求。 • 「模組性是軟體的單一屬性,以使程式在理智上是可管理的。 • 單體的(monolithic)軟體(即一個大程式是由單一個模組所組成)無法由軟體工程師輕易地掌握。 • 控制路徑的數量、參照的跨度(span)、變數的數量和整體的複雜度將連瞭解都成為不可能。
分割與克服(divide and conquer) • 當你將複雜的問題分割成為可管理的部分時,問題就比較容易地解決。 • 這對模組性與軟體有重要的意涵。 • 可能的結論是,如果我們沒有明確地細分軟體,發展所需的投入將會變成可忽略的少! • 不幸的,其他的力量因此進入,造成此一無效的(悲傷地)結果。
模組數與投入曲線 • 發展個別的軟體模組的投入(成本)確實會因模組總數的增加而減少。 • 給定相同的需求集合,更多的模組意味著較小的個別規模。 • 當模組的數目成長時,與整合模組結合的投入(成本)也會成長。 • 這些特性導出總成本或投入曲線,如圖9.2所示。
最佳模組數 • 有一數目為M的模組將會有最低的發展成本,但是我們沒有必要保證預測出M。 • 當考慮模組性時,如圖9.2所顯示的曲線確實提供有用的指導。 • 我們應該模組化,但是應該小心地處於M的附近。 • 模組性不足(undermodularity)或過度模組性(overmodularity)都應該避免。 • 我們如何知道在M的附近呢? • 我們應該如何以模組來發展軟體呢?
模組化的好處 • 模組化一個設計(並做為結果的程式)的好處 • 發展可以更容易地計畫; • 軟體增量可以被定義與遞交; • 改變可以更容易地調適; • 測試與除錯可更有效率的導入,並且長期的維護將被導入而沒有嚴重的副作用。
9.3.5 資訊隱藏 • 模組性的概念引導每位軟體設計者面對一個基本問題: • 我們如何分解軟體的解決方案而獲得最佳模組的集合? • 資訊隱藏 (information hiding)的原則建議模組是「藉由設計決定對所有其他都是隱匿的(每一個)而描繪出其特性」。 • 模組應該被指明與設計,以使包含在某個模組裡的資訊(演算法與資料)對其他不需要此資訊的模組是難以存取的。
資訊隱藏的益處 • 隱藏意味著有效的模組性可藉由定義一組獨立模組,它與另一個只有資訊需求的模組相互通訊,以達成軟體的功能。 • 抽象化協助定義組成軟體程序的(或資訊的)實體。 • 隱藏模組內的程序細節和由模組所使用的任何局部資料結構,定義並實施存取的限制。 • 當在測試或稍後的期間中必須要修改時,為模組化系統而使用資訊隱藏做為設計的準則,將可以提供最大的利益。 • 因為大部份的資料與程序對軟體的其他部分都是隱藏的,所以在修改期間因為漫不經心所引起的錯誤,比較沒有可能會漫延到軟體其他的地方。
9.3.6 功能獨立 • 功能獨立(functional independence)的概念是模組化、抽象概念和資訊隱藏的直接結果。 • 功能獨立是藉由「專一的(single-minded)」功能和「厭惡(aversion)」與其他的模組極度的互動所發展出的模組而達成。 • 我們要設計軟體以使每個模組針對某個特定需求的子功能(subfunction),並且由程式結構的其他部分,有個可用來觀看的簡單介面。 • 質問獨立性為什麼那麼重要是很公平的。
有效模組性與功能獨立 • 具有有效模組性的軟體(即獨立的模組)因其功能可被劃分,且介面也被簡化(當由團隊導入發展時,要考慮其分歧),因此較為容易發展。 • 獨立模組是比較容易維護(與測試),因為由設計或程式碼修改所造成的次要影響是有限的、錯誤傳播也會降低,且可重複使用的模組成為可能。
評估獨立性的性質 • 功能獨立是良好設計的關鍵,而設計是軟體品質的關鍵。 • 獨立性使用兩個質性的(qualitative)標準評估:凝聚(cohesion)與耦合(coupling)。 • 凝聚是一個模組相對功能強度的象徵。 • 耦合是在模組之間相對的相互依賴(interdependence)的象徵。
凝聚與耦合 • 凝聚是資訊隱藏概念的自然擴展。 • 一個凝聚的模組實行單一任務,對程式的其他部分只需要與其他的元件有很少的互動。 • 一個凝聚的模組應該(理想上)只做一件事情。 • 耦合是在軟體結構中模組之間相互連接的指示。 • 耦合依賴模組之間的介面複雜度、設計給模組的進入或參照點,和跨越介面所傳遞的資料。 • 在軟體設計中,我們努力將可能的耦合降到最低。 • 在軟體模組間簡單的連接會較為容易瞭解,並減少易於造成某個位置的錯誤發生與傳遍整個系統的「漣波效應(ripple effect)」。