2

所以我一直在查找更多关于 MVC 设计模式的教程和文章,以加深对它们的理解,我开始怀疑我是否做错了。所以是的,这些模式的目标是使代码可重用并最大限度地减少重复代码,对吗?

我一直在看到如何解释这些设计模式的各种方式,这让我有点困惑。过去我认为这是模型和视图之间的控制器作为中介的方式,但现在我知道这是错误的,视图实际上不仅仅是一个模板。然后我还在某处(我认为在这里)读到,在真正的 MVC 模式中,根据定义只有一个模型,所有其他“模型”只是单个模型的不同方面。是这样吗?这是分离代码并使其可重用的最佳方法吗?这在代码中会是什么样子?我又在其他地方读到,对于 Web 应用程序,最好坚持 MVVM 模式。

所以现在我有点困惑。在 Web 应用程序中分离关注点并使代码可重用的最有效模式是什么?我不仅希望看到对这种模式的描述,还希望看到一个简短的代码示例,以便我更好地理解它。

4

3 回答 3

6

所以是的,这些模式的目标是使代码可重用并最大限度地减少重复代码,对吗?

这是分离代码并使其可重用的最佳方法吗?

没有。真的不是。

MVC 和受 MVC 启发的模式的目标是将业务逻辑(模型层)与用户界面隔离开来。在 UI 中 - 将其划分为管理输入和输出。

基本上,MVC 和 MVC 启发的模式是实现被称为关注点分离的原则的架构设计模式。

然后我还在某处(我认为在这里)读到,在真正的 MVC 模式中,根据定义只有一个模型,所有其他“模型”只是单个模型的不同方面。是这样吗?

不,模型不是“事物”(类、对象)。它是一层。就像您可以说所有控制器和视图都包含在表示层或 UI 层中一样。

人们所说的“模型”通常要么是领域对象,要么是(更糟糕的情况)某种形式的活动记录实现。

我又在其他地方读到,对于 Web 应用程序,最好坚持 MVVM 模式。

MVVM 模式在视图和模型层之间添加了另一层。它最适合用于无法控制视图或/和模型层的实现的情况。

大多数人将其与使用表示对象 (M.Fowler 有这种讨厌的习惯,即在所有内容中添加“模型”,这会造成无限的混乱)概念混淆。表示对象旨在隔离 UI 逻辑的可重用部分。

这在代码中会是什么样子?

创建 MVC 和受 MVC 启发的模式是为了管理大型代码库。当简单地使用面向对象的实践不足以使代码易于理解时,您可以应用 MVC 模式。您可以通过向代码库添加额外的约束来做到这一点。MVC 不会向您的应用程序添加任何新内容。相反,它限制了可以编写的代码的位置和代码。

并且“排序代码示例”实际上不会说明该模式。要真正理解它是如何工作的,您应该阅读类似PoEAA book .. 或类似的东西。

在 Web 应用程序中分离关注点并使代码可重用的最有效模式是什么?

这是一个见仁见智的问题。

于 2013-08-23T22:04:05.297 回答
3

在 Web 应用程序中分离关注点并使代码可重用的最有效模式是什么?

没有经过验证的模式。当您想到这一点时,您可能希望减少代码重复(尤其是在 Views 中&&)并尽可能使您的代码可读可维护。

这是数据抽象的问题

事实上,根据它的定义,它引导你以正确的方式思考类似的事情。

我不仅希望看到对这种模式的描述,还希望看到一个简短的代码示例,以便我更好地理解它。

首先 - 继承是要走的路,直到它同时满足Liskov 替换原则单一责任原则

如上所述,没有经过验证的模式,但有一种经过验证的技术。

在 PHP 世界中,您的MVC/MVVM应用程序必须至少实现:

要记住的常见事项:

1.模型是一个抽象层(在MVC/MVVM/MVP中)

它由许多处理应用程序核心逻辑的类组成。如果你调用一个对象Model,那么你最终会违反单一责任原则

错误的实现:

让我们想象一下,那个模型是一个类,

由于在大多数情况下我们处理表单,我们基本上想要:

  • 有效的表格
  • Insert/Update/..如果记录有效,则

所以,这个的“模型”看起来像这样:

$model = new RegisterForm(...);

if ($model->isFormValid($formData)) {

   if ($model->insertRecord($formData)) {
      echo 'Thanks for registration';
   }
}

