浅谈三层架构中的实体类(C#)
???????? 本文所指的實(shí)體類僅限于三層中的實(shí)體類,即數(shù)據(jù)庫(kù)表的映射。
?
一、為什么要用實(shí)體類?
?
???????? |? 使程序簡(jiǎn)潔易懂,便于維護(hù)。
???????? |? 暗合接口不變?cè)瓌t。
???????? |? 體現(xiàn)面向?qū)ο笏枷搿?/span>
?
????????舉例說(shuō)明:
?
???????? 不用實(shí)體類的三層
????????假如程序有所變動(dòng),需要增加一個(gè)參數(shù),學(xué)生年齡
????????用實(shí)體類的三層
????????同樣增加一個(gè)參數(shù),學(xué)生年齡
?
???????? 很明顯的看出,用實(shí)體類之后,代碼明顯變得簡(jiǎn)潔,面向?qū)ο蠓庋b思想。
???????? 最重要的是,如果將來(lái)有所改動(dòng),只需要改動(dòng)實(shí)體類,方法間調(diào)用接口,完全不需要變動(dòng),大大減少了程序修改量,迎合了面向?qū)ο笾薪涌诓蛔兊乃枷搿?/span>
???????? 甚至在程序設(shè)計(jì)時(shí),就把將來(lái)可能需要的屬性預(yù)先放在實(shí)體類中,這樣以后變動(dòng)時(shí),連實(shí)體類都不用變動(dòng)。
?
二、實(shí)體類缺點(diǎn)在哪(僅是個(gè)人觀點(diǎn))?
?
???????? 雖然實(shí)體類有明顯的優(yōu)勢(shì),但親身使用時(shí)會(huì)發(fā)現(xiàn)一個(gè)明顯的問(wèn)題:代碼可讀性貌似降低了。
???????? 上邊例子中體現(xiàn)的不是很明顯。再來(lái)一個(gè)簡(jiǎn)單的例子。
???????? 假如有一個(gè)方法(沒(méi)有用實(shí)體類):
???????? selectByPartDate(DateTime startDate,DateTime endDate){}
???????? 此方法用來(lái)查詢某段時(shí)間內(nèi)的記錄,兩個(gè)參數(shù):一個(gè)是起始時(shí)間,一個(gè)是結(jié)束時(shí)間。
???????? 雖然沒(méi)有用實(shí)體類,可是讓人看起來(lái)很舒服,一看就知道要干什么。
???????? 用了實(shí)體類后(假設(shè)實(shí)體類名是LoginLog):
???????? selectByPartDate(LoginLog startDate, LoginLog endDate){}
???????? 讓人看了不知所措,難以理解到底想做什么。
???????? 當(dāng)然,這種不知所措可以通過(guò)兩個(gè)途徑解決:
?????? ? |? 良好的命名規(guī)范,達(dá)到 “見(jiàn)名知意”。
???????? |? 良好的文檔說(shuō)明或者代碼注釋。
?
???????? 在這,引出一個(gè)問(wèn)題:三層中,所有的方法都要用實(shí)體類傳遞參數(shù)嗎?
???????? 最明顯的就是上邊selectByPartDate例子,還有諸如:deleteByID(longid){}這樣的方法。真的有必要傳遞實(shí)體類嗎?
???????? 實(shí)體類的確是容易擴(kuò)展、修改,可這不違反設(shè)計(jì)原則嗎?
???????? 設(shè)計(jì)原則是:盡量避免對(duì)原有代碼的修改,而是通過(guò)增加代碼的方式去解決。
???????? 諸如selectByPartDate、deleteByID這樣的方法,目的已經(jīng)很明確了:查詢某段時(shí)間內(nèi)的記錄、根據(jù)id刪除記錄。換句話說(shuō),這就是它們存在的意義。
???????? 程序再怎么擴(kuò)展,能涉及到這類方法?假如真的把這類方法擴(kuò)展了,那么它們完全失去了自己的意義!
???????? deleteByID就是根據(jù)id刪除,擴(kuò)展了,就不是根據(jù)id刪除了!這時(shí)候你可以再添加一個(gè)新的方法,何必和deleteByID過(guò)不去呢?
???????? 對(duì)于參數(shù)極少,目的明確的方法,個(gè)人認(rèn)為沒(méi)必要用實(shí)體類。
???????? 這只是我的個(gè)人看法,歡迎高人指點(diǎn)!
????????
三、源自實(shí)體類的靈感!
?
???????? 三層中,大家都知道U層的邏輯應(yīng)該盡量少,盡可能的轉(zhuǎn)移到B層。
???????? 但是實(shí)際應(yīng)用中如何轉(zhuǎn)移卻是個(gè)問(wèn)題。
???????? 就拿刪除記錄來(lái)說(shuō),U層調(diào)用B層,B層調(diào)用D層,由D層返回布爾值,來(lái)說(shuō)明刪除是否成功。
???????? 這樣傳遞參數(shù),最終U層得到的是一個(gè)布爾值,真或假,攜帶的信息太少了,只能反饋給用戶成功或者失敗(同時(shí)多了一次判斷邏輯),而為什么失敗,就無(wú)從得知了。
???????? 現(xiàn)實(shí)應(yīng)用中有很多這樣的例子,有時(shí)候?yàn)榱私o出用戶更詳細(xì)的提示,不惜把B層分的很細(xì),然后在界面大量的調(diào)用B層方法,加上大量的判斷,才能給用戶一個(gè)完整的提示。
???????? 這樣的情形顯然不是我們想要的?那么怎么解決呢?
???????? 造成這種情況的根本原因就是布爾型返回值攜帶的信息太少,哪個(gè)類型多?當(dāng)然是字符串型!
???????? 在D層,可以返回布爾值,讓B層判斷使用。但是B層返回給U層的值,強(qiáng)烈反對(duì)是布爾型的!
???????? 按照這個(gè)思路,在B層使用復(fù)雜的邏輯,然后把執(zhí)行結(jié)果以字符串的形式的返回。這樣一來(lái),U層無(wú)需任何判斷,直接把B層返回的字符串顯示出來(lái)就行了!
???????? 舉個(gè)例子(B層的一個(gè)方法):
[csharp] view plaincopyprint????????? 很明顯的看出,一切判斷都是在B層完成的,然后把結(jié)果以字符串形式返回給U層,簡(jiǎn)潔明了,U層不需要任何邏輯,直接show就行了!
???????? 這樣看上去很好,但是字符串還是比較讓人不舒服,既然是面向?qū)ο?#xff0c;為何不返回一個(gè)實(shí)體類呢?
???????? 我們可以定義一個(gè)實(shí)體類,名字就叫LayerParameter。給這個(gè)實(shí)體類加一個(gè)字符串型的resultString屬性,就把剛剛的字符串返回值封裝進(jìn)來(lái)了。就用這個(gè)實(shí)體類作為B層給U層的返回值。
???????? 這樣做簡(jiǎn)直完美!
???????? 有經(jīng)驗(yàn)的朋友可能遇到過(guò)刷新界面的問(wèn)題,也就是U層需要根據(jù)實(shí)際情況來(lái)刷新界面數(shù)據(jù),在B/S結(jié)構(gòu)中尤其明顯。有了實(shí)體類做返回值,就啥都不怕了!不就是刷新嗎?在LayerParameter實(shí)體類中加一個(gè)布爾型屬性refresh,U層調(diào)用B層后,show一下返回值(LayerParameter類實(shí)例)的resultString屬性,把執(zhí)行信息告訴用戶,然后再判斷一下refresh屬性,決定是否刷新界面數(shù)據(jù)(U層一點(diǎn)邏輯都沒(méi)有是不可能的!),此時(shí)B層給U層的返回值,仍然是LayerParameter,接口無(wú)需任何改動(dòng)。
???????? 以上僅僅是個(gè)人想法,希望大牛指點(diǎn)!
?
???????? 最后,申明一點(diǎn):
???????? 一切的一切還是要以項(xiàng)目實(shí)踐為基礎(chǔ),經(jīng)驗(yàn)才是王道,否則一切討論都是空穴來(lái)風(fēng)!
總結(jié)
以上是生活随笔為你收集整理的浅谈三层架构中的实体类(C#)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 为什么需要实体类
- 下一篇: 用MyEclipse自动生成hibern