我应该如何创建我的数据映射器/域对象/服务?

Posted

技术标签:

【中文标题】我应该如何创建我的数据映射器/域对象/服务?【英文标题】:How should I create my Data Mappers/Domain Objects/Services? 【发布时间】:2013-11-03 11:24:50 【问题描述】:

所以我正在用 php 制作这个 Web 应用程序,并且我想用领域对象和数据映射器制作一个体面的模型层(尽可能),所有这些都由服务编排。

现在我在想,我应该如何创建我的对象?

工厂?

然后:

如果一个对象实现了某个接口(通常是DataMapper),我必须使用反射来实际执行。其他人没有他们需要实现的设置方法;我不想依赖名称,因为命名约定改变)。 我必须通过将工厂传递给 ServiceFactory 来违反 demeter 定律,然后它只会将其传递给它创建的服务。

new 关键字?

然后:

我在单独测试代码时会遇到问题。 感觉耦合太紧了。

还有什么?

我不知道,这就是我问的原因! :P

我该怎么办?有更好的方法吗?

【问题讨论】:

您可以使用类型提示来强制类型而不使用反射。我建议使用像 Doctrine2 这样的东西来为你抽象出所有这些。 我通常采用工厂(无反射)并使用spl_autoload 来捕获此类依赖项。当然,这只有在您有一些命名约定(如 PSR-0)时才有效 【参考方案1】:

Brian Vanderbusch 的评论暗示了最好的方法。您应该使用依赖注入来注入您需要的映射器。但是,为了减少耦合,您还应该键入hint 最基本的类型,通常是接口。

如何将 Data Mapper 实际注入到您的(大概)模型层并不重要。依赖注入容器可以存储有关哪些类需要哪些数据映射器的所有元数据,并自动为您注入依赖项。但是,在不使用 DIC 的情况下,您的代码的顶层在最基本的层面上应该如下所示:

    $model = new ProductsModel(new ProductsDataMapper(new Db('localhost', 'u', 'p', 'd')));

当然,映射器和数据库几乎肯定会在现实世界中的其他对象之间共享,并且您会传递对现有实例的引用。如果您需要模型层中的多个映射器,请将它们全部作为构造函数参数传递。

这里的关键是在应用程序的最顶层构建整个对象图,而不是担心事后定位它们。这是控制反转的前提,您可以将其视为由内而外构建结构。

【讨论】:

您(显然还有 Brian)误解了模型(或者更确切地说,服务)应该如何实际工作。服务可以根据需要创建和销毁尽可能多的域对象或数据映射器(对于注册,我会创建一个 User 对象,但对于复杂的数据处理,我可能会创建 50 个域对象和 10 个数据映射器来映射它们到/从数据库。 我不同意,映射器本身不应该是短暂的。可以创建/销毁域对象,但映射器应该是持久的(或者至少只要需要它们的服务存在)。如果单个服务正在创建 10 个不同的映射器,我建议这暗示关注点分离非常差。如果(为了简单起见)每个映射器都与一个数据库表相关,那么您可能需要从一个类中的 50 个表中访问什么? 为什么你神奇的“ProductsModel”会意识到自我拯救? 这只是一个需要使用数据映射器的服务的示例名称。数据映射器将处理加载/保存记录,服务/模型层将使用数据映射器并存储实际处理数据的逻辑。随意用更合适的东西编辑答案。 @tereško 那是一个非常小时。

以上是关于我应该如何创建我的数据映射器/域对象/服务?的主要内容,如果未能解决你的问题,请参考以下文章

我是不是正确使用域对象?

具有核心数据的 Alamofire 对象映射器

如何在 Keycloak 中创建脚本映射器?

对象引用未设置为对象实例的自动映射器问题

将创建的对象实例传递给映射器

根据映射器代码中的某些逻辑,将映射器中的一些数据(行)写入单独的目录