DAO类的CRUD方法与DAO类的实体特定方法对比

4
我想知道在以下两种方法中,创建DAO模式的正确方式是哪一种。
场景:我有一个电影院的Web应用程序,包括实体如Film和Showing。它是一个PHP应用程序,但我认为这个问题与任何OO编程语言都相关......
选项A:仅CRUD
创建单个DAOInterface类,定义CRUD方法insert、get、update和delete,并在类如FilmDAO和ShowingDAO中实现该接口。 这样,我将使用相同的方法get来检索“今天所有电影”或“给定类型的所有电影”,因此我需要设置一些参数数组来决定要检索的实体...
选项B:特定于实体的方法
创建不同的接口,如FilmDAOInt和ShowingDAOInt,定义特定于每个具体实体的方法,例如getFilmsByDate、getFilmsByGenre、getShowingsWithDiscount等等。
问题是:这只是品味问题,还是其中一个方法比另一个更好?为什么?

例如,上一次我使用Hibernate时,具体的DAO会为静态类型在运行和编译时装饰一个通用的DAO,但是对于底层持久化层来说,它具有灵活的核心。 - Florian Salihovic
2个回答

2
甚至可以将两者结合起来,这样你就会有一个接口层次结构和一个并行的实际类层次结构,即:
伪代码如下:
// generic Dao interface applies to any Dao
interface IGenericDao[T] {
   findById(Long Id): T
   findAll(): List[T]
   countAll(): Integer
   delete(Id: Long)
   create(element: T)
   modify(Id: Long, modification: T)
}

// offers everything from IGenericDao plus Film-specific
interface IFilm extends IGenericDao[Film] {
   findByName(filmName: String): List[Film]
}

// offers everything from IGenericDao plus Showing-specific
interface IShowing extends IGenericDao[Showing] {
   findByDayAndTime(when: Timestamp): List[Showing]
}

class GenericDao[T] implements IGenericDao[T] { ... }
class FilmDao extends GenericDao[Film] implements IFilm { ... }
class ShowingDao extends GenericDao[Showing] implements IShowing { ... }

1
在一个正常的应用程序中,当您控制数据和其他层,并且数据层仅在该应用程序中使用(而不是作为库使用)时,应用程序的其余部分应仅与特定于实体的接口交互,以适应应用程序的需求。有很多原因:
  • 你的应用程序的其余部分通常需要在数据层中执行一些无法通过基本的CRUD方法有效完成的操作。例如,您可能需要一个很好地映射到SQL group by的报告。

  • 即使基本的CRUD方法可以完成其他层需要的任何操作(例如,它们可以采用查询语言片段),但使用它们需要其他层了解数据库结构。

  • 对于任何给定的实体类型,某些CRUD方法可能无效。也许您的应用程序存储日志,并且禁止更新或删除日志行。不向应用程序的其余部分公开执行此操作的方法是一种很好的强制执行方式。

  • 对于任何给定的实体类型,某些CRUD方法可能不需要。如果不需要它们,则不要编写它们。

  • 特定实体DAO具有比CRUD DAO更多的方法,但它们可以用较少的总方法调用量来完成工作,其参数更简单(例如没有查询语言片段)。因此,它们更容易在测试中进行存根和模拟。

当然,对于使用ORM框架的实体特定类来说,自动拥有所有基本的CRUD方法并由程序员添加实体特定方法是很常见的。在这种情况下,通常没有必要拥有一个单独的实体特定层来隐藏DAO层;通常只需要使用代码标准来要求应用程序的其余部分仅使用实体特定方法或那些不泄露数据库知识的基本CRUD方法即可。不幸的是,这需要纪律性,任何看过控制器充满ActiveRecord查询的Rails应用程序的人都知道这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接