1. 程式人生 > >程式碼結構中Dao,Service,Controller,Util,Model是什麼意思,為什麼劃分?

程式碼結構中Dao,Service,Controller,Util,Model是什麼意思,為什麼劃分?


作者:蘿魏紫
連結:https://www.zhihu.com/question/58410621/answer/156915364
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

簡單點,不用長篇大論。你只要記住一個核心兩個要點就可以了。

核心就是封裝,也就是我入口小,裡面大,你別管我用了幾千幾百行程式碼實現了什麼功能,我一封裝,就是一行API給你,你調我,我給你我說好的功能,這就是封裝。

兩個要點:1分層,2傳遞。 分層就是我把一組同樣功能的封裝放一起。和資料庫打交道的放一起,這層就是DAO,database access object。 把提供業務功能的分一層,就是service,有的地方叫做domain service,把控場的分一層,controller。 傳遞就是我要在各個東西之間傳遞引數,是的函式有呼叫引數?這個是面向過程的思想傳下來的,面向物件我們傳遞的是實體,物件,並不是你給我四個數,我幫你算個24點出來,而是你給我四張牌的結合,我幫你算個24點,這就是model,各種現實社會的實體,在這裡抽象成model。

架構 就這麼簡單。


作者:暗滅
連結:https://www.zhihu.com/question/58410621/answer/156868800
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

 

首發於知乎專欄。

適合受眾:2年以下的初級程式設計師和0基礎的門外漢

內容大綱:

1.為什麼需要一個好的程式碼結構

2.什麼樣才是一個好的結構

3.每一個分類代表什麼含義

4.是否適用於WEB,Android和IOS?

5.進一步的學習的話,是要學習系統架構麼?

 

一 為什麼需要一個好的程式碼結構

  1. 好的程式碼結構並不僅僅是為了看上去清晰,它更像是我們對一個系統的拆解和組裝。
  2. 好的程式碼結構可以讓你在遇到程式碼交接這種天理不容的情況時,減少提刀砍人的可能性。
  3. 好的程式碼結構可以讓多人協作開發更容易,而不會纏纏綿綿到天涯,再相愛相殺。

我們經常形容一個壞的程式碼結構,像屎一樣。

 

我們稱它為一坨,說真的,接手過爛程式碼之後,真的找不到比屎更能描述自己感受的詞了。

“屎”代表著混亂,一坨,各種雜質。接手一堆爛程式碼的難度就像是用一坨屎來做沙畫。

有時候我們還會用一團毛線來形容程式碼,大概是這樣的。

 

對的,這種感受是絕對不會錯的。而我們要做的就是把這團毛線,變成像瑞士軍刀一樣的清晰。

 

你們覺得哪個更有成就感?

 

二 什麼樣才是一個好的結構

  1. 好的結構應該保持單一職責。
  2. 好的結構應該是通用的。
  3. 好的結構應該是有明確定義的。

這其實就是所謂的腳手架提供的最大的價值,一般而言,Java,Android,IOS都有一套明確的框架體系,JS本來沒有,後來有了,然後。。他們就打起來了。

所以,好的體系應該就像。。。他們一樣。

 

該噴火的噴火,該噴水的噴水,每個人分工都很明確。

 

三 每一個分類代表什麼含義

1.Model

Model是模型,一般而言,會有人分的更細,VO,DTO等等。我並不推薦分的更細,這個Model常常和持久化的資料一一對應,如Mysql和MongoDB。

Model承載的作用就是資料的抽象,描述了一個數據的定義,Model的例項就是一組組的資料。整個系統都可以看成是資料的 流動,既然要流動,就一定是有流動的載體。

 

這個紅圈標的就是Model。它就應該是一個純資料的集合,就是被各種東西傳來傳去,被各種加工處理的資料團。

通常會有很多Model,一條業務流就是對應一條或者多條資料流,拿知乎為例子。

文章是一個Model,一般叫Article,包括Title,Summary,Author,Content等等。

評論也是一個Model,一般叫Comment,包括Content,userID等等。

對於初學者而言,第一個要學會,就是建模,把業務邏輯對映成資料模型。

 

2.Util

Util是工具的意思,一般來說,常常用來描述和業務邏輯沒有關係的資料處理。

