## 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
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up