很多時候我參與API的設計/實現,我面臨着這樣的困境。編寫/實現API:可測試性與信息隱藏
我的information hiding一個非常強有力的支持者,並嘗試使用各種技術的是,包括但不限於內部類,私有方法,包私人預選賽等
的問題,這些技術是他們傾向於防止良好的可測試性。雖然其中一些技巧可以解決(例如通過將課程放入同一個包中來實現包的私密性),但其他技術可能需要反思魔術或其他技巧。
讓我們看看具體的例子:
public class Foo {
SomeType attr1;
SomeType attr2;
SomeType attr3;
public void someMethod() {
// calculate x, y and z
SomethingThatExpectsMyInterface something = ...;
something.submit(new InnerFoo(x, y, z));
}
private class InnerFoo implements MyInterface {
private final SomeType arg1;
private final SomeType arg2;
private final SomeType arg3;
InnerFoo(SomeType arg1, SomeType arg2, SomeType arg3) {
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
}
@Override
private void methodOfMyInterface() {
//has access to attr1, attr2, attr3, arg1, arg2, arg3
}
}
}
有充足的理由不暴露InnerFoo
- 沒有其他類,庫應該可以訪問它,因爲它並沒有定義任何公共合同和筆者特意沒」 t希望它是可訪問的。然而要實現100%TDD-猶太和訪問沒有任何反映技巧,InnerFoo
需要重構這樣的:
private class OuterFoo implements MyInterface {
private final SomeType arg1;
private final SomeType arg2;
private final SomeType arg3;
private final SomeType attr1;
private final SomeType attr2;
private final SomeType attr3;
OuterFoo(SomeType arg1, SomeType arg2, SomeType arg3, SomeType attr1, SomeType attr2, SomeType attr3) {
this.arg1 = arg1;
this.arg2 = arg2;
this.arg3 = arg3;
this.attr1 = attr1;
this.attr2 = attr2;
this.attr3 = attr3;
}
@Override
private void methodOfMyInterface() {
//can be unit tested without reflection magic
}
}
這examply只涉及3個ATTRS,但它是相當合理的,有5-6和OuterFoo
構造函數將不得不接受8-10個參數!在頂部添加getters,並且您已經有100行完全無用的代碼(獲取這些attrs以進行測試也需要getter)。是的,我可以通過提供構建器模式來改善情況,但我認爲這不僅是過度工程,而且也會挫敗TDD本身的目的!
此問題的另一個解決方案是公開類Foo
的受保護方法,將其擴展到FooTest
並獲取所需的數據。再次,我認爲這也是一個不好的方法,因爲protected
方法的確定義合同並通過公開它我現在已經隱式簽署它。
不要誤解我的意思。 我喜歡寫可測試代碼。 我喜歡簡潔,乾淨的API,短代碼塊,可讀性等。但是我不喜歡的是在信息隱藏方面做出任何犧牲只是因爲單元測試更容易。
任何人都可以提供任何想法(通常,特別是)?給出的例子還有其他更好的解決方案嗎?
你基本上提出了一個討論話題,而不是問一個可以回答的具體問題。至少對於你提出更好的方法來編寫特定代碼的部分,你最好在http://codereview.stackexchange.com上提問。 – 2011-02-17 16:55:47
如果您認爲這不僅僅是一個問題而是一個討論主題,請隨意將其轉換爲社區wiki。至於codereview ..它只有229個問題在整個網站和出席是糟糕的。我不知道人們不允許在SO問題上發佈代碼......而且,這更多的是僞代碼而不是具體的代碼。 – mindas 2011-02-17 16:59:12
不知道你爲什麼會努力避免反思。它有它自己的缺點,但是如果它允許你維護你想要的安全模型而不需要僞代碼,這可能是一件好事。 – 2011-02-17 17:17:55