軟件工程
一、軟件工程基礎知識
1. 軟件的生存周期
(1)可行性分析與項目開發計劃。這個階段主要確定軟件的開發目標及其可行性。參與該階段的人員有用戶、項目負責人、系統分析師。產生的文檔有 可行性分析報告、項目開發計劃。
(2)需求分析。該階段的任務不是具體的解決問題,而是要確定軟件系統要做什么,確定軟件系統的功能、性能、數據和界面等要求,從而確定系統的邏輯模型。參與該階段的人員有用戶、項目負責人、系統分析師。產生的文檔主要是 軟件需求說明書。
(3)概要設計。該階段開發人員把確定的各項功能需求轉換成需要的體系結構。概要設計就是設計軟件的結構,明確軟件由哪些模塊組成,這些模塊層次結構是怎樣的,調用關系是怎樣的,每個模塊的功能是什么。參與該階段的人員有系統分析師、軟件設計師。產生的文檔主要是 概要設計說明書。
(4)詳細設計。該階段的主要任務是對每個模塊的功能進一步詳細、具體的描述。參與該階段的人員有軟件設計師、程序員。產生的文檔主要是 詳細設計文檔。
(5)編碼。把每個模塊的控制結構轉換成計算機可接受的程序代碼,即寫成某種特定程序設計語言表示的 源程序 清單。
(6)測試。測試是保證軟件質量的重要手段。參加測試的人員通常是另一部門(或單位)的軟件設計師或系統分析師。產生的文檔主要是 軟件測試計劃、測試用例、測試報告。
(7)維護。軟件維護是軟件生存周期中時間最長的階段。軟件已交付且正式投入使用后,便進入維護階段。對軟件進行修改的原因包括:①運行中發現隱含的錯誤而需要修改;②為了適應變化的(或變化后的)工作環境而修改;③需要對軟件功能進行擴充、增強而進行的修改;④為將來軟件維護活動做預先準備。
2. 軟件過程
1.能力成熟度模型(CMM)
能力等級 | 特點 | 關鍵過程區域(KPAs) |
---|---|---|
初始級 | 過程不可預測、缺乏控制,依賴個人能力。 | |
可重復級 | 基本項目管理能力建立,可跟蹤成本、進度和功能。 | 需求管理、項目計劃、項目跟蹤與監督、配置管理、質量保證、子合同管理。 |
已定義級 | 過程標準化、文檔化,組織級一致性增強。 | 同行評審、組間協調、軟件產品工程、集成軟件管理、培訓大綱、組織過程定義、組織過程集點 |
定量管理級 | 過程可量化控制,質量與性能可預測。 | 定量過程管理、軟件質量管理。 |
優化級 | 持續改進,缺陷預防與技術創新。 | 過程變更管理、技術變更管理、缺陷預防。 |
2.能力成熟度模型集成(CMMI)
CMMI提供了兩種表示方法:階段式模型和連續式模型。
(1)階段式模型。結構類似于CMM,它關注組織的成熟度。CMMI-SE/SW/IPPD 1.1版本中有五個成熟度等級。
(2)連續式模型。關注每個過程域的能力,一個組織對不同的過程域可以達到不同的過程域能力等級(簡稱CL)。CMMI中包括六個過程域能力等級。
二、軟件開發模型
1. 瀑布模型與V模型
瀑布模型
瀑布模型將軟件生命周期中的各個活動規定為依據線性順序連接的若干階段的模型,包括需求分析、設計、編碼、測試、運行與維護。如同瀑布流水逐級下落,如圖所示。
以文檔作為驅動、適合于軟件需求很明確的軟件項目,或者二次開發(需求穩定)
缺點:必須完整、正確和清晰地表達需要
V模型
瀑布模型的一個變體是V模型
V模型特點是增加了很多輪測試,并且這些測試貫穿于軟件開發的各個階段,不像其他模型都是軟件開發完再測試,很大程度上保證了項目的準確性。V模型開發和測試級別對應如下圖:
2. 演化模型(原型模型和螺旋模型)
演化模型是迭代的過程模型,使得軟件開發人員能夠逐步開發出更完整的軟件版本。演化模型特別適用于對軟件需求缺乏準確認識的情況。
原型
與瀑布模型相反,原型 針對的就是需求不明確的情況,首先快速構造一個功能模型,演示給用戶看,并按用戶要求及時修改,中間再通過不斷的演示與用戶溝通,最終設計出項目,就不會出現與用戶要求不符合的情況,采用的是迭代的思想。不適合超大項目開發。
原型模型又根據使用目的的不同,分為探索型原型、實驗型原型和演化型原型。
探索型原型用于快速驗證需求或概念的可行性,通常出現在項目早期階段。這類原型聚焦于核心功能或用戶痛點的模擬,忽略細節實現,幫助團隊明確方向。
實驗型原型針對特定技術或設計假設進行驗證,例如性能測試、算法可行性或新材料應用。通過可控實驗收集數據,為決策提供依據。
演化型原型以迭代方式逐步完善,最終形成正式產品。每個版本在用戶反饋和技術優化的基礎上持續改進,常見于敏捷開發或MVP策略。
螺旋模型
螺旋模型將瀑布模型和演化模型結合起來,增加了風險分析,特別適用于龐大、復雜并且具有高風險的系統。
需要開發人員具有相當豐富的風險評估經驗和專門知識。
3. 增量模型
增量模型:首先開發核心模塊功能,而后與用戶確認,之后再開發次核心模塊的功能,即每次開發一部分功能,并與用戶需求確認,最終完成項目開發,優先級最高的服務最先交付,但由于并不是從系統整體角度規劃各個模塊,因此不利于模塊劃分。難點在于如何將客戶需求劃分為多個增量。與原型不用的是增量模型的每一次增量版本都可作為獨立可操作的作品,而原型的構造一般是為了演示。
4. 噴泉模型
噴泉模型是以用戶需求為動力、以對象為驅動的模型。適用于面向對象的開發方法,克服了瀑布模型不支持軟件重用和多項開發活動集成的局限性。噴泉模型使開發過程具有迭代性和無間隙性。
缺點:需要大量的開發人員,要求嚴格管理文檔。
5.統一過程(UP)模型
統一過程(UP)模型是一種“用例和風險驅動,以架構為中心,迭代并增量”的開發過程,由UML方法和工具支持。
統一過程的典型代表是RUP,RUP是UP的商業擴展,完全兼容UP,比UP更完整、更詳細。
6.敏捷方法
敏捷方法的總體目標是通過“盡可能早地、持續地對有價值的軟件進行交付”使客戶滿意。適用于:適合小項目小團隊,“小步快跑”的思想。
敏捷方法的核心思想主要有以下三點:
①敏捷方法是“適應性”而非“預設性”的。
②敏捷方法是以人為本,而不是以過程為本。
③迭代增量式的開發過程。敏捷方法以原型開發思想為基礎,采用迭代增量式開發,發行版本小型化。RUP相比,敏捷方法的周期可能更短。敏捷方法在幾周或者幾個月的時間內完成相對較小的功能,強調的是能盡早將盡量小的可用的功能交付使用,并在整個項目周期中持續改善和增強,并且更加強調團隊中的高度寫作。
**敏捷軟件開發宣言:**相對于過程和工具,更強調個人和交互;相對于嚴格的文檔,更重視可工作的軟件;相對于合同談判,更注重與客戶的合作;相對于遵循計劃,更專注于對變化的響應。
常用的方法:極限編程(XP)、水晶法(Crystal)、并列爭球法(Scrum)、自適應軟件開發(ASD)、敏捷統一過程(AUP)。
極限編程(XP)
因為知道計劃永遠趕不上變化,XP 無需開發人員在軟件開始初期做出很多的文檔。XP提倡 測試先行,為了將以后出現bug的幾率降到最低。
三、軟件開發方法
四、需求分析
一個好的需求應該具有無二義性、完整性、一致性、可測試性、確定性、可跟蹤性、正確性、必要性等特性。
需求分析階段的產物:軟件需求規格說明書(SRS)
1. 結構化的需求分析
結構化特點:自頂向下,逐步分解。
面向數據三大模型:功能模型(數據流圖)、行為模型(狀態轉換圖)、數據模型(E-R圖)以及數據字典
2. 需求分類
3. 需求分析工具
數據流圖(DFD)
DFD的基本圖形元素:外部實體、加工、數據存儲、數據流。
層次結構:頂層圖、0層圖、底層圖、父圖、子圖。
DFD的審查
(1)一致性:父圖與子圖平衡、數據守恒、具備數據存儲、輸出不能與輸入同名。
(2)完整性:奇跡(無入有出)、黑洞(有入無出)、灰洞(無法出)。
數據字典(DD)
數據字典有以下4類條目:數據流、數據項、數據存儲和基本加工。(源點和終點不再系統之內,不在字典中說明)
邏輯描述方法
常用的加工邏輯描述方法有結構化語言、判定表和判定樹3種。
- 結構化語言采用接近自然語言的格式,但通過限制詞匯和句式確保邏輯清晰。通常分為順序、選擇(IF-THEN-ELSE)和循環(WHILE-DO)三種結構,適合描述具有明確步驟或分支的業務規則。
- 判定表通過表格形式列舉所有條件組合及對應動作,適用于條件復雜且存在多分支的場景。表格分為條件樁(條件列表)、動作樁(動作列表)和規則(條件與動作的映射)。
- 判定樹以樹形結構展示條件與動作的層級關系,直觀呈現邏輯分支路徑。節點表示條件,分支表示條件取值,葉子節點表示動作,適合可視化復雜決策過程。
五、系統設計
進入設計階段,要把軟件“做什么”的邏輯模型轉換成 “怎么做” 的物理模型。
**系統設計的主要內容包括:**新系統總體結構設計、代碼設計、輸出設計、輸入設計、處理過程設計、數據存儲設計、用戶界面設計和安全控制設計等。
常用的設計方法有:面向數據流的結構化設計方法(SD)、面向對象的分析方法(OOD)。
系統設計基本原理
- 抽象化;
- 自頂而下,逐步求精;
- 信息隱蔽;
- 模塊獨立(高內聚,低耦合)。
系統設計包括兩個基本的步驟:概要設計、詳細設計。
1.概要設計
概要設計基本任務:設計軟件系統總體結構、數據結構及數據庫設計、編寫概要設計文檔(概要設計說明書、數據庫設計說明書、用戶手冊及修訂測試計劃)、評審
2.詳細設計
詳細設計的基本任務:模塊內詳細算法設計、模塊內數據結構設計、數據庫的物理設計、其他設計(代碼、輸入/輸出格式、用戶界面)、編寫詳細設計說明書、評審。
3. 模塊設計
- 保持模塊的大小適中;
- 盡可能減少調用的深度;
- 多扇入,少扇出;
- 單入口,單出口;
- 模塊的作用域應該在模塊之內;
- 功能應該是可預測的。
模塊的設計要求獨立性高,就必須 高內聚,低耦合
(1). 內聚是指一個模塊內部功能之間的相關性。
內聚類型 | 描述 | 示例 |
---|---|---|
偶然內聚(偶然內聚) | 模塊內元素無邏輯關聯,僅因巧合被分組 | 將打印日志、驗證輸入等無關功能放入同一模塊 |
邏輯內聚 | 通過參數控制執行不同但邏輯相似的操作 | 一個"數據處理"模塊根據參數選擇排序或搜索 |
時間內聚(瞬時內聚) | 元素在相同時間段執行(如初始化/關閉模塊) | 系統啟動時同時加載配置、建立數據庫連接 |
過程內聚 | 按特定過程順序執行相關操作 | 用戶注冊流程:驗證輸入→保存數據→發送確認郵件 |
通信內聚 | 操作相同數據集但無嚴格執行順序 | 報表生成模塊:讀取數據→計算統計量→格式化輸出 |
順序內聚 | 前一個操作的輸出是后一個操作的輸入 | 流水線處理:圖像解碼→濾鏡處理→壓縮 |
功能內聚 | 所有元素協同完成單一明確功能 | 加密模塊僅實現AES算法 |
(2). 耦合是指多個模塊之間的聯系
耦合類型 | 描述 | 典型場景 |
---|---|---|
非直接耦合 | 模塊之間不直接交互,而是通過中間媒介傳遞信息 | 如消息隊列、事件總線、共享數據庫等 |
數據耦合 | 模塊間通過參數傳遞基本數據類型,依賴度最低 | 函數調用時傳遞整數、字符串等簡單數據 |
標記耦合 | 模塊間通過傳遞數據結構(如記錄、對象),但只使用其中部分字段 | 傳遞結構體但僅讀取特定成員變量 |
控制耦合 | 一個模塊通過控制信號(如標志位)直接影響另一個模塊的執行邏輯 | 通過布爾參數控制函數內部分支選擇 |
外部耦合 | 模塊依賴共同的外部環境(如全局變量、共享文件) | 多個模塊讀寫同一配置文件或數據庫表 |
公共耦合 | 多個模塊共享同一全局數據結構,任一模塊修改會影響其他模塊 | 多個類方法直接操作同一靜態變量 |
內容耦合 | 一個模塊直接訪問另一個模塊的內部數據;一個模塊不通過正常入口轉到另一個模塊的內部;兩個模塊有一部分程序代碼重疊;一個塊有多個入口 | 繞過接口直接訪問另一模塊的私有成員 |
4.人機界面設計
人機界面設計的三大原則:置于用戶控制之下、減少用戶的記憶負擔、保持界面的一致性。
置于用戶的控制之下
- 以不強迫用戶進入不必要的或不希望的動作的方式來定義交互方式提供靈活的交互;
- 允許用戶交互可以被中斷和取消;
- 當技能級別增加時可以使交互流水化并允許定制交互;使用戶隔離內部技術細節;
- 設計應允許用戶和出現在屏幕上的對象直接交互。
減少用戶的記憶負擔
- 減少對短期記憶的要求; 建立有意義的缺省;
- 定義直覺性的捷徑;
- 界面的視覺布局應該基于真實世界的隱喻;
- 以不斷進展的方式揭示信息。
保持界面的一致性
- 允許用戶將當前任務放入有意義的語境
- 在應用系列內保持一致性
- 如過去的交互模型已建立起了用戶期望,除非有迫不得已的理由,不要去改變它。
5.架構設計
架構設計的一個核心問題是能否達到架構級的軟件復用。
架構風格反映了領域中眾多系統所共有的結構和語義特性,并指導如何將各個構件有效地組織成一個完整的系統。
架構風格定義了用于描述系統的術語表和一組指導構建系統的規則。5大基本架構風格:
(1) 數據流風格
批處理序列: 構件為一系列固定順序的計算單元,構件之間只通過數據傳遞交互。每個處理步驟是一個獨立的程序,每一步必須在其前一步結束后才能開始,數據必須是完整的,以整體的方式傳遞,
管道-過濾器:每個構件都有一組輸入和輸出,構件讀取輸入的數據流,經過內部處理,產生輸出數據流。前一個構件的輸出作為后一個構件的輸入,前后數據流關聯。過濾器就是構件,連接件就是管道。Unix命令行工具是經典案例。
(2) 調用/返回風格
主程序/子程序:基于分層調用,主程序協調子程序完成功能。C語言中的main()
函數調用庫函數是典型例子。
面向對象:通過對象封裝數據和行為,利用繼承和多態實現復用。Java或C++中的類與對象交互是核心體現。
層次結構:
- MVC(Model-View-Controller):分離數據(Model)、顯示(View)和控制邏輯(Controller),常見于Web框架(如Django)。
- C/S(Client-Server):客戶端請求服務,服務器響應,如HTTP協議。
- B/S(Browser-Server):基于Web的C/S變體,瀏覽器作為通用客戶端。
(3) 獨立構件風格
進程通信:構件通過消息傳遞(如RPC、消息隊列)交互,微服務架構是典型應用。
事件驅動系統:構件通過事件隱式觸發(如發布-訂閱模式)。GUI框架(如Node.js的事件循環)依賴此風格。
(4) 虛擬機風格
解釋器:通過解釋執行中間代碼(如Python解釋器處理字節碼)。
基于規則的系統:規則引擎(如Drools)按條件-動作規則執行,適用于專家系統。
(5) 倉庫風格
數據庫系統:以數據為中心,通過事務和查詢語言(如SQL)管理數據。
超文本系統:非線性的信息鏈接(如Web頁面通過超鏈接關聯)。
黑板系統:多個構件通過共享的“黑板”協作解決問題,常見于AI領域(如語音識別系統)。
六、軟件測試
1. 測試基礎
測試應遵循的基本原則:
- 應盡早并不斷的進行測試;
- 測試工作應該避免由元開發軟件的人或小組承擔;
- 在設計測試方案時,不僅要確定輸入數據,而且要根據系統功能確定預期的輸出結果
- 既包含有效、合理的測試用例,也包含不合理、失效的用例;
- 檢驗程序是否做了該做的事,且是否做了不該做的事;
- 嚴格按照測試計劃進行;
- 妥善保存測試計劃和測試用例:
- 測試用例可以重復使用或追加測試
- 修改后應進行回歸測試
- 尚未發現的錯誤數量與該程序已發現錯誤數成正比
軟件測試分為靜態測試和動態測試。
(1)靜態測試: 被測程序不在機器上運行,采用人工檢測和計算機輔助靜態分析的手段對程序進行測試,包括人工檢測、計算機輔助靜態分析。
桌前檢查:程序員檢查自己編寫的程序,在程序編譯后,單元測試前。
代碼審查:由若干個程序員和測試人員組成評審小組,通過召開程序評審會來進行審查。
代碼走查:也是采用開會來對代碼進行審查,但并非簡單的檢查代碼,而是由測試人員提供測試用例,讓程序員扮演計算機的角色,手動運行測試用例,檢查代碼邏輯。
(2)動態測試: 通過運行程序發現錯誤,一般采用黑盒測試和白盒測試。
1)**黑盒測試:**也稱功能測試,在不考慮軟件內部結構和特性的情況下,測試軟件的外部特性。
2)**白盒測試:**也稱結構測試,根據程序的內部結構和邏輯來設計測試用例,對程序的路徑和過程進行測試,檢查是否滿足設計的需要。
3)灰盒測試法:即既有黑盒,也有白盒。
2. 黑盒測試
黑盒測試用例: 將程序看做一個黑盒子,只知道輸入輸出,不知道內部代碼,由此設計出測試用例。
分為下面幾類:
等價類劃分: 把所有的數據按照某種特性進行歸類,而后在每類的數據里選取一個即可。
等價類測試用例的設計原則: 設計一個新的測試用例,使其盡可能多地覆蓋尚未被覆蓋的有效等價類,重復這一步,直到所有的有效等價類都被覆蓋為止;設計一個新的測試用例,使其僅覆蓋一個尚未被覆蓋的無效等價類,重復這一步,直到所有的無效等價類都被覆蓋為止。
邊界值劃分: 將每類的邊界值作為測試用例,邊界值一般為范圍的兩端值以及在此范圍之外的與此范圍間隔最小的兩個值,如年齡范圍為 0-150,邊界值為0,150,-1,151四個。
錯誤推測:沒有固定的方法,憑經驗而言,來推測有可能產生問題的地方,作為測試用例進行測試。
因果圖:由一個結果來反推原因的方法,具體結果具體分析,沒有固定方法。
3. 白盒測試
測試類型 | 定義 | 特點 |
---|---|---|
語句覆蓋 | 確保程序的每條語句至少執行一次。 | 簡單易實現,但無法檢測邏輯錯誤或未執行的代碼分支。 |
判定覆蓋(分支覆蓋) | 確保每個條件語句的真假分支均被測試。 | 比語句覆蓋更嚴格,能發現更多邏輯問題,但可能遺漏復雜條件組合。 |
條件覆蓋 | 確保每個條件的真假值均被獨立測試。 | 覆蓋更細粒度,但可能忽略條件間的依賴關系。 |
條件組合覆蓋 | 每個判定中的各種可能值的組合都至少出現一次。 | 同時滿足判定覆蓋、條件覆蓋、判定/條件覆蓋。 |
路徑覆蓋 | 測試所有可能的執行路徑(包括循環和嵌套分支)。 | 覆蓋最全面,但實現復雜且成本高,適合關鍵代碼段。 |
循環覆蓋 | 專門測試循環結構的邊界條件(如零次、一次、多次迭代)。 | 針對循環結構設計,能發現邊界值錯誤。 |
4. 測試階段
(1)單元測試:也稱為模塊測試,測試的對象是可獨立編譯或匯編的程序模塊、軟件構件或OO軟件中的類(統稱為模塊),測試依據是軟件詳細設計說明書。
(2)集成測試:目的是檢查模塊之間,以及模塊和已集成的軟件之間的接口關系,并驗證已集成的軟件是否符合設計要求。測試依據是軟件概要設計文檔。(自頂向下、自底向上、三明治)
(3)確認測試:主要用于驗證軟件的功能、性能和其他特性是否與用戶需求一致。根據用戶的參與程度,通常包括以下類型:
- 內部確認測試:主要由軟件開發組織內部按照 SRS進行測試。
- Alpha 測試:用戶在開發環境下進行測試。
- Beta測試:用戶在實際使用環境下進行測試,通過改測試后,產品才能交付用戶。
- 驗收測試:針對 SRS,在交付前以用戶為主進行的測試。其測試對象為完整的、集成的計算機系統。驗收測試的目的是,在真實的用戶工作環境下,檢驗軟件系統是否滿足開發技術合同或SRS。驗收測試的結論是用戶確定是否接收該軟件的主要依據。除應滿足一般測試的準入條件外,在進行驗收測試之前,應確認被測軟件系統已通過系統測試。
(4)系統測試:測試對象是完整的、集成的計算機系統;測試的目的是在真實系統工作環境下,驗證完成的軟件配置項能否和系統正確連接,并滿足系統/子系統設計文檔和軟件開發合同規定的要求。測試依據是用戶需求或開發合同。
主要內容包括功能測試、健壯性測試、性能測試、用戶界面測試、安全性測試、安裝與反安裝測試等,其中,最重要的工作是進行功能測試與性能測試。功能測試主要采用黑盒測試方法;性能測試主要指標有響應時間、吞吐量、并發用戶數和資源利用率等。
(5)配置項測試:測試對象是軟件配置項,測試目的是檢驗軟件配置項與SRS的一致性。測試的依據是 SRS。在此之間,應確認被測軟件配置項已通過單元測試和集成測試。
(6)回歸測試:測試目的是測試軟件變更之后,變更部分的正確性和對變更需求的符合性,以及軟件原有的、正確的功能、性能和其他規定的要求的不損害性。
5. McCabe復雜度計算
計算有向圖G的環路復雜度公式為:V(G)=m-n+20
有向圖中有向邊數為m,節點數為n。
對一個程序流程圖,每一個分支邊(連線)就是一條有向邊,每一條語句(語句框)就是一個頂點。