谁应该处理复杂查询,数据映射器或服务层中的条件?
这个问题在解决这个问题上做了很好的工作,但是我很难find关于服务层的确切限制的可靠来源。
对于这个例子,假设我们正在处理书籍,我们想要作者得到书籍。 BookDataMapper
可以有一个通用的get()
方法来接受条件,比如书籍的唯一标识符,作者姓名等。这个实现相当简单(逻辑上),但是如果我们想要多个条件需要更多的条件复杂的查询?
比方说,我们想要得到某个作者在特定发布者下写的所有书。 我们可以扩展BookDataMapper->get()
方法来parsing多个条件,或者我们可以编写一个新的方法,如BookDataMapper->getByAuthorAndPublisher()
。
最好让服务层直接调用这些[更具体的]方法,或者在调用具有多个条件的更通用的BookDataMapper->get()
方法之前parsing条件? 在后一种情况下,服务层会做更多的逻辑“繁重工作”,使数据映射器相当简单。 前一个选项会将服务层几乎全部减less到只有中间人,从而在像BookDataMapper->getByAuthorAndPublisher()
这样的方法BookDataMapper->getByAuthorAndPublisher()
条件逻辑留给数据映射器。
让服务层parsing条件的一个明显的问题是一些域逻辑泄漏出数据映射器。 (这在这里的链接问题中有解释,但是,如果服务层处理条件,则逻辑将不会使其脱离模型层;控制器无论如何都将调用$book_service->getByAuthorAndPublisher()
。
数据映射模式只告诉你,它应该做什么,而不是应该如何实现。
因此,在这个话题中的所有答案应该被视为主观的,因为它们反映了每个作者的个人喜好。
我通常尽量保持mapper的界面简单:
-
fetch()
,检索域对象或集合中的数据, -
save()
,保存(更新现有的或插入新的)域对象或集合 -
remove()
从存储介质中删除域对象或集合
我把这个条件保留在域对象本身中:
$user = new User; $user->setName( 'Jedediah' ); $mapper = new UserMapper; $mapper->fetch( $user ); if ( $user->getFlags() > 5 ) { $user->setStatus( User::STATUS_LOCKED ); } $mapper->save( $user );
这样你就可以有多种检索条件,同时保持界面清洁。
这样做的缺点是你需要一个公共的方法来从域对象中检索信息来fetch()
这个fetch()
方法,但是无论如何你都需要执行save()
。
对于映射器和域对象交互,没有真正的实现“告诉别人问题”的经验法则。
至于“如何确保你确实需要保存域对象?” ,这可能会发生在你这里 , 在这里已经介绍了 ,在代码中有大量的代码示例和一些有用的东西。
更新
如果你希望处理一组对象,你应该处理不同的结构,而不是简单的域对象 。
$category = new Category; $category->setTitle( 'privacy' ); $list = new ArticleCollection; $list->setCondition( $category ); $list->setDateRange( mktime( 0, 0, 0, 12, 9, 2001) ); // it would make sense, if unset second value for range of dates // would default to NOW() in mapper $mapper = new ArticleCollectionMapper; $mapper->fetch( $list ); foreach ( $list as $article ) { $article->setFlag( Article::STATUS_REMOVED ); } $mapper->store( $list );
在这种情况下,集合是荣耀的数组,能够接受不同的参数,然后用作映射器的条件。 当映射器试图存储集合时,它也应该让映射器获取列表中已更改的域对象。
在这种情况下,映射器应该能够构build(或使用预设的)具有所有可能条件的查询(作为开发人员,您将了解所有这些条件,因此您无需使其工作在无限的条件下)为该集合包含的所有未保存的域对象更新或创build新条目。
注意:在某些方面,你可以说,mapper与build造者/工厂模式有关。 目标不同,但解决问题的方法非常相似。
我通常更喜欢这是更具体的,如:
BookDataMapper->getByAuthorAndPublisher($author, $publisher)
那是因为我不需要重新发明SQL。 数据库对此更好,数据映射器在这里注意,应用程序的其余部分不需要知道具体如何存储或查询事物。
如果你使这个更具dynamic性,你可以很容易地通过接口提供太多的function。 不好。
看看你的应用程序。 你会发现没有太多的东西会被质疑。 对于通常大约5-10个例程的数据的主要部分(如果有的话)。 它的写入速度比甚至想到一些实际上属于它自己的层次的dynamic系统要快得多。