本文是java.net上的一篇博客,作者Curtis Cooley對編寫好的面向?qū)ο蟠a有些建議,希望對大家都有所幫助。(2008.10.08最后更新)
獲取經(jīng)驗沒有捷徑。編寫好的面向?qū)ο蟠a需要經(jīng)驗,但這兒有三種做法能幫你在一開始就很順利,即便你是老頑固:
1. 使用測試驅(qū)動開發(fā)(TDD)編寫你所有的代碼
2. 遵循簡單法則
3. 告之而非問之
使用TDD編寫所有代碼
按測試先行編寫的代碼與按測試后行編寫的代碼是極為不同的代碼。按測試先行編寫的代碼是松耦合與高聚合的。當某個屬性或私有方法需要暴露給測試程序時,按測試后行編寫的代碼常會打破封裝,因為該類并不是為了測試而設(shè)計的。如果你首先編寫測試代碼,你的依賴將會更好,你的代碼將是松耦合與高聚合的。后面會有更多關(guān)于測試能幫助你設(shè)計更佳代碼的內(nèi)容。
遵循簡單法則
代碼是簡單的,只要當它:
1. 執(zhí)行了所有的測試
2. 不包含重復(fù)
3. 表達了所有的意圖
4. 使用最少的類和方法
注意到我用的是個被排序了的列表是很重要的。順序是重要的。只有一個main()方法的的GodClass[1]不會是簡單的。這個類可能執(zhí)行了所有的測試,但在任何比"Hello, world!"更復(fù)雜的程序中,它肯定包含了重復(fù),并且也沒有表達出全部的意圖。
我努力使用簡單法則去關(guān)注If問題。我不知道如何使用簡單法則去阻止某人編寫重量級的If代碼。有人可能會提出不同意見,我也嘗試過,但這樣的重量級If代碼確實無法表達意圖。但當你閱讀如下代碼時
alert();
}
我還有一點兒靈感顯現(xiàn)。如果有那樣的代碼,那么在其它地方肯定還會有更多那樣的代碼。這些代碼可能就像:
registerGasReading();
}
sendTextMessage();
}
notifyLocation();
}
告之而非問之
簡言之,告之而非問之意指不要先問一個對象的狀態(tài),然后才讓它去工作。而應(yīng)該告之對象如何去工作。這就意味著之前所有的那些If例子應(yīng)該變?yōu)椋?/span>
傾聽你的測試程序也能幫助你保持代碼的簡潔。
void alert(Mobile mobile);
}
public class Siren implements Alarm {
public void alert(Mobile mobile) {
if (mobile.getType == MobileTypes.STANDARD) {
soundSiren();
}
}
}
public class TestSiren extends TestCase {
public void test_alert() {
LocationMobile mobile = new LocationMobile();
Siren siren = new Siren();
siren.alert(mobile);
assert(sirenSounded());
}
}
private Alarm alarm;
public LocationMobile(Alarm alarm) {
this.alarm = alarm;
}
public void alert() {
alarm.alert(); // alert on Alarm no longer needs a mobile
}
}
public class TestLocationMobile() extends TestCase {
public void test_alert() {
Alarm alarm = EasyMock.createMock(Alarm.class);
alarm.alert();
EasyMock.replay(alarm);
Mobile mobile = new LocationMobile(alarm);
mobile.alert();
EasyMock.verify(alarm);
}
如果你使用TDD,并遵循簡單法則和告之而非問之原則去編寫所有的代碼,你就處于成為一個更好的面向?qū)ο蟪绦騿T的道路上了。好的面向?qū)ο蟠a易于閱讀和維護,但難以編寫,至少,在開始時是這樣的。你寫的越多,你就會變得越好,也會獲得更多的經(jīng)驗。同時,這些實踐經(jīng)驗也會使你在自己的道路上受益匪淺。
譯注
[1]GodClass(上帝類)指包含了太多內(nèi)容的類。