php - 谁应该处理复杂查询中的条件,数据映射器还是服务层?

标签 php domain-driven-design datamapper

this question很好地消除了我对此事的困惑,但我很难找到关于服务层的确切限制应该是什么的可靠来源。

对于这个例子,假设我们正在处理书籍,并且我们想要按作者获取书籍。 BookDataMapper 可以有一个通用的 get() 方法,它接受诸如书籍的唯一标识符、作者姓名等条件。这个实现相当简单(逻辑上) ,但是如果我们想要有多个条件需要更复杂的查询怎么办?

假设我们想要获取某个作者在某个特定出版商下所写的所有书籍。我们可以扩展 BookDataMapper->get() 方法来解析多个条件,或者我们可以编写一个新方法,例如 BookDataMapper->getByAuthorAndPublisher()

是让服务层直接调用这些[更具体的]方法,还是在调用更通用的 BookDataMapper->get() 方法并传递多个条件之前解析条件?在后一种情况下,服务层将完成更多逻辑上的“繁重工作”,而使数据映射器相当简单。前一个选项会将服务层几乎完全减少为一个中间人,将条件逻辑留给 BookDataMapper->getByAuthorAndPublisher() 等方法中的数据映射器。

让服务层解析条件的明显问题是一些域逻辑从数据映射器中泄漏出来。 (这在链接问题 here 中进行了解释。但是,如果服务层要处理这些条件,则逻辑不会脱离模型层; Controller 将调用 $book_service->getByAuthorAndPublisher() 无论如何。

最佳答案

The data mapper pattern only tells you, what it is supposed to do, not how it should be implemented.
Therefore all the answers in this topic should be treated as subjective, because they reflect each authors personal preferences.

通常尽量保持映射器的界面尽可能简单:

  • 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 );

这样你就可以有多个检索条件,同时保持界面干净。

这样做的缺点是您需要一个公共(public)方法来从域对象中检索信息以具有这样的 fetch() 方法,但是无论如何您都需要它来执行 save( )

没有真正的方法来实现映射器和域对象交互的“告诉不要问”经验法则。

至于“如何确保您确实需要保存域对象?”,您可能会想到,它已被涵盖here ,在注释中有大量的代码示例和一些有用的位。

更新

如果您希望处理对象组,我认为您应该处理不同的结构,而不是简单的领域对象

$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 );

在这种情况下,集合是美化数组,能够接受不同的参数,然后用作映射器的条件。当映射器试图存储集合时,它还应该让映射器从该集合中获取列表更改域对象。

这种情况下的映射器应该能够构建(或使用预设的)具有所有可能条件的查询(作为开发人员,您将知道所有这些条件,因此您不需要使其在无限条件下工作)并为该集合包含的所有未保存的域对象更新或创建新条目。

注意:在某些方面,您可以说映射器与构建器/工厂模式相关。目标不同,但解决问题的方法非常相似。

关于php - 谁应该处理复杂查询中的条件,数据映射器还是服务层?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11942842/

相关文章:

php - sql中while循环获取不到count值?

php - 如何使用 .htaccess 重定向除一个请求以外的所有请求?

Javascript/PHP - 使用 PHP 从服务器检索数据并使用 Javascript 生成/重新排列它是个好主意吗?

c# - 学习和实践领域驱动设计,寻找一些指导

java - DDD : How to hide specific aggregate root constructors from integration layers in Kotlin

mysql - DataMapper 将列迁移到新的数据类型

ruby - 使用 Sinatra 制作日历

php - Laravel 5.1 身份验证 - token 不匹配

c# - 基于公司而非用户的复杂领域模型

php - 如何使用 Datamapper 计算 Codeigniter 中查询返回的行数