## Ch1 Basic Introduction to Software Engineering - 軟體分為三種類型 - Type C:Casual(隨意型) - Type B:Business(商業型) - Type A:Acute(嚴苛型) ### Casual Systems(Type C) - 最常見的小型系統 - 通常由1~2位開發者完成 - 可能有暫時性錯誤 - e.g.學校作業 ### Business Systems(Type B) - 對企業運作極為重要 - 若無良好設計與維護,會從資產變成負債 - 能夠透過軟體工程受益 ### Acute Systems(Type A) - 關鍵任務型系統,任何錯誤都會造成巨大代價(人命或金錢) - 超出本課程範圍 ### SWEBOK(Software Engineering Body of Knowledge) - 收錄軟體工程的核心知識,由ISO/IEC制定標準化指南 - 目的:提供系統化的學習與專業依據 - 分成: 1.Requirements 2.Design 3.Construct 4.Maintain 5.Refactor 6.Project manager #### Requirements ==會考== - 系統為滿足客戶需求所必須的功能,包含服務品質屬性(QoS, Quality of Service) - **功能需求(Functional Requirements)**:系統應該**做什麼**(What),明確描述功能 - **非功能需求(Non Functional Requirements)**:系統該**如何運作**(How),描述產品屬性 - e.g.Performance, Availability, Capacity, Fault tolerance, Security, Privacy, Interoperability, Maintainability, Usability - 需求常常變更,而且客戶通常不知道自己想要什麼 #### Design - 決定軟體系統主要程式單元(modules)的過程 - 著重於介面的設計,不關注方法的具體實作 - Abstraction:只有一小部分是公開、可見的(public),大部分細節會被隱藏(private) #### Construction - 軟體開發的實作階段,實際編寫程式的過程 - 避免過度設計,使用太多不必要的專業技術 #### Testing - 確認軟體在特定測資下能否得到預期的結果 - **Unit Testing(單元測試)** - 測試小而獨立的程式單位(例如函式或類別) - 驗證邏輯的正確性 - 執行速度快、容易除錯,提供開發者即時回饋 - **Integration Testing(整合測試)** - 測試多個模組間的互動,例如 API 與資料庫 - 確保模組整合後能正確協同運作 - 偵測介面不匹配、整合錯誤與資料流問題 - **End-to-End Testing(端到端測試)** - 從使用者角度測試整體系統 - 驗證完整流程與業務邏輯 - 確認系統在實際情境中符合期望   ### Maintenance - Corrective:修正系統錯誤或缺陷 - Preventive:改進結構以防未來問題 - Adaptive:調整系統以因應環境變更(新硬體、OS) - Evolutionary:擴充功能以滿足新需求 - Refactoring:重構現有程式以改善可讀性與效能 ### Refactoring - 在不改變外部行為的前提下,重新整理內部結構,以提高可讀性、維護性與效能 - Legacy Systems(舊系統) - 使用舊技術(舊語言、舊作業系統、舊資料庫)的系統 - 維護成本高、風險大,但並非無用 ### Processes - 開發軟體時應遵循的活動,分為兩大類: - **瀑布式(Waterfall)**  - 優點: - 結構清晰、易於管理 - 里程碑明確 - 缺點: - 缺乏彈性 - 客戶回饋太晚 - 最後階段才有成品可測 - **敏捷式(Agile)**  - 特性: - **合作與溝通(Collaboration and Communication)** - **彈性與適應性(Flexibility and Adaptability)** - **持續改進(Continuous Improvement)** - 優點: - 高彈性,可隨時調整需求 - 客戶持續參與,確保方向正確 - 缺點: - 難以預測進度與預算 - 容易產生範圍膨脹(Scope Creep) - 不適合大型或法規嚴格的專案 - 造成軟體困難的原因: - **複雜性(Complexity)** - **多樣性與從屬性(Conformity)** - **易變性(Ease of Change)** - **不可見性(Invisibility)** ## Ch2 Process - 一系列步驟,包含輸入、限制條件、資源,最後產生輸出 - 軟體開發流程:有結構的活動,用來開發一個軟體系統,所有流程都包含以下核心活動: - **Requirements Specification**:定義系統應該做什麼 - **Design and Implementation**:系統架構與實際實作 - **Verification & Validation**:驗證系統是否正確、是否符合客戶需求 - **Evolution**:依據使用者需求變更持續改進系統  - **軟體開發流程模型**(development process model):一種流程的抽象表示,提供結構化、簡化的觀點,用來說明理想的開發順序(A simplified, abstract view of how development should proceed) ==會考== - 包含以下元素: - Activities:組成流程的各種活動(例如分析、設計、測試) - Products:每個活動的成果(例如需求文件、程式、測試報告) - Roles:負責活動的人員與職責(如開發者、測試者、PM) - Pre- & Post-conditions:在活動執行前後必須成立的條件(如文件審核通過後才能進下一步) - 可以用圖形化的方式來呈現: - Directd Graph(有向圖):以節點和邊組成 - 優點:簡單、直觀 - 缺點:細節表達能力有限  - UML Activity Diagram: - 一種標準化圖形表示法 - 可顯示活動、決策、與平行流程 - 廣泛應用於軟體工程中  - BPMN(Business Process Model and Notation): - 商業流程模型與標註 - 描述業務流程的標準 - 具有豐富的符號表示事件、閘道、訊息等 - 協助業務與資訊技術間的協調  - Gantt Chart(甘特圖) - 一種時間軸圖表表示法 - 條狀圖顯示任務的持續時間與排程 - 用於專案管理與進度追蹤 - 小型專案:Code & Fix model - 優點:低負擔、適用於小型專案 - 缺陷:修復成本會越來越高、沒有需求分析與設計階段、可能與使用者需求不符   - 大型專案:BDUF(Big Design Upfront):在寫程式前先把整個系統規劃好 1. **Waterfall Model**:==(會考)== 有兩項改進:  - **回饋循環**(Feedback loops): - 問題:跨階段回饋會導致高昂的返工成本 - 改進:僅允許相鄰階段之間的回饋 - 優點:減少錯誤傳遞、降低返工成本 - **原型製作**(Prototyping): - 概念:做兩次 - 第一次快速建立原型,第二次根據驗證後的結果開發系統 - 目的:驗證需求與設計是否正確、降低理解錯誤的風險 - 六種文件:功能是知識傳遞、團隊溝通、為未來維護奠基 1. 需求規格書 2. 系統設計文件 3. 模組設計文件 4. 測試計畫 5. 測試報告 6. 維護手冊 - 優點: - 結構簡單、容易管理 - 可預測性高,里程碑明確 - 缺點: - 缺乏彈性:後期發現問題時難以修正 - 回饋延遲:使用者意見通常只在初期收集 - 成品晚出:要到後期才能看到可運作的軟體 - Waterfall 失敗原因:**複雜性(Complexity)、從屬性(Conformity)、易變性(Ease of Change)、不可見性(Invisibility)** 1. 需求:功能空間是無限且難以預測的 2. 過度文件化:文件通常冗長且實用性有限、實作階段很少真正被使用 2. **Prototyping Process Model**: ==會考== - **適用於客戶沒有提供具體需求**,開發者不確定演算法效率、系統適應性、人機互動設計  - 分成五階段: 1. **Communication**:定義目標,確認已知需求,找出不確定區域 2. **Quick Design**:專注於可見面向 3. **Prototype Construction**:建立初步版本 4. **Evaluation**:讓客戶測試並提供回饋 5. **Iteration**:依回饋調整需求與原型 - 問題: - 客戶誤以為原型就是最終系統 - 架構缺乏品質或可維護性 - 開發者為了加快速度偷工減料,導致長期結構不佳 - 優點: - 減少需求變更的影響 - 早期且頻繁地讓客戶參與 - 適用於小型專案 - 降低產品被拒收的風險 - 缺點: - 客戶頻繁參與可能造成進度延遲 - 原型可能被誤當成正式產品釋出 - 拋棄式原型造成工作浪費 - 難以規劃與管理整體進度 3. **Spiral Process Model**: - 以螺旋路徑前進:每一圈都是一次迭代,逐步接近最終目標  - 軟體以演化式版本(evolutionary releases)發展: - 早期迭代:建立模型或原型 - 後期迭代:製作完整的工程化版本 - 分成四階段: - Planning:本回合要建構什麼? - **Risk Analysis**:可能出什麼錯?如何避免? - Development:建立部分系統 - Evaluation:測試、收集回饋、準備下一輪 - 可以先交付有限版本,之後再逐步改進 - 挑戰:難以說服客戶是可控的,難以評估與管理風險 - 優點: - 持續的客戶參與 - 系統性地管理風險 - 適合大型且複雜的專案 - 適用於可擴充產品 - 缺點: - 若風險分析失敗,專案可能直接失敗 - 整體流程難以管理 - 需要具備專業的開發團隊  4. **Unified Process Model**:採用迭代式與漸進式開發  - 分成四階段: 1. **Inception**(構想階段): - 與客戶溝通與規劃、定義需求 - 透過初步的使用案例描述主要功能 - 辨識資源、評估主要風險、訂定初步時程 2. **Elaboration**(精化階段): - 細化需求與模型、根據需求持續更新與修改計畫 - 以五個視角建立系統的架構基準: 1. Use Case Model(使用案例模型) 2. Analysis Model(分析模型) 3. Design Model(設計模型) 4. Implementation Model(實作模型) 5. Deployment Model(部署模型) 3. **Construction**(建構階段): - 實作該版本所需功能 - 撰寫原始程式碼 - 為每個元件進行單元測試 - 依照使用案例進行整合與驗收測試 4. **Transition**(移交階段): - 進行交付與回饋 - 軟體與文件釋出以進行 Beta 測試 - 收集使用者回饋:包括缺陷與修改需求 - 最終成果:可使用的軟體版本 - **Production Phase**(正式運作階段): - 軟體的部署與長期使用 - 監控使用情況與環境支援 - 處理缺陷回報與變更請求 - 特性: - 早期回饋:使用者可在早期迭代中就對原型提供意見 - 架構為中心:著重於建立穩定的軟體架構,以預防後期結構性問題 - 使用案例驅動:開發過程以使用者需求為導向,確保最終產品符合實際需求 - 複雜性管理:漸進式開發讓團隊能將大型系統拆解成較小、可管理的部分 - 需要有經驗的團隊: - Iterative and overlapping phases:需要強大的專案管理能力 - Architecture-centric:需具備穩健的設計專業 - Use-case driven:需精確進行需求分析 - Cross-role collaboration:各職能間的合作需嚴謹紀律與溝通 - Incremental integration:持續整合與版本控制極為重要 - 優點: - 強調文件品質與可追蹤性 - 持續的客戶參與 - 對需求變更具有彈性 - 適用於維護性專案 - 缺點: - 使用案例可能不夠精確 - 各增量之間整合困難 - 階段重疊可能造成管理問題 - 需要專業開發團隊 - 進階瀑布模型比較: | 模型名稱 | 原型開發模型(Prototyping Process Model) | 螺旋模型(Spiral Process Model) | 統一流程模型(Unified Process Model) | |-----------|------------------------------------------|----------------------------------|------------------------------------| | **主要概念** | 透過快速建立原型來釐清需求,並在反覆過程中改進 | 在每個循環階段進行風險分析(Risk Analysis)的迭代式開發 | 採用迭代與漸進式開發,分為四大階段(Inception、Elaboration、Construction、Transition) | | **主要目標** | 透過可運作的原型來降低需求不確定性 | 在系統演化過程中系統性地管理風險 | 建立與使用案例、架構、持續用戶回饋一致的軟體 | | **優點** | ・早期即可發現真實用戶需求<br>・鼓勵用戶參與<br>・適用於需求不明確的專案 | ・強大的風險管理能力<br>・適合大型、高風險專案<br>・持續讓利害關係人參與 | ・以架構為中心(Architecture-centric)<br>・以使用案例為導向(Use-case driven)<br>・支援早期回饋與逐步改進 | | **缺點** | ・容易導致需求範圍擴張(scope creep)<br>・用戶可能誤以為原型是最終產品<br>・不適合大型專案的結構化開發 | ・管理複雜度高<br>・需要具備風險分析能力的專業團隊<br>・難以說服客戶其可控性 | ・需要有經驗的開發團隊<br>・案例的精確度可能不足 | | **最適用專案** | 小型到中型、需求尚未明確或持續變動的專案 | 大型、高風險系統,特別是需要嚴格風險管理的情況 | 中型到大型專案,需要明確架構、反覆精化與多方協作 | - **Agile**(敏捷開發):  - 核心概念: - 專注於短週期迭代式開發 - 先從關鍵功能開始、每個週期都新增新功能,並獲得客戶確認 - 當所有優先功能完成時結束開發  - 其他特徵: - 減少對文件的依賴(前期大型設計) - 高度的客戶參與 - 小團隊(5–11 人) - 現代化實務:自動化測試、程式重構、持續整合與部署 - 優點: - 靈活性與適應力:可在任何階段改變需求 - 顧客協作:頻繁的回饋確保產品符合需求 - 缺點: - 可預測性低:難以準確估算時間與成本 - 範圍膨脹風險:靈活性可能導致功能失控成長 - 不適用於所有專案:大型、法規嚴格或範圍固定的專案不適合採用 - 常見方法: 1. **Extreme Programming** (XP)  - 著重於:靈活性、簡單性、客戶滿意度 - 核心價值:溝通、簡單、回饋、勇氣、尊重、可持續的節奏 - 指導原則:經濟性、持續改進、接受失敗、小而穩的步驟、個人責任 - 實作方式: - Pair Programming(結對編程):兩位開發者在同一台電腦共同工作,一人是駕駛員(Driver)負責撰寫程式,一人是導航員(Navigator)負責檢查、思考策略,兩者的角色需定期交換 - Test-Driven Development (TDD):在寫程式前先撰寫測試 - Continuous Integration(持續整合):頻繁整合與測試程式碼 - Refactoring(重構):持續改善程式架構 - Small Releases(小版本發佈):短週期交付可運行版本 - On-site Customer(駐場客戶):團隊中有客戶代表參與 - 外包開發需要簽訂合約,合約類型有: - 固定範圍合約(Closed Scope):客戶定義開發範圍、供應商設定價格與期限 - **協商範圍合約**(Negotiated Scope):依照每人時數(person-hours)計費,每次迭代後重新定義工作範圍與合約 - 優點:鼓勵品質提升、避免被迫交付產品、客戶容易更換供應商 - 缺點:需要客戶高度參與、預算與時程不確定、合約管理成本較高、範圍蔓延風險(Risk of scope creep) 2. **Scrum**  - 核心:短衝週期,通常為期 1 個月以內(常見為 2 週) - 團隊成員: - Product Owner(產品負責人):定義與排序 Product Backlog,代表客戶與利害關係人(例如IT主管)  - Scrum Master(敏捷教練):協助團隊遵守 Scrum 原則,移除非技術性障礙 - Development Team(開發團隊):自我組織,設計、開發與測試產品 - Sprint:團隊實作使用者故事(user stories),由PO負責定義與釐清 - Product Backlog(產品待辦清單): - 集中管理所有使用者故事與工作項目的清單 - 具有優先排序、動態調整兩種特性 - 團隊成員之間地位平等,沒有階級制度(PO不是開發者的主管),開發者有權決定要不要接案 - Sprint結束: - Sprint Review(成果檢視會):向客戶展示功能 - Sprint Retrospective(回顧會):反思並改善 - Definition of Done(DoD):定義故事的完成標準 - Scrum Board:  - 全流程: ==會考==  3. **Kanban**  - 與 Scrum 的差異: - 更簡單、沒有時限 - 角色和會議都是可選的,適合自律的團隊 - Kanban Board  - 成員有空時才拉下任務,完成後再移至下一階段 - Work in Progress (WIP)限制:為每個流程階段設定最大任務數量 | 面向 | **XP** | **Scrum** | **Kanban** | | ------ | ------------------------------- | ------------------------------------ | --------------------------------- | | 核心目標 | 透過**工程實作**確保品質與快速回饋 | 以**固定衝刺**節奏交付可用增量 | 以**拉式流程**與**WIP 限制**優化流動 | | 節奏/時間框 | 可有迭代(1–2 週)但重在**持續整合與回饋** | **時間盒 Sprints**(常見 2 週) | **無時間盒**,**連續流** | | 角色 | 客戶代表、教練、開發者、追蹤者(視團隊而定) | **PO**、**Scrum Master**、**Dev Team** | 無強制角色;可沿用現有組織 | | 核心會議 | 站立會、規劃、回顧;重**客戶現場**溝通 | 每日站會、規劃會、評審會、回顧會 | 依需要進行看板補貨/補拉、改進會 | | 需求單位 | **User Story** + 驗收測試 | **Product Backlog** → Sprint Backlog | **看板卡片**(工作項),可含 Class of Service | | 變更策略 | 擁抱改變;以小步快跑、重構應對 | Sprint 內**避免變更**,Sprint 間調整 | **隨時變更優先順序**,拉到就做 | | WIP 限制 | 非核心,但鼓勵小批量 | 非顯式(以 Sprint 容量間接限制) | **顯式 WIP 限制**(每欄/每泳道) | | 工程實務 | **TDD、結對、持續整合、重構、集體程式所有權、簡單設計** | 未規定工程實務;可搭配 XP 做法 | 未規定工程實務;可搭配 XP 做法 | | 視覺化 | 可用任務牆 | **Sprint 看板** | **流程看板**(明確流程欄位與政策) | | 適用情境 | 高變動、需高品質與快速技術回饋的產品/平台 | 需要**節奏感**與**明確儀式**的產品團隊 | 穩定/服務型流程、維運與多專案併行、追求**流速** | | 優點 | 產品品質高、技術債可控、回饋快 | 節奏穩、對齊好、透明度高 | 變更友善、交付可預測、瓶頸可視化 | | 風險/代價 | 對工程文化要求高;結對/測試初期成本 | 儀式過重或形式化、Sprint 內變更彈性低 | 容易只貼卡不改善;無紀律時 WIP 膨脹 | ## Ch3 Requirements and Specifications ### Software Requirements: - 使用者與開發者之間的橋樑,定義系統該做什麼以及如何表現 - 流程:Define(定義問題) -> Collect(收集需求) -> Specify(撰寫需求文件) -> Validate(確認需求正確) -> Manage(持續追蹤與版本控制) - 需求分為兩類: ==會考== - **Functional Requirements(功能性需求)**: - 定義系統**該做什麼**,描述系統的功能、服務或行為 - **Non-functional Requirements(非功能性需求)**: - 例如**品質需求**:正確性、明確性、完整性、一致性、可驗證性 ### software requirement specification (SRS): - 好的SRS應具備: 1. **Correctness(正確性)**:每一項需求都反映出系統的實際需求 1. **Unambiguity(明確性)**:每個需求只能有一種解釋,使用統一且一致的專業術語 2. **Completeness(完整性)**: - 所有重要的需求都必須被納入 - 定義軟體對所有合法與非法輸入的回應 - 包含完整的參考資料、定義、圖表與術語 3. **Consistency(一致性)**:不能出現互相衝突的需求 4. **Importance Ranking(重要性排序)**:每個需求都應標示其優先級,例如:Essential(必要)、Conditional(條件性)、Optional(可選) 5. **Stability Ranking(穩定性排序)**: - 每個需求都應標示其預期的變動頻率 - 反映該需求因商業或環境因素而變更的可能性 6. **Verifiability(可驗證性)**:每個需求都必須可被測試(有具體標準) 7. **Modifiability(可修改性)**:結構良好、易於更新與維護,每個需求應獨立呈現 8. **Traceability(可追蹤性)**: - Backward traceability(向後追蹤):每個需求都能明確連結到其來源 - Forward traceability(向前追蹤):每個需求都有唯一識別碼,方便在設計、測試與維護階段被追蹤 - 需求蒐集: - Interviews(訪談法): - Closed interviews(封閉式):使用預先設計的問題。 - Open interviews(開放式):以探索方式自由討論。 - Scenarios(情境法):描述系統在真實世界中的使用情境 - Use Cases(用例法): - 基於情境的 UML 技術,辨識角色與他們與系統的互動 - 包含高階圖(Use Case Diagram)與詳細描述表格 - 序列圖(Sequence Diagram)則可補充流程細節 - Prototypes(原型設計): - 用來澄清模糊的需求,幫助使用者探索不同的設計選項 - 低擬真(Low-fidelity) 原型可避免將注意力集中在細節上 - User Stories(使用者故事): - 常見於 Agile 開發中,對功能做簡短、高層次描述,使用客戶的語言撰寫 - 需求規格化(Specification): - **Requirements Classification(需求分類):** - Functional / Non-Functional(功能性/非功能性) - Product / Process(產品/過程) - Importance(重要性)、Stability(穩定性)、Scope(範圍) - **Conceptual Modeling(概念建模):** - Use Case Diagram: - 用來捕捉系統需求的方法 - 描述系統應該做什麼(What) - 主要元素包含:Actors(角色)、Use Cases(用例)、Subject(主體系統) - **Architecture Design(架構設計):** - 系統架構最終必須被設計出來 - 在需求與系統設計之間存在重疊 - 需求分配:指定每個系統元件應負責滿足哪些需求 - **Requirements Negotiation(需求協商):** 客戶提出互不相容的需求、超出可用資源、功能性需求與非功能性需求間存在衝突 - **Requirements Specification(需求規格化):** 產出一份正式文件,用於審查與核准 - 複雜系統可分為:System Definition(系統定義)、System Requirements(系統層需求)、Software Requirements(軟體層需求) - **Requirements Validation(需求驗證):** 確保 SRS 符合品質特性 - User Stories (3Cs): 1. **Card**(卡片):作為討論提醒的小卡 2. **Conversation**(對話):產品負責人與開發團隊之間持續的討論 3. **Confirmation**(確認):用驗收測試(acceptance tests)驗證故事是否達成 - Good User Stories (INVEST): - Independent (相互獨立) - Negotiable (可協商) - Valuable (有價值) - Estimable (可估算) - Small (精簡) - Testable (可測試) - Use cases: - 詳細描述使用者與系統互動的文件 - 不是演算法,目標是了解並界定問題範圍,不提出解法 ### Minimum Viable Product (MVP) - 最小可行性產品:只包含必要功能、能驗證市場是否真的存在、必須是可實際使用的產品  - MVP 開發循環: - **Build**:實作 MVP 以驗證想法 - **Measure**:讓真實用戶使用並收集數據 - **Learn**:分析結果、獲得驗證性學習 - 可能結果: - Pivot(轉向):大幅改變方向,重新開始 - Refine(微調):小幅修正後重複循環 - Give up(放棄):若無資源或市場反應 - Success(成功):達成產品與市場契合 - MVP 是可能失敗的實驗,不必遵守所有軟體工程規則,但必須遵守**Performance(效能)、Usability(可用性)、Availability(穩定度)** | 比較項目 | MVP | Prototype | | --------- | ------- | ---------- | | **目的** | 驗證市場可行性 | 驗證需求或設計概念 | | **最小化程度** | 僅包含核心功能 | 可能包含完整介面 | | **交付對象** | 真實使用者 | 管理者或內部團隊 | | **成果** | 真實可使用產品 | 不一定可運作的展示品 | ### A/B Testing - 用來比較系統兩個版本在用戶反應上的差異,兩版本僅在單一需求上不同 - 目標:找出哪個版本能更有效支持最終系統 - 以**數據驅動**(Data-driven)方式選擇最佳版本 ## Ch4 Models - 目標:在需求與程式碼之間架起橋樑 - 目的:用模型來記錄解決方案,以應對需求中所定義的問題 - 建模是對系統的一種抽象化,有意忽略某些細節以凸顯重點 ### UML(統一塑模語言,Unified Modeling Language) - 用於描述與紀錄物件導向應用的圖示工具 - 在實作前,建立應用的設計模型  - 三大類別: - **結構圖**(Structure Diagrams):用來表示系統的靜態結構 - Class Diagram(類別圖) - Component Diagram(元件圖) - Object Diagram(物件圖) - Package Diagram(套件圖) - Deployment Diagram(部署圖) - **行為圖**(Behavior Diagrams):顯示系統的動作或流程 - Use Case Diagram(用例圖) - Actors(角色):與系統互動的人或外部系統。 - Use Cases(用例):角色想完成的目標。 - Relations(關係):角色與用例之間的連線(包含 extend/include) - Activity Diagram(活動圖) - State Machine Diagram(狀態圖) - **互動圖**(Interaction Diagrams):顯示物件之間的互動 - Sequence Diagram(時序圖) - Communication Diagram(通訊圖) - Timing Diagram(時間圖) - **Functional Models**(功能模型):Use Case Diagram - **Structural Models**(結構模型):Class Diagram - **Dynamic Models**(動態模型):Sequence Diagram / Activity Diagram ## Object-Oriented Programming - **Class**(類別):建立物件的藍圖,定義屬性(成員變數)與行為(方法) - **Object**(物件或實例):從類別中具體產生出來的實體,包含實際的資料值 - **Struct**(結構):類似類別,只是沒有存取限制  | 屬性 | struct | class | | ------ | ------------ | ------------ | | 預設存取權限 | public | private | | 繼承方式 | public | private | | 常見用途 | 儲存資料(簡單資料結構) | 封裝行為(有邏輯的物件) | - OOP - 優點: - **Reusability(重用性)**:類別與方法可跨專案重用 - **Modularity(模組化)**:分工清楚、可讀性高 - **Maintainability(可維護性)**:容易更新或擴充功能 - **Scalability(可擴充性)**:適用於大型、複雜系統 - 缺點: - **Complexity(複雜度)**:小專案可能顯得過於繁瑣 - **Performance(效能開銷)**:物件管理比程序式慢 - **Over-Engineering(過度設計)**:可能造成不必要的抽象 - 五大核心概念: ==(會考)== 1. **Abstraction(抽象化)**: - 隱藏實作細節,只呈現必要功能 - e.g. Car 類別提供 start() / stop() 方法,但不顯示引擎內部細節 2. **Encapsulation(封裝)**: - 將屬性與函式包裝成一個類別 - 使用 public / private 控制訪問權限 | 權限 | 描述 | | ------------- | ------------------- | | **private** | 僅限於同一類別或朋友函式使用(預設) | | **protected** | 子類別可存取,但外部不可 | | **public** | 任何地方皆可存取 | 3. **Aggregation(聚合)**: - 類別之間的 has-a(擁有)關係 - 範例:一個 Department 類別包含多個 Employee 類別 - 員工獨立存在,即使部門被刪除,員工仍可存在 4. **Inheritance(繼承)**: - 一種 is-a 關係,子類別可繼承父類的屬性與方法 - 促進程式重用與階層結構化  | 類型 | 公開成員 | 保護成員 | 私有成員 | | -------------------------- | ------------ | ------------- | ---- | | class B : public A {} | 保留為 public | 保留為 protected | 無法存取 | | class B : protected A {} | 變為 protected | 保留為 protected | 無法存取 | | class B : private A {} | 變為 private | 變為 private | 無法存取 | 5. **Polymorphism(多型)**: - 不同類別能針對同一方法(method)給出不同實作 - 範例:draw() 方法在 Circle 與 Rectangle 類別中行為不同,e.g. ```cpp class Shape { virtual void draw() const; }; class Circle : public Shape { void draw() const override; }; class Rectangle : public Shape { void draw() const override; }; ``` - **Virtual Function** - 在基底類別中使用關鍵字 virtual 宣告 - 程式在**執行時**決定呼叫哪個子類版本,子類可覆寫(override)基底類別的行為 - **Pure Virtual Function** - 使用 = 0 宣告 - 使該類別成為「抽象類別」(abstract class),不能直接建立物件,必須由子類別覆寫該函式 ```cpp class Animal { public: virtual void makeSound() = 0; // 純虛擬函式 }; ``` - **Abstract Class**(抽象類別) - 至少包含一個「純虛擬函式」的類別 - 不能直接建立物件,提供其他類別繼承的基底 - 可以同時擁有資料成員與已實作的方法 - **Interface**(介面) - 定義類別必須實作的函式 - C++中,以全為純虛擬函式的抽象類別呈現  - **Virtual Table**(虛擬函式表,vtable) - 一張由編譯器建立的「函式指標表」,用來支援動態多型(dynamic polymorphism)  - **Static Polymorphism**(靜態多型) - 在編譯時決定要呼叫哪個函式 - 無需 vtable,因此執行效能較高 | 特性 | Static Polymorphism | Dynamic Polymorphism | | ---- | ------------------- | -------------------- | | 解決時間 | 編譯期(Compile-time) | 執行期(Runtime) | | 效能 | 較快 | 較慢(因查表) | | 彈性 | 較低 | 較高 | - **Class Template**(類別模板) - 可針對**任意資料型態**運作的藍圖,實現泛型程式設計(generic programming) ```cpp template <typename T> class Vector_ { private: T* m_data; }; ``` - **Curiously Recurring Template Pattern**(CRTP) - 沒有執行期負擔的靜態多型 - 常用於 policy-based design,支援型別特化 + 行為注入  - **Pointers** - **指向常數值的指標**(Pointer to constant value) - 它指向的記憶體位置中的值,不能透過這個指標修改 - 但這個指標本身可以被改變,指向其他記憶體位置 - e.g.`const Circle* ptr = new Circle{};` - **指向值的常數指標**(Constant pointer to value) - const 關鍵字是套用在指標變數本身 - 一旦初始化後,指標所儲存的記憶體位址不能改變 - `Circle* const ptr = new Circle{};`  ### Class Diagram(類別圖) - 描述類別的方法、屬性、可見性(visibility)  - 箭頭永遠是「使用者 → 被使用者」的方向(父類是被繼承的一方)  | 關係類型 | 意義 | 符號 | | ---------------------------- | ------------------- | ------ | | Generalization / Inheritance | A 是 B 的一種(繼承) | 空心三角箭頭 | | Realization / Implementation | A 實作 B(B 是介面) | 虛線空心箭頭 | | Association | A 與 B 有關聯 | 實線箭頭 | | Aggregation | A 擁有 B,但生命周期不同 | 空心菱形箭頭 | | Composition | B 是 A 的一部分,隨 A 一起存在 | 實心菱形箭頭 | | Dependency | A 使用 B(弱依賴) | 虛線箭頭 | - **Generalization / Inheritance(一般化/繼承)** - 子類別與父類別共享結構與行為,代表「is-a」階層  - **Realization / Implementation(實作)** - 類別實作介面或抽象類別所定義的行為  - **Association(關聯)** - 類別 A 有一個類別 B 的屬性 b  - **Multiplicity(多重性)** - 一個屬性可以對應多少個物件  - **Aggregation(聚合)** - 部分(part)可以獨立存在的整體-部分關係 ```cpp class Employee {}; class Department { private: std::vector<Employee*> employees; }; ``` - **Composition(組合)** - 部分與整體的生命週期緊密相連 ```cpp class Engine {}; class Car { private: Engine engine; }; ```  - **Bidirectional Associations(雙向關聯)** - 兩個類別彼此都知道對方存在,並能互相存取對方 - e.g.一個人最多一支手機,一支手機最多屬於一個人  - **Circular Include Dependency(循環包含依賴)** - 當 A.h 引入 B.h,而 B.h 又引入 A.h,就形成循環依賴 - #pragma once 只能防止同一檔案被重複包含,但無法解決「互相引用」的邏輯問題 - 前置宣告(forward declaration):讓編譯器「知道某個類別存在」,但暫時不需要知道它的完整內容 - **Package Diagrams(套件圖)** - 提供系統的高層次視圖,顯示一組類別(packages)與它們之間的依賴關係 - 每個套件以一個帶有梯形標籤的矩形表示  - **Sequence Diagrams(循序圖)** - 行為圖或動態圖(Behavioral or dynamic diagrams) - 模擬系統中物件的互動,顯示在某個使用情境中,被執行的方法順序  - 垂直虛線:不活躍(inactive,沒有在執行方法) - 垂直長方形:活躍(active,正在執行某個方法) - 水平箭頭:方法呼叫 - 虛線箭頭:回傳值(有時可省略)   - **Activity Diagrams(活動圖)** - 行為圖或動態圖 - 用於建模業務流程或工作流程 - Token(令牌)在節點之間流動  | 節點類型 | 說明 | | ---------------- | ------------------ | | **Initial node** | 建立 token 開始執行 | | **Action** | 從輸入傳遞 token 至輸出 | | **Decision** | 根據條件選擇輸出路徑 | | **Merge** | 將多條輸入匯成單一路徑 | | **Fork** | 將一個 token 分成多個並行流程 | | **Join** | 等待所有 token 結束後再繼續 | | **Final node** | 結束流程執行 | ## Ch5 Design Principles ### Design Principles - **概念完整性(Conceptual Integrity)** - 系統功能、設計、實作決策之間的一致性 - e.g. UI外觀應一致、變數命名應統一 - C++ Uniform Initialization:一種一致化初始化物件的現代方式(C++11後),使用大括號 {} 初始化  - **資訊隱藏(Information Hiding)** - 每個模組應只公開它「需要被其他模組知道的資訊」 - 模組的內部細節應保持隱藏(私有) - 可透過「介面」或「API」進行互動,而不是直接操作內部資料   - 沒有驗證:餘額可以被直接設為負值,這對銀行帳戶沒有意義 - 狀態不一致:持有人姓名可以被清空,導致物件變成無效狀態 - 安全問題:無法保護關鍵操作(例如存款或提款)避免被誤用 - private 可用來防止未預期的操作,例如未經授權的實例化、錯誤使用繼承 - **Singleton**:確保整個程式中僅存在一個該類別的實例,並提供一個全域的存取點 - 需要由單一物件協調整個系統的行為,或需要集中式控制(例如設定、日誌、快取) - **Private Constructor**:防止在類別外部建立新實例 - **Static Instance**:確保僅有一個共享物件 - **Global Access Point**:透過 getInstance() 取得存取權 - 過度或錯誤使用 Singleton 會導致程式碼過度耦合、難以測試、難以維護 - Curiously Recurring Template Pattern (CRTP) - 一種使用模板(template)的 C++ 設計模式 - 可實現靜態多型(static polymorphism) - **內聚(Cohesion)** - 模組中各元素為單一目的而協作的程度 - **高內聚(High Cohesion)**: - 每個模組都有清楚、集中的職責 - 較容易理解、測試與維護 - **低內聚(Low Cohesion)**: - 模組同時處理多個不相關的任務 - 更難重複使用,也更容易出錯 - **耦合(Coupling)** - 模組之間的依賴程度 - **低耦合(Low Coupling)**: - 模組透過明確定義的介面互動 - 獨立、靈活、易於修改 - **高耦合(High Coupling)**: - 模組嚴重依賴彼此的內部細節 - 一個模組的變更會造成連鎖影響  ### Design Principles - 作為做出設計決策的指引 - 設計原則 -> 設計屬性 - Single Responsibility -> Cohesion(內聚) - Interface Segregation -> Cohesion(內聚) - Dependency Inversion -> Coupling(降低耦合) - Favor Composition over Inheritance -> Coupling(降低耦合) - Demeter -> Information Hiding(資訊隱藏) - Open/Closed -> Extensibility(可擴充性) - Liskov Substitution -> Extensibility(可擴充性) - **Single Responsibility Principle (SRP)** - 每個類別或模組應該只負責功能的一部分 - 該職責應該完全由該類別封裝 - 效益: - Simplifies maintenance:副作用更少 - Enhances reusability:類別更小、更聚焦 - Improves testing:容易隔離測試功能 - Supports scalability:更容易修改或擴充 - **Interface Segregation Principle (ISP)** ==(會考)== - 大型介面應拆分為更小、更具體的介面 - 每個介面應有效服務於一種類型的使用者   - 效益: - Reduces code bloat:減少程式冗餘與不必要依賴 - Improves flexibility:容易修改與擴充 - Simplifies testing:聚焦於小而明確的介面 - Supports SRP:保持職責獨立 - **Dependency Inversion Principle (DIP)** - 高層不應直接依賴低層細節 - 雙方都應依賴共同的抽象(例如介面或抽象類別)   - 效益: - Decouples modules:模組解耦,可獨立開發 - Improves testability:容易模擬依賴(mock dependencies) - Facilitates scalability and maintenance:提升擴充與維護性 - **Open/Close Principle (OCP)** - Open:可以被擴充以加入新行為 - Closed:現有程式碼保持不變且穩定 - 核心理念:建立能安全成長的彈性系統 - 效益: - Enhances stability — 減少程式反覆修改 - Improves scalability — 容易支援新功能 - Encourages abstraction — 藉由介面或多型 - Reduces risk — 不需修改已運作的元件 - **Liskov Substitution Principle (LSP)** - 衍生類別必須保留基底類別的行為 - 子類別應擴展,而非削弱父類的契約 - 違反此原則會導致意外或錯誤行為,e.g.企鵝是鳥(會飛)但,企鵝不會飛 - Guarantees correctness:在使用多型時保證正確性 - Prevents fragile hierarchies:防止破壞替代性的脆弱繼承階層 - Encourages consistent class behavior:鼓勵在繼承中保持一致的類別行為 - Improves reusability:提升可重用性,元件能被安全替換 - **Prefer Composition to Inheritance(偏好組合而非繼承)**: - Inheritance:透過擴展行為(is-a)來重用程式碼 - Composition:透過物件組合(has-a)來重用程式碼 - 組合提供更鬆耦合與更高彈性 - 避免深層繼承樹,因為會降低靈活性 - **Demeter Principle**: - 又稱為最少知識原則 - 一個方法應該只呼叫: - 自己的其他方法 - 自身成員(fields)的方法 - 自己建立的物件的方法 - 傳入參數物件的方法 - 減少元件之間的耦合、避免過長的物件呼叫鏈 - 鼓勵乾淨、模組化的類別間溝通、促進封裝性與可維護性 - Improves encapsulation:隱藏內部細節。 - Reduces coupling:模組之間能獨立修改。 - Simplifies maintenance:重構時減少連鎖效應。 - Improves readability:呼叫鏈更短、語意更清晰。
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.