随笔-199  评论-203  文章-11  trackbacks-0
在不分层的系统里,我们可以将所有的代码都写到一个地方,比如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的一个方法,等等。

posted on 2009-05-14 18:13 Werther 阅读(5550) 评论(8)  编辑  收藏

评论:
# re: 区分Action, Service 和 Dao功能 2009-05-14 19:39 | too young too simple
too young too simple sometimes native

在实际开发中 这样的分层是对效率的极大浪费  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-14 19:58 | Edward's
@too young too simple
实际开发就是这样吧  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-14 20:49 | stone2083
根据需求来决定的。
系统分层,和公司设立部门的概念是同样的。

一个创业型公司,很可能整个公司就一个人:即是老板,又是程序员,同时还是业务员,等等,
如同一个系统中,一个action做了所有的业务;

一个中型公司,有一个老板,有一个技术人员,有一个业务人员,有一个运营人员,等等,
如同一个系统中,有action层,biz层,service层,dao层等,通过jar包依赖调用;

一个大型公司,有CEO,有技术部们,有业务部门,有运营部门,等等,
如同系统模型中,每个模块存在独立service系统服务,依赖dao api,依赖search engine api,依赖DW api等;
前台又有不同的业务系统,有自己的action,依赖biz层,biz层又依赖独立模块的service api;
系统之间的依赖,采用SOA架构等

不同的企业规模,决定不同的公司组织架构;
不同的产品需求,决定不同的系统架构;



  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-15 09:11 | guest
其实biz层,service层两者可以合并为一层,你们觉得如何  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-15 12:23 | stone2083
一般应用中,biz层和service层的概念就是同一个,硬做分层,是脱了裤子放屁 ,自找麻烦。 :)

当公司规模大了,应用庞大了,复杂了:
比如,当web应用有几十,上百个;task应用几十,上百个。。。
该如何控制和维护业务人员编写的biz和dao呢?

于是乎,就需要抽象出service层(核心组件服务/核心产品服务),service依赖dao api,search engine api,dw api等等,并且通过某些协议,暴露自己的service api

前台应用(web应用,task应用等),通过biz层,调用不同service api(不再涉及dao等底层服务)

如此一来,底层实现发生变化,比如数据库重构等,只要维持service api不变,不会涉及前台应用的变动。

如同上面说的,要不要biz,service,还是根据应用规模来决定的。

  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-16 23:22 | jinfeng_wang
to 楼上:
是不是“脱了裤子放屁”,得取决于你的肠道的功能好不好,不小心有一天,你就会以为是放屁,其实是拉稀。

顺手牵羊式的“脱裤子放屁”,绝对是减少“莫名其妙”问题出现可能性的一个绝佳机会。 在系统演变的越来越复杂的时候,是没有心思和时间再去演变你的原有代码结构的。

如果你的公司,允许你随意改动“既成的可运行”的代码,麻烦你说一下,你公司名字。

  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-05-21 13:25 | stone2083
比喻很形象,也比较能说明问题。站在技术角度上,我非常认同你说的观点。
对于一家长期发展的公司,系统演变会越来越复杂,前期为了贪图方便的设计,总有一天,会带来无穷的痛楚。这些俺都明白。目前也在经历这些痛楚。

但是,确实也存在很多系统,本身业务并不复杂(比如外包公司接手的一次性的小项目),并且也很难看到未来的发展方向(比如针对一些创业型公司的项目),之后重写+数据迁移的方案代价远远小于系统重构的代价,那么我,决不会采用复杂的架构,把简单问题复杂化。
PHP,ROR(使用action+model,没有过多分层)的项目,在中小型项目中,比较流行的,也能说明一些问题。

很多的系统,如果能标标准准按照action->biz->dao的结构写,已经是相当不错了(通过一些应用抛出的错误异常看,很多甚至在jsp上书写大量的业务逻辑,或者在action属性大量的业务逻辑)。要在biz层抽象出biz->service的概念的系统,并不是太多。(至少是中型公司及以上,才需要考虑的)

我说这些,不是为了否决楼上的说辞--其实我是非常认同的观点。
我只是想表明,任何的架构设计,都是需要根据需求以及未来的发展,来决定的。  回复  更多评论
  
# re: 区分Action, Service 和 Dao功能 2009-06-26 17:20 | API
受益良多  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: