日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

如何在struts+spring+hibernate的框架下構(gòu)建低

系統(tǒng) 1788 0
一.問題的提出

我常常在思考一個問題,我們?nèi)绾文茉O(shè)計出高水平、高質(zhì)量的軟件出來。怎樣是高水平、高質(zhì)量的軟件?它應(yīng)當(dāng)是易于維護、易于適應(yīng)變更、可重用性好的一個系統(tǒng)。如何做到這一點呢?答案當(dāng)然是“低耦合、高內(nèi)聚”了。低耦合就是軟件在構(gòu)造的時候,各個模塊、各個功能、各個類都不會過度依賴于它周圍的環(huán)境。只有這樣,才能使我們的模塊(功能、類)在周圍發(fā)生變更時不受影響,做到易于維護和易于適應(yīng)變更。正因為如此,也使它更易于重用到其它功能類似的環(huán)境中,提高了重用性。高內(nèi)聚則使軟件中的各個模塊(功能、類)能夠各盡其能而又充分合作,也就是對于軟件問題空間中需求的各個功能,系統(tǒng)可以合理地把它分配給各個模塊(功能、類)來共同完成,而不是一個或幾個八面玲瓏、包打天下的超級類一個人完成。而對于該系統(tǒng)中的某一個模塊(功能、類),具有自己高度相關(guān)的職責(zé),即該職責(zé)中的幾個任務(wù)是高度相關(guān)的。每一個模塊(功能、類)都決不去完成與自己無關(guān)職責(zé)的任務(wù)。

那么怎樣能構(gòu)造一個低耦合、高內(nèi)聚的系統(tǒng)呢,時下最流行的框架結(jié)構(gòu)之一的struts+spring+hibernate為我們提供了方便。使用struts我們可以應(yīng)用MVC模型,使頁面展現(xiàn)與業(yè)務(wù)邏輯分離,做到了頁面展現(xiàn)與業(yè)務(wù)邏輯的低耦合。當(dāng)我們的頁面展現(xiàn)需要變更時,我們只需要修改我們的頁面,而不影響我們的業(yè)務(wù)邏輯;同樣,我們的業(yè)務(wù)邏輯需要變更的時候,我們只需要修改我們的java程序,與我們的頁面無關(guān)。使用spring我們運用IoC(反向控制),降低了業(yè)務(wù)邏輯中各個類的相互依賴。假如類A因為需要功能F而調(diào)用類B,在通常的情況下類A需要引用類B,因而類A就依賴于類B了,也就是說當(dāng)類B不存在的時候類A就無法使用了。使用了IoC,類A調(diào)用的僅僅是實現(xiàn)了功能F的接口的某個類,這個類可能是類B,也可能是另一個類C,由spring的配置文件來決定。這樣,類A就不再依賴于類B了,耦合度降低,重用性提高了。使用hibernate則是使我們的業(yè)務(wù)邏輯與數(shù)據(jù)持久化分離,也就是與將數(shù)據(jù)存儲到數(shù)據(jù)庫的操作分離。我們在業(yè)務(wù)邏輯中只需要將數(shù)據(jù)放到值對象中,然后交給hibernate,或者從hibernate那里得到值對象。至于用Oracle、MySQL還是SQL Server,如何執(zhí)行的操作,與我無關(guān)。

然而我要說的是,即使我們使用了struts+spring+hibernate框架構(gòu)建我們的軟件,就可以做到“低耦合、高內(nèi)聚”了嗎?我認為這是遠遠不夠的!我認為我們在使用struts+spring+hibernate框架的時候常常會有以下幾個問題值得改進。

二.分析與解決

1.編寫DAO的時候不要直接去使用hibernate或spring對hibernate的支持。

