业务逻辑是否存在于模型或控制器中?

时间:2015-10-13 22:34:15

标签: model-view-controller mvvm business-logic

在阅读https://softwareengineering.stackexchange.com/questions/165444/where-to-put-business-logic-in-mvc-design/165446#165446之后,我仍然对于我希望将代码用于计算折扣的位置感到困惑。计算产品或服务的折扣价格我认为绝对是业务逻辑的一部分,不是应用程序路由或数据库交互的一部分。有了这个,我正在努力摆放我的业务逻辑。

实施例

class Model
{
    public function saveService($options)
    {
        $serviceId = $options['service_id'];

        //Model reads "line Item" from database
        $service = $this->entityManager->find('Entity\ServiceLineItem', $serviceId);
        //uses the data to compute discount
        //but wait.. shouldn't model do CRUD only?
        //shouldn't this computation be in Controller?   
        $discount = ($service->getUnitPrice() * 0.25);

        // Add the line item
        $item = new SalesItem();
        $item->setDiscount($discount);
    }
}


class Controller
{
    function save()
    {
        $this->model->saveService($options);
    }
}

问题:

高于$discount计算,它应该保留在模型中,还是进入控制器?如果它进入Controller,Controller必须首先调用$service(通过Model),然后在Controller内部计算$discount,然后将值发送回要保存的Model。那是这样做的吗?

请注意

我可能会将模型与“存储”混淆。我可能需要一个模型,我在那里做业务逻辑,数据库/持久存储应该是一个单独的层。

5 个答案:

答案 0 :(得分:5)

业务逻辑属于服务,因此您需要添加服务层。

业务逻辑倾向于跨越多个模型,这表明它不属于任何单个模型。因此,不清楚你应该把逻辑放在哪个模型中。

输入服务类。 我倾向于为软件设计的每个用例提供服务。 在您的情况下,可能会有import './main.html'; // I placed peer.js from the node_modules/peerjs/dist/peer.js into the client folder and it works fine // import {Peer} from 'peerjs'; import {AdapterJS as Adapter} from 'adapterjs'; Template.hello.onCreated(function helloOnCreated() { // counter starts at 0 window.peer = new Peer({ 来计算您的总金额,包括折扣。 这样每个服务都有一个特定和直观的目的。然后,当控制器需要一些业务逻辑时,它会调用为此目的而定制的服务。

可以在此处找到MVC模式中服务功能的详细说明: MVCS - Model View Controller Service

我将引用最重要的部分:

  

服务层将负责:

     
      
  • 从各种数据源(或数据访问对象)中重新创建和创建“模型”。
  •   
  • 跨各种存储库/资源更新值。
  •   
  • 执行特定于应用程序的逻辑和操作等
  •   

编辑:我刚看到kayess回答。我会说他的回答比我的回答更准确,但考虑到你问题的不确定程度,我不知道它是多么相关。所以我希望我的早期阶段可以帮助一些人。

答案 1 :(得分:3)

回答这样的问题通常是自以为是,或者可以说这实际上取决于您的业务用例。

首先,我会在您的Modelservice措辞中感受到一些混淆。 model应该是domain model,而service应该是domainapplication service,位于不同的类或不同的层中。

在架构上认为你可以遵循一个相当简化的DDD - ish实现。

即:

  1. 您在域模型中实现了与模型当前状态相关的所有行为概念
  2. 使用将查询存储库中的订单项的工厂
  3. 在您计算折扣的情况下(如果您需要可重复使用的逻辑,例如在更多模型或服务中),请使用域服务来处理与您的模型无关的所有内容。您不希望污染具有非相关机制和依赖关系的域模型
  4. 对于持久性,您最好使用不同的层,这样您最好将大多数问题分开,其中一个原因是可测试性和另一个原因 - 最多的其他原因 - 以后更少的代码更改
  5. 要通过长期维护代码来实现更清晰的架构并减少痛苦,请不要忘记考虑设计模式和SOLID principles如何帮助您实现针对给定业务用例的解决方案。< / p>

答案 2 :(得分:1)

关于如何将业务逻辑与数据分离的问题不容易回答。但是,Daniel Rocco已经构建了a good discussion of the subject,如果不是针对这个特定问题,您可能会发现它很有用,然后用于构建业务应用程序。

答案 3 :(得分:0)

我使用了一个名为“Yii Framework”的框架,使用MVC,它在控制器中使用了一个名为beforeSave()的函数,用于在保存之前更改模型值。

遵循这个逻辑,最好的做法是在保存模型之前(在您的控制器中)将折扣应用于您的价格

答案 4 :(得分:0)

下面的图片展示了我如何看待你的商业&#34;逻辑应该去:)

enter image description here

上面的图片有&#34;服务&#34;图层作为服务器端&#34;控制器&#34;。

这是&#34;客户&#34;之间的中间人。侧控制器和&#34;逻辑&#34;层

所有需要某种类型的&#34;逻辑&#34;喜欢

  

&#34;计算产品或服务的折扣价格&#34;

如果需要,将进入ProductLogic类,从服务中获取输入,并使用该信息来帮助计算折扣价。

ProductLogic类还将查询&#34;数据&#34;如果需要来源以获得物品的当前价格。

ProductLogic类将从服务和存储库收集的信息拼凑起来进行计算,如果需要返回给用户,则ProductLogic类会将其发送到服务层。

如果它只需要保存在存储库中,那么逻辑会将信息传递给存储库来处理。

希望这会有所帮助:)

祝你有美好的一天!