谁能解释在选择使用钩子而不是使用中间件来实现身份验证或缓存等功能时是否有任何显着的优点或缺点?例如 - 我可以通过自定义中间件获取请求对象并设置应用程序语言变量来实现翻译功能,该变量可用于在应用程序执行时加载正确的翻译文件。或者我可以在路由之前添加一个钩子并读取请求变量,然后在应用程序执行期间加载正确的文件。是否有任何明显的原因让我错过了一个选择比另一个更好?
2 回答
超级TL/DR;(非常简短的回答)
在首次启动应用程序的某些方面时使用中间件,即路由器、启动过程、登录确认期间,并在其他任何地方使用挂钩,即在组件或微服务中。
TL/DR;(简短的回答)
当执行顺序很重要时使用中间件。正因为如此,中间件经常被添加到代码的各个方面的执行堆栈中(中间件通常在启动时添加,同时添加记录器、身份验证等。在大多数实现中,每个中间件函数随后决定是否继续执行。
但是,当执行顺序无关紧要时使用中间件往往会导致错误,其中添加的中间件不会错误地继续执行,或者预期的顺序被打乱,或者有人只是忘记了添加中间件的位置或原因,因为它几乎可以在任何地方添加。这些错误可能很难追踪。
挂钩一般不知道执行顺序;每个钩子函数都被简单地执行,这就是所有的保证(即在另一个钩子之后添加一个钩子并不能保证第二个钩子总是第二个执行,只是它会被简单地执行)。执行其任务的选择由函数本身决定(调用状态以停止执行)。大多数人认为这要简单得多,并且活动部件更少,因此统计上产生的错误更少。然而,为了检测它是否应该运行,在钩子中包含额外的状态是很重要的,这样钩子就不会进入应用程序并与它本身不关心的事情耦合(这可能需要纪律来推理好吧,但通常更简单)。此外,由于它们的简单性,钩子往往被添加到某些命名的代码点,
一般来说,钩子更容易推理和存储,因为它们的顺序没有得到保证或考虑。因为钩子可以自我否定,所以钩子在计算上也是等价的,使得中间件只是一种编码风格或常见问题的简写形式。
深潜
今天,架构师普遍认为中间件是一个糟糕的选择。中间件可能会导致噩梦,并且在调试方面的额外努力很少能被所实现的任何速记所抵消。
中间件和 Hooks(以及 Mixins、Layered-config、Policy、Aspects 等)都是“策略”类型的设计模式的一部分。
策略模式,因为每当涉及代码分支时都会调用它们,因此可能是最常用的软件设计模式之一。
策略模式的知识和使用可能是检测开发人员技能水平的最简单方法。
每当您需要应用“if...then”类型的逻辑(可选执行/分支)时,都会使用策略模式。
在软件上进行的计算思维实验越多,可以在精神上减少和随后重构的分支就越多。这本质上是“方面代数”;构建问题的“骨架”,或者一遍又一遍地思考正在发生的事情,将程序简化为它的基本概念/第一原则。在重构时,这些思想实验是架构师花费最多时间的地方;找到共同的方面并减少不必要的复杂性。
降低复杂性的目的是出现(在系统理论白话中,特别是软件,在特殊层中应用配置而不是首先编写软件)和monads。
如果开发人员不小心,Monads 倾向于将正在做的事情抽象到一个可能导致代码执行时间增加的水平。
Monads 和 Emergence 都倾向于将问题抽象出来,以便可以使用基本构建块普遍应用这些部分。使用 Monads(适用于小型)和 Emergence(适用于大型),理论上任何复杂的软件都可以由尽可能少的部分构建而成。
毕竟,在重构中:“最容易维护的代码是不再存在的代码。”
函子和映射函数
不断降低复杂性的一个好方法是应用函子和映射函数。函子通常也是实现分支的最快方法,让编译器深入了解问题,以便以最佳方式优化事物。它们也非常易于推理和维护,因此将您的工作留到一天中并使用部分重构的应用程序提交您的更改几乎没有什么坏处。
函子的名字来源于数学(特别是范畴论,其中它们被称为在两个集合之间映射的函数)。然而,在计算中,函子通常只是以一种或另一种方式映射问题空间的对象。
关于什么是或不是计算机科学中的函子存在很大的争论,但根据定义,您只需要关注映射问题的行为,并使用“函子”作为临时思想支架允许您将问题抽象出来,直到它成为配置或实现的一个因素而不是代码。
据我所知,这middleware
对于每个路由工作来说都是完美的。并且hooks
最适合在应用程序范围内做任何事情。对于您的情况,我认为它应该hooks
比中间件更好用。