現(xiàn)在我們在編寫DAO的時候普遍都是直接繼承spring對hibernate的封裝類HibernateDaoSupport,然后使用該類提供的諸如saveOrUpdate(), saveOrUpdateCopy(), find()等等。另外,在使用excute()方法實現(xiàn)一些更復(fù)雜的hibernate功能的時候還會使用hibernate的類,諸如Query, Session, Type等。這樣直接使用spring和hibernate的類存在的問題在于,你的代碼將不得不依賴與spring和hibernate的某個版本。比如說,現(xiàn)在hibernate3出來了,改動挺大,實際上最要命的是包結(jié)構(gòu),hibernate2的包結(jié)構(gòu)是net.sf.hibernate.*,然而hibernate3是org.hibernate.*。同樣,spring為了支持hibernate3,包名也改為org.springframework.orm.hibernate3.*。假如,你現(xiàn)在新開發(fā)一個項目,這沒什么關(guān)系,如果是升級一個項目問題就來了。如果你希望將你的一個項目從hibernate2升級為hibernate3,你不得不修改DAO中所有對hibernate和spring-hibernate的引用。如果你的代碼中出現(xiàn)hibernate2與hibernate3不兼容的方法和類,比如saveOrUpdateCopy()(在hibernate3中已經(jīng)沒有了),你還將不得不改寫。那么你可能會說,我不會這樣升級。如果你的軟件生命周期有好多年,hibernate升級到4,升級到5,你還是依然使用hibernate2?如果你以這種方式開發(fā)一個平臺,你能要求所有使用你平臺的軟件項目都只能使用hibernate2?更進一步說,我現(xiàn)在開發(fā)一個產(chǎn)品,今后的客戶將是成千上萬。經(jīng)過1、2年我需要升級了,這時我的升級包有幾十M,幾乎把所有的DAO都換了個遍,這樣的升級無異于重裝。也許,有人會提出另一個方案,在HibernateDaoSupport與DAO中間增加了一個基礎(chǔ)類,這樣將基礎(chǔ)類中的org.springframework.orm.hibernate.support.HibernateDaoSupport,改為了org.springframework.orm.hibernate3.support.HibernateDaoSupport,這樣其下面繼承的DAO就不用改動了。然而在源碼上是小小的改動,但對于類來說,兩個不同版本的HibernateDaoSupport其相關(guān)的屬性和方法還是有不少變化,那么在基礎(chǔ)類重新編譯的同時,你的繼承類重新編譯否。既然已經(jīng)重新編譯了,因此你的所有DAO在升級的時候依然要打入升級包,問題依然存在。

以上問題,究其原因,是我們項目中的DAO依賴于hibernate和spring,因為我們對它們的使用是繼承,是一種很強的關(guān)聯(lián),就是一種依賴。我們只需要稍微進行一些調(diào)整,就可以解決這個問題,那就是不使用直接繼承,而使用接口進行分離。可以使用Fa?ade模式,先建立一個叫BasicDao的基礎(chǔ)類,從名稱我們可以看出,它是所有DAO的基礎(chǔ)類,實現(xiàn)DAO操作所需的所有諸如save()、delete()、load()、query()等方法,除了一些基本的方法,諸如翻頁查詢、getCount、解析查詢條件形成HQL語句等功能也在這里實現(xiàn),但是不要使用與hibernate或spring有關(guān)的任何方法和類。同時,BasicDao調(diào)用一個叫DaoSupport的接口,DaoSupport的接口則是提供持久化所需的基本方法,最原始的元素。然后,我為DaoSupport接口提供各種不同的實現(xiàn),比如hibernate2的實現(xiàn)DaoSupportHibernateImp、hibernate3的實現(xiàn)DaoSupportHibernate3Imp,整個結(jié)構(gòu)如下圖所示。BasicDao可以使用hibernate或spring提供的方法,但是不是直接使用,而是通過調(diào)用DaoSupport的實現(xiàn)類來使用。然而BasicDao到底是使用的那個實現(xiàn)類,我們通過spring的IoC,通過配置文件來決定到底使用哪個實現(xiàn)。同時,BasicDao也不要使用諸如SpringContext的類來實現(xiàn)IoC,而是通過建立setDaoSupport()和getDaoSupport()方法,然后在spring配置文件中建立引用。
如何在struts+spring+hibernate的框架下構(gòu)建低耦合高內(nèi)聚的軟件

