第 20 章:進階程式設計

哈囉!歡迎來到「進階程式設計」單元。在這裡,我們將深入探討讓現代軟體變得穩健且具擴展性的進階理念與技術。如果有些概念起初看起來很抽象,別擔心——我們會將這些強大的概念逐一拆解,例如從全新的角度看待程式設計(範式),以及如何處理意料之外的問題(異常處理)。掌握這一章,你將從一名稱職的程式設計師蛻變為進階的軟體架構師!


20.1 程式設計範式 (Programming Paradigms)

程式設計範式本質上是一種撰寫電腦程式的基本風格或方法。它是一套哲學,決定了程式設計師如何構建程式碼,以及如何看待他們試圖解決的問題。

課程大綱要求理解四種主要範式:低階語言、指令式(程序式)、物件導向,以及宣告式。

1. 低階程式設計範式 (Low-Level Programming Paradigm)

此範式涉及撰寫非常接近電腦原生語言(機器碼)或人類可讀性稍高的版本(組合語言)的指令。

  • 特性:低階程式碼專注於直接控制硬體、記憶體位址和暫存器。它精確地指示 CPU 下一步要執行哪一個微小的步驟。
  • 應用:用於對執行速度、記憶體佔用極小化或直接操作硬體(如控制嵌入式系統或裝置驅動程式)有嚴格要求的場景。
核心概念:定址模式 (Addressing Modes)(4.2 章節複習)

編寫低階程式碼時,你必須指定 CPU 如何找到所需的資料。以下是我們存取記憶體的方式:

  1. 立即定址 (Immediate Addressing):運算元就是資料本身。
    範例:LDM #10(將實際數值 10 載入累加器)。
  2. 直接定址 (Direct Addressing):運算元是儲存資料的記憶體位址
    範例:LDD 500(載入位址 500 處的內容)。
  3. 間接定址 (Indirect Addressing):運算元是一個位址,該位址中存放著資料的位址(指標)。
    範例:LDI 600(前往位址 600,讀取那裡的數值,假設為 800;然後前往位址 800 並載入該內容)。
  4. 索引定址 (Indexed Addressing):位址是透過運算元位址加上索引暫存器 (IX) 的內容計算得出。非常適合用於遍歷陣列。
    範例:LDX 400(有效位址 = 400 + IX 的內容)。
  5. 相對定址 (Relative Addressing):位址是透過將運算元加到程式計數器 (PC) 的內容中計算得出。用於跳轉,使程式碼具備位置無關性。
