第 20 章:進階程式設計
哈囉!歡迎來到「進階程式設計」單元。在這裡,我們將深入探討讓現代軟體變得穩健且具擴展性的進階理念與技術。如果有些概念起初看起來很抽象,別擔心——我們會將這些強大的概念逐一拆解,例如從全新的角度看待程式設計(範式),以及如何處理意料之外的問題(異常處理)。掌握這一章,你將從一名稱職的程式設計師蛻變為進階的軟體架構師!
20.1 程式設計範式 (Programming Paradigms)
程式設計範式本質上是一種撰寫電腦程式的基本風格或方法。它是一套哲學,決定了程式設計師如何構建程式碼,以及如何看待他們試圖解決的問題。
課程大綱要求理解四種主要範式:低階語言、指令式(程序式)、物件導向,以及宣告式。
1. 低階程式設計範式 (Low-Level Programming Paradigm)
此範式涉及撰寫非常接近電腦原生語言(機器碼)或人類可讀性稍高的版本(組合語言)的指令。
- 特性:低階程式碼專注於直接控制硬體、記憶體位址和暫存器。它精確地指示 CPU 下一步要執行哪一個微小的步驟。
- 應用:用於對執行速度、記憶體佔用極小化或直接操作硬體(如控制嵌入式系統或裝置驅動程式)有嚴格要求的場景。
核心概念:定址模式 (Addressing Modes)(4.2 章節複習)
編寫低階程式碼時,你必須指定 CPU 如何找到所需的資料。以下是我們存取記憶體的方式:
-
立即定址 (Immediate Addressing):運算元就是資料本身。
範例:LDM #10(將實際數值 10 載入累加器)。 -
直接定址 (Direct Addressing):運算元是儲存資料的記憶體位址。
範例:LDD 500(載入位址 500 處的內容)。 -
間接定址 (Indirect Addressing):運算元是一個位址,該位址中存放著資料的位址(指標)。
範例:LDI 600(前往位址 600,讀取那裡的數值,假設為 800;然後前往位址 800 並載入該內容)。 -
索引定址 (Indexed Addressing):位址是透過運算元位址加上索引暫存器 (IX) 的內容計算得出。非常適合用於遍歷陣列。
範例:LDX 400(有效位址 = 400 + IX 的內容)。 - 相對定址 (Relative Addressing):位址是透過將運算元加到程式計數器 (PC) 的內容中計算得出。用於跳轉,使程式碼具備位置無關性。
# 表示立即定址)。
2. 指令式(程序式)程式設計範式 (Imperative/Procedural Programming Paradigm)
這是你在 AS Level 階段專注學習的「經典」結構化方法。它將計算定義為一系列改變程式狀態(變數)的語句。
- 特性:專注於程式如何運作。它使用結構化程式設計概念:循序 (Sequence)、選擇 (Selection, IF/CASE) 及迭代 (Iteration, Loops)。問題透過模組解決:程序 (Procedures)(執行動作)和函數 (Functions)(回傳數值)。
- 必備技能:你必須能夠使用變數、常數、所有控制結構、程序和函數(包括以傳值和傳址方式傳遞參數)來編寫程式碼。
3. 物件導向程式設計 (OOP) 範式
OOP 將程式視為一組相互作用的物件 (Objects) 集合。它旨在程式中模擬現實世界的實體,從而使程式碼更具可重用性且易於維護。
OOP 核心術語
-
類別 (Class):建立物件的藍圖或範本。它定義了該類別所有物件共有的結構(屬性)與行為(方法)。
類比:汽車工廠的藍圖。 -
物件 (Object / Instance):從類別建立出的具體實體。
類比:依照汽車藍圖生產出的那台紅色 Honda。 -
屬性 (Property / Attribute):定義物件狀態的資料或特徵(類別內部的變數)。
範例:汽車的顏色、速度、引擎排氣量。 -
方法 (Method):物件可以執行的動作或函數。
範例:汽車的啟動引擎()、加速()、剎車()。 - 封裝 (Encapsulation):將資料(屬性)與操作這些資料的方法綑綁成單一單元(物件),並隱藏內部細節的原則。
- Getter 與 Setter:用於控制屬性存取的特殊方法,以維護封裝性。Getter 用於檢索(讀取)屬性值;Setter 用於修改(寫入)屬性值,通常包含驗證檢查。
-
繼承 (Inheritance):一種機制,允許根據現有類別(父類別/超類別)建立新類別(子類別)。子類別會自動繼承父類別的所有屬性和方法,促進程式碼重用。
範例:卡車類別繼承自車輛類別。 -
多型 (Polymorphism):意為「多種形式」。它允許不同類別的物件以各自獨特的方式回應同一個方法呼叫。
範例:狗物件和貓物件都有發出聲音()方法,但狗會叫,貓會喵。 -
包含關係 (Containment/Aggregation):當一個類別的屬性是另一個類別的物件時。它代表一種「擁有 (has-a)」的關係。
範例:汽車類別擁有一個引擎物件。
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. 檔案組織與存取方法
檔案的儲存方式會影響搜尋特定資料的速度。
- 序列檔案 (Serial File):記錄依照建立順序一個接一個儲存。存取時必須依序進行。要找到第 100 筆記錄,必須先讀取前 99 筆記錄。
- 循序檔案 (Sequential File)(使用關鍵欄位):記錄根據關鍵欄位 (Key field)(例如按姓氏字母順序)以特定順序儲存。存取通常是循序的,從頭開始讀取直到找到匹配的鍵值。
- 隨機檔案 (Random File):無需讀取前置記錄即可直接存取記錄。使用公式(或鍵值查找)計算記錄在磁碟上的確切物理位置(位址)。這能實現極快的檢索速度。
編寫檔案處理程式碼時,請記住你必須能夠讀取和寫入完整的記錄 (Records)(通常對應於程式中定義的記錄結構或類別物件)到檔案中。
2. 異常處理的重要性
在現實世界的程式設計中,意外狀況總是會發生:網路斷線、使用者輸入文字而非數字,或者磁碟空間不足。程式出錯時如果直接崩潰,是非常不專業且不可靠的。
定義與重要性
- 異常 (Exception) 是程式執行期間發生的、中斷正常指令流程的事件。通常是執行時期錯誤 (Runtime Error)。
-
異常處理的重要性:
- 防止程式突然崩潰(終止)。
- 允許程式優雅地失敗,向使用者提供有用的回饋。
- 讓開發者有機會從錯誤中恢復(例如重試網路連線或正確關閉檔案)。
何時使用異常處理
每當一段程式碼依賴於無法嚴格控制的外部資源或使用者操作時,就應該使用異常處理。常見情況包括:
- 嘗試開啟不存在的檔案(找不到檔案錯誤)。
- 嘗試連線到無法使用的資料庫或網路。
- 計算產生未定義的數學狀態(例如除以零)。
- 嘗試將資料轉型為不適當的型別(例如將 "hello" 轉換為整數)。
編寫異常處理程式碼
基本結構通常包含一個受保護的程式碼區塊 (TRY),以及一個在錯誤發生時執行的獨立程式碼區塊 (CATCH 或 EXCEPT)。
範例結構(偽代碼概念):
TRY
OPENFILE("data.txt", READ)
// 正常處理程式碼
CATCH (FileNotFoundError)
OUTPUT "錯誤:找不到資料檔案,請檢查磁碟。"
END TRY