<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Sky's blog

    我和我追逐的夢

    常用鏈接

    統計

    其他鏈接

    友情鏈接

    最新評論

    淺談spring和依賴注入的價值

    javaeye上看到有帖子,置疑spring和依賴注入的價值,回復內容整理如下:

    依賴注入對設計有利,而spring則促進了依賴注入的使用。

    如果業務處理類,它所使用的倚賴,都是依靠在這個類內部實現或者查找,那么必然使得正常的業務邏輯和獲取依賴的方法混在一起。

    我取個最簡單的場景,某個注冊的工作類,它需要獲取當前"容許的用戶名的最大長度",這個依賴非常簡單吧?基本每個注冊類都有這個限制,我們現在 把場景考慮的全面一點,對于復雜一點的系統,這個最大長度的限制可能來源很多,比如配制文件,數據庫,可能類工作在前臺比如web而配制在后臺,可能需要 和第三放系統一起工作而需要到第三方系統中獲取而對方只提供web service...

    這么一個簡單的依賴,“用戶名的最大長度”,如果用依賴注入,只要一個簡單的setUsernameMaxLength()方法就可以搞定。考慮 上面那么多種可能都出現,最惡劣的情況是要求一個系統可以同時支持然后通過配制方式進行,這對于將一個產品賣給n家客戶的公司來說是最正常不過的要求。

    那么我們來看一個很有"spring"風格的采用依賴注入的設計,通常都將會是這樣:

    注冊工作類:
    public void RegisterWork {
    public void setUsernameMaxLengthProvider(UsernameMaxLengthProvider provider) {
    int maxLength = provider.getUsernameMaxLength(); //簡單獲取結果,不管provider細節
    }
    ....
    }
    “用戶名的最大長度”的提供者接口
    public interfacd UsernameMaxLengthProvider {
    public int getUsernameMaxLength();
    }
    “用戶名的最大長度”的提供者則可以有以下實現,都只負責讀取數據,不關心數據被誰使用,怎么使用:
    1.直接提供,可以用spring 構造函數方式注入usernameMaxLength值,也可以junit測試時直接new DirectdProvide對象
    public class DirectdProvider implements UsernameMaxLengthProvider {
    private int usernameMaxLength = 10;
    public int getUsernameMaxLength() {
    return UsernameMaxLength;
    }
    public DirectdProvider (int usernameMaxLength) {
    this.usernameMaxLength = usernameMaxLength;
    }
    }
    2.讀本地配制文件
    public class LocalConfigFileProvider implements UsernameMaxLengthProvider {
    public void read(File configFile) {
    usernameMaxLength = ....
    }
    }
    3.類似的從數據庫讀取 DatabaseProvide
    4.類似的web service從第三方讀取 WebServiceProvider
    5.其他的可能擴展的方式

    開發時邏輯清晰,代碼可讀性超強,基本看類名和函數名搞定。測試時,輕松測試RegisterWork,testcase中只要 worker.setUsernameMaxLengthProvider(new DirectdProvider(20))就搞定。而針對UsernameMaxLengthProvider的幾個實現類,更是輕松使用junit,每 個都覆蓋一遍。

    呵呵,現在我們可以砍刀,最簡單的一個int型的“用戶名的最大長度”,都可能遭遇如此復雜的場景。如果不用倚賴注入,而是選擇在RegisterWork中自己搞定“用戶名的最大長度”的獲取,那么可能要遇到以下問題:
    1. RegisterWork極其復雜,可以想像類似的依賴肯定還有其他
    2. 獲取“用戶名的最大長度”的方式和注冊的業務處理邏輯完全沒有直接聯系,對注冊過程來說它只關注結果,“用戶名的最大長度”是10還是20,而不是到底讀本地文件還是讀數據庫。喧賓奪主了,次要邏輯干擾了主要邏輯
    3. 難于測試。獲取“用戶名的最大長度”的方式的這些代碼,被藏在RegisterWork類中,而且很有可能是private方法不對外暴露(如果不依賴注入還需要暴露嗎?暴露給誰呢),怎么用mock測試?怎么能保證以上幾種的實現都覆蓋到?
    4. 難于擴展。就算上面都搞定了,某一天突然來了一個變態需求,要求用ldap從另一個地方取配置呢?難道再把ldap請求的那一大片代碼也寫到RegisterWork里面?
    5. 更難于被第三方擴展。運氣好,上面這個ldap取配制的變態需求客戶開始沒有要求。順利開發完成測試通過然后準備上線,最后一晚了客戶才發現,"哦,給忘 了,你們想辦法給加上,快,快,明天一早就要上線運行了...你們寫死在代碼里面了?那只能你們修改了原代碼了"。吐血了吧,先罵一頓,可是活還的干啊, 咬牙切齒的把新的實現代碼加上了,還得編譯打包更新重啟...如果是spring多好,單獨寫一個LdapProvider類,測試(這個測試比雜在 RegisterWork里面測試簡單的多)通過后單獨提供這個class仍classpath下,修改spring的配制將原來的 ***Provider替換掉,輕松搞定,甚至可以把這活仍給客戶的開發人員,告訴他們怎么替換就可以了,管你ladp還是其他,誰讓你們需求不明確,自 己擴展去。
    6. 容易出錯。剛吐血完成上面的變態需求,更新完畢,一會客戶電話來了,“...怎么...不正常了?”。又吐血幾升地檢查,終于找出來了,原來是剛才寫 ladp訪問的代碼時不小心改錯了RegisterWork的一個地方,誰讓RegisterWork類有幾十上百個方法好幾千行呢,一時急,又沒有測試 到......可是客戶不會理解的。

    上述的場景,spring + 依賴注入的設計方式,優點很明顯吧。

    再考慮一下維護和二次開發的問題,上面的spring + 依賴注入的代碼,好看易懂,方便擴展,維護起來輕松。如果是那么堆在RegisterWork里面,在那個大堆中代碼要找出這些代碼并讀懂,估計不是件輕松的事情。

    代碼維護是需要成本的,寫出易于維護的代碼,是一個優秀程序員的基本素養,至少,不能讓下一個接手的人罵娘吧?

    posted on 2008-01-11 22:30 sky ao 閱讀(3089) 評論(6)  編輯  收藏 所屬分類: spring & IOC

    評論

    # re: 淺談spring和依賴注入的價值 2008-01-12 11:47 lingos

    樓主的例子為什么非要是spring + 依賴注入的設計方式才能做到?
    只要設計做的好,80%的東西根本就不需要依賴注入,比如
    public interface UsernameMaxLengthProvider {
    public int getUsernameMaxLength();
    }

    public void setUsernameMaxLengthProvider() {
    //獲取接口的實現類
    UsernameMaxLengthProvider provider=HandlerFactory.getInstance().getHandler(UsernameMaxLengthProvider.class)
    }

    配置:
    <handler-config>
    <handlers>
    <UsernameMaxLengthProvider>
    LocalConfigFileProvider
    </UsernameMaxLengthProvider >
    </handlers>
    </handler-config>

    一樣也可以做到hotswap任意接口實現類!
      回復  更多評論   

    # re: 淺談spring和依賴注入的價值 2008-01-12 11:49 lingos

    最是厭惡spring動不動的一堆bean.xml,IOC過渡使用的一個典型!  回復  更多評論   

    # re: 淺談spring和依賴注入的價值 2008-01-14 14:00 楊一

    首先是解耦,解耦后的第二個問題就是代碼的復雜性和可讀性。當然獨立思考的精神總是值得鼓勵的。  回復  更多評論   

    # re: 淺談spring和依賴注入的價值 2008-01-15 09:50 愛上鳥的魚

    挺難!沒有看懂,以后再來拜讀!  回復  更多評論   

    # re: 淺談spring和依賴注入的價值 2008-01-15 23:48 chenge

    呵呵,世界很小,我google到你了。
    那個問題我提的。

    如果只需要一種provider的話,可以如下:
    RegisterWork (){
    provider = new XProvider(); //更換只需要修改這行代碼,也 可以寫成hotswap
    }

    如果需要同時用到不同的provider,可以考慮工廠方法。

    new已經用了十幾年了,就像向前走路,突然變成后退著走很不習慣,也沒感覺到有什么好。

    只有需要聲明式事務處理和AOP才需要spring.  回復  更多評論   

    # re: 淺談spring和依賴注入的價值 2008-02-04 12:17 areon

    現在的人連設計模式都懶得學了 祭出spring來 知其然不知其所以然的 看看GoF,MF的原著吧  回復  更多評論   

    主站蜘蛛池模板: 7777久久亚洲中文字幕| 亚洲Av无码专区国产乱码DVD| 亚洲成人网在线播放| 99久久久国产精品免费蜜臀| 亚洲AV电影院在线观看| 222www在线观看免费| 亚洲人成电影青青在线播放| 丁香花在线观看免费观看| 亚洲婷婷第一狠人综合精品| 毛片免费观看的视频在线| 激情亚洲一区国产精品| 午夜免费福利网站| 精品亚洲国产成人av| 亚洲日韩中文在线精品第一| 本免费AV无码专区一区| 亚洲色四在线视频观看| 色窝窝免费一区二区三区| 亚洲国产欧美一区二区三区| 亚洲精品456播放| 久久国产免费观看精品| 亚洲欧洲精品在线| 热久久精品免费视频| 72pao国产成视频永久免费| 久久亚洲国产成人亚| 成年性生交大片免费看| 深夜免费在线视频| 亚洲精品免费视频| 免费无码成人AV片在线在线播放 | 久久青青草原亚洲av无码app| 亚洲黄色免费电影| 韩国亚洲伊人久久综合影院| 国产亚洲一区区二区在线| 6080午夜一级毛片免费看 | 国产99精品一区二区三区免费 | 国产亚洲精品精品精品| 亚洲热妇无码AV在线播放| 男女做羞羞的事视频免费观看无遮挡| 亚洲日韩在线中文字幕综合| 亚洲欧洲国产精品你懂的| 午夜寂寞在线一级观看免费| 中文字幕在线免费播放|