为什么要远离对日外包_远离魔法-或:为什么我不想再使用Laravel

为什么要远离对日外包

by Niklas Schöllhorn

由NiklasSchöllhorn

远离魔法-或:为什么我不想再使用Laravel (Moving away from magic — or: why I don’t want to use Laravel anymore)

It is time for a change in the tools that I use. And I’ll tell you why!

现在该改变我使用的工具了。 我会告诉你为什么!

First of all, I want to make sure that you know about my intentions. I am not trying to rant about Laravel or why other frameworks might be better.

首先,我想确保您了解我的意图。 我不是要抱怨Laravel或为什么其他框架可能会更好。

This article is very subjective. I’ll give you my thoughts and try to get you to rethink your framework choices as well. And when you stick with Laravel after reassessing, that’s fine. I have no intention to convert people away from Laravel to other frameworks or languages. But it is important to look closer and to make sure you know what you are using and why you are using it.

本文非常主观。 我会给您我的想法,并尝试让您重新考虑您的框架选择。 当您在重新评估后坚持使用Laravel时,就可以了。 我无意将人们从Laravel转向其他框架或语言。 但重要的是要靠近并确保您知道自己在使用什么以及为什么使用它。

介绍 (Intro)

I’ve worked with Laravel for about 2 years now. I always enjoyed how easy it was to spin up an application and get going in minutes. It provides so many useful tools out of the box. The console commands support you in every aspect during coding. They generate classes, scaffolding for authentication and much more.

我已经与Laravel合作了大约2年。 我一直很喜欢启动一个应用程序并在几分钟之内完成它是多么容易。 它提供了许多开箱即用的有用工具。 在编码过程中,控制台命令在各个方面都为您提供支持。 它们生成类,用于身份验证的脚手架等。

But the deeper you go and the bigger the projects become, the more complicated the development with Laravel will get. Or, let me rephrase it: the better other tools will do the job. I’m not even saying it’s only Laravel’s fault. It’s also partly due to PHP not being very well designed.

但是您越深入,项目越大,Laravel的开发就会越复杂。 或者,让我改一下:其他更好的工具可以胜任这项工作。 我什至不说这只是Laravel的错。 这也部分是由于PHP的设计欠佳。

Now, let’s start!

现在,让我们开始吧!

口才ORM (Eloquent ORM)

If you’ve already worked with Laravel, you surely know about Eloquent. It’s the ORM that’s shipped with a default installation. It comes with a lot of neat features. But its design makes your application needlessly complex and prevents the IDE from correctly analyzing your code.

如果您已经与Laravel合作,那么您肯定知道Eloquent。 默认安装附带的是ORM。 它具有许多简洁的功能。 但是其设计使您的应用程序不必要地复杂,并阻止IDE正确分析您的代码。

This is partly due to the Active Record ORM pattern that’s being used and partly due to the fact that Eloquent wants to save the developer from having to write more code. To do that, it lets the developer stuff a lot into the model that doesn’t belong there.

这部分是由于使用了Active Record ORM模式,另一部分是由于Eloquent希望避免开发人员不得不编写更多代码。 为此,它使开发人员可以将不属于该模型的模型塞入很多模型中。

Sounds like good intentions, but I started to dislike this more and more.

听起来像是个好主意,但我开始越来越不喜欢这个。

Let’s have a look at an example:

让我们看一个例子:

The first thing you see is that there are no properties on the model. This seems irrelevant but for me, it makes quite a difference. Everything is injected “magically” into the class by reading the table metadata. Of course, your IDE does not understand that without help. And you get no chance to name your properties differently from your columns.

您看到的第一件事是模型上没有属性 。 这似乎无关紧要,但对我而言,却有很大的不同。 通过读取表元数据,将所有内容“神奇地”注入到类中。 当然,如果没有帮助,您的IDE将无法理解。 而且,您没有机会以不同于列的名称来命名属性。

Now check out the scope method. For Laravel users, it’s pretty clear what it does. If you call this method, it scopes the underlying SQL query by adding the given WHERE clause.

现在检查范围方法。 对于Laravel用户而言,它的作用非常明显。 如果调用此方法,则它将通过添加给定的WHERE子句来限定基础SQL查询的范围。

