菜鳥之系統(tǒng)建模經(jīng)驗(yàn)之談:"機(jī)房收費(fèi)系統(tǒng)"三層架構(gòu)
經(jīng)歷了錯誤,才懂得正確的來由。學(xué)習(xí)就是一個不斷經(jīng)歷錯誤、不斷改正、不斷得出認(rèn)知的過程。
---題記
一、四大發(fā)明之活字印刷----面向?qū)ο笏枷氲母事?/strong>
每一位優(yōu)秀程序員都知道編寫一個軟件,前期的軟件需求分析、軟件設(shè)計(jì)與建模要比編寫代碼的時間長很多,原因何在?
先來看一個這樣古老的故事:
話說三國時期,曹操帶領(lǐng)百萬大軍攻打東吳,大軍在長江赤壁駐扎,軍船連成一片,眼看就要滅掉東吳,統(tǒng)一天下,曹操大悅,于是大宴眾文武,在酒席間,曹操詩性大發(fā),不覺吟道:"喝酒唱歌,人生真爽..."。眾文武齊呼:"丞相好詩!"于是一臣子速命印刷工匠刻版印刷,以便流傳天下。
樣張出來給曹操一看,曹操感覺不妥,說道:"喝與唱,此話過俗,應(yīng)改為'對酒當(dāng)歌'較好!",于是此臣就命工匠重新來過。工匠眼看連夜刻版之工,徹底白費(fèi),心中叫苦不迭。只得照辦。
樣張?jiān)俅纬鰜碚埐懿龠^目,曹操細(xì)細(xì)一品,覺得還是不好,說:"人生真爽太過直接,應(yīng)改問語才夠意境,因此應(yīng)該為'對酒當(dāng)歌,人生幾何?......'",當(dāng)臣轉(zhuǎn)告工匠之時,工匠暈倒......
可惜三國時期活字印刷還未發(fā)明,所以類似事情時有發(fā)生。如果有了活字印刷,則只需更改四個字即可,其他的工作也都未白做,實(shí)在妙哉。
這個故事恰恰體現(xiàn)了面向?qū)ο缶幊讨械膸状筇匦裕阂?要改,只需要更改要改之字,此為可維護(hù);二.這些字并非用完這次就無用,完全可以在后來的印刷中重復(fù)使用,此乃可復(fù)用;三.此詩若要加字,只需另刻字加入即可,這是可擴(kuò)展;四.字的排列其實(shí)可能是豎排可能是橫排,此時只需將活字移動就可做到滿足排列需求,此是靈活性好。
其實(shí)客觀的說,曹操這樣的客戶的要求也并不過分,不就是改幾個字嘛,但面對已完成的程序代碼,卻是需要幾乎重頭來過的尷尬,這實(shí)在是痛苦不堪。其實(shí),原因出在我們原先寫的程序,不容易維護(hù),靈活性差,不容易擴(kuò)展,更談不上復(fù)用,因此面對需求變化,加班加點(diǎn),對程序動大手術(shù)的那種無奈成了非常正常的事了。
之后,我們了解了面向?qū)ο蟮姆治鲈O(shè)計(jì)編程思想,開始考慮通過封裝、繼承、多態(tài)把程序的耦合度降低,傳統(tǒng)印刷術(shù)的問題就在于所有的字都刻在同一版面上造成耦合度太高所致,開始用分層的結(jié)構(gòu)使程序更加的靈活,容易修改,并且易于復(fù)用。
二、述說我的"機(jī)房收費(fèi)系統(tǒng)"建模之路
了解了面向?qū)ο蟮暮锰帲帉戃浖?dāng)然要向可維護(hù)、可擴(kuò)展、靈活性好等方向發(fā)展,這不我的小軟件"機(jī)房收費(fèi)系統(tǒng)"中就使用三層架構(gòu)思想建模,加上了一些設(shè)計(jì)模式。
這時我們需要了解一下分層的目的:分層是為了解耦,更換掉一層不至于使系統(tǒng)重新做。
1.初始經(jīng)典的三層架構(gòu)圖:
面向?qū)ο笳Z言幾個特征:封裝、繼承、多態(tài)。這里的三層架構(gòu)圖是邏輯上的分層,把一個系統(tǒng)分成三層,每一層具有的職責(zé)不同,也就是將每層具有的功能封裝起來。在DAL層連接不同的數(shù)據(jù)庫使用多態(tài)的思想。
2.迷糊狀態(tài):我初次改造的"機(jī)房收費(fèi)系統(tǒng)"三層架構(gòu)圖
三層架構(gòu)包圖對應(yīng)的程序集中的項(xiàng)目
這時,我的理解僅僅停留在:具有UI、BLL、DAL層的系統(tǒng)就是使用了三層架構(gòu)思想;當(dāng)然三層架構(gòu)系統(tǒng)中還可以加設(shè)計(jì)模式、SqlHelper等層,這時使系統(tǒng)具有多層;也稍微了解每層應(yīng)實(shí)現(xiàn)什么功能。
這里我犯了幾點(diǎn)錯誤,從圖中可以看出
1) 命名不規(guī)范,當(dāng)時我以為此系統(tǒng)是"機(jī)房收費(fèi)系統(tǒng)",所以就在UI、BLL、DAL等前面加上了字母"JF",對于實(shí)體因?yàn)槲铱戳艘粋€視頻中某老師使用的是Model,我也跟著寫成了Model,沒去問為什么。
2) 根本不理解三層之間真正的調(diào)用關(guān)系。沒分清哪一層調(diào)用哪一層的方法,沒明白誰向誰傳參數(shù)。
3)理論上明白分層的目的,實(shí)際操作時卻丟了分層的目的。我把設(shè)計(jì)模式"工廠方法"放到了D層,本來要使B層和D層分開的,我的做法恰恰不讓他們分開;雖然程序可以實(shí)現(xiàn),但是我違背了解耦的原則。
3.豁然開朗:經(jīng)過師哥師姐指正,重新建模
通過師哥師姐幫我分析,前后對比,我明白了分層的真正目的,也明白了自己上圖的做法并沒有解耦。
犯錯了,領(lǐng)悟了,才了解為什么這么做是正確的…
三.建模之路,我的收獲
經(jīng)過"機(jī)房收費(fèi)系統(tǒng)"這個建模過程,我得到了幾點(diǎn)系統(tǒng)建模經(jīng)驗(yàn),寫出來與大家分享……
經(jīng)驗(yàn)1.真正理解三層的意義,包之間的引用關(guān)系
所謂三層開發(fā),就是關(guān)于表現(xiàn)層、業(yè)務(wù)邏輯層和數(shù)據(jù)訪問層的開發(fā)。這其實(shí)只是大方向的分層,每個層中都有可能再分為多個層次和結(jié)構(gòu)。三層架構(gòu)中,上層包向下層包傳遞參數(shù),上層包調(diào)用下層包的方法,下層包向上層包傳回返回值。
經(jīng)驗(yàn)2.既然用設(shè)計(jì)模式,就要明白設(shè)計(jì)模式的真正意義
這里我用到了工廠方法模式,工廠方法模式到底是干嘛的?工廠是用來創(chuàng)建對象的,實(shí)際上這里的工廠是為了生產(chǎn)DAL。使用工廠方法是為了使BLL層與DAL層解耦,另一個作用是為了使數(shù)據(jù)庫更換方便。
注意:這個三層架構(gòu)中使用了工廠+反射,若只使用工廠而不使用反射,又怎么建模呢?
經(jīng)驗(yàn)3.架構(gòu)圖要與程序集代碼完全對應(yīng)
軟件設(shè)計(jì)完,編寫代碼過程要完全按照圖來進(jìn)行,圖和文檔是我們編寫代碼的依據(jù)。這里所說的對應(yīng)不僅僅指包圖名稱與程序集中項(xiàng)目名稱對應(yīng),而且要使包中的引用關(guān)系與程序集中的引用相對應(yīng)。
注意:程序集中的引用項(xiàng)與包圖之間的引用關(guān)系是一個意思。
經(jīng)驗(yàn)4.程序集中的項(xiàng)目引用項(xiàng),不能添加多的引用,也不可少引用某層
看下圖
這個圖添加的引用是正確的,有的人在調(diào)試程序時出錯,就在引用項(xiàng)中加入了"DAL"。看下面的錯誤圖,比較與上圖的區(qū)別:
在UI層引用"DAL"就錯了,因?yàn)榫帉懞玫某绦虼虬驞AL不是僅僅打包成一個.DLL文件,而是將DAL.DLL文件打包到UI中了,這樣做,更換 DAL時,系統(tǒng)就會報(bào)錯。為了解決這一問題,需要使用深層路徑,只是將DAL的路徑打包到UI中,也就是使引用中不含有DAL 而 debug項(xiàng)中含有DAL相關(guān)項(xiàng),這樣打包完依然是解耦狀態(tài),這時更換DAL,只要路徑對了,就不會報(bào)錯了。
還有一點(diǎn),有的人將SqlHelper數(shù)據(jù)庫工具類寫到了DAL層,這樣做也是破壞了解耦原則。
經(jīng)驗(yàn)5.命名要規(guī)范
編寫的代碼 or 畫的UML圖不僅僅是給自己看的,更多的是用來交流。為了保證代碼的一致性,便于交流和維護(hù),編寫代碼要遵照一定的規(guī)范。
經(jīng)驗(yàn)6.注釋要清晰、正確
有沒有這種感覺,寫過去的程序放幾個月再回頭看,不知道這段代碼寫的是什么了?原因在于你沒有寫好注釋。注釋不僅僅是寫給自己,也是讓自己的隊(duì)友來看的。這些都是良好的編程習(xí)慣,慢慢養(yǎng)成。
通過這次"機(jī)房收費(fèi)系統(tǒng)"建模,對軟件的編寫過程有了更清晰的理解。上面介紹了我的建模過程及我從中獲得的經(jīng)驗(yàn),既是我學(xué)習(xí)過程的總結(jié)也希望對看到此博客的人有益!
原文鏈接:http://blog.csdn.net/mazhaojuan/article/details/7818475