业务逻辑应该与模型分离吗?

6
我们正在开发一个PHP5项目,代码量相当大,最近一周我在进行RESTful API的PoC。我们将Model Classes与Business Classes分开。
在尝试实现CRUD功能时,我发现直接针对Models实现CRUD将非常简单,而针对Business Logic实现则不然,因为它的功能是特定于当前存在的Views,并且其接口没有提供我需要实现API所需的通用数据访问模型。
思考这个问题,我想到了以下几个问题:
1. 如何以保持模型的灵活性和同时保持模型当前不关心的功能(例如在更改电子邮件地址时发送激活链接)的情况下与数据交互?
2. 在之前与Django一起工作时,由于大多数业务逻辑都是在模型中实现的,为什么还要将业务逻辑分开呢?你有任何现实生活中的例子吗?如果有的话,这解决了哪些问题?
此外,我也想到了一些可能的解决方案:
1. 将整个业务逻辑放入模型中。在调用save方法之前/之后检查哪些字段已更改。
2. 使用观察者模式来通知业务对象模型中的更改并直接与模型交互。
在你的看法中,这些方案的优缺点是什么?你会采取哪种方案?

在MVC中,Model并不是数据库(或其他持久化方式)。MVC中的Model是解决业务问题的重要算法所在之处。恰好,Model通常通过数据访问层(即Gateway、Data Access、Active Record和/或Data Transfer对象)与数据库进行通信。@Luc Franken写道。 - orangepips
1个回答

2

如果你将存储分离成数据访问层,你就可以得到所需的分离和模型中的功能:

DAL (doing queries etc)
  |
Model (doing business)
  |
Controller
  |
View

所以在视图中,你有一个操作:标记为已付款。因此,你的控制器接收到请求(POST)/invoice/1/markaspaid(或者其他你使用的url结构)。然后控制器调用模型:
$Invoice=new Invoice();
$Invoice->markAsPaid(1);

然后您的模型调用数据访问层(DAL)来实际存储此更改。没有必要将其与模型分离。如果非常复杂或涉及交易,您可能需要考虑为复杂任务单独创建一个服务。这样您的模型就会变得更加轻便,而复杂部分则被分离出来。
“在保持模型灵活性和不需要使用模型功能时(例如在更改电子邮件地址时发送包含激活链接的电子邮件),最好的与数据进行交互的方法是什么?”
我并不完全理解这个问题。就我所看到的而言,您应该将发送电子邮件的过程与正常代码运行分开。因此,将其放入队列中,并从那里查找它。它不是您正常代码路径的一部分。您可以从模型中启动它,但仅限于此。
请参阅此问题,其中包含有关该主题的相关信息: Cakephp cron job to call a controller's action

1
谢谢你的回答!我们已经在分离发送电子邮件的过程了。我的意思是,最好的方法是如何直接更改数据(例如$user->email = "foo@bar.com";),而不会失去在特定值更改时必须执行其他任务的可能性。 - stefreak
希望你现在明白我说的话,如果我的英文让你难以理解,我很抱歉 ;) - stefreak
你真的想要直接向模型写入数据吗?那么该如何保存呢?我通常会调用像 $Invoice->save() 这样的方法,这样你就可以决定何时将数据更新到数据存储中。 - Luc Franken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接