2.編寫Action的時候不要直接使用spring和spring的繼承類

前面我說了應(yīng)當(dāng)避免DAO引用spring或hibernate及其繼承類。同樣的事情也發(fā)生在Action中。由于Action通常不納入spring的管理,因此Action在通過spring調(diào)用某個BUS的時候,往往是去引用一個叫SpringContext的類(spring的類ContextLoaderServlet的繼承類),然后使用它的getBean()方法。如此的使用,我們的Action將依賴與spring。我們同樣可以使用一個叫BasicAction的父類,然后用一個接口來隔離spring。由于Action通常不納入spring的管理,我們通過一個*.property的配置文件來決定接口到底調(diào)用哪個實現(xiàn)類。這樣的結(jié)構(gòu)的另一個好處是,我們還可以將所有Action都必須使用的諸如寫日志、用戶校驗、異常處理都放在父類BasicAction中,提高系統(tǒng)的可維護性。

3.當(dāng)BUS需要獲取別的模塊的數(shù)據(jù)的時候,不要直接去使用該模塊的DAO

我舉一個簡單的例子:我需要設(shè)計一個軟件評審的管理軟件,該軟件分為評審組織者制訂評審計劃、評審者分別填寫評審表后由評審組織者匯總評審表、評審組織者制作評審報告。這是一個非常簡單的項目,分成了三個人來完成。但是項目進行快結(jié)束的時候卻出現(xiàn)了問題。填寫評審表需要獲得評審計劃中的一些數(shù)據(jù),制作評審報告的數(shù)據(jù)來源于評審表。項目組在開始編程前先開了一次會,大家約定好了各個部分的數(shù)據(jù)格式及其規(guī)則,然后開始工作。然而數(shù)天后項目組把各個模塊整合以后發(fā)現(xiàn),系統(tǒng)根本跑不起來,為什么呢?設(shè)計評審計劃的人發(fā)現(xiàn),所有評審計劃應(yīng)當(dāng)按照產(chǎn)品編號來進行管理而不是項目編號。由于這個變更,填寫評審表模塊在待評審列表中什么都無法顯示;同樣,設(shè)計評審表的人發(fā)現(xiàn),在一個評審計劃中評審表與評審者不是一對多的關(guān)系,而是一對一的關(guān)系,因而修改了這兩個表的關(guān)聯(lián)。因為這樣,在制作評審報告時就不能正確得到評審表數(shù)據(jù)。其實一個軟件項目在整個進行過程中總是不斷變更。我們需要做的不是去抑制這些變更,而應(yīng)當(dāng)是通過軟件的結(jié)構(gòu)去適應(yīng)這些變更,即是降低各模塊間的依賴(耦合),提高內(nèi)聚。