Util一般要和私有方法對比:私有方法一般來說是隻是在特地場景下使用的,私有方法越多,程式碼結構越亂。常見的重構策略就是首先從一個很多行數的程式碼裡抽象出若干個私有方法,然後再抽出公用的Util。

如果有可能,儘可能的少用私有方法,而是把他換成一個公用的Util,代表他和業務邏輯是不相關的。通常命名也是ArticleUtil,CommentUtil之類的。

 

像這種打包,不管是充氣娃娃還是別的什麼東西,都打包。你可以理解為圖中的黑衣人就是一個Util。

某中程度上也會跟Service有點接近。但是Service一般而言,都是包含有業務邏輯的,很少能做單元測試。

Util一般來說,就是一個明確的輸入和一個明確的輸出結果。單元測試中,多數也是來測試Util。

積累好自己的Util是一件很重要的事兒。

 

3 Service

Service比Util的概念大很多,它的重點是在於提供一個服務。這個服務可能包括一系列的資料處理,也有可能會呼叫多個Util,或者是呼叫別的服務。總歸一句話,就是,有什麼事情,你來找我。

 

就像這個圖上的妹妹一樣,她就是一個Service,她能提供什麼樣的服務?這個是必須定義好的。如果是洗腳,她要幫你脫鞋,要端盆子燙你的腳。這裡面,你的腳就是一個Model,盆子裡的水相當於Util,不管裡面放進去啥都能燙一燙。

幫你脫鞋可以是一個Service,也可以是一個私有函式,也可以是一個Util。看你的是讓這個小妹妹幫你脫,還是別的小妹妹脫,還是自動脫鞋機。

如果是你自動脫。。。說明你在Model裡面加上了功能,你的腳就不是一個純粹的資料模型了,而是一個包含業務功能在裡面的充血模型。

這樣不好。老老實實讓小妹妹幫你脫鞋不好麼。

 

4.Dao

Dao一般而言,都是用來和底層資料庫通訊,負責對資料庫的增刪改查。

 

是的。他就是一個Dao。他從來不關心這些貨物要去哪裡,他只關心。入庫,出庫,查詢和更換。

所謂的CRUD就是建立,讀取,更新,刪除。

Dao最好都是要獨立出來。

到現在為止,最佳實踐就是一個Service只對應一個Dao。Service會做一些額外的檢查,如貨物是否損壞,入庫單是否完整,等等等等。

我並不推薦在Service裡呼叫多個Dao,也不推薦在Service裡呼叫多個Service,大多數情況下我都不推薦這麼幹。

具體原因以後再說,這也是一個開放性的話題。

現在我們分清楚了Model,Util,Service和Dao,可是誰來做總的排程呢?

5.Controller

 

控制中心,所有的指令,排程都從這裡發出去。

哪一個Service做什麼事兒,誰的資料提供給誰,一般而言,都是在Controller裡實現的。

Controller也是最常見的容易產生髒程式碼地方,通常他們會把一些不該放到Controller裡東西也放進來。

大概的感覺就是這樣的。

 

幹嘛的都有。想想如果打小針,抽血,查尿也混雜到門診大廳的感覺?

可是大部分人寫程式碼就是這樣的。

 

四.是否適用於WEB,Android和IOS?

Java後臺是有很清楚的結構的,畢竟在JSP裡寫Sql語句的蠻荒時代已經過去了。

Android本身就是一個良好的框架體系,基本上問題也不大,最多就是MVP和MVC的差別之類。

IOS雖然沒有官方提供這種框架體系,特別是很多人喜歡直接在Dict裡用key取資料,這本身就破壞了程式碼的層次性。

但是畢竟是有李明傑提供的Json解析Util,只是各家要求的力度而已。

最難以理解的是WEB,也就是JS。

我不是在黑JS,我是在黑JS程式設計師。分層結構一直都不是JS社群裡最注重的,在JQuery時代更是如此,不管是Html還是JS還是CSS混在一起是正常的。

那個時候叫外掛,現在改名了,叫元件。

你很難在JQuery裡找到一套清晰的分層結構,就跟十幾年前所有的人都在Jsp裡寫邏輯語句的道理差不多。

直到google的大神偶爾遛達過來一看,咦?你們怎麼還在刀耕火種?我來給你們加點現代感的東西吧。

