Posted on 2008-10-29 22:20
非魚 閱讀(3051)
評論(0) 編輯 收藏 所屬分類:
面向對象設計 、
Java技術
6. 使用具體的類定義變量
使用具體的類來定義變量,可能導致代碼中存在抽象問題。這里所說的變量包括靜態變量、實例變量、本地變量、方法的參數和返回值。
更加具體一點說,在組織內部的代碼中,如果存在一個類繼承關系,并且這個類繼承關系中的具體類被用來定義變量,則這里有問題的可能性比較高。我們定義抽象類或接口的目的就是抽象使其脫離易變的實現細節,如果抽象了穩定的接口而不在變量定義中使用它,那還有什么意義呢?
使用具體類定義變量的問題就在于,這通常綁定了實現類而缺乏抽象,難以適應未來需求的發展,難以維護而增加成本。
相對來說,使用具體類定義本地變量的影響是最小的,在可以控制的范圍之內;使用具體類定義實例變量和靜態變量,如果變量是private的,基本也在可控的范圍內。
如果實例變量和靜態變量package、protected或public的,需要特別的當心。這時候實際上已經向外界(當前類之外)隱含的“發布”了這些變量,它們可能已經不在你的控制范圍之內了。由于封裝的不嚴密并且直接泄漏了具體的、不穩定的實現,極易導致代碼在維護過程中的失控,并且給測試帶來了困難。如果沒有特別的理由,這樣的代碼是一定要修正的。修改變量的可見性是最好的方式,這要求對變量的使用情況進行檢查(現代的IDE一般都支持Find Usage),如果這些變量已經被類外部的代碼使用了,修改的工作量會大大增加,同時修改可見性也需要對最初的設計進行重新評估;這樣把具體類修改成抽象類或者接口就成為了退而求其次的解決方案。如果時間允許,二者同時進行是最好的,長遠來看也是最低成本的。
使用具體類定義方法的參數和返回值也不好,這樣做的危險程度是中等的。這使對象之間的通信契約建立在了相對具體的層次上,缺乏抽象而難以適應變化,自然也帶來了維護成本的增加。但契約的修改比直接對“隱私”的侵犯稍好一點,并不會帶來對內部實現的大規模、不可控的破壞。當然,如果在代碼檢查中發現了這樣的問題,也要盡可能修改。
在代碼檢查工具的實現上,對具體類定義本地變量、實例變量、靜態變量、方法參數和返回值的檢查可能是分離的。這樣我們也有機會對檢查的詳細程度進行定制。我個人的觀點是,除本地變量之外的情況是一定要檢查的。
對于第三方產品來說,也應該盡量使用抽象類和接口來定義變量。不然你就把自己放在了一個比較危險的境地了。而且,部分代碼檢查工具,可能并不會檢查這樣的情況。
concrete class, variable, code review, abstraction, visibility