l

2013年3月4日 星期一

Public Interface不等於Published Interface

Mar. 2 22:45~23:51

image

前幾天寫了《要不要幫Private Method寫單元測試?》以及後續的補充說明文《Private Method不該有複雜的邏輯嗎?》,沒想到不但沒有達到說明的效果,反而越描越黑挑眉質疑。之前寫的技術文章好像都沒獲得什麼迴響,難得這次有文章引起引起比較多的討論,今天就再「歹戲拖棚」一次,說明之前那兩篇沒解釋清楚的地方。

***

幾件事補充說明一下:

  1. Teddy以前寫程式針對比較複雜的private method是會直接幫它寫單元測試的,以前Teddy並不會特別覺得這樣有什麼不對,只是覺得透過reflection的方式來測試(Java)private method不太直覺也不是很方便而已。
  2. 前兩篇文章中所謂「private method有著複雜的邏輯」,並不是說這個private method一定要幾百行以上,或是要有N層的nested結構,或是有非常複雜的條件判斷式。Teddy只是單純從可否透過測試public method就可不必太費功夫測試到private method的角度來判斷這個private method是否過於複雜。
  3. 前幾天Teddy重讀《JUnit Recipes》,看到書中對於是否要直接測試private method的看法,當下覺得蠻有道理的(N年前讀過這一段沒什麼感覺)。此時Teddy回想以前開發的軟體,的卻有不少情況當自己將public method的實作整理成呼叫若干個private method之後,得到了所謂的「比較複雜的private method」。當時Teddy並沒有覺得這樣的現象有什麼問題,但是現在回想起來,有不少情況是因為當初的設計讓一個類別負擔太多責任而自己不自知。
  4. 還有一個觀念是Teddy在前兩篇文章中沒有提到的,就是「public method不等於published method」。先撇開測試問題不談,大部分的人應該都會認為一但把method變成public,日後要修改這個method的介面便會影響到呼叫該method的所有client。這樣的觀點是把public method等同published method,如果可以將者兩者區分,在設計上(與測試上)會有很多彈性。「Public method不等於published method」的觀念是2002年Teddy還在念書時,讀了Martin Fowler發表在IEEE Software的《Public versus Published Interfaces》這篇文章所學到的。舉個例子,Teddy認為Eclipse的設計套用了這樣的觀念,在Eclipse中有許多class被放在internal package。從程式語言的角度來看,放在internal package的public class/method雖然是屬於public interface,但從設計者的角度來看,並不是published interface。也就是說,放在internal package的類別介面很可能會一直變動,若客戶端堅持要直接呼叫,日後介面改變的風險請自負。
  5. 軟體設計原本就沒有標準答案,也請鄉民們不要在「搞笑談軟工」找標準答案。Teddy在部落格中無病呻吟的一狗票文章,也僅是提出Teddy寫文章當下的「個人看法」,鄉民們都有權利同意不同意Teddy的看法。同意或不同意都是好的現象,只要不要看不懂就好了…XD。
  6. 最後,Teddy將前兩篇關於是否要測試private method的看法再整理一次。
    • 請先考慮透過public method來測試private method。
    • 如果透過public method來測試private method很難,請檢視一下該類別是否負擔太多責任。
      • 如果是,請重構。
      • 如果自己認為不是,請找朋友幫你確認一下熱戀
      • 如果真的、真的不是,那答案就呼之欲出了。要嘛就是寫稍微複雜一點的測試案例,還是透過public method來測試private method;要嘛就是直接測試private method。
    • 如果還不清楚,可參考這篇文章《Testing Private Methods with JUnit and SuiteRunner》(感謝Joey Chen提供補充資料)。

***

鄉民:我還有一個問題,如果published interface改變了怎麼辦?

Teddy:這個問題 很久以前 Teddy在《Checked or unchecked exceptions (3)》有提過:

  • Separating a public interface from a published interface
  • Refactoring unpublished interfaces
  • Declaring published interfaces with circumspection
  • Making published interfaces immutable

***

友藏內心獨白:一個問題生出三篇,好划算啊熱戀

沒有留言:

張貼留言