於是Angular橫穿出世,一次性的構建了一個清晰的框架結構。每次看到Angular的時候都忍不住 驚歎,原來前端程式碼也可以這樣!

 

而原來的感覺就是這樣。。。

 

現在基本上可以分成兩大陣營,一個是React和Vue,一個是Angular。

React和Vue本身更偏得於外掛化,哦,不,元件化。所以他們需要便宜桶,來拼接整個前端的架構體系。

Angular卻是有典型的Java架構風格,妥妥的硬漢子。

所以,實際上說,這套體系也是可以應用在WEB上的,就像Android和IOS一樣的,但是你喜歡,或者不喜歡,自己選啦。

 

五 進一步的學習的話,是要學習系統架構麼?

是的。進一步要學習,並不僅僅是學習系統架構。

這裡還沒有講到Service的設計,互相之間的呼叫,解耦,服務之間的通訊和管理。

訊息佇列這個神器還沒有登場,MongoDB這種戰略要塞也沒出場。

所以以上內容,僅適用於2年以內的各種工程師。


作者:超維
連結:https://www.zhihu.com/question/58410621/answer/157153091
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

程式是對現實的抽象和模擬。程式設計中的這些概念單純看定義和名詞解釋是很難理解的,要在現實世界中找到對應關係。

以到銀行轉賬為例:

選擇查詢、取款還是轉賬是controller
點鈔驗鈔機是util
轉賬是service
賬戶是model
更新餘額是DAO

所以如果現實中的業務結構是混亂的,即使開發中套用這些技術框架,也不可能寫出結構清晰的程式。所以首先要業務建模和業務模式重組啊同學們!
 


作者:Ivony
連結:https://www.zhihu.com/question/58410621/answer/157049250
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

 

先名詞解釋吧:

DAO = Data Access Object = 資料存取物件

Service = 服務

Controller = 控制器

Util = 工具

Model = 模型

 

首先,一個程式碼是不是有完善的結構,和是不是有上面這些東西沒有什麼關係,只是通常來說,我們做一個大專案會把專案分解成很多不不同的模組(Module),然後根據用途和角色,我們對這些模組有一個通用的命名規則,這也就是上面這些英文單詞的來歷。

 

所以,請一定記住,專案中是否包含這些模組或者單詞,和你的專案結構是否完善一毛錢關係沒有。但是當你的專案結構相對完善的時候,你會發現有這樣一些角色的存在。

 

接下來一個個的來詳細討論一下這個東西是如何出現的:

DAO,資料存取物件。通常我們會遇到很多要和資料庫打交道的場景,如果為每一個場景都去寫一些SQL語句,會讓我們程式碼變得很奇怪,我們希望我們的程式碼比較乾淨整潔,那麼一個很容易想到的方案就是把資料庫封裝一下,讓我們和資料庫的交道看起來比較像和一個物件打交道。這個物件通常就是DAO,當我們操作這個物件的時候,這個物件會自動的產生SQL語句來和資料庫打交道,而我們只需要和DAO打交道就可以了。

當然,從本質上來說,DAO並不需要和資料庫有什麼必然的聯絡,DAO只是資料存取物件的縮寫,所以只要是把資料持久化包裝成一個物件的訪問(讀寫),這種物件都可以被稱之為DAO,譬如,用JSON格式存到硬碟上。

 

Service,我們有時候會需要一些相對獨立,與業務系統沒啥關係的功能。但不是所有的功能都可以做成一個服務,服務是一個相對獨立的功能模組,完成一些指定的工作,這些工作高度抽象和通用。一個典型的服務像是資料庫服務、快取服務、檔案儲存服務、身份驗證服務、訊息佇列服務等。

關係型資料庫服務可以視為是一個接收SQL語句並給出一個查詢結果的服務,我們不必關心服務內部具體是如何處理問題的,我們只需要關注服務給出的介面。

並不是所有的模組都適合做成服務,一個服務首先最重要的是獨立性,這個服務必須可以獨立的完成指定的工作。複雜的服務可能依賴於一個或者多個更基礎的服務,但是服務通常不應當依賴於任何具體的業務程式碼,服務必須具有高度的抽象性。關係型資料庫服務就具有高度的抽象性,事實上只要我們撰寫標準的SQL,不論後面是MySQL、SQL Server還是Oracle,他們都會呈現出幾乎完全相同的行為。

