YUUNJIEE.COM
til-refactor-code-smells.md
[_][□][✕]
📄til-refactor-code-smells.md×
blog/til-refactor-code-smells.md

TIL: 重構程式碼的原則

2026-05-21·3 min read·updated 2026-05-21·OOPrefactoringDesign PatternsOOAD

OO 是為了讓程式容易改,不是設計漂亮。紀錄 Move Method、Switch Smell 兩個Bad Code,以及什麼時候不需要做物件導向。

最近 OOAD 課講重構原則,整理幾個覺得很有用的觀念。

重點

物件導向的主要目的,是讓程式碼可以輕鬆地維護、改變和演化。不是為了讓設計看起來漂亮,也不是為了效能,好的架構不等於好的效能

課堂中老師說到:不要 Over Design。如果一段程式碼幾乎沒有變動需求,硬要轉成 OO 基本上是浪費時間。重構和設計模式是工具,用在對的地方才有價值。

Move Method

A method should be on the object whose data it uses.

如果一個方法大量使用另一個 class 的資料,那它應該搬過去。

java
// 問題:OrderPrinter 的 print() 幾乎都在用 Order 的資料class OrderPrinter {    void print(Order order) {        System.out.println(order.getCustomer());        System.out.println(order.getTotal());        // ...    }}// 搬過去比較自然class Order {    void print() {        System.out.println(this.customer);        System.out.println(this.total);    }}

判斷的問題可以問自己:這個 class 真的需要知道這件事嗎? 如果不需要,就搬。搬移本身就是重構,不需要改任何邏輯。

Switch Smell

It is bad to do a switch based on an attribute of another object.

java
// 問題:根據 animal.type 決定行為,邏輯分散在外面switch (animal.getType()) {    case "dog":  animal.bark();  break;    case "cat":  animal.meow(); break;}

問題是每次新增一種動物,就要找到所有 switch 去加 case,容易漏改。

解法是用繼承把行為封裝進去:

java
abstract class Animal {    abstract void speak();}class Dog extends Animal { void speak() { System.out.println("Woof"); } }class Cat extends Animal { void speak() { System.out.println("Meow"); } }// 呼叫端只需要animal.speak();

新增動物只要加一個子類別,不用動任何 switch。

繼承的限制

An object cannot change its class during its lifetime.

如果物件的狀態或行為會在執行期間改變,繼承就會卡住:

java
Movie m = new NewReleaseMovie("Inception");// 一個月後,它變成舊片了...// 沒辦法直接把 m 的 class 換掉,只能 clone & destroy// 但其他地方還持有 m 的 reference,很容易出問題

這時應該改用 Strategy Pattern:把「會變的行為」抽成獨立物件,讓主物件持有它。

java
class Movie {    private Price price;    void setPrice(Price p)     { this.price = p; }    double getCharge(int days) { return price.getCharge(days); }}// 變成舊片,只要換 price 物件就好movie.setPrice(new RegularPrice());

主物件不換,策略換。

這樣就不是 code reuse,而是 pattern reuse 了。

繼承共享的是程式碼本身;Strategy 共享的是解題的思路。後者在面對需求變動時彈性高很多。


之前有一篇筆記是從租片系統實作角度寫 Strategy Pattern,可以對照著看。

share
ONLINE·yuun@blog·v2.7.0