<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)度的限制可能來(lái)源很多,比如配制文件,數(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í)支持然后通過(guò)配制方式進(jìn)行,這對(duì)于將一個(gè)產(chǎn)品賣給n家客戶的公司來(lái)說(shuō)是最正常不過(guò)的要求。

    那么我們來(lái)看一個(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ù)被誰(shuí)使用,怎么使用:
    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ò)展的方式

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

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

    再考慮一下維護(hù)和二次開(kāi)發(fā)的問(wèn)題,上面的spring + 依賴注入的代碼,好看易懂,方便擴(kuò)展,維護(hù)起來(lái)輕松。如果是那么堆在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過(guò)渡使用的一個(gè)典型!  回復(fù)  更多評(píng)論   

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

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

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

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

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

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

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

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

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

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

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

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


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


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 久久精品国产亚洲麻豆| 亚洲精品高清在线| 日本卡1卡2卡三卡免费| 亚洲一区二区三区香蕉| 免费看黄视频网站| 国产福利电影一区二区三区,免费久久久久久久精| 国产亚洲精品a在线无码| 成年人免费视频观看| 日本一区午夜艳熟免费| 亚洲色偷偷综合亚洲av78| 国产成人亚洲精品91专区手机| 嘿嘿嘿视频免费网站在线观看| 免费视频精品一区二区| 91亚洲精品麻豆| 亚洲色欲一区二区三区在线观看| 成全视频在线观看免费高清动漫视频下载 | 日本免费人成黄页网观看视频 | 国产久爱免费精品视频 | 亚洲精品国产情侣av在线| 免费一级成人毛片| 亚洲一区二区免费视频| 一边摸一边桶一边脱免费视频 | 俄罗斯极品美女毛片免费播放| 在线观看永久免费| fc2成年免费共享视频网站| 99久久婷婷国产综合亚洲| 久久精品亚洲综合专区| 免费一级毛片正在播放| 三年片在线观看免费观看高清电影 | 欧洲 亚洲 国产图片综合| 亚洲成人动漫在线| 久久青青草原亚洲av无码| 免费看a级黄色片| free哆啪啪免费永久| 男女午夜24式免费视频| 国产成人无码免费看片软件| 美女被免费网站视频在线| 亚洲欧美第一成人网站7777 | a视频免费在线观看| 一级黄色毛片免费看| 国产精品亚洲专区无码不卡|