php真的有那么糟糕吗?

2021-12-04  本文已影响0人  追梦人在路上不断追寻

Slack 的大部分服务器端应用程序都在使用 PHP,这在当今是一个不寻常的选择。为什么会选择一个性能不够好,而且被很多人诟病的编程语言呢?

大多数PHP的程序员都知道两件事:

这并不完全矛盾。

PHP有许多缺陷,但 PHP的优点让人暂时忽略了它的缺点,而且一些项目改进了他的缺陷。

总而言之,PHP 为构建、更改和运营成功的项目提供了更好的支持。

背景

在现代语言中,PHP是独一无二的,它诞生于 Web 服务器。它的优势是与面向请求的服务器端执行上下文紧密耦合。

PHP 最初代表个人主页。它于 1995 年由 Rasmus Lerdorf 首次发布,旨在支持小型、简单的动态 Web 应用程序,例如在 Web 早期流行的留言簿和点击计数器。

从 PHP 一开始,它就被用于比其创建者预期的复杂得多的项目。

它经历了几次重大修订,每一次都带来了处理这些更复杂应用程序的新机制。

它是混合范式开发人员生产力语言 ( MPDPL) 家族中功能丰富的成员,其中包括 JavaScript、Python、Ruby 和 Lua。如果您上次接触 PHP 还是在早期的化,那么现代 PHP 代码库可能会给您带来特征闭包生成器惊喜。

PHP 的优点

首先,状态。每个 Web 请求都从一个完全空白的请求开始。它的命名空间和全局变量是未初始化的,除了提供原始功能和生命支持的标准全局变量、函数和类。通过从已知状态开始每个请求,我们得到了一种有机的故障隔离;如果请求t遇到软件缺陷而失败,这个bug不会直接干扰后续请求t+1的执行. 当然,状态确实驻留在程序堆以外的地方,并且有可能有状态地弄乱数据库、内存缓存或文件系统。但是 PHP 与所有可以想象的允许持久性的环境都有相同的弱点。将请求堆彼此隔离可以降低大多数程序缺陷的成本。

第二,并发。单个 Web 请求在单个 PHP 线程中运行。乍一看,这似乎是一个愚蠢的限制。但是由于您的程序是在 Web 服务器的上下文中执行的,因此我们有一个天然的并发源:Web 请求。异步处理到本地主机(或什至另一个 Web 服务器)提供了一种利用并行性的无共享、复制输入/复制输出的方式。在实践中,这比大多数其他通用语言提供的锁和共享状态方法更安全,更能抵御错误。

最后,PHP 程序在请求级别运行这一事实意味着程序员工作流程快速高效,并且随着应用程序的变化保持快速。许多开发人员生产力语言声称这一点,但如果它们不为每个请求重置状态,并且主事件循环与请求共享程序级状态,它们几乎总是有一些启动时间。例如,对于典型的 Python 应用程序服务器,调试周期将类似于“思考;编辑; 重启服务器;发送一些测试请求。” 即使“重启服务器”只需要几秒钟的挂钟时间,我们有限的人类大脑必须保持最微妙的状态所需的15-30 秒时间也会大大减少。

我声称 PHP 的“思考”更简单;编辑; 重新加载页面”循环使开发人员更有效率。在漫长而复杂的软件项目的生命周期过程中,这些生产力的提高是复合的。

PHP的缺点

  1. 类型转换。现在几乎所有的语言都允许程序员用 >= 运算符比较整数和浮点数,即使是 C 也允许这样做。其意图非常清楚。不太清楚用 == 比较字符串和整数是什么意思,不同的语言做出了不同的选择。PHP 在这个部门的选择尤其反常,会导致意外和未被发现的错误。例如, 123 == “123foo” 评估为真(看看它在那里做什么?),但 0123 == “0123foo” 是假的(嗯)。

  2. 围绕引用、值语义的不一致