You can see, it is not static. That would mean that this method operates on a specific object of the class. But in this case, it does not. A scope is called on a query builder. It has nothing to do with the model object itself. I’ll explain that after you see how you usually call those scopes:

您可以看到,它不是静态的。 这意味着该方法对类的特定对象进行操作。 但是在这种情况下, 它不是 。 在查询生成器上调用范围。 它与模型对象本身无关 。 在您了解通常如何调用这些范围之后,我将进行说明:

You’re calling a static method popular() that nobody ever defined. But since Laravel defines a __call() and __callStatic() method, it gets handled through them. Those methods forward the call to a query builder.

您正在调用没有人定义的静态方法popular() 。 但是由于Laravel定义了__call()__callStatic()方法,因此可以通过它们进行处理。 这些方法将调用转发给查询构建器。

This is not only something that your IDE doesn’t understand. It makes refactoring harder, might confuse new developers, and static analysis gets harder as well.

这不仅是您的IDE无法理解的。 它使重构更加困难,可能使新开发人员感到困惑,并且静态分析也变得更加困难。

In addition, when putting such methods on your model, you are violating the S of SOLID. In case you are not familiar with that, SOLID is an acronym that stands for:

此外,将此类方法应用于模型时,将违反SOLID的S。 如果您不熟悉它,SOLID是一个缩写,代表:

  • Single Responsibility Principle

    小号英格尔责任原则

  • Open/Closed Principle

    Ø笔/封闭原则

  • Liskov Subsitution Principle

    大号 iskov Subsitution原理

  • Interface Segregation Principle

    覆盖整个院落分离原则

  • Dependency Inversion Principle

    d ependency倒置原则

When you use Eloquent, your models have multiple responsibilities. It holds the data from your database, which is what models usually do, but it also has filtering logic, maybe sorting and even more in it. You don’t want that.

使用Eloquent时,您的模型有多个职责。 它保存着数据库中的数据,这通常是模型所要做的,但是它也具有过滤逻辑,也许还有排序逻辑。 你不要那样

全球帮手 (Global Helpers)

Laravel comes with quite a few global helper functions. They seem very handy and yes, they are handy.

Laravel具有很多全局帮助器功能。 它们似乎非常方便,是的,它们非常方便。

You just have to know that you sacrifice your independence for that handiness and your global namespace gets polluted. It rarely leads to conflicts, but avoiding that altogether should be preferred.

您只需要知道您会为此方便而牺牲自己的独立性,并且全局名称空间会受到污染。 它很少导致冲突,但是应该完全避免这种冲突。

Let’s look at a few examples. Here’s a list of three helper methods that we have but don’t need since there are better alternatives:

让我们看几个例子。 这是我们有但不需要的三个辅助方法的列表,因为有更好的选择:

  • app_path() — why? If you need the path of the app, ask the app object. You get it by type hinting.

    app_path() -为什么? 如果您需要应用程序的路径,请询问应用程序对象。 您可以通过类型提示获得它。

  • app() — huh? We don’t need this method. We can inject the app instance!

    app() —是吗? 我们不需要这种方法。 我们可以注入该应用实例!

  • collect() — This creates a new instance of the Collection class. We can just new an object up by ourselves.

    collect() —这将创建Collection类的新实例。 我们可以自己新建一个对象。

One more concrete example:

一个更具体的例子:

We are using Laravel’s global request() helper to retrieve the POST data and put it in our model as the attributes.

我们正在使用Laravel的全局request()帮助器来检索POST数据,并将其作为属性放入我们的模型中。

Instead of using the global helper, we could type hint a Request object as a parameter in the controller method. The dispatcher in Laravel knows how to provide us with the needed object. It will call our method with it and we don’t have to call a helper.

代替使用全局帮助器,我们可以在controller方法中键入hint一个Request对象作为参数。 Laravel中的调度员知道如何为我们提供所需的对象。 它将使用它来调用我们的方法,而不必调用一个助手。

And we can take this a step further to decouple even more. Laravel is PSR-7 compliant. So, instead of type hinting the Request object, you could also type hint ServerRequestInterface. That allows you to replace the whole framework with anything that’s PSR-7 compliant. Everything in this method will continue to work. This would fail if you’re still be using the helper methods. The new framework wouldn’t come with the helper method and therefore, you’d have to rewrite that part of your code.

