[Guideline] AVOID PREMATURE INHERITANCE

看板OOAD作者 (!H45)時間17年前 (2007/12/04 19:53), 編輯推噓8(804)
留言12則, 3人參與, 最新討論串1/1
____________________ AVOID PREMATURE INHERITANCE Inheritance needs time to evolve. ﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉﹉ ※ 節錄自 Prefactoring 第 63 頁 沒事不要繼承,繼承需要很長的時間才會演化。 (此為不負責任翻譯......) 在設計 Applet 的時候,為了切割圖形、控制、模組會採用 MVC Pattern 這邊的 MVC Pattern 是單純指圖形類別、控制類別、模組類別。 我下面所要描述的重點在控制類別,有很多人會把控制器寫成下面這個樣子: if (第一個按鈕被按下) { 做第一種事情(); } else if (第二個按鈕被按下) { 做第二種事情(); } /* ... */ else if (第 n 個按鈕被按下) { 做第 n 種事情(); } 如果有 n 個按鈕,就有 n 個 if-else 要寫。 更慘的是,如果有新的按鈕或是新的事件要加入這段程式碼又要被改寫一次 這完全違背開閉原則 (Open-Close Principle)! 一個類別設計完之後,除了繼承它或是使用它之外 不應該再度修改它內部的程式碼! 當程式設計師發現一大串的 if-else 或是 switch-case 就應該聯想到 Class Inheritance 利用類別的多型來取代難以閱讀的 if-else 或 switch-case 可以讓原來的程式碼不會被修改的情況下,新增按鈕或是事件到一個新的類別 開發需求所述的新功能! 舉例而言 (JAVA): public class ButtonHandler implements ActionListener { public void actionPerformed(ActionEvent actionEvent) { final String command = actionEvent.getActionCommand(); if ("Load Image".equals(command)) { this.loadImage(); } else if ("Histogram Equalization".equals(command)){ this.histogramEqualization(); } else if ("Mean Filter".equals(command)) { this.meanFilter(); } } } 這三個 if-else 區塊分別處理三種不同的按鈕事件 分別是讀影像、做直方圖等化、以及做平均過濾。 還好只有三個 if-else 區塊,一開始還沒什麼大不了的 但是隨著需求的改變,按鈕愈來愈多,程式碼會開始大量地成長 public class ButtonHandler implements ActionListener { public void actionPerformed(ActionEvent actionEvent) { final String command = actionEvent.getActionCommand(); if ("Load Image".equals(command)) { this.loadImage(); } else if ("Histogram Equalization".equals(command)){ this.histogramEqualization(); } else if ("Mean Filter".equals(command)) { this.meanFilter(); } /* 想像這邊以後有一大串 if-else 區塊 */ } } 這可不是開玩笑的,每次加一個按鈕就要修改原來的程式碼並不是一個好現象! 倒不如切割整個類別為多個小類別,實作同一個介面 ActionListener public class LoadImageHandler implements ActionListener { // ...... } public class HistogramEqualization implements ActionListener { // ...... } public class MeanFilter implements ActionListener { // ...... } 這樣的話,每次要新增一個按鈕或事件處理,就只要新增一個類別實作 ActionListener 不需要再修改原來的程式碼了!符合開閉原則 (Open-Close Principle) 有人會問:「那原來的 if-else 到哪裡去了?消失了嗎?」 我會回答:「可以說它消失,也可以說它還存在。 if-else 確實不見了,它原本的功能散落在不同的 ActionListener 子類別 裡。判斷的機制仍然存在,只是現在改由設定按鈕的控制器實體,而不再由 控制器自己判斷要做哪一種動作了!」 有人續問:「判斷的機制仍然存在?那有比較好嗎?」 我會回答:「加入新按鈕的時候,設定新按鈕的控制器為新的控制器, 我們加入全新的類別不會更動原類別的任何程式碼, 在物件設計的角度來看是比較好的。」 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.116.247.13 ※ 編輯: H45 來自: 140.116.247.13 (12/04 19:56) ※ 編輯: H45 來自: 140.116.247.13 (12/04 19:56)

12/04 20:44, , 1F
總覺得標題跟後半部文章沒啥關係耶...
12/04 20:44, 1F

12/04 21:11, , 2F
btw, 這本書我想賣...
12/04 21:11, 2F

12/04 22:21, , 3F
後半部文章是說明什麼是成熟的繼承。
12/04 22:21, 3F

12/04 22:22, , 4F
回二樓,我覺得這本書很難讀,是有一點點想賣 XD
12/04 22:22, 4F

12/05 00:28, , 5F
我是覺得這本書有點囉唆,也沒太多新穎之處,相較refactoring
12/05 00:28, 5F

12/05 00:29, , 6F
看到一半就懶得繼續看下去了,以後大概也不會看
12/05 00:29, 6F

12/05 07:53, , 7F
我和你的看法相反,覺得 Refactoring 有點囉唆,看到一半就懶
12/05 07:53, 7F

12/05 07:54, , 8F
得讀下去,倒是 Prefactoring 有很多令我玩味的點子...
12/05 07:54, 8F

12/05 16:32, , 9F
那真是太有趣了 XDXD 不過我覺得有個可能原因是,
12/05 16:32, 9F

12/05 16:33, , 10F
我看 ref.. 比 pref.. 早很多,時空上有不小的差異...
12/05 16:33, 10F

12/05 16:35, , 11F
真有趣 XDXD 我也讀 ref.. 比 pref.. 早很多,我覺得原因是,
12/05 16:35, 11F

12/05 16:37, , 12F
我讀的 ref.. 是中文版,而 pref.. 是英文版,讀感差很多
12/05 16:37, 12F
文章代碼(AID): #17LJ-wFK (OOAD)
文章代碼(AID): #17LJ-wFK (OOAD)