可能在开发生涯中最困难的一步是从早期简单的类 crud 项目跳到一些高级的项目,这些项目有更大的架构和更高层次的代码质量责任。因此,在本文中,我试图列出在处理大型 Laravel 项目时需要考虑的问题 (和一些答案)。
这篇包含了我自己的内容和社区资源的外部链接,随时查看它们。
声明:什么是大型项目?
首先,我想解释一下我所说的 “大” 是什么意思。有些人会说是数据库的记录,比如用户表中的万行是很大的。是的,但是它是一个大型的 数据库,而不是 Laravel 项目本身。
我所说的大型项目主要是指需要管理的实体数量。简单来说,你的项目有多少模型。如果你有很多模型,这通常意味着复杂性。有了这些,作为次要度量数字,您可以计算路由或控制器方法的数量。
举一个开源项目 Monica CRM project 的例子,它的 routes/web.php 文件中有 300 多行:
由于工作量非常庞大,通常有多个开发人员在项目上工作,这给管理代码库带来了复杂性。
此外,大型项目的第三个非技术特征是错误的代价。我想强调的是那些效率低下或代码中断可能导致真金白银损失的项目:比如电子商店中 30 分钟的停机时间可能会轻易损失 10,000 美元。或者,一些失败的如果声明可能导致真正的几十人不下订单。
所以,我将在下面讨论那些大型项目。
1. 自动测试
在小项目中,通常有较小的预算或者需要快速开发某个应用,所以自动化测试会被认为是” 额外的工作量”
在大型项目中,在你发布项目之前无法手动测试所有的功能 代码发布之前你可以测试你自己的代码,但是你不能确定不会改动其他人的代码。这样想想太可怕了,你甚至不知道这些代码或者这些模块是怎么工作的 ,因为你只关注你开发这个一个应用的一部分.
所以,如何确保你发布的代码不会有 Bug 呢?一般来说,新代码是对旧代码的重构,如果你更改了项目中的某些内容,你如何保证这些测试的内容没有被破坏呢?不要陷入我称之为手指交叉驱动开发的心态。
此外,回到大型项目的定义上来 —— 请记住,bug 的代价是很高的。因此,从字面上看,你错误的代码可能会给企业带来经济损失。如果这个参数仍然不能说服您使用测试来覆盖代码,那么可能没有其他方法能说服您。
是的,我知道 “我们没有时间编写测试” 的典型论点。我有一个完整的视频。
但这正是你需要找到时间的地方。它包括一些交流:评估最后期限,考虑写测试的时间,还要和经理谈谈如果你不写测试会发生什么。然后他们会理解并允许这些额外的时间。如果他们不这样做,那就意味着他们不那么在乎质量,那么也许是时候找另一家公司了?
现在,我们没必要谈论神话般的「100% 测试覆盖率」。如果您真的很赶时间,请选择对您的应用程序工作至关重要的功能进行测试。正如 Matt Stauffer 的名言,「首先,为功能编写测试,如果它们损坏,将导致您失业」。因此,要关注任何与支付、用户访问、最常用的核心功能的稳定性有关的事情。
2. 架构和项目结构
啊,是的,一个价值百万的问题:如何构建 Laravel 项目?我曾经在 2019 年就该主题发表了 5 小时课程,但我仍然觉得我只是触及了表面。
您可以遵循许多不同的模型或想法:将项目 分成模块,使用 DDD 方法,从 设计模式 中挑选一些,或者只是遵循 SOLID 原则。这完全是个人喜好。
问题是,没有灵丹妙药(there’s no silver bullet),也没有一刀切的解决方法。例如没有人敢说所有大型的 Laravel 项目都要遵循 DDD。即使是 SOLID 原则,有的时候也被认为不是最好的方案。
但问题很明显:随着你的项目结构增长,你需要改变某些事情,需要重新将文件 / 文件夹 / 类整理成更易于管理的样子。那么你需要做些什么呢?
首先,将全部东西都移入次级目录和命名空间中。这个 Monica CRM 的示例做得很好。
其次,确保你的类 / 方法都不是很大。没有什么魔法数字可以用,当你感觉到你需要经常地上下滚动屏幕,或者总是花费很多的时间去搞清楚类 / 方法的功能,那么这时就该重构代码并将代码归类到其他地方了。最常见的例子是这个超大的控制器文件。
这只是两个建议,但是这两个变化使您的代码更具可读性、可维护性和可测试性。
是的,有时候它需要对类进行大的 “冒险” 重构,但是,嘿,您可能有自动化测试来检查所有的东西,对吗?对吧?
3. 用工厂和种子 “伪造数据”
一个与我们已经讨论过的自动化测试相关的主题。如果要对应用程序特性进行压力测试,则需要大量数据。工厂 + 种子是一个完美的组合,很容易实现这一点。
只要养成习惯,当创造一个新的模型,创造一个工厂和种子立即,从一开始。那么,将来无论谁用它来生成一些虚假数据,都会非常感谢你。
但这不仅仅是测试。另外,考虑一下应用程序的全新安装。大型成功的项目只会变得更大,所以你肯定需要新的开发人员。如果他们没有任何样本数据可以使用,那么他们在安装过程和加速方面会有多大的困难呢?
您可能还需要在各种服务器上多次安装应用程序 —— 本地服务器、临时服务器、一些基于 docker 的环境等等。您可以自定义种子,以便在生产环境或本地环境下运行。
4. 数据库结构
虽然我在开始提到数据库大小不是大型 Laravel 项目的定义,但是数据库结构对于长期的性能和可维护性是非常重要的。
该使用哪种关系?在 Laravel 术语中,应该是 HasOne ?HasMany ? BelongsToMany ? Polymorphic ?
另外,其它的问题。是该用一张较大的表还是几张较小的表?使用枚举字段还是关系表? UUID 还是 ID 字段。当然,每个案例都是个别的,我有一个 关系型数据库完整课程。
试着去问 「未来的自己」,这些数据表中未来会有哪些查询,并尝试先编写这些查询语句。
换言之,考虑最终目标,然后从终点对结构进行反向思考。这可以帮助你「感觉出」正确的结构。
如果你已经准备好了工厂和种子,你将可以很轻松地模拟未来的使用情况,甚至可以具体去量化两种选项,并选出哪个是更好的。这时实际非常重要:在未来有大量线上实时数据时更改数据库结构可能是最复杂、最昂贵、最危险的变动。所以你最好在那之前事先做好决定。
也就是说,在真的需要重构数据库时,你不需要担心什么。将一些数据移动到一个单独的较少使用的表中,将 HasMany 改为 Polymorphic,选择其他字段类型等。
只需确保你没有丢失用户数据。
5. 外部包和升级 Laravel
当你确定了你的 composer.json 中要包含哪些 Laravel/PHP 包,一开始会非常简单,都是最新版本的包,只要确保这些包是可用的,只管用就可以了。
但是过了一段时间,当项目存活了一两年后,不仅是 Laravel 本身,还有这些包,都面临版本更新的需求。
幸运的是,Larave 从每 6 个月更新一次,变为每年发布,稍后又改为 Laravel 9 发布时间改为与 Symfony 同步。因此开发人员再也不用每 6 个月就头痛一次了。
一般来说,框架本身具有一个相当稳定的内核,升级到新版本时相对容易,只需要一点时间。此外,有一个叫 Laravel Shift 的得力助手,致力于帮助开发者在这方面节省时间。
但问题来自于你使用的包。
非常典型的情景:你想要给项目中的 Laravel 升级到新的版本,但是一些 composer 中的包还没有发布支持新版 Laravel 的新版本。因此,以我的经验,至少是在 Laravel 官方发布几个月后,包作者们跟进后才升级项目。
还有更糟糕的情况:当包作者们没有时间开发新版本(切记,大部分包作者都是用自己的业余时间,无偿开发的),甚至是放弃了这个包,该怎么办?
首先,当然,您可以帮助创建者,并提交一个包含建议升级的拉取请求 (不要忘记包含自动化测试)。但即便如此,他们也需要审查、测试和批准你的 PR,所以我很少在现实生活中看到这种情况发生。这些包要么是主动维护的,要么是接近废弃状态的。因此,唯一合理的解决方案就是在将来使用自己的版本。
但是,一个更好的决定,是在选择使用什么软件包的时候思考得更深入。要问的问题是: “我们真的需要这个包裹吗?” 以及 “软件包创建者是否在维护其软件包方面享有声誉?“
6. 项目性能
如果项目成功,它的数据库就会随着更多的数据而增长,服务器需要同时为更多的用户提供服务。因此,加载速度成为一个重要因素。
通常,在 Laravel 社区,我们讨论的是模型查询的性能优化。事实上,这是性能问题的第一个典型原因。
但是 Eloquent 和数据库只是其中的一个方面。为了提高速度,你还需要优化其他一些东西:
– 队列机制:你的用户不应该花费 5 分钟等待发票电子邮件
– 加载前端资源:如果你能压缩它们,则不应该提供 1 MB 大小的 CSS/JS 文件
– 运行自动化测试套件:你不能等待一个小时来部署新的版本
– 网络服务器和 PHP 配置:当 10000 用户浏览网站,用户不应该排队等待
– 等等.
当然,每个主题都是一个可以深入研究的独立世界,但是你应该做的第一件事是建立一个测量和报告系统,这样如果某个地方有一个慢查询,或是访问者在某个时间达到峰值,或是服务器的 CPU 接近极限,你就会得到通知。
7. 部署过程和停机时间
在传统的小型项目中,你可以用 SSH 登录到服务器,运行几句 git 和 artisan 命令,来将新的更改部署到服务器上。
但如果你的流量更大,团队更大,你需要注意两件事:
不停机部署:为了避免访客看到「部署中」的字样和部署前后的冲突。这是官方在这方面的项目 Envoyer,和一些替代方案:laravel-deployer、laravel-zero-downtime-deployment。
自动化部署:并不是团队中每个人都有(或是应该有)生产环境的 SSH 权限,所以应该是某处的一个按钮触发部署,或者是在某些 git 动作上自动触发部署。
另外,还记得自动化测试吗?是的,你应该自动化他们的自动化。我的意思是测试应该在任何部署之前自动运行。或者,事实上,只要将新代码推送到 staging/develop 分支,它们就应该运行。
您可以安排在那时执行更多自动化操作。通常,此构建 / 部署过程的自动化称为 持续集成或持续交付 (CI/CD)。它在发布新功能时减轻了一些压力。
最近,实现这一目标的最流行工具变成 Github Actions,以下是一些相关资源:
– 使用 GitHub 操作构建、测试和部署 Laravel 应用程序
– 如何使用 GitHub 操作为 Laravel 应用程序创建 CI/CD
但是这不仅仅是关于设置软件工具的事,重要的是人为因素:每个开发者都应该知道部署进程和他们各自的责任。每个人都应该知道在哪个分支上工作、如何提交代码、如何关闭 issue,并且应该在潜意识上遵循「不要直接推送到主分支」、「测试通过后才能合并」之类的事。
也要有类似于「不要在周五上线」的社会规则,但这是有争议的,请看下面的视频。
8. 可扩展硬件架构
如果你的项目使用量足够大,优化代码不足以满足所需要的性能,这时你需要在硬件方面对其进行扩展。增加服务器的电源,或者根据访客来预测扩大或缩小性能,例如黑色星期五的情况。
此外,在多台服务器之间进行 负载平衡 是有益的,即使其中一台服务器因一些原因出现故障时,程序仍能正常运行。 为此,您可以使用 Laravel Forge,请参阅下面的屏幕截图。
此外,不要忘记 外部 服务的扩展。 有单独的基础架构硬件解决方案来支持您的文件存储、队列、Elasticsearch/Algolia、套接字实时内容、数据库等。每个领域都值得大书特书。
市面上有太多各种各样的工具,我无法明确推荐某一个,特别是,一切都取决于您的项目需求、预算以及您对某个生态系统的熟悉程度。
显而易见,世界上服务器能力最强的领导者是拥有 AWS 生态系统的亚马逊,但是通常很难理解它的文档,甚至还有像 AWS 这样的用简单英语解释的网站。
此外,还有一个相对较新的 “玩家” 在这里,所谓的服务器。 随着 Laravel Vapor – 一个由 AWS 提供动力的 Laravel 无服务部署平台的发布,它成为了 Laravel 世界的一件事。
也许在这个缩小的世界里,最好的资源就是 Scaling Laravel.
9. 备份和恢复策略
大家可能都知道您需要对数据库进行定期备份。而且,从表面上看,使用一个简单的 Spatie Laravel Backup 包很容易做到:
当然,你也需要让这方面「自动化」起来,就像「设置它并忘记它」。但是一个重要的问题是,你有没有尝试过至少一次从数据库备份中恢复?
你需要实际的测试这个场景:如果当前的数据库彻底宕机了,或者某人删除了完整的生产环境数据,而你拥有备份 SQL。尝试从 SQL 中导入,再测试导入过程是否没有中断。如果备份恢复有问题,你最好是能在这个灾难发生之前就能预先知道。
此外,如果你有多个数据库服务器,并且备份正在进行,而你希望在备份过程中不降低服务器的访问速度,这时事情会变得更加复杂。因此你可以调整整个流程或是直接使用一些数据库备份工具,哪怕是在 Laravel 世界之外。
10.Bug 监控过程
当然,代码库越大,bug 发生的概率就越大。此外,当有许多特性时,开发人员不能自己测试它们,甚至自动化测试也不能捕获所有可能的场景和案例。在生产环境中,bug 发生在系统的真正用户身上。
作为一个团队,你的目标是监控它们,并在它们发生时得到通知。有各种各样的工具可以帮助解决这个问题,我个人使用的是 Bugsnag,但是也有 Flare,Sentry,Rollbar —— 它们几乎都有相同的功能:通知你漏洞,以及所有可能帮助追踪和修复漏洞的信息。
这不是工具的问题,而是人为因素的问题。团队需要了解谁对哪些 bug 做出反应的流程,以及具体的做法:哪些 bug 是紧急的,哪些是可以推迟的,哪些是可忽略的。
另外,「今天谁值班」的问题也很相关:如果错误跟踪软件通知了一些事情,那么「谁」需要「在哪里」获得消息?在我们的团队中,我们使用 Slack 通知工具,在理想情况下,由负责出现问题的应用程序的开发人员修复这个问题。当然在实际情况中,这种情况并非经常发生,但至少团队需要知悉其反应时间。
团队中还有另一部分成员:非技术人员。 开发人员需要与客户支持人员和经理保持联系,告知他们情况的严重性和状态,「前台」人员会相应地与客户交谈。
11. 安全
这个问题比较明显,我就不详细解释了。 除了一般情况下避免被黑客入侵之外,最重要的可能是保护您用户的个人数据 —— 无论是来自 多租户系统 还是来自外部的其他用户的个人数据。
我建议阅读这篇文章:如何保护您的 Laravel Web 应用程序免受 OWASP 十大安全风险
另外,我建议你试着 攻击自己。 是的,我没有开玩笑 — 让一些值得信赖的朋友 / 公司从外部入侵你的应用程序搞点破坏。有一家名叫 Heck 的公司甚至为此买单 — 有专门从事这个领域的公司。当然,你也可以自己这么做,但作为代码的作者,你会有一定的 倾向性,所以可能做不到像真正的黑客那样采用的是难以意料的攻击方式.
最后,我想表达的是我很开心,因为我们不再需要去解释 SSL 证书的必要性,随着浏览器的警告策略的变更,以及像 Let’s Encrypt 这样的免费工具,没有借口可以让您的网站中看不到 https:// 。
12. 新开发人员入职文档
这篇大文章的最后一点是关于 人 的。如果您不是从项目的第一天开始工作,请记住您被介绍给它的那一天。您还记得那种安装所有东西,阅读文档,玩弄测试数据,试图了解事物如何工作的感觉吗?
现在,想象一下一个新开发人员在当前项目上这样做的想法,这并不复杂。所以,你需要尽可能多地帮助那些可怜的家伙。
我建议你甚至可以做一天的「新开发人员」。 你上一次尝试从头开始安装应用程序是什么时候? 例如,在新的计算机安装操作系统或重新安装操作系统。所以,试试看,你可能会有一些不愉快的「惊喜」需要解决。
如上述文件中的安装说明 (也有可能是 Docker 镜像), 代码中的注释,可以使得代码在 IDE 中「可点击」, 你可以方便且快捷的跳转到代码所在的文件,git commits 中添加便于理解的消息 – 这些都应该注意。而且,记住我们讨论过的工厂文件和种子文件, 在这里非常适用.
顺便一提,这里有一些工具可以帮助你,像这样 Readme generator.
这不仅仅是关于新的开发人员 – 任何现有的团队可能发生同样的情况,他们需要修复模块中以前没有见过的东西.
————————————————
原文作者:haodudecao
转自链接:https://learnku.com/laravel/t/62237
版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请保留以上作者信息和原文链接。
有话要说