【问题标题】:Program to an interface and the Observer Pattern编程接口和观察者模式
【发布时间】:2016-07-06 08:49:41
【问题描述】:

首先,做一个简短的介绍,以帮助您了解我的出发点:我不知道如何为这个问题命名,无论是原样还是存储库跟踪更改的工作单位

我有两个接口,ChangeListenerChangeSubject,它们是耦合的:

interface ChangeListener
{
    public function onSubjectChanged(ChangeSubject $subject, array $data);
}
interface ChangeSubject
{
    public function addChangeListener(ChangeListener $listener);
}

我还有一个存储库和一个工作单元(WIP,我会省略一些部分):

interface UnitOfWork extends ChangeSubject
{
    public function commit();
    public function hydrateChange(array $data, ArrayService $arrayService);
}

interface Repository extends ChangeListener
{
    public function commit() : \bool;
    public function commitCount() : \int;
}

现在,在我的UnitOfWork 实现中,我们称之为Book,更准确地说,在hydrateChange 方法中,我将更改通知存储库,这很简单:

$repository->onSubjectChanged($this, $newHydration);

现在的问题是,在存储库中,我需要知道这本书的 ID。但是存储库的处理方法会收到一个ChangeSubject,它没有id(Book 有)。

如何正确设计这样的系统?

如果 PHP 有泛型,那将是可能的。一个我不喜欢的 hacky 解决方案是使用 instanceof

【问题讨论】:

  • 在这种情况下,您最终会在某处使用instanceof。为什么要将 UnitOfWork 与业务对象结合起来?业务对象不应该意识到与持久性相关的问题。
  • @SebastianKeßler 您在哪里看到业务对象和持久性之间的依赖关系?它是依赖倒置,持久性从外部作为 ChangeListener 注入,但也可能有其他的,比如跟踪谁做了什么的安全服务(安全术语中的会计)。如果 PHP 支持泛型,instanceof 就没有必要了。
  • 很难理解这和 DDD 有什么关系...
  • @AlexeyZimarev 这个问题也被标记为design patternsoop。我已将其标记为ddd,因为所涉及的类也是 UOW 和存储库。这意味着在PHP中做DDD的人很可能遇到过这种情况。当然,DDD 不仅仅是在这种情况下所说明的,它是无处不在的语言,它是有界上下文,等等。
  • 您误解了工作单元是什么。 UoW 是一组更改,应该存储所有内容或不存储任何内容。在 DB 世界中,它可以由事务来表示。 martinfowler.com/eaaCatalog/unitOfWork.html

标签: php oop design-patterns architecture domain-driven-design


【解决方案1】:

您误解了一些概念。如果你做对了以下几点,你应该回到正轨:

  • 不要在您的域对象中实现工作单元。 工作单元只是跟踪更改的技术助手。所以工作单元引用业务对象,例如注意“ID 32 的书已更改”,但它与业务对象不同。

  • 为您的聚合类型创建具体的存储库。BookRepository 应包含GetById(BookId)GetByAuthor(Author) 等方法。注意:在具有泛型的语言中,可能有机会提取泛型部分,但在 PHP 中,最好处理具体的聚合类型,例如 Book

我建议您了解有关工作单元和存储库模式的更多信息。在尝试使用它们之前,请确保您完全理解它们。还要确保您了解不同的存储库变体(例如命令样式存储库与集合样式存储库),以便为您的项目做出明智的决定。

【讨论】:

  • 是的,关于你的第一个要点:确实我已经混合了它们。关于第二个:是的,我在书库中确实有这些方法。对我来说,准确跟踪哪本书的哪些字段被修改非常重要,这就是为什么我通过hydrateChange 方法传递操作转换列表的原因。好的,所以我将拆分业务逻辑和 UoW,但我仍然需要以某种方式跟踪每个更改。你会怎么做?用 id 将一本书标记为“脏”是不够的,我需要准确地知道发生了什么变化。我可以追溯计算变化,但这不是最理想的。
  • 我不确定在将 Book 传递回存储库进行保存时计算更改(通常称为快照比较)是一件坏事。这是大多数 ORM 开箱即用的支持,也是大多数项目使用的。如果您真的想知道何时发生更改,那么您需要基于代理的更改跟踪 来为您的聚合。不过,这对于自己构建可能并非易事,因此您可能需要寻找开箱即用的支持它的 ORM。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-12
  • 2016-02-20
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多