这显然破坏了SRP。如果你从那里继承,也许是LSP 。

正确实现:

由于模型是一个层,那么它应该如下所示:

模型层的文件夹结构类似于

/User/Login
  - FormValidator.php
  - FormValidatorInterface.php
  - RecordManager.php

从那时起,用法本身就是:

$formValidator = new User_Login_FormValidator(...);

if ($formValidator->isValid(..form data..)) {

   $recordManager = new User_Login_RecordManager($pdo);

   if ($recordManager->insert(..form data..)) {
      echo 'Logged in';
   }

} else {

   print_r($formValidator->getErrors());
}

现在让我们分解一下,

当您的模型是图层时:

当您的模型是对象时,例如FooModel

  • 你做错了——你把一个概念和一个实现混在一起
  • 你最终违反了 SRP 和 LSP

2.什么是真正的MVC?

如您所知,它由 3 个组件组成,但不是对此进行讲座,而是让我们看一下

  • 模型是一个抽象层,包含应用程序的核心逻辑
  • 视图是直接从模型中读取数据并处理用户表示逻辑的类。

    比如说,如果在登录页面上用户没有登录,(该信息来自模型),您必须显示错误,否则进行重定向 - 这是 UI 逻辑的处理

  • 控制器(也称为 Editor)将变量分配给模型(来自$_POSTor$_GET或视图

    请记住,数据验证永远不应该在控制器中完成。您必须在模型中定义它,然后从视图中调用它

还要注意,

你不应该echo/print从课堂上得到任何东西。绝不!这应该在三合会之外完成,像这样,

$modelLayer = new ModelLayer(...);

$view = new View($modelLayer, $controller);

$controller = Controller($modelLayer);
$controller->indexAction($_POST[...])

echo $view->render(); // render() should `include()` and capture (via ob_* functions) a HTML template.

3.什么不是MVC?

这里有一系列错误的想法,你也应该记住,你会一遍又一遍地遇到:

  • 一个模型——它$instance实现了某种 ActiveRecord 或 ORM,或抽象表访问。
  • 视图是一个愚蠢的 HTML 模板

  • 控制器是模型和视图之间的桥梁,它从模型收集信息然后将其传递给视图。它还进行数据验证并显示错误。

“通用工作流程”为

<?php

$model = new Model();
$view = new View();
$controller = new Controller($model, $view);

$controller->indexAction();

4. MVVM 怎么样?

这是一篇给你的好文章,它解释了它。请注意,他命名一个类Model只是为了演示。

于 2013-08-24T00:49:09.977 回答
2

浏览开源代码是最好的学习方式

这个问题的答案很长,很可能会引起辩论,因为您似乎在征求意见。在这种情况下,最“有效模式”的最佳答案是解决您的问题的模式。

“您的设计应该针对手头的问题,但也应该足够通用以解决未来的问题和需求” - GoF(设计模式 - 可重用对象的元素)

正如您所说,有人说使用 MVVM(我还没有听说过),而我们中的一些人使用 MVC 架构。如果您两者都知道,请使用特定于您的问题的一个,否则使用任何对您有用的。

学习 MVC 架构和其他模式的最佳方法不仅是通过理论,而且是通过编码。拿一些你写的代码,试着在不知道的情况下找到你在哪里使用了这些模式(例如,你可能使用了 Facade)。我学习和继续学习的方式是浏览开源代码并尝试以类似的方式组织我的代码。

如果您正在寻找一种方法来知道文件的确切放置位置,我认为您找不到它。您能做的最好的事情就是大致了解文件的组织方式。要学习 MVC,请下载CodeIgniter并查看文件的组织方式,同时查看其文档。还可以查看其他开源代码框架,例如cakePHP。等等。我认为这是最好的方式来清楚地了解它。

我认为您的问题是您阅读太多,而没有尝试实现您阅读的某些内容。

至于代码示例,我认为您应该在谷歌上搜索,因为它不会是“短”。您还需要查看实际代码而不是示例。我相信你现在已经从你所学过的教程中看到了足够多的例子。

编辑:

请注意,我使用的是“架构”而不是“模式”,这就是我所学的。:) 但我认为这没什么大不了的。#只是一个意见

于 2013-08-23T19:25:44.443 回答