8

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

Zend Framework 不使用 ActiveRecords,而是使用 Table Data Gateway 和 Row Data Gateway 模式,并使用 DataMapper 将 Row Data Gateway 的内容映射到模型,因为当您的模型没有 1 时 ActiveRecord 会崩溃: 1 映射到您的数据库表。Zend 快速入门指南中有一个示例。

对我来说,他们的例子看起来非常臃肿,到处都是大量的 getter 和 setter。我遇到了各种关于域驱动设计的博客文章,他们认为使用这么多的 getter 和 setter 是不好的做法,因为它会将所有内部模型数据暴露给外部,因此它与公共属性相比没有优势。这是一个例子

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

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

4

5 回答 5

2

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

于 2009-06-20T22:45:36.427 回答
2

使用值对象,您可以消除其中一些公共 setter 方法。这是对Entity 和 Value Objects 之间区别的描述。值对象是不可变的,通常与实体相关联。如果使用构造函数传入所有值,则无需从外部代码设置这些属性。

一些额外的东西,与答案没有直接关系,但更专注于 DDD:

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

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

于 2009-06-23T18:06:30.633 回答
1

从我对帖子的阅读来看,这个问题更具哲学性而不是实际性。

我没有时间深入写,但这是我的两分钱。虽然我同意您希望限制 get 和 set 请求的数量,因为类应该隐藏其内部,但您还需要考虑 Java 和 PHP 是不同的工具并且具有不同的用途。在 Web 环境中,每个请求都会构建和删除您的类,因此您编写的代码不应依赖于巨大的类。在您指出的文章中,作者建议将视图逻辑放在类中。这在网络上可能没有意义,因为我可能希望以多种格式(rss、html 等)呈现视图。因此,使用访问器方法(get & set)是必要的。你仍然想慎重地使用它们,这样你就不会在脚下开枪了。关键是尝试让您的班级为您完成工作,而不是试图强迫他们在外部完成工作。通过使用方法而不是直接访问您的属性,您可以隐藏您想要的内部结构。

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

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

于 2009-06-22T19:31:58.730 回答
1

这里有两种方法:我称之为“告诉不问方法”,另一种是 ViewModel/DTO 方法。本质上,问题围绕着您认为的“模型”是什么。告诉不问要求对象可以外化的唯一方法是从对象本身。换句话说,要渲染一个对象,您将有一个渲染方法,但该渲染方法需要与接口对话。像这样的东西:

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 甚至不需要暴露自己!

于 2009-11-09T21:26:31.887 回答
0

在我看来,实现 getter 和 setter 有两个优点:

  1. 您可以选择公开哪些属性,因此您不必公开所有模型的内部结构
  2. 如果您使用带有自动完成功能的 IDE,那么当您开始键入“get”或“set”时,所有可用的属性都将在一个 TAB 之外——这对我来说就足够了。
于 2009-07-09T21:42:01.173 回答