DataMapper模式是否会破坏MVC?

时间:2009-06-19 08:50:23

标签: zend-framework activerecord domain-driven-design dry model-view-controller

我一直在阅读多个PHP框架,尤其是Zend框架,但我对前进的正确方法感到困惑。

Zend Framework不使用ActiveRecords,而是使用表数据网关和行数据网关模式,并使用DataMapper将行数据网关的内容映射到模型,因为当模型没有时,ActiveRecord会崩溃1:1映射到数据库表。 Zend快速入门指南中有一个example of this

对我来说,他们的例子看起来非常臃肿,到处都是大量的吸气剂和制定者。我发现了各种关于Domain Driven Design的博客文章,认为使用如此多的getter和setter是不好的做法,因为它将所有内部模型数据暴露给外部,因此它没有公共属性的优势。 Here is one example

我的问题:如果删除那些getter和setter,你将如何呈现你的观点?在某些时候,数据必须点击视图,以便您可以实际向用户显示某些内容。遵循DDD建议似乎打破了MVC中M和V之间的分离。继MVC和Zend之后,似乎打破了DDD并让我为所有模型输入了大量的getter,setter和DataMappers。除了做大量工作外,它似乎也违反了DRY。

我真的很感谢一些(链接)好的例子或更多关于它们如何组合在一起的信息。我正在努力提高我的架构和设计技巧。

5 个答案:

答案 0 :(得分:2)

您不需要实现所有getter / setter,您可以使用_get()和__set()。那有什么问题呢?

答案 1 :(得分:2)

使用Value Objects,您可以消除其中一些公共setter方法。以下是the difference between Entity and Value Objects的说明。值对象是不可变的,通常与实体绑定。如果使用构造函数传递所有值,则无需从外部代码设置这些属性。

额外的东西,与答案没有直接关系,但更侧重于DDD:

(免责声明:我对Zend Framework的唯一了解就是我在链接文章中读到的内容。)Zend Framework使用DataMappers而不是Repositories。这真的是DDD吗?好吧,Fowler's interpretation of a Repository可能会说不。但是,Eric Evans表示DDD存储库可以非常简单。最简单的,Repository 一个DataMapper(参见DDD书)。对于更复杂但仍然是DDD的东西,请参阅Fowler文章。 DDD有一个概念存储库,可能与模式定义不同。

我恳请您继续阅读有关域驱动设计的内容。我认为假设getter和setter违反DDD存在缺陷。 DDD专注于领域模型和实现这一目标的最佳实践。访问者只是一个小细节。

答案 2 :(得分:1)

从我对这篇文章的阅读来看,这个问题更具哲学性而非实际性。

我没有时间深入写作,但这是我的两分钱。虽然我同意你想限制get和set请求的数量,因为一个类应该隐藏它的内部,你还需要考虑Java和PHP是不同的工具,并有不同的目的。在Web环境中,您的类正在构建并随每个请求一起被删除,因此您编写的代码不应该依赖于庞大的类。在您指出的文章中,作者建议将视图逻辑放在类中。这可能在网络上没有意义,因为我可能想要以多种格式(rss,html等)呈现视图。因此,使用存取方法(get& set)是必要的恶。你仍然想要经常使用它们,这样你就不会用脚射击自己。关键是要让你的课为你做的工作,而不是试图强迫他们在外部工作。通过方法而不是直接访问您的属性,您可以隐藏您想要的内部结构。

同样,这篇文章可以使用一些例子,但我现在没有时间。

其他人可以提供一些为什么访问者方法不邪恶的例子?

答案 3 :(得分:1)

这里有两种方法:我称之为“告诉不要问方法”,另一种是ViewModel / DTO方法。 基本上,问题围绕着您视图中的“模型”。 告诉不要求要求对象可以外化的唯一方法是来自对象本身。换句话说,要渲染对象,您将拥有一个render方法,但该render方法需要与一个接口进行通信。 像这样:

class DomainObject {
   ....
   public function render(DomainObjectRenderer $renderer) {
        return $renderer->renderDomainObject(array $thegorydetails);
   }
}

在Zend Framework的上下文中,您可以继承Zend_View并让您的子类实现此接口。

我以前做过这件事,但有点笨拙。

第二个选项是将您的域模型转换为ViewModel对象,这类似于数据的简化,扁平化,“纵向”视图,为每个特定视图(每个视图一个ViewModel)自定义,以及返回的方式,将POST数据转换为EditModel。

这是ASP.NET MVC世界中非常流行的模式,但它也类似于用于在应用程序中的“层”之间传输数据的类“DTO”模式。您需要创建映射器来为您执行脏工作(实际上与DataMapper不同)。在PHP 5.3中,您可以使用反射来更改私有属性,因此您的DomainObject甚至不需要公开自己!

答案 4 :(得分:0)

在我看来,实现getter和setter有两个好处:

  1. 您可以选择公开哪些属性,因此您不必公开所有模型的内部结构
  2. 如果您使用具有自动填充功能的IDE,当您开始输入“get”或“set”时,所有可用的属性都将成为TAB,这对我来说是足够的理由。