简化存储库模式和 SOA 的实施

Streamlining the implementation of a Repository Pattern and SOA

我正在与 Laravel 5 合作,但我认为这个问题可以应用于单个框架或语言的范围之外。最近几天我一直在为存储库编写接口和实现,然后将服务绑定到 IoC 和所有这些东西。感觉特别慢。

如果我在我的服务中需要一个新方法,比如说,Store::getReviews() 我必须在我的实体模型中创建关系 class(数据源,在本例中为 Eloquent)然后我必须在 repo 接口中声明该方法以使其成为任何其他实现所必需的,然后我必须在 repo 实现中编写实际方法,然后我必须在调用 repo 的服务上创建另一个方法以提取所有评论the store...(故意运行-上句)感觉过分了。

现在创建新模型不再像扩展基础模型那样简单 class。我必须编写和跟踪太多文件。有时我会搞不清楚我到底应该把东西放在哪里,或者在设置方法的一半时发现我错了class。我还在服务中丢失了 Eloquent 的查询构建。每次我需要 Eloquent 拥有的东西时,我都必须在 repo 和服务中实现它。

这个架构背后的想法很棒,但我发现实际的实现非常乏味。 有没有更好、更快的做事方式?我觉得我太乱了,尽管我把常用的方法和东西放在抽象的 class 中。要写的太多了。

当我搬到 Laravel 5 时,我已经与所有这些东西搏斗过。那时我决定改变我的方法 (it was tough decision)。在这个过程中,我得出了以下结论:

  1. 我决定放弃 Eloquent(以及 Active Record 模式)。我什至不使用查询生成器。我仍然使用 DB fascade,因为它对于参数化查询绑定、事务、日志记录等事情很方便。开发人员应该知道 SQL,如果他们需要知道它,那么为什么要强制另一个它们之上的抽象层(无法完全或有效地替代 SQL 的层)。请记住,从 OOP 世界到关系数据库世界的桥梁永远不会很漂亮。请耐心等待,继续阅读...
  2. 因为#1,我切换到默认关闭 Eloquent 的 Lumen。它快速、精简,并且仍然可以满足我在 Laravel.
  3. 中需要和喜爱的一切
  4. 每个查询都属于两个类别之一(我想这是 CQRS 的一种形式):

    3.1。 Repositories(命令):这些处理改变状态(写)和你需要水化对象并在改变状态之前应用一些规则的情况(有时你必须做一些读来做一个写)(有时你会进行批量写入并且水合作用可能效率不高,所以只需创建也可以执行此操作的存储库方法)。所以我有一个名为 "Domain" 的文件夹(用于领域驱动设计),里面有更多文件夹,每个文件夹代表我对我的业务领域的看法。对于每个实体,我都有一个配对的存储库。这里的实体是一个 class,就像其他人所说的 "model",它拥有属性并具有帮助我保持属性有效或对其进行处理的方法,这些方法最终将保留在存储库中.存储库是一个 class,其中包含一系列方法,这些方法代表我需要执行的与该实体相关的所有查询类型(即 $repo->save())。这些方法可能会接受一些参数(以允许在内部进行一些动态查询操作,但不要太多),您会在内部找到原始查询和一些代码来混合实体。您会发现存储库通常接受 and/or return 个实体。

    3.2。 Queries (a.k.a.screens?):我有一个名为 "Queries" 的文件夹,其中有不同的 classes 方法,里面有原始查询进行展示工作。 classes 只是有助于将事物组合在一起,但与存储库不同(即它们不进行水合、写入、return 实体等)。目标是将它们用于读取和大多数显示目的。

  5. 不要这么没必要的接口。接口适用于您 需要 的多态情况。您知道您将在多个实现之间切换的情况。当您工作时,它们是不需要的额外工作 1:1。另外,很容易拿一个 class 并在以后把它变成一个界面。您永远不想过早地过度优化。
  6. 由于#4,您不需要很多服务提供商。我认为为我的所有存储库提供服务提供商未免太过分了。
  7. 如果您想要切换数据库引擎的时间几乎是神话般的,那么您所要做的就是去两个地方。上面#3 中提到的两个地方。您替换里面的原始查询。这很好,因为您拥有应用程序所需的所有持久化方法的列表。您可以在这些方法中定制每个原始查询,以数据存储调用的独特方式使用新数据存储。该方法保持不变,但内部查询发生了变化。重要的是要记住,更改数据库所需的工作显然会随着您的应用程序的增长而增加,但您的应用程序的复杂性必须得到解决。每个原始查询都代表着复杂性。但是您已经封装了这些原始查询,因此您已尽最大努力屏蔽应用程序的其余部分!

我成功地使用了这种受 DDD 概念启发的方法。一旦您使用了存储库方法,就几乎不需要使用 Eloquent 恕我直言。而且我发现我没有写额外的东西(正如你在问题中提到的那样),同时仍然保持我的应用程序灵活以应对未来的变化。这是另一位 Artisan 的 approach(尽管我不一定同意使用 Doctrine ORM)。祝你好运,编码愉快!

Laravel的Eloquent是一个Active Record,这个技术需要大量的处理。域实体被理解为普通对象,为此尝试使用 Doctrime ORM。我按照 link.

建立了一个使用 Lumen 和 ORM 学说的促进者

https://github.com/davists/Lumen-Doctrine-DDD-Generator

*对于精确的性能分析,有 cachegrind。

http://kcachegrind.sourceforge.net/html/Home.html