跟着项目学设计模式(六):三层架构
前面用5個章節介紹了單例模式和工廠系列模式,這個過程中,如果算上網站開發人員的表示層,那么項目經歷了二層到多層的演變:
數據訪問層+表示層 =》
數據訪問層+業務邏輯層+Client層+表示層
至此,這個系列中對創建型設計模式的介紹也到此為止了。后面的文章,我們會把關注點放到具體的代碼實現上,比如層與層之間如何調用,工廠模式與抽象工廠在代碼實現上的異同等等,這里面會涉及到很多結構型設計模式相關的知識,由于代碼架構變得愈加復雜,也只有請結構型設計模式來救場。
那有人要問了,既然提升了系統復雜度,為什么要使用多層架構?
什么是三層架構?
為什么要用三層架構?
為了達到“高內聚,低耦合”的程序設計思想,引入了三層架構,在表現層和業務層分離開來,再加上數據訪問層,便形成了今天的三層架構。
沒錯上面又是百度百科的解釋,雖然這個答案簡練得連面試的要求都達不到,但無疑是百分百正確的答案,沒有摻雜任何個人理解的回答。初學者最不喜歡的就是這種答案,他們更喜歡的是富有個人強烈感情色彩的解釋,即使偏激。
來看摻雜了筆者個人理解,詳細到能應付面試的解答:
要回答這個問題首先要知道什么是一層架構和二層架構
一層架構:只有一個表示層
二層架構:?第一層:表示層
? ? ? ? ? ? ? ? ? ?第二層:數據訪問層
沒錯,一層架構就是只有一個表現層的架構。您可能會有疑問:只有一個表示層,怎么可能?
這里以后OA系統的用戶模塊為例,給一個5-10人的小公司用,只需要一個管理員賬戶,用戶名密碼都是admin,所有人都用這一個賬號登錄,代碼里寫死就可以了,業務邏輯就是登陸的時候判斷? if(username=="admin"&&pwd=="admin")。
是的,你沒有任何理由來批判一層架構的缺點,因為架構本身并沒有缺點,只有適不適合。只是一個顯示"Hello World"的功能,是不需要分什么層的,當然,如果非要有云"Hello World"這種需求,那就不好說了。
后來,使用OA的公司慢慢做大,成了幾百人的公司,OA系統需要增加考勤模塊作為主打功能,這意味著每個員工都需要一個用戶名來做考勤,而admin則負責管理用戶。我們需要在數據庫添加用戶表和門禁表。
管理員可以通過表單編輯用戶表中的性別、出生日期和照片,用戶只能編輯部分個人信息(照片和個性簽名)
管理員修改用戶信息
[Authorize("admin")] [HttpPost] public ActionResult?AdminEdit(User entity) {using(var context=new DBContext()){var user = context.Users.Where(d => d.id == entity.id).FirstOrDefault();user.sex=entity.sex;user.birth=entity.birth;user.photo=entity.photo;if(context.SaveChanges()>0){...}....} }用戶修改個人信息,我們把上面的代碼copy過來,略加修改就可以了。
[Authorize] [HttpPost] public ActionResult?UserEdit(User entity) {using(var context=new DBContext()){var user = context.Users.Where(d => d.id == entity.id).FirstOrDefault();user.photo=entity.photo;user.sign=entity.sign;if(context.SaveChanges()>0){...}....} }表示層中多個用戶表的編輯操作,造成了代碼的重復,重復是遠比壞味道還要嚴重的多的問題,我們修要提供一個通用的修改用戶信息的方法來優化代碼:
private bool UpdateUser(User entity,params string[] columnNames) {...do Update... }[Authorize("admin")] [HttpPost] public ActionResult?AdminEdit(User entity) {//如果編輯成功if(UpdateUser(entity, "sex", "birth","photo")){...} }[Authorize] [HttpPost] public ActionResult?UserEdit(User entity) {//如果編輯成功if(UpdateUser(entity, "photo","sign")){...} }?一層架構為解決數據庫操作造成的代碼重復,不斷地提供的通用方法,他們分散在表示層中的各個角落,這便是數據訪問層的原型。
二層架構將這些通用方法抽離成數據訪問層:
[Authorize("admin")] [HttpPost] public ActionResult?AdminEdit(User entity) {//如果編輯成功if(new UserDal().Update(entity, t => t.id == entity.id, "sex", "birth","photo")){...} }[Authorize] [HttpPost] public ActionResult?UserEdit(User entity) {//如果編輯成功if(new UserDal().Update(entity, t => t.id == entity.id, "photo","sign")){...} }所以,對于高質量的代碼下的一層架構來說,重構成二層所帶來的改變僅僅是把對數據庫的通用方法拿出來,換個地方而已,并沒有其他任何復雜的改動。
{{
【能夠通過sonar代碼質量檢查的一層架構】 VS 【能夠通過sonar代碼質量檢查的二層架構】
優點:代碼好找(管理)了,以前是在本模塊里找,現在是在本模塊的某一層里面找,利于分工,使開發人員可以專注于某一層。
缺點:維護起來變麻煩了,每次改動需要提交的文件變多了
具體要不要重構,看項目實際情況和個人喜好吧
----------------------------------------------------------------------------------------------------
【能夠通過sonar代碼質量檢查的一層架構】 VS 二層架構
毫無疑問,二層架構會被完爆!!!為什么?因為只要是能夠通過sonar代碼質量檢查的一層架構重構的二層架構,只是把代碼換了個位置,略加修改,肯定通過sonar代碼質量檢查的。
所以【能夠通過sonar代碼質量檢查的一層架構】就約等于【能夠通過sonar代碼質量檢查的二層架構】
如果連一層架構的代碼都組織不好,何談二層?
}}
?
-----------------------------------------------------------------------------------------------------------------------
如果后面項目需求變得更加復雜,業務規則、合法性校驗等業務邏輯增多,高質量代碼下的一層架構肯定是提供了很多業務邏輯的通用方法,因此
高質量代碼下的一層架構可以隨意的重構到二層和三層,物理文件的增加,代碼位置的變動,僅此而已。
所以呢,人們都說高手所見略同,模塊到了他們那群高手的手中,雖然在物理上并沒有分層,但是分層的思想已經隨處可見了。獨孤求敗草木竹石皆可為劍,就是這個道理。
但是正如三國演義里,呂布說過:“我有赤兔馬方天戟,過河如履平地!”,這個時候陳宮說:“你有赤兔馬,你當世無敵,但是將士們不行呀!”
你不能要求所有人都有那么高的水平,筆者去年參加的項目,也是多層架構,要求是代碼合格率達到60%就可以了,當時寫代碼就跟應付考試似的,實在是能力有限,但是進度趕得緊。
要記住,是因為通用方法的出現才不得不在物理上分層,而不是分層之后,才去寫通用方法。如果一開始你分層的目的是妄圖通過分層達到變相的約束程序員去寫通用方法的做法,是很難實現的。
真正起到一些作用的是接口,是設計模式。我接口里聲明了這些方法,你就必須去實現,而且要調用這些通用方法也只能通過接口,而設計模式來決定接口到底如何設計,我單層架構也可以用抽象工廠模式,你管我放哪兒干嘛?我就是把所有的接口和類全寫一個文件里它也是抽象工廠模式。
面試問題:
什么是三層架構:
從三層架構的視角來看一層和二層:
一層架構:包含復雜數據庫操作和業務邏輯的表示層
二層架構:?第一層:包含復雜業務邏輯的表示層
? ? ? ? ? ? ? ? ? ?第二層:數據訪問層
為了達到“高內聚,低耦合”的程序設計思想,引入了三層架構,將表現層和業務層分離開來,把業務規則、數據訪問、合法性校驗等通用方法都放到了中間層進行處理,再加上數據訪問層,便形成了三層架構。
?
三層架構的優缺點:
【能夠通過sonar代碼質量檢查的一(二)層架構】 VS 【能夠通過sonar代碼質量檢查的三層架構】
【能夠通過sonar代碼質量檢查的二層架構】?約等于【能夠通過sonar代碼質量檢查的三層架構】只是通用方法位置不同。
優點:代碼好找(管理)了,以前是在本模塊里找,現在是在本模塊下的某一層里面找,利于分工,使開發人員專注于某一層。
缺點:維護起來變麻煩了,每次改動需要提交的文件變多了
?
【能夠通過sonar代碼質量檢查的一(二)層架構】 VS 【三層架構】
沒有可比性,架構本身并不能解決代碼質量的問題。
真正起到一些作用的是接口,是設計模式。設計模式通過接口約束必須實現哪些方法,層與層之間只能調用通過接口中聲明的方法。這在某種程度上是一種限制,但并不影響我在具體的實現該方法的代碼里,究竟干了什么。
?
?
?
?
?
總結
以上是生活随笔為你收集整理的跟着项目学设计模式(六):三层架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搭配emuc-b202 can卡通讯时,
- 下一篇: 如何在FreePBX ISO 中文版本安