三层开发中容易犯的错误
三層開發(fā)中容易犯的錯(cuò)誤
前記:
相信大家對(duì)三層開發(fā)都已經(jīng)耳熟能詳,可是我卻發(fā)現(xiàn)新公司的既有代碼中有一些違背分層開發(fā)思想的東西,現(xiàn)在與大家分享這些錯(cuò)誤,我們共勉之。
如果有人覺得對(duì)三層開發(fā)拿捏得不是太準(zhǔn),請(qǐng)參照李天平的文章:分層開發(fā)思想與小籠包,這篇文章用隱喻說明分層開發(fā),是非常好的一篇文章。
正文:
1.界面層參與非界面邏輯,搶業(yè)務(wù)邏輯層的飯碗
什么是界面邏輯:
界面層應(yīng)該有的邏輯就是顯示的邏輯,例如根據(jù)邏輯結(jié)果顯示某一個(gè)Panel不顯示另外一個(gè)Panel,或者有一個(gè)數(shù)據(jù)集應(yīng)該在界面上怎么呈現(xiàn),這是界面層的邏輯
例子場(chǎng)景:
用戶登錄時(shí)首先驗(yàn)證用戶輸入的用戶名是否有效,如果用戶名有效,然后再驗(yàn)證用戶輸入的密碼是否和用戶名匹配,如果匹配則表示用戶可以登錄,增加用戶的登錄次數(shù),然后將用戶的信息寫入Session中;否則返回錯(cuò)誤。在這個(gè)過程中除了將用戶信息寫入Session這一步屬于界面邏輯以外其他的操作都應(yīng)該放在業(yè)務(wù)邏輯層。
錯(cuò)誤代碼示例:
private?void?buttonLogin_Click(object?sender,?EventArgs?ev)????????{
????????????string?userName?=?textBoxUserName.Text;
????????????string?password?=?textPassword.Text;
????????????if?(Business.Account.Exists(userName))
????????????{
????????????????bool?success?=?Business.Account.Login(userName,?password);
????????????????if?(success)
????????????????{
????????????????????Business.Account.AddLoginTime(userName);
????????????????????Session["user"]?=?new?User(userName,?password);
????????????????????Redirect("/");
????????????????}
????????????????else
????????????????{
????????????????????this.labelMessage.Text?=?"登錄失敗。";
????????????????}
????????????}
????????????else
????????????{
????????????????this.lableMessage.Text?=?"用戶名不存在。";
????????????}
????????}
?
分析:在上面的代碼中一個(gè)UI層的一個(gè)事件中調(diào)用了三次rules層的方法:
Business.Account.Exists(userName)
Business.Account.Login(userName, password)
Business.Account.AddLoginTime(userName);
還附加有條件判斷,這種方法在執(zhí)行效果上面是沒有什么錯(cuò)誤的,可是卻造成了邏輯前移;本來應(yīng)該在邏輯層執(zhí)行的判斷放在了界面層,是不合適的。
2.數(shù)據(jù)訪問層參與了大量的業(yè)務(wù)邏輯
這種現(xiàn)象經(jīng)常出現(xiàn)在大量使用存儲(chǔ)過程的系統(tǒng)中,將一大堆邏輯統(tǒng)統(tǒng)放在一個(gè)存儲(chǔ)過程中實(shí)現(xiàn)了,乍一看可能很有效率,其實(shí)造成了系統(tǒng)結(jié)構(gòu)的失調(diào),給維護(hù)帶來困難,數(shù)據(jù)訪問層甚者數(shù)據(jù)庫(kù)要搶邏輯層的飯碗了。
還以用戶登錄為例:
下面是業(yè)務(wù)邏輯層的登錄方法:
?
//業(yè)務(wù)邏輯層的登錄方法????????public?int?Login(string?userName,?string?password)?
????????{
????????????return?DataAccess.UserAccount.Login(userName,?password);
????????}
?
下面是數(shù)據(jù)層的登錄方法:
?
//數(shù)據(jù)訪問層的登錄方法????????public?int?Login(string?userName,?string?password)
????????{?
????????????SqlParameter[]?parameters?=?new?SqlParameter[]{
????????????????//?
????????????};
????????????return?SqlHelper.ExecuteProcedure("Login",parameters);
????????}
?
下面是登錄的存儲(chǔ)過程:
?
CREATE?PROC?Login????????????@userName?varchar(20),
????????????@password?varchar(20)
?????????AS?
????????????IF?NOT?EXISTS(SELECT?*?FROM?UserAccount?WHERE?UserName?=?@userName)
????????????????RETURN?-1
????????????IF?NOT?EXISTS(SELECT?*?FROM?UserAccount?WHERE?UserName?=?@userName?AND?password?=?@password)
????????????????RETURN?1
?????????
????????????UPDATE?UserAccount
????????????SET?LoginTimes?=?LoginTimes?+?1
????????????WHERE?UserName?=?@userName
?????????
????????????RETURN?0
?
分析:從上面三段代碼中我們可以很顯然得看到登錄的業(yè)務(wù)邏輯已經(jīng)全部被后移到了數(shù)據(jù)庫(kù)的存儲(chǔ)過程中。這樣使用的三層結(jié)構(gòu)就失去了意義,邏輯層名存實(shí)亡了;而數(shù)據(jù)庫(kù)的壓力會(huì)越來越大;我們修改業(yè)務(wù)邏輯的時(shí)候不是到邏輯層修改,而是要到數(shù)據(jù)庫(kù)中去修改了。
3.將界面層上的數(shù)據(jù)組件(如SqlDataSource)作為參數(shù)傳遞到業(yè)務(wù)邏輯層去賦值
這樣做的壞處很明顯,本來是界面層依賴于業(yè)務(wù)邏輯層的,現(xiàn)在業(yè)務(wù)邏輯層反過來去依賴界面層的類,需要邏輯層引用System.Web命名空間,顯然是錯(cuò)誤的。
4.為了省事兒,不是直接將參數(shù)傳遞到業(yè)務(wù)邏輯層,而是通過HttpContext直接獲得界面層應(yīng)該傳遞的參數(shù)
例子:在系統(tǒng)設(shè)計(jì)的初期沒有記錄用戶登錄的IP地址,而到了后期發(fā)現(xiàn)了這個(gè)問題,要求紀(jì)錄用戶IP了,為了不修改業(yè)務(wù)邏輯層方法的定義,也不用修改界面層的調(diào)用方法,于是便寫出了下面的代碼:
public?int?Login(string?userName,?string?password)????????{
????????????string?userIP?=?System.Web.HttpContext.Current.Request.UserHostAddress;
????????????//follow?is?login?steps
????????}
?
這一點(diǎn)犯的錯(cuò)誤和3中的錯(cuò)誤相同,導(dǎo)致層之間形成了依賴環(huán)。
5.將事務(wù)處理放在數(shù)據(jù)訪問層來做
事務(wù)處理應(yīng)該放在業(yè)務(wù)邏輯層處理,原因是
1)事務(wù)的劃分是根據(jù)業(yè)務(wù)邏輯來定義的,通常一個(gè)事務(wù)就代表完成了一個(gè)完整的邏輯操作;
2)一個(gè)業(yè)務(wù)邏輯可能有幾個(gè)數(shù)據(jù)操作,修改幾個(gè)表中的數(shù)據(jù),而通常數(shù)據(jù)層的類的劃分是根據(jù)數(shù)據(jù)庫(kù)表來劃分的,如果把事務(wù)處理放在數(shù)據(jù)訪問層,那么業(yè)務(wù)層的方法需要調(diào)用兩個(gè)以上的數(shù)據(jù)層方法時(shí),就會(huì)出現(xiàn)執(zhí)行兩個(gè)事務(wù)的情況,顯然這是不合理的。
總結(jié):
1.在三層結(jié)構(gòu)的劃分中我們應(yīng)該使三層各負(fù)其責(zé),誰也不能越權(quán),誰也不能懶惰,通常情況下,邏輯層應(yīng)該在滿足各負(fù)其責(zé)的條件下,盡可能的厚。
2.三層結(jié)構(gòu)中的依賴關(guān)系很明確,界面層依賴于邏輯層,邏輯層依賴于數(shù)據(jù)訪問層,不能互相依賴,而形成依賴環(huán)。
轉(zhuǎn)載于:https://www.cnblogs.com/smallfa/archive/2007/07/18/822420.html
總結(jié)
以上是生活随笔為你收集整理的三层开发中容易犯的错误的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: XHTML和HTMl区别
- 下一篇: 在C#中利用SharpZipLib进行文