而且,我们可以采取进一步的措施来进一步分离。 Laravel符合PSR-7 。 因此,除了键入提示Request对象的类型外,您还可以键入hint ServerRequestInterface 。 这样一来,您就可以使用与PSR-7兼容的任何产品来替换整个框架。 此方法中的所有内容将继续起作用。 如果您仍在使用辅助方法,则此操作将失败。 新框架不会附带helper方法,因此,您必须重写代码的这一部分。

You rarely switch the whole framework, but there are people who do. And even if you might never switch, it is still important for interoperability. Being able to inject dependencies and have a concise data flow instead of resolving and requesting dependencies and data inside out is the way to go. It makes testing, refactoring, and nearly everything easier when you get a grip of it.

您很少切换整个框架,但是有些人这样做。 即使可能永远都不会切换,它对于互操作性仍然很重要。 能够注入依赖关系并拥有简洁的数据流,而不是从头解决并请求依赖关系和数据是可行的方法。 当您掌握了它时,它将使测试,重构和几乎所有操作变得更加容易。

I was happy when I read that with Laravel 5.8 the string and array helpers get removed from the core and put into a separate package. This is a good first step. But the documentation should start to discourage usage of all helper functions.

当我读到Laravel 5.8时,我很高兴能将字符串和数组助手从核心中删除并放入一个单独的包中。 这是一个很好的第一步。 但是文档应该开始阻止所有助手功能的使用。

外墙 (Facades)

The arguments from the last part come into play here as well. Facades seem to be a nice tool to quickly access some methods that are not really static. But they tie you into the framework once again. You use them to manually resolve dependencies instead of instructing the environment to provide them.

最后一部分的论点也在这里起作用。 外观似乎是快速访问某些并非真正静态的方法的好工具。 但是它们再次将您束缚到框架中。 您可以使用它们来手动解决依赖关系,而不是指示环境提供依赖关系。

The same goes for the complexity by passing everything through the magic methods.

通过将所有内容都传递给魔术方法来解决复杂性问题。

Since we were talking about IDE support, I know some of you might direct me to the IDE helper package from barryvdh. You don’t need to. I already know this package. But why is it even needed? Because some design decisions in Laravel are just not good. There are frameworks where you don’t need that. Take Symfony for example. No need for IDE helper files, because it’s well designed and implemented.

自从我们谈论IDE支持以来,我知道你们当中有些人可能会引导我进入barryvdh的IDE帮助程序包 。 不用了 我已经知道这个包了。 但是,为什么甚至需要它呢? 因为Laravel中的某些设计决策并不好。 有不需要的框架。 以Symfony为例。 不需要IDE帮助程序文件,因为它经过精心设计和实施。

Instead of facades, we could use dependency injection again as we did in the previous example. We’d have a real object and could call real methods on it. Much better.

可以像上一个示例一样再次使用依赖项注入来代替Facade。 我们将有一个真实的对象,并可以在其上调用真实的方法。 好多了。

I will once again give you an example:

我将再举一个例子:

We could easily clean this up. Let’s tell Laravel to inject a ResponseFactory and pass us the current request:

我们可以轻松清理它。 让我们告诉Laravel注入ResponseFactory并将当前请求传递给我们:

We have now successfully eliminated the use of facades from our controller. The code still looks clean and compact, if not even better than before. And since our controllers always extend the general Controller class, we could take everything a step further by moving the response factory to that parent class. We need it in all other controller classes anyways.

现在,我们已成功从控制器中消除了外墙的使用。 该代码看起来仍然干净整洁,即使没有比以前更好。 而且由于我们的控制器总是扩展通用的Controller类,因此我们可以通过将响应工厂移到该父类来使一切更进一步。 无论如何,我们在所有其他控制器类中都需要它。

I heard that some people provide “too many constructor parameters” as an argument against injecting everything. But I don’t agree with that. It’s only hiding the dependencies and thus complexity in the first place. If you don’t like having 10 to 20 arguments in your constructor, you are right.

我听说有人提供“太多构造函数参数”作为反对注入所有内容的论据。 但是我不同意。 首先,它只是隐藏了依赖关系,因此也隐藏了复杂性。 如果您不喜欢在构造函数中使用10到20个参数,那么您是对的。