一個更為簡單的服務像是快取服務,我們把一坨資料放進去,在一段時間內可以快速的獲取這坨資料,在一段時間後資料就會消失。

當你的程式碼需要一個高度抽象高度標準化的功能,而這個功能又不能簡單的實現,或者這個功能需要很多資源的配合,例如快取服務需要記憶體資源,而資料庫服務通常需要磁碟資源,身份驗證服務通常需要資料庫服務支援。這個時候就可以考慮將這個功能模組做成一個服務。

服務作為基礎的部件,我們通常會要求它能夠應付各種各樣的情況,一個優質的服務通常會有非常高的可用性,因為我們的系統可能會依賴於各種各樣的服務,而整個系統的可用性將不可能比其中任何一個服務的可用性更高。

所以服務的特徵:抽象、獨立、穩定。

 

評論中提到Java專案中的Service通常是指Business Service,這裡也簡單說說。

很多時候,我們發現服務的特徵對於我們開發一個大型專案的時候很有幫助。就拿獨立性來說,關係型資料庫服務如SQL Server可以獨立發售,獨立安裝和部署。它可以自行測試自己的介面,如果都達到了預期的效果,並且能夠應付各種情況,這個服務就可以作為一個產品獨立的出售給我們安裝。這意味著關係型資料庫服務並不需要配合我們的業務系統一起進行測試和除錯,或者作出什麼變更。

在完成一個大型的業務系統時,我們發現一些子模組或者子系統也可以像服務一樣獨立的部署和測試。例如會員系統、支付系統、訂單系統等等,他們的業務邏輯可能非常複雜,但是邏輯相對獨立,並且高度內聚。如果我們將這些系統分別獨立的測試和部署,就可以大大的降低我們的測試、部署和運維的成本。

這些可以獨自完成某一方面業務功能,高度內聚,可以獨立部署測試的模組,我們可以稱之為Business Service,業務服務。它同樣具有服務的特徵,抽象、獨立和穩定。一個會員系統內部的邏輯可能非常複雜(積分規則,分級規則,風險控制,行為資料),但是在其外部,會員的概念可以非常簡單。


 

Util,Util通常來說是我們找不到合適的名字的時候的選擇,Util就是工具,在做專案的時候我們總會遇到一些奇奇怪怪的小功能或者重複的程式碼需要提取。像是URL編碼或者解碼(當然這個類庫通常會提供,不過就以 .NET Framework 為例,提供這個方法的型別名稱叫做HttpUtility),或是自創的加密簽名演算法等等。


 

Model,模型,通常來講,我們會把模型和另一個東西放在一起來說:View,檢視。

模型通常認為是檢視的核心,何謂之檢視?我們正在與之互動的知乎網站的介面就是檢視,而模型是指他的核心:資料。

知乎的資料是問題和答案,問題分為標題和描述,答案有內容和作者以及各種狀態。知乎有很多個UI,例如移動頁面,普通PC頁面,手機APP,以及改版前的舊介面,這些被稱作不同的檢視。而所有這些形態迥異的檢視,其核心都是一樣的,這個核心我們就稱之為模型(Model)。

將Model和View的概念拆分開來,有助於我們關注不同的方面,也可以更有效的分工。有些工程師更關注於核心也就是模型,通常來說,他們被稱之為後端工程師。有些工程師更關注於使用者介面的互動和展示,通常來說,他們被稱之為前端工程師。


作者:Cyandev
連結:https://www.zhihu.com/question/58410621/answer/156921734
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

個人簡單理解:

 

DAO(Data Access Object)顧名思義就是用 OO 的方式去執行資料庫的操作,包括函式化的 CRUD,可以自己去寫也可以用 ORM 框架。

Service 可以處理事務和業務邏輯,比如使用者登入的校驗等。

Controller 其實就與業務無關了,它更多的是將 Service 層的結果加以處理返回給 View,也可能會處理一些簡單的引數檢驗工作。

Util 的話就是一些輔助類(或函式),涉及面可能比較廣,粒度小,比如生成 MD5 的便利函式等。

Model 是最簡單的,Java 裡對應的就是 Beans,ORM 框架也將根據 Model 中的定義去生成 SQL 語句,在其他語言中也是一些 Plain Old Object,自身可能會有一些資料表達的處理功能,但更多的不應該涉及副作用。