首页
Preview

解释了在 Laravel 中编写更好代码的面向对象编程原则

一个小故事:我是如何开始使用 Laravel 的

我曾经花了很多年时间使用 WordPress,因为我的客户想要一个低成本的解决方案,可以让他们自己更新网站。对于小型公司来说,这是一个典型的需求。

然而,随着 WordPress 变得越来越大和流行,越来越多的人开始构建自己的插件。开发变得难以忍受。网站变得不稳定、不安全、庞大而缓慢。

有一天,在花费数小时寻找我一个网站上的错误后,我对自己说:“够了!”我研究了其他选项,发现了几个流行的框架。我几乎立刻喜欢上了 Laravel,并开始学习全新的 Web 开发方法。

压垮骆驼的最后一根稻草

面向对象编程的一个主要原则是SRP——单一职责原则。然而,WordPress 使用了“专家级”的 SoC。显然是讽刺!

我管理但未创建的一个网站使用了一个推荐信插件。插件的作者认为将推荐信分组与文章类别连接是个好主意。当删除类别后发生了什么?整个主页以一种非常奇怪的方式崩溃了。所有块都被放置在右侧的一个位置上。类别的一个简单变化摧毁了整个网站。WordPress 的惊人代码架构!

设计良好的代码 vs. 糟糕的代码。金钱——时间——客户

许多程序员感受到来自客户的很大压力。显然,客户希望工作快速而便宜。价格越低越好,但仅限于开始阶段。糟糕的代码成本可能实际上非常高!作为专业人士,你必须能够更好地向客户或雇主解释它。

这张图片显示了糟糕代码和设计良好的代码之间的典型比较。

经过深思熟虑的代码需要更多的工作和思考。初始结果并不那么快,并且价格更高。然而,适当的代码将容易扩展或更新。这对程序员和客户都是值得的长期考虑。

与设计不良的代码的经验

我已经多次经历了“红色情况”。一个客户要求我更新别人混乱的代码。很明显,“这是不可能的”。程序员告诉客户,他已经无法再更新它了,他已经放弃了。

非常长的函数没有适当的命名规范。循环内的判断嵌套循环内的判断,嵌套 while 循环内的更多判断。一个新的程序员需要多长时间才能理解这样的函数?这不值得。我们必须从头开始。

最近,我开始了一个新的项目,其中有类似的糟糕概念。PHP、SQL 调用、HTML——全部在一个文件中。关注分离在这个项目中死了。创建代码的人甚至不费心分离 HTML 头。每个页面都有自己的头。现在,如果客户要求更改网站图标,他们将不得不更新 30 多个文件。他们从来没有听说过DRY原则吗?

我和客户谈了这个问题,他说他认识程序员,他们已经做了很长时间的生意,所以他们不可能是坏人。嗯,如果一个程序员一遍又一遍地犯同样的错误,他的经验无论是几年还是几十年都不重要。代码是糟糕的,没商量。

OOP 规则将帮助你创建更好的代码

OOP 规则很好,它们确实帮助你编写更好的代码。然而,学习如何实际应用它们非常困难。原则相当清楚,但不幸的是,如何遵循它们通常非常不直观。我在微软担任高级程序员的朋友一直是我最重要的知识和技巧来源。互联网已经不再足够有用。一个可以直接为你的使用案例提供建议的人更有价值。

我们不会在这里解释主要原则,而是展示一些如何有效使用 OOP 的示例。

以下是一些最重要的术语:

其中一些术语显然重叠,但它们将帮助你搜索更深入的知识,特别是如果设计模式需要一些经验来确定何时以及在哪里使用它们。作为程序员,你必须在许多标准中决定适当的妥协,如复杂性、时间、代码可读性、程序速度、开发速度、团队合作等。

从图层开始设计,你的生活将变得更加轻松!

最重要的编程原则之一是一个架构模式——简单地说,图层。让我们想想我们通常需要的每个层次做什么。有没有适合大多数典型 Web 应用程序情况的良好方法?

典型 Web 应用程序的可能层。

  1. 路由。用户或 API 客户端调用某个 URL 并期望发生某些事情。我们的应用程序必须识别 URL。这是通过路由类完成的。在 Laravel 中,有一个伟大的路由系统,具有许多有用的功能[1]。VueJs 也包括一个伟大的路由机制[1]。2. 应用程序检查通话的重要属性。它是否有适当的头文件?会话是否活动?用户是否已登录?调用是否被授权?用户是否有使用此调用的适当权限?

各种调用验证由中间件管理。在 Laravel 中,你可以创建所需的许多中间件。许多中间件已经为你准备好了。

  1. Laravel 创建一个封装所有输入数据的 Request 对象。Laravel 将 Request 对象发送到 Controller

