學員會診之03:你那慘不忍睹的三層架構

陸敏技發表於2018-09-21

        最近檢查作業,雖然我們反覆強調三層架構就是:表示層、業務邏輯層、資料訪問層,每個層只做自己應該做的事情,但是,部分同學的作業還是不理想啊~~~

        你以為的三層架構是這樣的:

        而實際上你的三層架構是這樣的:

        如果我們尚不能完全瞭解把握各個層的邊界,那麼我們首先僅需要記住下面兩句話:

        1:除了UI層,任何其它層不要出現System.out;

        2:除了DAO層,任何其它層不要出現SQL;

 

1.除了UI層,任何其它層不要出現System.out

        在三層架構的作業中,我們寫到:

        這句話本來說的是service層應該是和具體的資料儲存無關的,但是反過來說,service同時也應該是和具體的頁面展示無關的。這是什麼意思呢?

        先來看趙同學的這個專案結構:

        Very清晰,沒有任何問題(其實有問題)。但現在讓我們開啟biz下的一個檔案:

        可以看到,在Service層的ScoreService相關方法中,出現了很多接受使用者輸入的程式碼。

        這是不能接受的,如果是在BS程式中,相當於我們把網頁寫到了service層。

        接受使用者輸入一定是在UI層完成的,修改之後的這兩個方法,應該長成這樣才行:

        仔細比對下之前的save。在呼叫save方法之前,name和pwd和grade應該在UI層就已經得到了。另外,我也去掉了id,為什麼呢?如果你的id在資料庫中是自增的,那麼根本不需要得到它。當然存在一種情況,我們不需要id由資料庫自己生成,而是由程式碼根據業務特點自己生成,那麼確實就應該放在Service的當前方法來生成。但是看這段程式碼,顯然不需要,因為趙同學首先從資料庫取id的max值,然後+1,然後再insert回去,那不就是資料庫的自增欄位嗎?所以這樣做又是何必呢。

        上面的save還可以繼續改造

        也就是說,service所要引數是UI層已經構造好的物件。到了web階段,尤其使用了各種MVC框架後,這些物件可以直接由框架構造好,故service層用到的引數是這些實體物件才是更常見的。

 

2.除了DAO層,任何其它層不要出現SQL

        接著來看第二個同樣重要的問題

        怎麼可以這樣呢,趙同學,你傷我的心了~~~

        你可是一個月寫了6篇部落格的同學,然而到了這個作業一下子坍塌了,是不是太驕傲導致你看都不看什麼是三層架構?

        請把所有見得到的sql丟到dao層去。

 

3.Dao層返回什麼?

        趙同學的作業簡直慘不忍睹,把所有能犯的錯誤全部犯了,如下:

        在這個queryall的dao方法中,它返回了一個void,然後列表直接在方法中遍歷輸出,我只能說一個大大的服

        而正常的做法是,返回List<Score>,然後在UI層輸出。

除了select,CRUD中的CUD返回什麼呢?

        Insert、update、delete語句JDBC都會返回一個int值,表明在資料庫中影響的行數,舉例來說,

        如果新增一條記錄,則jdbc返回的就是1;

        如果更新了10條記錄,則jdbc返回的就是10;

        而dao就是要真實反映資料庫操作,故以趙同學的delete為例

        應該修改為:

        看到沒,我連方法名都改了(哼哼,還有SQL隱碼攻擊哦)。

 

4.Service怎麼處理dao層返回的int值?

        Service層不應該再反映資料庫的狀態了,所以,以deleteByName為例,service應該這麼寫:

        或者這麼寫:

        如果是第一種寫法,得有一個全域性處理異常的地方,如果是後一種寫法,則UI層自己展示刪除結果資訊給使用者。

 

5.其它問題

        A:SQL隱碼攻擊。這個問題就不多說了,用引數化SQL解決之;

        B:分層不應該用package,而應該是project,這是作業裡面要求的;

        C:命名不規範;

        暫時就這些吧,如果寫多了估計會打擊趙同學的積極性,畢竟,我們還要趙同學笑著活下去呢~~

相關文章