現在后臺分成如下幾個層:
Domain:提供getter/setter
Dao:接口,定義了持久化方法,CRUD
DaoImpl:Dao的實現
Service:業務邏輯
但是在實際的過程中發現,service里面有很多涉及到持久化的查詢、更新操作,那么,這些方法是在dao中定義呢?還是在service中定義和實現?
比如,對于一個 客戶資料UserOrder 實體
dao中定義了getUserOrderByID() getAllUserOrder() insertUserOrder() updateUserOrder() delUserOrder()五個方法
現在需要一個 根據地區查詢客戶getUserByArea(),或者 根據產品線和地區查詢客戶 getUserByAreaSrv()
這樣的方法,定義在service還是dao中?
第二個問題。service層肯定是面向客戶端調用的,那么dao層對于客戶端是否暴露?
就是說,service層中是否提供dao中的方法,比如getAllUserOrder() insertUserOrder()這些方法?
如果不提供,那么客戶端需要知道哪些是dao中提供的,哪些是service提供的
如果提供這些方法,意味著所有的方法需要在dao中定義,daoimpl中實現,service中包裝,是否太重復和煩瑣?
1.
DAO只負責數據庫操作,不涉及任何邏輯,Service就需要業務邏輯了,比如getUserOrder()在DAO,你就查數據庫就行,在service中,你可能需要首先驗證當前用戶是否有這個操作權限,然后調用DAO,最后記錄日志
2.需要在dao中定義,daoimpl中實現,service中包裝,是否太重復和煩瑣?
其實這不會發生,因為你認為getUserByAreaSrv()方法肯定一定要完全從數據庫完成,其實不然,其實我可能只從數據庫查詢一個ID集合,然后,在服務層再通過緩存訪問封裝成完整的Model。這些都需要在Service完成(只是一個比喻)。
預留Service是為防止你的業務系統復雜化之后有一個插腳的地方。
現在很多系統就沒有這種插腳的地方,在struts的Action中直接調用Hibernate數據庫操作,如那個日本人做的開發框架RoR就是這樣,這些以喪失可維護性做代價的快速開發都是偽框架。
所以,為你的系統將來留著Service
3.我認為Dao層還是不要暴露在最外層為妙,即Service以外的層次都無法調用。否則實體化與應用邏輯以及界面之間的耦合度將無法控制,導致產品的生命周期縮短,可擴展性遭到破壞。
Service層當然也可以有getUserOrderByID() 這樣的操作,但最好通過調用DAO來實現,或者像banq說的以dao-cache的方式來實現,而不是直接去做實體操作。這樣做可能會感掉有些重復繁瑣,但會給產品今后的升級補充帶來好處。可能會多出這30%的代碼量,但帶來的好處是起碼能延長代碼30%的生命。
Service的方法定義和方法內的參數定義更傾于業務邏輯,而不是存儲方式。而Dao的定義則跟存儲方式直接掛鉤,而不需要過度考慮業務邏輯。所以代碼上的“繁瑣”恰恰代表了邏輯上的“簡單”。
更重要的是Service是必須的。
22一般service層是怎么實現的?是不是就是一個擁有很多靜態方法的類,每個靜態方法處理一些業務邏輯,還是有什么其它的方法,望指教
1我還有疑問,比如CoreFeeService好像是操作CoreFee這個domain bean的,如果我有一段業務邏輯,是調用CoreFeeService改變CoreFee的一些屬性,然后將CoreFee持久化到數據庫,接著可能要調用另一個domain bean的service方法。
在Struts框架中,這段代碼是寫在Action中,還是別的地方,Action又好像應該只控制轉發,不應該有業務的代碼在里面。但像上面那樣,可能還有事務處理,這時我該怎么做好呢?
2你描述的這段設計本來就是包含了業務邏輯。當然應該在Service里。service本身包含了粒度不同的操作,粗粒度的操作(方法)里可以包含很多細粒度的操作。這些細粒度的操作可以是private,也可是是public(如果別的action需要它)。
Action的概念當然跟業務本身是有一定關系的。你可以在action的代碼中表示出一些業務上的邏輯關系,但要節約。能在service中實現的最好在service中。這對程序結構是有好處的。
你說:“Action又好像應該只控制轉發,不應該有業務的代碼在里面”——這句話體現出你可能已經成為“框架”的“受害者”了。要用“框架”來提煉你的設計,而不要用來約束你的思維。不要指望從“框架”中找到理清軟件開發一切思路的“銀彈”——因為它根本不存在。