posts - 80,comments - 749,trackbacks - 2
          又是很久沒有寫B(tài)log了,這兩天大量的時間貢獻(xiàn)給了兩件事,一是看Eclipse的源代碼(工作需要),二是不斷回復(fù)以前寫的文章的評論。今天請了假, 抽了點時間來討論討論重構(gòu)。下面寫的東西您可能不太贊同,可能沒有遇到,也可能有其它更好的辦法,而我的觀點來自于我對Eclipse源代碼的理解和感 悟,無論您有什么想法請評論告訴我,不甚感謝。

          1。如果讓您隨手寫一個類,多半人會寫出一個以名詞命名的類,是的,我們的軟件中大量的類是以名詞來命名的。一個名詞表明了一組對象的共同類型,那么這個類型一定包括該組對象的共同屬性和共同方法。

          2。在幾次迭代之后我們發(fā)現(xiàn)類的屬性和方法都增多起來,這種粗放型的發(fā)展不利于軟件系統(tǒng)的整體結(jié)構(gòu)。而事實上,有很多類在80%的時間只需用到20%的屬性代碼,而20%的時間卻需要用到80%的方法代碼,因此,將訪問率不同的屬性和方法分開是必然的趨勢。于是有了Descriptor模式,它將一個原始類分成屬性集中化和方法集中化的兩個類,屬性類的命名方式采用原類名+Descriptor的方式,方法類可能沿用原名稱,或重新取個名字以動詞命名。這種重構(gòu)還有一個好處就是屬性類隨時可以加載,而方法類可能要到需要用時才懶加載。

          3。在經(jīng)過多次迭代的增加該類的代碼之后,我們發(fā)現(xiàn)Descriptor類的屬性增多起來,過多的屬性使代碼變得重量化,同時使結(jié)構(gòu)變得不清晰,一個擁有 過多屬性的類也會因知識過多而不易維護(hù),此時最好的方法是將這個類分裂為兩個,或多個。分裂的方法也有橫向和縱向兩種。橫向的分裂使類變成兩個不同的類, 它們往往叫兩個不同的名字且都為名詞,同時也可能互相持有對方(Change Unidirectional Association to Bidirectional

          4。縱向的分裂方法(Extract Class)往 往會將比較公共的部分分離取名為原類名+Model,另一個類名稱不變,Model類是后者的父類。加過Model以后的類輕磅了很多,更便于管理,責(zé)任 也更輕。至于哪些屬性應(yīng)該放在父類界限不是很嚴(yán)格,通俗的辦法是和原類名緊密相關(guān)的(特有的)屬性應(yīng)該留在原處,不是緊密相關(guān)的(特有的)放在Model 類,比如ID、Label什么的就應(yīng)該放在Model類。

          5。上面的方法反復(fù)用幾次,屬性集中的類就會變得越來越多。這時軟件結(jié)構(gòu)雖然看的很清晰,可是使用起來大為不便,因為很多相關(guān)的屬性可能會在同一個場合下使用,而它們的實體卻可能分布在不同的對象中。解決這個問題的方法只有增加接口的數(shù)量(Extract Interface),多使用一些小接口,每個小接口表達(dá)了一個方面的含義,使用者在使用這些小接口時無法觸及它的實體對象(Prototype), 這種方法的優(yōu)劣性在于使用者對于架構(gòu)的理解,如果用的好這種方法會顯現(xiàn)出很多面向方面的特性,如果用的不好則是畫蛇添足,導(dǎo)致了接口的泛濫(還記得Dll Hell嗎,Java是不是正在形成一個Interface Hell?Eclipse是不是正在形成一個Plugin Hell?)。

          6。在大量應(yīng)用了方面接口之后,我們又面臨著這樣的問題,很多使用這些Model的人其實只是關(guān)心其中的一部分固定屬性,和幾個為數(shù)不多的固定方法,有時連重量級方法都不關(guān)心,只關(guān)心用以交互的查找型get方法,對于這些使用者,我們只需提供一個門面(Facade)即 可。一個Facade包括在一個Model類和Descriptor類的群體中提供一組可以找到任何一個屬性的線索,其中的每一個線索都開始于 Facade,結(jié)束于存放對應(yīng)屬性的屬性類,且遵循“最常用到的屬性,其線索最短”的原則。因而Facade絕不僅僅是一個類,而是一個完整的體系結(jié)構(gòu)。

          7。接下來還有一個持久化的問題。如果一個類型存在對一個復(fù)雜類型的引用,這個復(fù)雜類型很可能被深深的隱藏在Facade之后,而且很可能是個不可持久化 的類型,那么如果前者要持久化,它只能保存一個該復(fù)雜類型的關(guān)鍵碼,并在持久化喚醒時很容易通過某個服務(wù)取到該關(guān)鍵碼所對應(yīng)的對象。這個復(fù)雜過程沒理由要 求Facade以外的類來完成,因此有了Reference模式(Change Value To Reference),即為那個復(fù)雜類型定義一個類,類名為原類名+Reference,其責(zé)任是保存原類型的關(guān)鍵碼和查找原類型的真實對象。Reference類通常定義為可持久化。該模式的另一個好處是不必要常常訪問Facade,因為一個Facade也有可能極其復(fù)雜。

          8。在分析完屬性集中化的類和類群之間的關(guān)系之后,我們來看看方法集中化的類。這個類也有可能面臨方法激增的問題,此時想把一個類拆分成多個可沒有拆分屬 性集中化的類那么容易了,因為它們往往相互調(diào)用,耦合度極高,但又不能不拆(還記得Kent Beck曾經(jīng)說過的嗎,“如果一個類的責(zé)任超過三個,我們就必須把它拆開以保證每個類的責(zé)任都不超過三個”)!幸好我們有Delegate模式可 供選擇,一個方法類可以由它的訪問子和工作子兩個角色來完成,就像銷售部門和生產(chǎn)部門一樣。訪問子還以原類名來命名,但是它不做實際的工作,只作實際工作 的準(zhǔn)備工作(比如收集信息)和后續(xù)工作(比如轉(zhuǎn)換結(jié)果),生產(chǎn)性的工作交給工作子完成,后者通常以原類名+Delegate命名。這樣做的另一個好處就是 Delegate類可能很重磅,并面臨大量的資源分配,因而可以懶加載。

          9。現(xiàn)在我們有了一個不錯的體系結(jié)構(gòu),它包括一些輕量級的類、類的關(guān)系和設(shè)計模式,但是,不要以為這些東西是開始時就設(shè)計好了的,即使神仙也做不到那樣,令人驚奇的是,它們都是從剛剛您寫的一個名詞開始的。^_^

          經(jīng)常重構(gòu)的泡泡

          posted on 2005-04-13 10:54 Brian Sun 閱讀(2634) 評論(4)  編輯  收藏 所屬分類: 軟件

          FeedBack:
          # re: 高級重構(gòu)方法的連用
          2005-04-13 17:19 | tacyuko
          通宵3天的翻譯結(jié)束了,好開心啊
          看到你的長文,好郁悶啊  回復(fù)  更多評論
            
          # re: 高級重構(gòu)方法的連用
          2005-04-13 21:00 | idior
          屬性擴展的現(xiàn)象在個人應(yīng)用中還真不是那么明顯。在其他書上似乎也很少提到,泡泡個人感覺如何?(除了在eclpise)
          還有責(zé)任分配的那個模式gof叫做bridge。用XXXdelegate來取類名感覺會影響該類的重用性。(被限于XXX使用)  回復(fù)  更多評論
            
          # re: 高級重構(gòu)方法的連用
          2005-04-14 17:26 | Brian Sun
          呵呵,謝謝指點,我也覺得delegate的使用確實有些局限,但是在Eclipse當(dāng)中,情況是這樣的,在Eclipse中一個Action往往在窗體初始化時就需要關(guān)于它的很多屬性和特征,但是它的執(zhí)行實體卻只有在用戶點擊觸發(fā)這個Action時才會被懶加載,所以一個Action會把自己的執(zhí)行體包裝在一個ActionDelegate當(dāng)中。還有什么問題,請指正。。。。謝謝!

          泡泡
            回復(fù)  更多評論
            
          # re: 高級重構(gòu)方法的連用
          2007-06-21 13:38 | FrankShaka
          怎么以前沒發(fā)現(xiàn)你有這篇文章?

          在網(wǎng)上找了半天,好像只有你這里講到了Descriptor模式和Reference模式。現(xiàn)在Reference模式我用的很爽啊,哈哈。。。。。  回復(fù)  更多評論
            
          主站蜘蛛池模板: 泰和县| 丰城市| 得荣县| 东阳市| 明溪县| 台南市| 临湘市| 保定市| 泸溪县| 尼木县| 天津市| 内黄县| 柳州市| 韶关市| 柞水县| 九龙县| 龙山县| 肥西县| 泊头市| 申扎县| 通许县| 寿阳县| 达日县| 济源市| 姜堰市| 礼泉县| 枞阳县| 攀枝花市| 永春县| 中山市| 当涂县| 綦江县| 新和县| 朝阳县| 修武县| 洪雅县| 三穗县| 大竹县| 威远县| 保靖县| 武鸣县|