重點摘要(低階):核心在於效率與直接控制。當題目要求使用此範式編寫程式碼時,你必須正確應用特定定址模式的語法(例如使用 # 表示立即定址)。

2. 指令式(程序式)程式設計範式 (Imperative/Procedural Programming Paradigm)

這是你在 AS Level 階段專注學習的「經典」結構化方法。它將計算定義為一系列改變程式狀態(變數)的語句。

  • 特性:專注於程式如何運作。它使用結構化程式設計概念:循序 (Sequence)、選擇 (Selection, IF/CASE) 及迭代 (Iteration, Loops)。問題透過模組解決:程序 (Procedures)(執行動作)和函數 (Functions)(回傳數值)。
  • 必備技能:你必須能夠使用變數、常數、所有控制結構、程序和函數(包括以傳值和傳址方式傳遞參數)來編寫程式碼。
你知道嗎?「指令式 (Imperative)」一詞源自「祈使句」,意為命令。你是在一步步向電腦下達命令。

3. 物件導向程式設計 (OOP) 範式

OOP 將程式視為一組相互作用的物件 (Objects) 集合。它旨在程式中模擬現實世界的實體,從而使程式碼更具可重用性且易於維護。

OOP 核心術語
  1. 類別 (Class):建立物件的藍圖或範本。它定義了該類別所有物件共有的結構(屬性)與行為(方法)。
    類比:汽車工廠的藍圖。
  2. 物件 (Object / Instance):從類別建立出的具體實體。
    類比:依照汽車藍圖生產出的那台紅色 Honda。
  3. 屬性 (Property / Attribute):定義物件狀態的資料或特徵(類別內部的變數)。
    範例:汽車的 顏色速度引擎排氣量
  4. 方法 (Method):物件可以執行的動作或函數。
    範例:汽車的 啟動引擎()加速()剎車()
  5. 封裝 (Encapsulation):將資料(屬性)與操作這些資料的方法綑綁成單一單元(物件),並隱藏內部細節的原則。
  6. Getter 與 Setter:用於控制屬性存取的特殊方法,以維護封裝性。Getter 用於檢索(讀取)屬性值;Setter 用於修改(寫入)屬性值,通常包含驗證檢查。
  7. 繼承 (Inheritance):一種機制,允許根據現有類別(父類別/超類別)建立新類別(子類別)。子類別會自動繼承父類別的所有屬性和方法,促進程式碼重用。
    範例:卡車 類別繼承自 車輛 類別。
  8. 多型 (Polymorphism):意為「多種形式」。它允許不同類別的物件以各自獨特的方式回應同一個方法呼叫。
    範例: 物件和 物件都有 發出聲音() 方法,但狗會叫,貓會喵。
  9. 包含關係 (Containment/Aggregation):當一個類別的屬性是另一個類別的物件時。它代表一種「擁有 (has-a)」的關係。
    範例:汽車 類別擁有一個 引擎 物件。
記憶口訣 (OOP 四大支柱):想到 OOP 的主要優勢時,請記住 A PIE(抽象 Abstraction、多型 Polymorphism、繼承 Inheritance、封裝 Encapsulation),但也別忘了在定義中包含類別、物件和包含關係!

4. 宣告式程式設計範式 (Declarative Programming Paradigm)

此範式專注於定義結果是什麼,而不是列出逐步執行的指令(「如何」做)。它通常依賴事實 (Facts) 與規則 (Rules)

  • 特性:程式是一組邏輯陳述(事實)和關係(規則)。系統會利用這些定義嘗試滿足給定的目標 (Goal)
  • 與指令式的對比:
    • 指令式:「要從 A 到 B,先左轉,然後直走,再右轉……」(逐步程序)。
    • 宣告式:「A 是目的地,B 是起點,找到一條有效路徑。」(定義結果,讓語言引擎自行找出路徑)。
  • 必備技能:你需要理解如何透過撰寫適當的事實和規則來解決問題,並展示使用此結構來滿足目標的能力(常見於 Prolog 等語言或進階 SQL 查詢)。
重點摘要(程式設計範式):核心差異在於焦點:低階(硬體步驟)、指令式(逐步指令)、物件導向(交互的現實世界物件)、宣告式(邏輯事實與目標)。

20.2 檔案處理與異常處理

處理檔案對於永久性資料儲存至關重要。當你超越了簡單的輸入/輸出,就需要穩健的方法來管理資料的儲存、檢索,以及處理發生問題時的情況。

1. 檔案處理操作

你必須能夠編寫程式碼執行標準的檔案處理操作:

A. 開啟與關閉檔案

在讀取或寫入之前,必須以特定的模式 (Mode) 開啟檔案:

  • 讀取模式 (Read Mode):允許從檔案檢索資料。如果檔案不存在,通常會發生錯誤。
  • 寫入模式 (Write Mode):允許將資料寫入檔案。如果檔案已存在,其內容通常會被覆寫(刪除)。
  • 附加模式 (Append Mode):允許將新資料新增到現有檔案的結尾。現有內容會被保留。

所有操作完成後,必須關閉檔案,以確保資料完整性並釋放系統資源。

B. 檔案組織與存取方法

檔案的儲存方式會影響搜尋特定資料的速度。

  1. 序列檔案 (Serial File):記錄依照建立順序一個接一個儲存。存取時必須依序進行。要找到第 100 筆記錄,必須先讀取前 99 筆記錄。
  2. 循序檔案 (Sequential File)(使用關鍵欄位):記錄根據關鍵欄位 (Key field)(例如按姓氏字母順序)以特定順序儲存。存取通常是循序的,從頭開始讀取直到找到匹配的鍵值。
  3. 隨機檔案 (Random File):無需讀取前置記錄即可直接存取記錄。使用公式(或鍵值查找)計算記錄在磁碟上的確切物理位置(位址)。這能實現極快的檢索速度。

編寫檔案處理程式碼時,請記住你必須能夠讀取和寫入完整的記錄 (Records)(通常對應於程式中定義的記錄結構或類別物件)到檔案中。

2. 異常處理的重要性

在現實世界的程式設計中,意外狀況總是會發生:網路斷線、使用者輸入文字而非數字,或者磁碟空間不足。程式出錯時如果直接崩潰,是非常不專業且不可靠的。

定義與重要性
  • 異常 (Exception) 是程式執行期間發生的、中斷正常指令流程的事件。通常是執行時期錯誤 (Runtime Error)。
  • 異常處理的重要性:
    • 防止程式突然崩潰(終止)。
    • 允許程式優雅地失敗,向使用者提供有用的回饋。
    • 讓開發者有機會從錯誤中恢復(例如重試網路連線或正確關閉檔案)。
何時使用異常處理

每當一段程式碼依賴於無法嚴格控制的外部資源或使用者操作時,就應該使用異常處理。常見情況包括:

  • 嘗試開啟不存在的檔案(找不到檔案錯誤)。
  • 嘗試連線到無法使用的資料庫或網路。
  • 計算產生未定義的數學狀態(例如除以零)。
  • 嘗試將資料轉型為不適當的型別(例如將 "hello" 轉換為整數)。
編寫異常處理程式碼

基本結構通常包含一個受保護的程式碼區塊 (TRY),以及一個在錯誤發生時執行的獨立程式碼區塊 (CATCHEXCEPT)。

範例結構(偽代碼概念):
TRY
    OPENFILE("data.txt", READ)
    // 正常處理程式碼
CATCH (FileNotFoundError)
    OUTPUT "錯誤:找不到資料檔案,請檢查磁碟。"
END TRY

快速複習(異常):如果 TRY 區塊內發生錯誤,程式會立即停止執行該區塊,跳轉至 CATCH 區塊,從而確保採取受控的回應而非直接系統崩潰。