PHP 3 有一个明确的语义,即赋值、参数传递和返回都是按值的,创建了相关数据的逻辑副本。程序员可以使用 & 注释选择引用语义[ [2](https://slack.engineering/taking-php-seriously/#2e75)** ]**. 不过,这与 PHP 4 和 5 中引入的面向对象编程设施相冲突。

PHP 的 OO 表示法大部分是从 Java 借来的,Java 的语义是对象按引用处理,而原始类型按值处理。所以 PHP 语义的当前状态是对象通过引用传递(选择 Java 而不是 C++),原始类型通过值传递(Java、C++ 和 PHP 同意),但旧的引用语义和 & 符号仍然存在,有时会以奇怪的方式与新世界互动。

  1. 无视失败的哲学

PHP 非常非常努力地保持请求运行,即使它做了一些非常奇怪的事情。例如,除以零不会抛出异常,或返回 INF,或致命地终止请求。默认情况下,它会发出警告并评估值为 false。由于在数字上下文中 false 被静默地视为 0,因此许多应用程序部署和运行时未诊断的除数为零。这个特殊的问题在PHP 7 中(http://php.net/manual/en/migration70.incompatible.php)得到了改变,但是在它可能有意义的时候继续向前推进的设计冲动也渗透到了库中。

  1. 标准库中的不一致

在 PHP 年轻的时候,它的受众最熟悉 C,许多 API 使用 C 标准库的设计语言:六个字符的小写名称,以整数返回值返回成功和失败,在被调用者中返回“真实”值 -提供“out”参数等。随着PHP的成熟,以为前缀的命名空间的C风格变得更加普遍:mysql...,json_...等。最近,CamelCase类上的camelCase方法的Java风格已经成为最流行的引入新功能的常用方法。所以有时我们会看到一些代码片段以一种不和谐的方式将诸如 new DirectoryIterator(path) 和 if (!(f = fopen($p, 'w+')) 之类的表达式交织在一起。

HHVM 和黑客

PHP 的后继系统称为 Hack [ [3](https://slack.engineering/taking-php-seriously/#8f9f)** ]**。

Hack 是人们称之为PHP的“渐进类型系统”的编程语言。“类型系统”意味着它允许程序员表达关于流经代码的数据的自动可验证的不变量:这个函数接受一个字符串和一个整数并返回一个 Fribbles 列表,就像在 Java 或 C++ 或 Haskell 中一样静态你喜欢的类型语言。“渐进”部分意味着您的代码库的某些部分可以是静态类型的,而其他部分仍处于粗略的动态 PHP 中。混合它们的能力可以逐步迁移大型代码库。

与其在这里大量描述 Hack 的类型系统及其工作原理,不如直接去玩玩它

这是一个简洁的系统,并且在它允许您表达的内容方面非常雄心勃勃。可以选择逐渐将项目迁移到 Hack,以防它变得比您最初预期的要大,这是 PHP 生态系统的独特优势。Hack 项目提供与所有流行编辑器和 IDE 的集成,以便在您完成输入后立即收到有关类型错误的反馈,就像在 Web 演示中一样。

让我们根据 Hack 评估 PHP 带来的一系列实际风险:

Hack 提供了 MPDPL 家族的其他流行成员所没有的选项:在初始开发后引入类型系统的能力,并且仅在价值超过成本的系统部分中引入。

高速虚拟机

Hack 最初是作为HipHop 虚拟机或 HHVM 的一部分开发的,HHVM 是 PHP 的开源 JIT 环境。HHVM 为成功的项目提供了另一个重要的选择:能够更快、更经济地运行您的站点。Facebook报告说,与 PHP 解释器相比,CPU 效率提高了 11.6倍,维基百科报告说提高了 6 倍。

Slack 最近将其 Web 环境迁移到 HHVM,并且所有端点的延迟都显着下降,但在撰写本文时,我们缺乏对 CPU 效率的逐一衡量。我们也在将部分代码库迁移到 Hack 中,并将在此处报告我们的经验。

展望未来

我们从一个明显的悖论开始,即 PHP 是一种非常糟糕的语言,被用于许多成功的项目。我们发现,孤立地看,它作为一种糟糕的语言的声誉是当之无愧的。使用它的项目的成功更多地与 PHP环境的属性以及它支持的高节奏工作流有关,而不是与 PHP 语言有关。并且该环境的优势(通过故障隔离降低错误成本;安全并发;以及高开发人员吞吐量)比语言缺陷造成的问题更有价值。

此外,在 MPDPL 中独一无二的是,有一条清晰的迁移路径,以 Hack 和 HHVM 的形式向更高性能、更安全和更易于维护的介质迁移。Slack 正处于向 HHVM 过渡的后期阶段,以及向 Hack 过渡的早期阶段,我们乐观地认为它们会让我们更快地开发出更好的软件。

上一篇下一篇

猜你喜欢

热点阅读