07 January 2014

今天跟同事 pair 時,設計到一些細節時,我很直覺的就做了 A 決定,接著他就反問為什麼要 A 而不是 B。當下的一瞬間我是答不出來的,我只知道要這樣做,但原因有點年代久遠,一時想不出來了。

一個例子是 Database table,這是記錄各個 App 各自用戶帳號的資料表,不同的 App 可以有重覆的帳號名稱:

Create Table AppAccount (
    id int primary key,
    appName varchar,
    userName varchar
);

顯然地,appName 和 userName 兩者合起來是唯一的,是 composite unique。然後我就加上了 id 這個欄位做為 primary key,這時同事則反問為何不是 appName, userName 這兩者直接變 composite primary key?

另一個例子是,我有一個 http request 的需求,有兩個 request 的參數很接近,差一兩個欄位:

class FooRequest {
    String userName,
    String token,
    String fooCertificate,
    boolean isProduction
}

class BarRequest {
    String userName,
    String token,
    String barKey
}

ok, 上面兩個 Request 做類似的事,都有 username 和 token 這兩個共通欄位,這時他建議抽一個共用的 Request,讓 Foo/Bar 去繼承,來共用欄位。我則說就保持這樣就好。

他的 顯然的決定我的 不同。他的想法直接,我的則好似拐彎抹角。我當下試圖解釋一番,但其實我也只敲了邊鼓,因為真正的原因早就忘了。我最近發現自己常幹這種事。

第一個例子的答案在 Surrogate key。Wikipedia 上明列了這個做法的優缺點。這些優缺點我也實際體驗過了,我的身體記得,為了應付需求變更,Entity 的 primary key 最好和 domain 無關。而且在大多數的情況下,可以保持 immutabilty,未來出錯的機會就低。(Surrogate key 一產生就永遠不會改了)。

第二個例子的答案這裡有一些:disavantages of inheritance。Joshua Bloch 在 Effective Java 有 3 個項目說少用繼承為妙,而久遠以前在 Javaworld 上也有一篇 Why extends is evil 。這些以前都讀過了,但我的身體只記得:如果物件沒有共通的 行為 ,那大概物件不適用繼承關係,就這樣。

當然,真正說起來沒所謂正確的決定,只有未來才會知道當時的決定是對的還是錯的。但我們工程師每天就是要面對一堆大大小小的問題,要迅速做決策。那怎辦?就以過去的經驗為前鑑,建立*最佳實踐*,期望不要再犯類似的錯誤。

我過去學了很多最佳實踐,不過現在只記得模糊的結論,其原由卻忘了差不多。某方面來說好像是被填鴨的考生,只背答案卻不知為什麼。某方面也像是說不出所以然、倚老賣老的傢伙。難怪常會聽到有人把一本書 K 好幾遍,時時複習。我想我該重讀一次 Effective Java 了。


回響

可以用 Tag <I>、<B>,程式碼請用 <PRE>