【问题标题】:Does business logic live in the Model or in the Controller?业务逻辑是存在于模型中还是存在于控制器中?
【发布时间】:2016-01-11 20:35:53
【问题描述】:

阅读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 计算之上,它应该留在模型中,还是进入控制器?如果它进入控制器,控制器必须首先调用$service(通过模型),然后在控制器内部计算$discount,然后将值发送回模型以保存。是这样的吗?

注意

我可能将模型与“存储”混淆了。我可能需要一个模型来处理业务逻辑,并且数据库/持久存储应该是一个单独的层。

【问题讨论】:

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


    【解决方案1】:

    业务逻辑属于一个Service,所以你需要添加一个服务层。

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

    输入服务类别。 我倾向于为软件设计的每个用例提供服务。 在您的情况下,可能会有一个 CheckOutService 来计算您的总金额,包括折扣。 这样,每项服务都有一个特定且直观的目的。然后,当控制器需要某些业务逻辑时,它会调用为此目的量身定制的服务。

    可以在此处找到有关服务在 MVC 模式中的作用的详细描述: MVCS - Model View Controller Service

    我将引用最重要的部分:

    然后服务层将负责:

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

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

    【讨论】:

      【解决方案2】:

      回答这样的问题通常是固执己见,或者说这真的取决于您的业务用例。

      首先,我感觉到您的Modelservice 措辞在这里有些混淆。 model 应该是您的 domain modelservice 应该是 domainapplication service,在不同的类或不同的层中。

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

      即:

      1. 您在域模型中实现所有与模型当前状态相关的行为概念
      2. 使用将从存储库中查询行项目的工厂
      3. 对于与您的模型无关的大部分内容使用域服务,在您的情况下计算折扣(如果您需要该逻辑可重用,例如在更多模型或服务中)。您不想用不相关的机制和依赖项污染您的域模型
      4. 为了持久性,您最好使用不同的层,这样您就可以更好地分离大多数关注点,这样做的一个原因是可测试性,另一个原因是 - 在许多其他方面 - 以后代码更改更少

      为了通过长期维护代码来实现更简洁的架构并减少痛苦,不要忘记考虑设计模式和SOLID principles 如何帮助您针对给定的业务用例实施解决方案。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            【解决方案5】:

            下图显示了我认为你的“业务”逻辑应该去哪里:)

            上图将“服务”层作为服务器端“控制器”。

            它是“客户端”端控制器和“逻辑”层之间的中间人。

            所有需要某种“逻辑”的任务,例如

            “计算产品或服务的折扣价”

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

            如果需要,ProductLogic 类还将查询“数据”源以获取商品的当前价格。

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

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

            希望这会有所帮助:)

            祝你有美好的一天!

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-03-12
              • 1970-01-01
              • 2010-09-19
              • 1970-01-01
              • 2010-12-15
              • 1970-01-01
              • 2016-01-25
              • 2011-01-13
              相关资源
              最近更新 更多