Posted on 2008-10-28 00:43
非魚 閱讀(2596)
評論(1) 編輯 收藏 所屬分類:
面向對象設計 、
Java技術
5. Feature Envy
Feature Envy,按照Martin Fowler的定義是:
函數對某個class的興趣高過對自己所處之host class的興趣。通常的代碼檢查工具會根據一個類中的方法調用另一個類中方法的次數來判斷是否存在Feature Envy。
遺憾的是這個定義是含糊的。Feature Envy做為一種代碼現象,如果不能精確的描述和界定其害處,就不能指導我們如何正確處理它,因此我們需要定義什么是有害的Feature Envy。
定義一個有害的Feature Envy,必須從封裝說起。
封裝是面向對象最根本的原則,泛泛的定義是“把數據和對數據的操作丟到一起就是封裝”。這對實踐毫無益處,每個人都可以很容易的理解這句話,但仔細想想,過往設計過的對象,有多少是封裝良好的?
因為我們不知道封裝的根基,這是東方文化中缺乏的東西。大家都知道要封裝,但不知道封裝什么:
“讓上帝的歸給上帝,凱撒的歸給凱撒。”不要把狗尾巴裝到貓身上。當然在實踐中總是不那么簡單的。在日常生活中,我們常常不知道誰有什么樣的權利,不知道某個東西屬于誰,不知道誰是管事的等等。長期處于這樣的環境中,使人習慣于一種莫愣兩可的態度。人都這樣了還怎么分的清楚權屬呢。但在設計之初記住這個還是有益的。
這是上一個原則的推論。西方人常說的兩句話是:It's you business, not mine. None of your business. 西方人認為你的是你的,我的是我的;中國人認為你的是我的,我的還是我的。在我們設計的類中,常常可見就現象就是大雜燴,什么方法都丟到一個類里面處理了。
這也是把不變的東西抽象出來的過程。變化無處不在以具有相對性,把相對不變和相對易變的東西分離開,這個過程是一個抽象的過程,也是對已封裝對象的解包和再封裝。顯然封裝變化是從時間的角度來考察對象,結合“軟件”的可變特性而來的。如果說封裝權屬和封裝職責在于尊重現實,那么封裝變化就是設計過程中真正體現價值的東西。前者意味著照貓畫虎,后者才見設計者的功力。
而所謂“代理”,基本上就是封裝職責(甚至封裝權屬,比較少見)和封裝變化的結合。
現在我們可以定義一個有害的Feature Envy了:在非代理情況下,對象權屬的屬性或數據、職責在另外一個對象中,并且被這個對象頻繁調用,從而破壞了封裝的情形。
借助于代碼檢查工具,我們可以輕易的找出類之間頻繁調用的方法;考慮上述定義,我們可以在恰當的時機進行重構,消除有害的Feature Envy。
feature envy, encapsulation, responsibility, refactor