強迫性 Immutable 症候群
自從看了 Domain-Driven Design 這本書之後,唉~ 不知該說好還是壞。就說裡面提到的 Side-effect free function 吧。side-effect free指的是 object 是 immutable 的,做了改變不會影響到本身也不會氾濫到其他的 object,而 function 則是指這個 method 可以執行多次而結果都一樣 (數學的 function 都是這樣)
直覺式的錢包計算:
//[code snip #1]
public class MoneyBag {
private int asset ;
public void spend(int expenditure) {
asset -= expenditure;
}
}
這樣夠嗎?當然不夠,還要加 precodition 和 post-condition:
//[code snip #2]
public class MoneyBag {
private int asset ;
public void spend(int expenditure) {
if(expenditure <= 0)
throw new IllegalArgumentException();
final int diff = asset - expenditure;
if(diff < 0){
throw new InsuffienctMoneyException();
}
asset = diff;
}
}
夠醜吧,真正的 logic 只有一行,卻弄成啊哩啊扎的
如果另外寫個 Immutable Value Object "Money":
//[code snip #3]
public class Money {
private int dollar ;
public Money(int dollar) {
if(dollar <= 0)
throw new IllegalArgumentException();
this.dollar = dollar ;
}
public Money minus(Money money) {
int diff = this.dollar - money.dollar ;
if(diff < 0){
throw new InsuffienctMoneyException();
}
return new Money(diff) ;
}
}
MoneyBag 就不用再煩惱 "錢" 的問題了,變得很簡捷:
//[code snip #4]
public class MoneyBag {
private Money asset;
public void spend(Money expenditure) {
asset = asset.minus(expenditure);
}
}
spend() 變得超直覺的 ==> "剩下的錢等於現在的錢 minus 消費額"
再看另一個例子:
//[code snip #5]
public Money calculateDiscount(Money expenditure) {
Money allowance = expenditure.multply(0.9) ;
return expenditure.minus(allowance);
}
不會有人看不懂這個method在做什麼吧.... 已經非常非常白話了。
- minus() 這個 method 重用了
- 隨便你怎麼 call、怎麼組合、call多少次都不會錯
- 核心邏輯可讀性很好,接手維護的人會感動到哭
這些優點都是歸功於 Side-effect free function 的設計理念。真是棒呆了...... 呃... 事情若這麼順利就好了。自從看完這個章節後.... 我的眼中只容的下 Immutable Object ! 哇咧~~ 一看到有什麼 method 不是 immutable 的,就想做 refactoring。再加上功力又不太夠,沒辦法很正確的判斷,搞得 原來的 class 一團亂 -_-;;。而且,本來嘛,那個 MoneyBag 是一個 class 就搞定了,現在要多生一個 Money class 出來,Immutable 好像天生就很容易增加 class 數量的樣子... 這樣到後來也不怎麼好維護吧?!
唉~ 不知該說好還是壞~~
0 Comments:
張貼留言
<< Home