选择语言
durumis AI 总结的文章
- 在軟體開發中,實務比理論更重要,透過簡單的程式可以了解物件導向設計的重要性。
- 以票務銷售應用程式為例,說明降低物件之間的依賴關係和耦合度以編寫靈活的代碼的方法,並比較程序式和物件導向 程式設計的差異。
- 物件導向設計可以創造可變更的代碼,物件作為一種自主的存在,負責自己的數據,需要適當管理合作物件之間的依賴關係。
導言
Robert L. Glass 認為實務比理論更重要。特別是在軟體開發中,實務往往先於理論,開發人員在實際編寫程式碼時,才能學到最多東西。因此,我們暫時先將理論和概念放一邊,來看看一個簡單的程式。
實作售票應用程式
- 為了宣傳小型劇場,我們計劃舉辦一個小型的活動。
- 活動內容:透過抽籤選出幸運觀眾,贈送免費觀賞演出的邀請函。
- 需要將參加活動的觀眾分為中獎和未中獎兩組。
- 活動中獎觀眾:憑邀請函兌換門票
- 活動未中獎觀眾:用錢購買門票
問題在哪裡?
Robert Martin 解釋了軟體模組(無論大小,任何構成程式的元素,例如類別、套件、函式庫)應具備的三種功能。
- 在執行時能夠正常運作。
- 為了修改而存在。
- 只要簡單的操作,就能進行修改。
- 與程式碼閱讀者進行溝通。
- 開發人員能夠輕鬆讀懂和理解。
前面的售票應用程式滿足了第一個約束,即能夠正常執行,但沒有滿足可修改性和溝通性這兩個目標。
出乎意料的程式碼
讓我們來看看為什麼程式碼無法滿足溝通性這個目標。
- Theater 類別中的 enter() 方法的作用
- 劇場會打開觀眾的包包,查看裡面是否有邀請函。
- 如果包包裡有邀請函,劇場會指示售票員將售票處保存的門票放入觀眾的包包中。
- 如果包包裡沒有邀請函,劇場會從觀眾的包包中取出等於門票價格的現金,購買門票,並將門票放入包包。
- 從觀眾的角度來看,他們必須眼睜睜地看著劇場這個第三方隨意翻查他們的包包、拿走現金並放入門票。
- 從售票員的角度來看,他們必須眼睜睜地看著劇場這個第三方未經許可就操作售票處的門票和現金。
- 可理解的程式碼指的是程式碼的運作不會與我們的預期相差太大,但上述劇場的情況超出了我們的預期。
- 觀眾應該自行從包包裡取出現金,支付給售票員,並獲得門票。
- 售票員應該自行從售票處取出門票,直接交給觀眾,並從觀眾手中收取現金,放入售票處。
- 此外,要理解 enter() 方法,必須記住很多細節。
- Audience 擁有 Bag。
- Bag 裡面有現金和門票。
- TiketSellet 在 TicketOffice 售票,TicketOffice 保存著現金和門票。
對修改敏感的程式碼
enter() 方法假設了兩個條件。
- 觀眾總是隨身攜帶包包,用於存放現金和邀請函。
- 售票員只在售票處售票。
那麼,以下情況呢?
- 觀眾可能沒有包包。
- 觀眾可能使用信用卡而不是現金。
- 售票員可能在售票處以外的地方售票。
例如,要滿足第一個需求,需要刪除 Audience 的 Bag 物件,並修改相關的 Theater 類別的 enter() 方法。這是因為 Theater 類別過於依賴觀眾會攜帶包包,以及售票員只在售票處售票這類細節。如果這些細節有任何變化,就必須修改相關類別(例如 Theater)及其依賴的類別。
這是一個與物件之間的依賴關係相關的問題,依賴關係暗示了修改的影響。然而,物件導向設計的目標是建立相互依賴並協同工作的物件群體,因此,我們不能無條件地消除依賴關係,而是應該只維持實作應用程式功能所需的最少的依賴關係,並消除不必要的依賴關係。
物件之間的依賴關係過高,稱為耦合度高。兩個物件之間的耦合度越高,它們一起修改的機率也越高。因此,設計的目標是降低物件之間的耦合度,以實現易於修改的設計。
改善設計
Theater 不需要知道觀眾是否有包包,也不需要知道售票員是否在售票處售票。Theater 只希望觀眾能進入劇場。因此,我們應該讓觀眾自行處理包包中的現金和邀請函,讓售票員自行處理售票處的門票和票價,讓他們成為自主的個體。
提高自主性
僅執行密切相關的工作,將不相關的工作委託給其他物件,這樣的物件被稱為內聚性高。建立自行處理其資料的自主物件,可以降低耦合度並提高內聚性。
過程導向和物件導向
- 過程導向
- Theater 的 enter() 方法是過程,Audience、TicketSeller、Bag、TicketOffice 是資料。
- 將過程和資料放在不同的模組中的方式稱為過程導向程式設計。
- 存在很多與我們的直覺相違背的程式碼(例如,觀眾自行管理現金和邀請函)。
- 難以縮小資料修改的影響範圍。
- 以集中式方式管理責任(由 Theater 管理所有)。
- 物件導向
- 將資料和過程放在同一個模組中的方式稱為物件導向程式設計。
- 可以使用符合我們直覺的程式碼。
- 可以通過封裝有效地縮小資料修改的影響範圍。
- 每個物件都對自己負責。
還可以做得更好
- Audience 類別中的 Bag 類別仍然是被動的,由 Audience 類別控制,因此我們應該讓 Bag 類別成為自主的物件。
- TicketSeller 類別中的 TicketOffice 也是被動的,由 TicketSeller 控制。我們應該讓 TicketOffice 成為自主的物件。
- 但是,修改之後,TicketOffice 與 Audience 之間產生了額外的耦合度。
- 設計需要權衡利弊。在本例中,為了降低 Audience 和 TicketOffice 之間的耦合度,我們可以協商讓 TicketOffice 變成一個比較被動的物件。
是的,這是一個謊言!
- 即使在現實世界中,某些事物是被動的,但一旦進入物件導向的世界,所有事物都會變成積極主動的、自主的個體。
- 建議使用擬人化,將被動物件想像成會笑、會說話、會生氣的個體。
物件導向設計
為什麼需要設計?
- 設計就是將程式碼安排好。
- 好的設計是指在滿足當前需求的同時,也能夠平滑地適應未來的修改。
物件導向設計
- 可修改的程式碼就是易於理解的程式碼。
- 物件導向範式幫助我們以看待世界的方式編寫程式碼。
- 物件是對自己的資料負責的自主個體。
- 優秀的物件導向設計是指能夠適當管理協作物件之間的依賴關係的設計。
資料來源
- 物件