The solution isn’t magic though. Needing that many dependencies in a single class means that this class most likely has too many responsibilities. Instead of hiding that complexity, refactor that class. Split it up into new ones and improve on your application architecture.

解决方案并不是魔术。 在单个类中需要许多依赖关系意味着该类很可能承担太多职责。 不必隐藏那种复杂性,而是重构该类。 将其拆分为新的并改进您的应用程序体系结构。

Fun fact: there’s a real design pattern called “facade pattern”, introduced in the Gang of Four’s book. But it has a completely different meaning. Laravel’s facades are essentially static service locators. The naming just doesn’t convey that. Same naming for different things also makes discussions about architecture in projects harder, because the other party might expect something completely different behind that name.

有趣的事实:《四人帮》(Gang of Four)的书中介绍了一种称为“外观模式”的真实设计模式。 但是它具有完全不同的含义。 Laravel的外墙本质上是静态服务定位器 。 命名并不能传达这一点。 对不同事物的相同命名也使对项目中的体系结构的讨论更加困难,因为另一方可能期望在该名称后面有完全不同的事物。

结论 (Conclusion)

Let’s come to an end. I might write a follow-up soon about which technologies I prefer to use nowadays. But for the moment, let me sum up what we’ve learned:

让我们结束吧。 我可能会很快就我现在喜欢使用哪些技术写一篇后续文章。 但是现在,让我总结一下我们学到的东西:

Laravel’s approach to making everything as easy as possible is good. But it’s hard to get along when your apps become more advanced. I prefer awesome IDE support, stronger typing, real objects, and good engineering. I might even go back to Laravel when I want to write a smaller app.

Laravel使一切变得尽可能简单的方法是好的。 但是,当您的应用程序变得更高级时,很难相处。 我更喜欢出色的IDE支持,更强的键入,真实的对象以及良好的工程设计。 当我想编写一个较小的应用程序时,我什至可以回到Laravel。

A lot of my points are not only Laravel’s fault. I could swap the parts I don’t like, for example the ORM. But instead, I’ll just switch the toolkit, where the defaults fit my needs better. I see no point in using a framework where I have to spend more time in avoiding traps it sets for bad engineering than in developing my app. Other frameworks and tools come with better designed defaults and less magic.

我的很多观点不仅是Laravel的错。 我可以交换我不喜欢的部分,例如ORM。 但是,我只需要切换工具箱即可,默认设置更适合我的需求。 我发现使用框架比开发应用程序要花更多的时间,在框架上花很多时间来避免因不良工程而造成的陷阱是没有意义的。 其他框架和工具具有更好的默认设计和更少的魔力。

So for now, I’ll say goodbye to Laravel.

所以现在,我将告别Laravel。

Thank you for your time. I’d appreciate a nice discussion in the comments and I am of course open for your questions and suggestions.

感谢您的时间。 非常感谢您在评论中进行了精彩的讨论,当然欢迎您提出问题和建议。

P.S.: Special thanks to Marco Pivetta for proof reading and additional input!

PS:特别感谢Marco Pivetta的校对和其他投入!

Edit March 1st, 2019:Since my article was posted on Reddit, I have created a Reddit account to answer a few comments. My account is not the one the article was posted from, but this one: https://reddit.com/u/nschoellhorn

编辑2019年3月1日:自从我的文章发布在Reddit上以来,我创建了一个Reddit帐户来回答一些评论。 我的帐户不是发布该文章的帐户,而是这个帐户: https : //reddit.com/u/nschoellhorn

Edit March 13th, 2019:If you read this far, you can as well check out my Twitter profile. Thank you for your continued interest in this topic! I am always open to productive discussions, so please feel free to get in contact, either here or on Twitter.

编辑2019年3月13日:如果您已阅读本文,则还可以查看我的Twitter个人资料 。 感谢您一直以来对该主题的关注! 我总是愿意进行富有成效的讨论,因此,请随时在此处或在Twitter上与我们联系。

翻译自: https://www.freecodecamp.org/news/moving-away-from-magic-or-why-i-dont-want-to-use-laravel-anymore-2ce098c979bd/

为什么要远离对日外包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值