在不分層的系統裡,我們可以將所有的代碼都寫到一個地方,比如struts的Action類。在這裡,我們不僅要處理頁面邏輯,還要做業務邏輯,還要做數據訪問。比如說:
public String addUser() {
if(user == null) {
return FAIL_NO_USER;
}
Result result = null;
if(Role.ADMIN.equals(user.getRole())) {
result = DOSomethingForAdmin(user) ;
} else {
result = DOSomethingForOthers(user);
}
Transaction trans = sess.beginTransaction();
Query query = sess.createQuery("update Result set level = :level");
query.setParameter("level", result.getLevel());
query.executeUpdate();
trans.commit();
sess.close();
return SUCCESS;
}那麼上面的代碼,哪些部分是頁面的部分,哪些是業務處理,哪些是數據訪問呢?我認為,這個劃分方法是:Action裡只做和頁面相關的事,不操作業務對象;Service不依賴於任何表現技術,不操縱任務用於表現的對象,對於業務對象,尤其是跨多個業務對象的操作,要放到Service裡面來;最後,單純的業務對象的存取,組裝放到DAO裡完成。上面所說的業務對象,就是像上例中role, result等和業務相關的對象,而SUCCESS, inputID等,則是頁面相關的部分。因些,可以將上例改為:
public String addUser() {
if(user == null) {
return FAIL_NO_USER;
}
Result result = service.process(user);
dao.update(result);
return SUCCESS;
}
在service裡:
public Result process(User user) {
Result result = null;
if(Role.ADMIN.equals(user.getRole())) {
result = DOSomethingForAdmin(user) ;
} else {
result = DOSomethingForOthers(user);
}
return result;
}
在dao裡:
public void update(Result result) {
Transaction trans = sess.beginTransaction();
Query query = sess.createQuery("update Result set level = :level");
query.setParameter("level", result.getLevel());
query.executeUpdate();
trans.commit();
sess.close();
}這樣分層,看起來會顯得很麻煩,但事實上確實是大有好處,首先:
代碼更易讀。每一層的每個方法的意義和目的更加明確,讀以起來受的干擾更少。
拆開後的每一層都更容易測試。
具體如何分層,還需要在開發中,多多體會,這沒有絕對的界限,也許一開始放在action裡的頁面的控制後來會上升為業務規則,並被其它地方重用,然後被移入service;也許某一塊對數據的存取也變得非常復雜,包含了業務邏輯,然後被移入service;也有可能發現以前寫的service根本沒有想像的那樣的業務邏輯,只是幫助做了一些頁面的流程控制,然後被重構成Action的一個方法,等等。