天天看點

跟着項目學設計模式(六):三層架構

前面用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 【三層架構】

沒有可比性,架構本身并不能解決代碼品質的問題。

真正起到一些作用的是接口,是設計模式。設計模式通過接口限制必須實作哪些方法,層與層之間隻能調用通過接口中聲明的方法。這在某種程度上是一種限制,但并不影響我在具體的實作該方法的代碼裡,究竟幹了什麼。

繼續閱讀