【问题标题】:Where to place classes which aren't models but act on models在哪里放置不是模型但作用于模型的类
【发布时间】:2015-03-15 13:13:19
【问题描述】:

在 MVC 模式中,描述不完全是模型但它们适用于模型的类的最佳方式是什么?

例如,我有一个Order 模型,它代表系统中的客户订单。我想要一个名为Orders 的类,除其他外,它将存储Order 的集合并对其执行功能。我不相信这属于 Models 文件夹,因为它不是真正的模型。

另一个例子是用户可以导入订单,所以我将有一个处理导入的Import 类。

我不相信这些是辅助类或插件,所以我不确定它们在文件夹结构方面的位置。

任何帮助表示赞赏!

编辑:只是为了描述我的Orders 类的要点——目前,每个Order 模型都有一个validate() 函数来检查外部WMS 的库存。这个调用非常昂贵(一个旧的 FoxPro 数据库),并且在导入订单时(您可以在其中一次导入多个订单),而不是为每个订单调用 WMS 1 次,我想将此验证功能提高 1 级所以我可以对 WMS 系统进行一次调用以获取库存水平。这就是为什么我要开设一个名为Orders 的课程。我同意Orders 实际上只是Order 的集合,但是我不确定现在将这个方法放在哪里。正如Engineer Dollery 所指出的,订单关系归客户所有(一个客户有很多订单),但我认为该功能属于客户是不正确的。

【问题讨论】:

  • 我称它们为服务
  • 我也是这么想的。只需阅读这篇文章 (stackoverflow.com/a/6216013/460043),听起来服务层就可以了。
  • 称它们为“服务”或“助手”或其他类似的东西是通过基本上在整个应用程序中散布业务逻辑来搞乱您的设计的第一步。您可能想阅读this question 和接受的答案。
  • 我对您的问题投了反对票,并投票决定将其关闭为“不清楚您在问什么”。在阅读了@Jon 的答案下方的 cmets 后,现在很明显,您不是在询问设计模式,而是在询问特定 php 工具对某些东西的实现,根据 Jon 的以下 cmets 之一,它没有正确实现 MVC。
  • @EngineerDollery:我不会说“执行不正确”,我当然不是 MVC 的权威。但确实有人会看 Phalcon 的Model 并得出错误的结论。

标签: design-patterns model-view-controller


【解决方案1】:

您对什么是“模型”感到有些困惑。

模型通常被认为是描述您的业务领域的相关对象集。在您的情况下,您有一个有订单的客户——可以说您的模型在客户和订单之间具有一对多的关系,并且这种关系本身称为“订单”。如果您以这种方式看待事物,那么您描述的方法可能属于关系的所有者——在本例中为客户。

您可能还需要代表贵公司的所有订单,而不仅仅是一位客户。您可以通过导航来实现这一点(遍历所有客户并检索客户的所有订单),或者您可以将其建模为您的公司与 Order 有一对多的关系——在这种情况下,再次,您将放置您的方法'正在对 Company 对象进行描述。

如果您考虑一下,只有客户或您的公司才能查看和更改订单。如果您有一个外部“事物”对订单执行某些操作,您应该找出该事物是什么并在您的模型中表示它。对数据的每次读取或写入都应通过您的模型。

编辑

您提到“用户可以导入订单”,假设“用户”是“客户”的同义词,那么导入方法应该在客户界面上。

现在,您在编辑中谈到了性能问题 - 验证方法非常慢 - 因此您希望通过同时验证多个订单来优化它。这实际上是一个实现细节,而不是接口细节(至少,不在您的公共接口中)。

您指出您有一个 Orders 对象,这对我来说听起来不错,但这可能不应该通过您的客户界面发布(您的用户不需要知道它)。 Orders 对象应该是 orders 集合的持有者,它应该属于一个客户(客户有订单)——并且客户实现应该将 validate 命令委托给 Orders 对象,它可以以任何需要的方式对其进行优化。

这意味着客户不知道如何验证订单(这是有道理的),但 Orders(您的对象)知道。如果不是因为您的性能限制,您可以以最简单的方式对订单实施验证(通过订单调用验证进行迭代),但是您确实有限制,因此您可能必须构建某种填充了信息的验证对象从订单集合中,将其传递给您的验证服务,并通过在各个订单上设置有效标志来响应响应。

参考文献

我想看看 Vaughn Vernon 的《实施领域驱动设计》一书,可以在 amazon 找到。

【讨论】:

  • 多么棒的答案。你肯定帮助我从关系所有者的角度来思考这个问题。
  • 谢谢。我对你的问题投了反对票,因为它混合了理论和一个可能不是真正 MVC 的具体实现(因为没有网络套接字,mvc 在网络上实际上是不可能的)。如果您删除“phalcon”标签,我很乐意删除我的否决/关闭投票。
  • 谢谢。我已经删除了。
  • 我已经编辑了我的帖子以更详细地描述我为什么想要Orders 课程。我实际上已经有了这些导航属性(以及客户->订单)。
【解决方案2】:

在 MVC 上下文中,您描述的类听起来确实像模型。

请记住,“模型”作为一个术语并不局限于指单个业务对象。任何表示实现业务逻辑的操作(例如Import)也是模型。

Orders 类的情况不太清楚,因为这听起来只是订单的集合,而且不清楚为什么类本身需要对订单执行功能(与只允许客户枚举命令并自行执行功能)。我会说这只是一个不太适合这种情况的例子。

【讨论】:

  • 好的,所以它们将是没有基础表的模型?问题是,他们并不真正需要从BaseModel 继承的任何方法,所以我对称它们为模型有点谨慎。
  • @Lock: 什么样的方法? BaseModel 应该是一个超级通用的概念。
  • \Phalcon\Mvc\Model所包含的方法,如findFirst等。基本上在Phalcon框架中的作用是针对Phalcon的ORM
  • @Lock:并非所有您的模型都应该继承自 Phalcon 的 Model。 IMO 非常不幸的是,Phalcon 选择将其抽象模型(甚至其抽象模型接口)等同于“映射到单个业务实体的东西”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
相关资源
最近更新 更多