拿這個實例來說,當(dāng)評審表需要調(diào)用評審計劃的數(shù)據(jù)的時候,不應(yīng)當(dāng)是自己寫一個DAO去調(diào)用評審計劃的數(shù)據(jù),而應(yīng)當(dāng)是調(diào)用評審計劃的接口,將這個任務(wù)交給評審計劃類來完成。當(dāng)評審報告需要調(diào)用評審表的數(shù)據(jù)的時候,同樣應(yīng)當(dāng)去調(diào)用評審表的接口,由評審表來實現(xiàn)。同時,這種調(diào)用應(yīng)當(dāng)是去調(diào)用BUS層的接口。為什么呢?比如在評審計劃中的一個業(yè)務(wù)邏輯是只有在評審計劃發(fā)布以后才能制作評審表,那么怎樣才是已發(fā)布的評審計劃呢?這個業(yè)務(wù)邏輯應(yīng)當(dāng)由誰來定義?當(dāng)然是評審計劃。在什么地方定義?當(dāng)然是BUS而不是DAO,因為DAO僅僅是實現(xiàn)數(shù)據(jù)的持久化,而BUS才是實現(xiàn)業(yè)務(wù)邏輯的地方。既然如此,如果評審表去調(diào)用評審計劃的DAO,那么已發(fā)布評審計劃的業(yè)務(wù)邏輯必然包含在了評審表的業(yè)務(wù)邏輯里了。我們假設(shè)有一天,已發(fā)布評審計劃的業(yè)務(wù)邏輯發(fā)生變更了(實際上這樣的會在你毫不經(jīng)意間就發(fā)生了),編寫評審計劃的人會很快就修改了評審計劃的業(yè)務(wù)實現(xiàn)并且測試通過了。他不知道評審表里也包含了這樣的業(yè)務(wù)邏輯,因而修改后的程序在運行到評審表的時候就很可能會出錯。不幸的是,在實際工作中,同樣一個業(yè)務(wù)邏輯可能包含在無數(shù)個你可能知道,但你也可能不知道的代碼中。這樣的結(jié)構(gòu)就是一個不易于維護的差的結(jié)構(gòu)。

三.總結(jié):從技術(shù)升級和需求變更兩方面適應(yīng)變化

軟件開發(fā)專家Alistair Cockburn在《敏捷軟件開發(fā)》中說過,軟件在整個生命周期中變更是無時無刻不發(fā)生的。我認為,軟件的變更一方面是技術(shù)的更新,今天我們使用struts+spring+hibernate,明天呢,我們將使用什么呢?正因為技術(shù)變更得太快,我們的系統(tǒng)應(yīng)當(dāng)不要太依賴于某個具體的技術(shù)或框架,以便于明天的技術(shù)更新。同時,來自客戶的需求變更也是我們必須面對的另一個壓力。一句經(jīng)典的話是這樣描述客戶的變更:“當(dāng)我看到時我的需求就變更了。(I changed just when I saw it.)”過去我們用需求說明書來抑制用戶的變更,現(xiàn)在發(fā)現(xiàn)不能這樣了。敏捷軟件開發(fā)提出了許多應(yīng)對用戶變更的辦法,其中建立低耦合高內(nèi)聚的軟件結(jié)構(gòu)也是辦法之一。系統(tǒng)中的所有對象都有自己的明確職責(zé),這個職責(zé)應(yīng)當(dāng)不多且高度相關(guān)。每個對象都應(yīng)當(dāng)只完成自己的職責(zé),而把其它的任務(wù)交給別人去做。正如我前面提到的例子,評審表對象只完成與評審表相關(guān)的操作,而在它需要完成的任務(wù)中,需要使用評審計劃數(shù)據(jù)的相關(guān)功能,交給評審計劃對象去完成,評審表只管調(diào)用。這樣的構(gòu)造要求開發(fā)者相互協(xié)調(diào),彼此多交流,同時,也需要有人來統(tǒng)一規(guī)劃,站在全局的設(shè)計這個系統(tǒng)。通過這些,我們才可以適應(yīng)變化,提高設(shè)計水平。

如何在struts+spring+hibernate的框架下構(gòu)建低耦合高內(nèi)聚的軟件


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 吴川市| 安陆市| 梁河县| 宣化县| 金昌市| 东乌珠穆沁旗| 长宁区| 东兴市| 通城县| 萨嘎县| 柳江县| 德昌县| 宜城市| 满洲里市| 台北县| 卢氏县| 海原县| 丰城市| 松桃| 全南县| 微博| 焦作市| 筠连县| 巴马| 南丰县| 绥宁县| 鹤峰县| 澄迈县| 迭部县| 两当县| 平泉县| 同江市| 金坛市| 额尔古纳市| 通江县| 潜江市| 沽源县| 山丹县| 鹤峰县| 齐齐哈尔市| 杭锦旗|