现在,我们在一个 Controller 中,它是我们应用程序的一种入口点。在控制器函数的末尾,应用程序应该返回一些数据。在入口点和返回语句之间,我们有一个业务逻辑来完成客户端所需的一些操作。

注意:对于大多数 Laravel 教程来说,控制器是一个最常见的结束点。对于简单的示例,构建更多的层级没有意义。然而,正因为如此,新的程序员很难学习更高级的东西。我自己也经历了这样的挣扎。

  1. 一个 Controller 应该验证传入的数据,调用一个执行一些业务逻辑的服务,然后以所需格式(例如 json 或 blade 视图)形成响应。

  2. 数据验证是一项非常重要的任务。许多程序员没有足够的注意力创建不安全的应用程序。SQL 注入只是众所周知的安全威胁之一。

记住,你永远不应该信任客户端的数据。即使它们来自你自己的前端客户端,也应该对它们进行验证。记住,API 可能被其他应用程序使用。

  1. 数据验证完成后,我们准备调用一个服务。业务逻辑应该与控制器分离,如果可能的话,也应该与框架本身分离。如果类不依赖于框架,则更容易对应用程序进行单元测试。推荐的实践是避免使用 resolve('ClassName'),而是采用控制反转或手动将依赖项传递到较低的层。

什么是业务逻辑?大多数情况下,你的应用程序将需要执行 CRUD 操作。服务类将获取传入的数据并将其保存到数据库中。或者,它将读取数据,将其放入所需的格式中,并返回回来。如果需要更复杂的操作,则服务类将调用其他服务。

7. 如果服务需要访问数据库,则调用一个 Repository 类。Repository 处理所有数据库调用。上面的层级不知道数据是如何存储的。你只需要调用

$userRepository->getById(1);

就可以了。对于服务来说,这不重要,无论你的数据库是 MySQL、NoSQL 还是通过 API 在云端保存数据。

  1. Laravel 原生模型非常强大,可以为创建简单应用程序节省一些时间。然而,它们违反了几个 OOP 规则。因此,我决定创建自己的系统,并完全摆脱 Active Record(反)模式。我将在本文后面解释这个想法。

一个 Repository 调用一个 DataMapper,它知道如何从数据库中获取数据。DataMapper 类是特定于数据库的。必须为每种类型的数据库(mySql、noSql、文件)分别创建它。然而,它的接口应该完全相同。我的 DataMappers 始终具有以下公共函数:

public function getById($id, $attributes = '*');
public function getBySlug($slug, $attributes = '*');
public function patchById (IModel $model, $selectedAttributes);
public function deleteById ($id);
public function search (array $criteria, $attributes = '*');
public function store (IModel &$model);

如果 DataMapper 需要一些特殊的函数,则在子类中实现它们。例如,UserDataMapper 需要函数,如 getByUserName()isRoot() 等。

  1. DataMapper 准备数据以供 Laravel 查询构建器使用。这是应用程序的最底层。查询构建器返回数据或如果出现错误则抛出异常。

重要规则:没有类或函数应该跳过层级!这会导致紧密耦合,并最终导致测试和分配工作给团队成员的问题。这个规则非常重要,然而,即使 Laravel 支持以可怕的方式打破它。

例子:Laravel Validator 是一个强大的工具。毫无疑问。但是,它允许你创建这样的验证规则:

'state' => 'exists:states'

它看起来简单而优雅。但是,从面向对象编程的角度来看,这是一个可怕的概念。它将你的顶层与底层(SQL 数据库)连接起来。除此之外,它还将你的验证与实际的数据库列名连接起来。这是一种极度紧密的耦合,最终会让你痛苦地重写你的代码的大部分内容。

除此之外,你甚至可以使用这个概念来验证用户的数据(伪代码):

IF Validator( 'email' => 'exists:emails') == False THEN createNewUser()

为什么这段代码危险? 如果在你的代码到达 save() 函数之前,电子邮件已经出现在数据库中怎么办?它很可能不会发生 99% 的时间。然而,当你的应用程序变得更繁忙时,为更多的客户提供服务时,你必须预计这种情况的发生。你的应用程序会崩溃而没有警告。验证通过,电子邮件没有被占用,但数据将不会被保存,电子邮件已经存在。你从未见过的异常可能会导致应用程序崩溃。

译自:https://betterprogramming.pub/laravel-oop-principles-for-writing-better-code-explained-part-1-531276365cba

版权声明:本文内容由TeHub注册用户自发贡献,版权归原作者所有,TeHub社区不拥有其著作权,亦不承担相应法律责任。 如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

点赞(0)
收藏(0)
anko
宽以待人处事,严于律己修身。

评论(0)

添加评论