隐藏DAO服务,为什么?

时间:2009-05-06 22:15:00

标签: java web-applications oop

在审核了一堆MVC风格的Web应用程序后,我注意到在业务层前面有一个非常大的服务接口是很常见的。该接口的实现通常包括一堆DAO。所以你有类似的东西:

public class FoodServiceImpl implements FoodService {

  private FruitDAO fruitDAO;
  private VegetableDAO vegetableDAO;
  private MeatDAO meatDAO;

  // ... DAO injection stuff

  public List<Meat> getMeat() {
    return meatDAO.getMeat();
  }

  public void addMeat(Meat meat) {
    meatDAO.add(meat);  
  }

  public List<Fruit> getFruit() {
    return fruitDAO.getFruit();
  }

  // ... tons of methods that mostly just delegate to DAOs

}

假设您的DAO首先不是具体的,为什么不将DAO暴露在更高层次?

所以而不是:

// assume foodService is injected at runtime
public void controllerMethod() {
  foodService.getFruit();
  foodService.getMeat();
}

你刚才

// assume DAOs are injected at runtime
public void controllerMethod() {
  fruitDAO.getFruit();
  meatDAO.getMeat();
}

一方面,将应用程序的整个内容包含在单个界面中看起来很不错....另一方面,最终可能会遇到一个巨大的接口,其实现只会委托给DAO

我可以看到在一个地方管理所有DAO很好。我还可以想象,如果将通过多种服务使用相同的DAO,这种模式将非常有用。

在启动Web应用程序时,这被视为“最佳做法”,还是仅在预期会出现某种程度和类型的复杂性时才适用?

5 个答案:

答案 0 :(得分:8)

我认为注入服务层更有意义,因为它知道工作单元。如果您的用例需要多个DAO参与一个工作单元,则需要一项服务来“拥有”该交易。

此外,它是面向服务架构的本质。忘记WS- *;服务映射到用例和业务流程。

答案 1 :(得分:6)

假设整个后端不仅仅是一个巨大的CRUD API,您通常会在服务层中看到调用的业务逻辑。业务逻辑可能直接在服务方法本身(a.k.a。“Anemic Domain Model”)中,或者服务层必须只负责调用传递给DAO层/从DAO层传递的实体的业务方法(“Rich Domain Model”)。您可能还会在服务层中看到安全性或审计等内容。或者,可以通过面向方面编程(AOP)将跨安全问题(如安全性或审计)应用于服务层。

答案 2 :(得分:3)

创建类只有一个原因:隐藏固定边界后面的实现等细节。在此示例中,您有一个名为FoodService的服务,以及一个了解各种DAO的实现类。那你藏什么?

看起来像两件事:

  1. 你有这些食物的事实
  2. 他们存储的方式。
  3. 如果他们存储的方式永远不会改变,那么你可能不需要这个。但如果您的DAO被替换为不同的机制 - 比如分布式Google BigTable - 您可能更愿意不需要触及所有代码来更改类型。

    当然,你总是有可能开始携带HealthAndBeautyAids,因此需要另一个课程。 (事实上​​,你可能最好不要有一个方法告诉你你可以访问的东西是什么类型,然后有方法可以访问它们的类型?)

答案 3 :(得分:2)

MVC主要是一种表示模式,大多数非平凡的系统使用分层方法,至少你有表示层,业务层和数据访问层。在您的情况下,您可以直接公开DAO,但在中间保留业务层可以更好地封装业务逻辑并有助于系统的可扩展性。假设您对存储肉的位置有新的要求:

if (meat.expirationDate-today >= 5 days)
   FridgeDAO.store(meat)
else if (meat.expirationDate-today <5 days)
   FreezerDAO.store(meat)
else 
   discard(meat)

如果您直接公开DAO,则需要将业务逻辑添加到演示文稿中,如果更改演示文稿技术(或者如果要公开功能),则可能会导致业务逻辑分散并且不得不重写它作为webservices)。使用接口作为业务层的入口点可进一步解耦表示和业务逻辑。

答案 4 :(得分:0)

进行远程处理的最佳方法是不进行远程处理。

在图层中执行代码很好,但您不必通过创建远程API来强制执行图层。任何没有任何真正的架构需求(即性能分析等)的人只会在没有任何内容的情况下抛出流行语或创建需求。

请记住,程序员的时间比整体上的硬件花费更多。