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

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

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

    Sky's blog

    我和我追逐的夢(mèng)

    常用鏈接

    統(tǒng)計(jì)

    其他鏈接

    友情鏈接

    最新評(píng)論

    淺談spring和依賴注入的價(jià)值

    javaeye上看到有帖子,置疑spring和依賴注入的價(jià)值,回復(fù)內(nèi)容整理如下:

    依賴注入對(duì)設(shè)計(jì)有利,而spring則促進(jìn)了依賴注入的使用。

    如果業(yè)務(wù)處理類,它所使用的倚賴,都是依靠在這個(gè)類內(nèi)部實(shí)現(xiàn)或者查找,那么必然使得正常的業(yè)務(wù)邏輯和獲取依賴的方法混在一起。

    我取個(gè)最簡(jiǎn)單的場(chǎng)景,某個(gè)注冊(cè)的工作類,它需要獲取當(dāng)前"容許的用戶名的最大長(zhǎng)度",這個(gè)依賴非常簡(jiǎn)單吧?基本每個(gè)注冊(cè)類都有這個(gè)限制,我們現(xiàn)在 把場(chǎng)景考慮的全面一點(diǎn),對(duì)于復(fù)雜一點(diǎn)的系統(tǒng),這個(gè)最大長(zhǎng)度的限制可能來源很多,比如配制文件,數(shù)據(jù)庫(kù),可能類工作在前臺(tái)比如web而配制在后臺(tái),可能需要 和第三放系統(tǒng)一起工作而需要到第三方系統(tǒng)中獲取而對(duì)方只提供web service...

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

    那么我們來看一個(gè)很有"spring"風(fēng)格的采用依賴注入的設(shè)計(jì),通常都將會(huì)是這樣:

    注冊(cè)工作類:
    public void RegisterWork {
    public void setUsernameMaxLengthProvider(UsernameMaxLengthProvider provider) {
    int maxLength = provider.getUsernameMaxLength(); //簡(jiǎn)單獲取結(jié)果,不管provider細(xì)節(jié)
    }
    ....
    }
    “用戶名的最大長(zhǎng)度”的提供者接口
    public interfacd UsernameMaxLengthProvider {
    public int getUsernameMaxLength();
    }
    “用戶名的最大長(zhǎng)度”的提供者則可以有以下實(shí)現(xiàn),都只負(fù)責(zé)讀取數(shù)據(jù),不關(guān)心數(shù)據(jù)被誰使用,怎么使用:
    1.直接提供,可以用spring 構(gòu)造函數(shù)方式注入usernameMaxLength值,也可以junit測(cè)試時(shí)直接new DirectdProvide對(duì)象
    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.類似的從數(shù)據(jù)庫(kù)讀取 DatabaseProvide
    4.類似的web service從第三方讀取 WebServiceProvider
    5.其他的可能擴(kuò)展的方式

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

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

    上述的場(chǎng)景,spring + 依賴注入的設(shè)計(jì)方式,優(yōu)點(diǎn)很明顯吧。

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

    代碼維護(hù)是需要成本的,寫出易于維護(hù)的代碼,是一個(gè)優(yōu)秀程序員的基本素養(yǎng),至少,不能讓下一個(gè)接手的人罵娘吧?

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

    評(píng)論

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

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

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

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

    一樣也可以做到hotswap任意接口實(shí)現(xiàn)類!
      回復(fù)  更多評(píng)論   

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

    最是厭惡spring動(dòng)不動(dòng)的一堆bean.xml,IOC過渡使用的一個(gè)典型!  回復(fù)  更多評(píng)論   

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

    首先是解耦,解耦后的第二個(gè)問題就是代碼的復(fù)雜性和可讀性。當(dāng)然獨(dú)立思考的精神總是值得鼓勵(lì)的。  回復(fù)  更多評(píng)論   

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

    挺難!沒有看懂,以后再來拜讀!  回復(fù)  更多評(píng)論   

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

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

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

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

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

    只有需要聲明式事務(wù)處理和AOP才需要spring.  回復(fù)  更多評(píng)論   

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

    現(xiàn)在的人連設(shè)計(jì)模式都懶得學(xué)了 祭出spring來 知其然不知其所以然的 看看GoF,MF的原著吧  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲中文字幕不卡无码| 亚洲一级片在线播放| 3d动漫精品啪啪一区二区免费| 亚洲国产成+人+综合| 国产精品视_精品国产免费 | 亚洲免费人成在线视频观看| 91久久青青草原线免费| 亚洲天然素人无码专区| 亚洲视频一区二区| 亚洲精品视频免费在线观看| 豆国产96在线|亚洲| 中文字幕亚洲综合精品一区| 免费被黄网站在观看| 国产亚洲精品不卡在线| 亚洲视频免费观看| 日韩免费高清一级毛片| 中文字幕亚洲综合精品一区| 亚洲国产精品国产自在在线| 精品免费人成视频app| 黄色大片免费网站| 亚洲精品综合久久中文字幕| 亚洲精品综合久久| 亚洲人成电影网站免费| 嫩草影院在线播放www免费观看| 亚洲国产精品无码久久| 免费看片A级毛片免费看| baoyu777永久免费视频 | 中文字幕免费高清视频| 国产精品亚洲综合网站| 亚洲第一页在线视频| 亚洲综合在线另类色区奇米| 成人免费视频一区| 日本最新免费网站| 免费在线观看一级片| 亚洲精品综合久久中文字幕| 中文字幕亚洲综合久久男男| 免费国产黄线在线观看| 在线观看免费av网站| a级毛片毛片免费观看久潮喷| 国产精品自拍亚洲| 亚洲精品无码永久在线观看男男|