我想知道在下面我解释的两个选项之间创建DAO模式的正确方法是什么。
我有一个电影院的网络应用程序,其中包含Film
和Showing
等实体。它是一个PHP应用程序,但我认为这个问题与任何OO编程语言都有关...
创建一个DAOInterface
类来定义CRUD方法insert
,get
,update
和delete
,并在FilmDAO
等类中实现该接口}和ShowingDAO
。
这样我将使用相同的方法get
来检索“今天的所有电影”或“给定类型的所有电影”,所以我需要设置决定要检索哪些实体的一些参数数组......
创建不同的界面,例如FilmDAOInt
和ShowingDAOInt
,定义特定于每个具体实体的方法,例如getFilmsByDate
,getFilmsByGenre
,getShowingsWithDiscount
等。点。
这仅仅是品味问题,还是这些方法中的任何一种都比其他方法更好?为什么?
答案 0 :(得分:1)
在正常的应用程序中,您可以控制数据和其他层,并且数据层仅在该应用程序中使用(而不是作为库),应用程序的其余部分应仅与设计的特定于实体的接口进行交互以满足应用程序的需求。原因有很多:
您的应用程序的其余部分通常需要在数据层中执行某些操作,而这些操作无法通过基本的CRUD方法高效完成。例如,您可能需要一个能够很好地映射到SQL group by
的报告。
即使基本的CRUD方法可以执行其他层所需的任何操作(例如,它们可能采用查询语言片段),使用它们也需要其他层来了解数据库结构。
对于任何给定的实体类型,某些CRUD方法可能无效。也许您的应用程序存储日志,并且禁止更新或删除日志行。不向这个应用程序的其余部分公开这样做的方法是强制执行该方法的好方法。
对于任何给定的实体类型,可能不需要某些CRUD方法。如果他们不需要,请不要写。
特定于实体的DAO具有比CRUD DAO更多的方法,但是它们可以通过较少的来自其他层的总方法调用来完成工作,并且它们的参数更简单(例如,没有查询语言片段)。因此,它们更容易在测试中存根和模拟。
当然,特定于实体的类通常使用类似ORM框架的类来自动拥有所有基本的CRUD方法,然后由程序员添加特定于实体的方法。在这种情况下,通常不值得努力拥有一个隐藏DAO层的独立的特定于实体的层;一个人通常只使用代码标准来要求应用程序的其余部分仅使用特定于实体的方法或那些不会泄漏数据库知识的基本CRUD方法。不幸的是,这需要纪律,因为任何人都知道谁看到Rails应用程序的控制器充满了ActiveRecord查询。
答案 1 :(得分:1)
或者甚至将两者结合起来,你将拥有一个接口层次结构和一个并行的具体类层次结构,即
在伪代码中:
// 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 { ... }