OOP DAO设计问题

时间:2009-09-10 07:11:49

标签: php oop dao

快速背景:我正在用PHP编程,我有一个带有单独数据访问层(DAO类)的域模型,负责从数据库中获取数据并创建域类。

假设我有一个DAO类负责创建 groupList 对象。您可以将这些群体想象成社交网络的一个组成部分;虽然这个问题对他们来说并不重要。

我需要能够让DAO根据各种不同的标准为我制作各种 groupList 对象:

  • 最近添加的群组
  • 最受欢迎的群体
  • 由管理员识别为“特色”的群组
  • 使用特定标记标记的群组
  • 与特定关键字匹配的群组
  • 特定类别中的群组
  • 由某个人创建的群组
  • 在某一天创建的群组

其中一些我现在并不需要,但我可以想象在项目完成之前我需要它们。现在我开始使用一个简单的DAO方法: createList 。这很有效。您可以将伪代码视为:

find out how many groups
create SQL query to fetch group details
loop through results
{
   create group object
   add to group list object
}

随着我的应用程序的进展,我创建了一个新方法 createFeaturedList 。这很有效。但它实际上非常类似于 createList ,查询略有不同。其余约150行代码中的很多都是相同的。

所以... 我应该怎么做才能解决我需要的所有略有不同的情况?大多数时候我真的只想根据某些标准对列表进行过滤和排序。问题是这个 - 我应该:

a)创建大量专注的创作方法,如:

  • createList()
  • createCategoryList(categoryObject)
  • createUsersList(userObject)
  • createTagList(tag)
  • createPopularList()

b)创建一个可以执行所有操作的BIG方法:   - createList(searchString,orderBy,filterByCategoryObject = null,filterByUserObject = null)

我非常喜欢(a)的想法,因为我的DAO界面更简单,不太可能需要更改(例如:当我突然需要传递 date 来比较时添加另一个参数当你想要能够与其他参数结合的搜索关键词之类的东西时,难度就来了;例如:搜索的类别列表,搜索的热门列表,搜索的标签列表等...(a)是我开始时的一种。

我对(b)的重构有过调情,但我可以看到我的方法变得非常大而且很复杂很快,很多“如果”和“选择”来处理构建时的不同情况SQL,以及许多输入到方法中的参数。但至少它是在一个地方。你可以把事情结合起来;例如:用户的组,用blah标记,匹配关键字blah。

5 个答案:

答案 0 :(得分:1)

您可以创建一个所有公共方法都调用的私有方法。 IE

private function _createList ( searchString, orderBy, ... )
{
    ...
}

public function createList()
{
    return $this->_createList('...', 'id');
}

public function createCategoryList()
{
    return $this->_createList('...', 'category_id');
}

这样,如果你的_createList函数需要稍后改变,你只需要重构这个DAO中的公共方法而不是所有使用这个DAO的类。

答案 1 :(得分:1)

我认为这不是严格意义上的任何一种情况。选项a是DAO暴露的一个很好的可用界面,所以我认为你应该保留它。对我来说,选项b看起来真的像实现特定的逻辑。因此,如果BIG方法适合您的目的,我会说使用它来执行实际处理逻辑,同时在选项a中公开接口。

也就是说,如果BIG方法变得过于复杂和复杂,并且代码重用实际上增加了代码复杂性并降低了应用程序的可维护性,那么您可能希望重构为每个接口方法保留单独的SQL语句但是执行辅助方法解析结果的常用逻辑。

答案 2 :(得分:1)

选项B中的 big 方法几乎可以保证减少代码重用,并增加复杂性和维护时间。

就个人而言,(并且根据Code Complete)方法应该做一件事并且做得很好而不是试图填补所有内容。避免将来重构并且第一次做得很聪明。

答案 3 :(得分:0)

编程基础知识:将代码分解为部分或函数是一种很好的做法。

我会选择(a);您需要维护和调试代码。当你确实遇到错误时,你会很高兴你将代码分解成各种方法。

此外,编写方法名称有助于您了解自己在做什么。

比较一下:

选项(a)

$obj->AddNewList( /* params */ );
$obj->UpdateList( /* params */ );

和此:

选项(b)

$obj->parse( /* first set of params */ );
$obj->parse( /* second set of params */ );

它可以节省人类从左到右阅读的时间。这就是为什么函数和方法名称总是在左侧找到的原因。

答案 4 :(得分:0)

如果性能不是主要问题,或者组的变化足够慢以使查询缓存有用,您可以编写过滤函数并将其传递给。如果您循环遍历组并具有可选的过滤数组你的循环将成为的方法:

for(group in group) {
    cont = true
    for(f in functions) {
        if ! f(group) {cont = false; continue;}
    }
    if(cont) Continue
    add group to list
}

这将允许您在不改变循环的情况下更改过滤参数,只需编写或更改函数。