@sambodhi
2021-09-27T16:04:11.000000Z
字数 5573
阅读 846
作者 | Chris Tankersley
译者 | Sambodhi
策划 | 蔡芳芳
本文最初发表于 PHPArch 网站 ,经原作者 Chris Tankersley 授权,InfoQ 中文站翻译并分享。
我要批驳 Education Station 的“PHP 最糟糕”这一观点,因为我已有将近二十年的编程经验,并使用过各种编程语言进行开发工作。对于我以前和现在的很多工作,我很荣幸地将 PHP 作为我工作的核心语言。从第一次使用 PHP 工作开始,我就听到了关于 PHP 语言的各种抱怨,但是我也看到了 PHP 的威力。
PHP 是一门有趣的编程语言,至少可以这样说。这门语言和用它构建的程序都有两种设计哲学,并且经常同时进行。在这里,我所说的并非软件开发生命周期,如瀑布或敏捷,而是关于管理软件应该是什么样的基本思想。那些被称为“正确的方式”(The Right Way)和 “更糟就是更好”(Worse is better)。
PHP 包含了一个奇怪的领域,当人们抱怨这门语言“很槽糕”时,他们说得没错。这门语言确实有很多错误的地方。搁在以前,这门语言还有更糟糕的地方。嘲笑 PHP 的博文《全面解析 PHP 的槽糕设计》(PHP: a fractal of bad design)确实有几个正确的观点,即使这些观点在九年前发表时就已经过时了。
然而,与此同时,PHP 允许开发者创建结构上“正确”的软件,并从其他语言中接受被视为良好实践的哲学。像 Laminas 和 Symfony 这样的框架使用了面向对象编程的最佳实践,这使得开发者可以编写结构正确的代码。
PHP 是怎么做到这些的呢?这是因为 PHP 最糟糕。
1991 年,Richard P. Gabriel 发表了一篇文章《Lisp:好消息,坏消息,如何赢得大》(Lisp: Good News, Bad News, How to Win Big)。这篇文章的论点是,在软件设计和寿命方面,“更糟就是更好”的哲学将是更好的选择。在意识到两种不同的程序设计流派出现之后,他得出了这一结论,命名为“麻省理工学院/斯坦福风格”(MIT/Standford Style),或者“正确的方式”,以及后来被称为“新泽西风格”(New Jersey Style)或者“更糟就是更好”。
这两种哲学在其目标上相似,但在关键的领域却有所不同。每种风格都侧重于哲学理念的四个关键领域:简单性(Simplicity)、正确性(Correctness)、一致性(Consistency)和完整性(Completeness)。
麻省理工学院风格是这样描述的:
至于新泽西风格,Gabriel 说,它将其目标定义为:
这场争论的关键是用 LISP 和 C 作为例子来说明为什么“更糟就是更好”。对于 LISP 程序员 Gabriel 来说,LISP 是一种比 C 更好的语言,速度和 C 一样快,而且 Common LISP 的设计、开发和标准化已经花了很多年。定义该语言的规范吸取了所有不同的 LISP 的精华,而现代开发环境对于 LISP 开发者来说是最好的。
LISP 代表了软件开发的“正确的方式”。LISP 被认为是简单的接口,你可以通过各种方式与它交互。希望从 Fortran 中调用 LISP?你可以从 Fortran 中调用 LISP 并将数据传入,反之亦然。在使用遗留代码时,你可以愉快地使用 LISP 的所有现代“豪华”特性。
LISP 拥有一致的设计,这得益于它的规范。假如你研究一下 Python 这样的现代语言,规范在提供多个后端和编译器方面有很大的作用,而且它们都以同样的方式解释或编译代码。这些工具是一流的,1991 年的 LISP 拥有我们今天仍然享受的所有舒适,比如步骤调试、数据检查和花哨的编辑器。
1991 年,LISP 作为一种语言,可能处于有史以来的最佳状态。这种技术上的正确性并没有被实际使用所证实。LISP 的开发商正在衰退。多年来负面新闻和错误定位阻碍了 LISP 的外部声誉。人们不再将其视为向最终用户交付软件的方式。
就开发而言,LISP 往往代表着许多与“大规模预先设计”(Big Design Up Front,BDUF)一样的理想。假如你曾经使用过瀑布模型(Waterfall Model)这样的设计方法,你就会发现问题出现了。“正确的方式”非常强调一致性、正确性,并确保所有能想到的问题都得到考虑。
LISP 本身并非一种单一的语言,而是一种语言家族。尽管 Common LISP 被设计成一种标准,但是 LISP 本身的实现方式是根据需要完成的各种工作而存在的。Lockless Inc 网站上的一篇文章指出,这种“碎片化”是 LISP 最终失败的决定因素之一。尽管 LISP 坚持软件设计的“正确的方式”,但是这些碎片仍然非常清晰,以致于代码维护和可移植性都受到影响。
同时,由于 Unix 的出现,C 语言逐渐成为软件开发的首选方法。C 语言是为 Unix 设计的,而 Unix 是用 C 语言设计的。它的开发人员与麻省理工学院的 LISP 及其作者有着不同的设计立场。
在 1972 年,C 语言被设计成一种简单的语言。到 1991 年,它已经发生了一些变化,但是 C 语言的基本原理没有改变。一些特性是为了满足开发者和 Unix 的需求而添加的。因为语言很简单,所以编写编译器和程序很容易。尽管这种语言并不会妨碍你进行复杂的编程,但是与 LISP 相比,C 语言估计有程序员所需的 50-80% 特性。
但是, C 语言却有很强的可移植性。相对于常用于 LISP 软件和环境的硬件,它也可以运行在低功率硬件上。这一因素使得它可以编译和运行软件到更多的机器上。C 语言和 Unix 很容易使用,Gabriel 认为 Unix 和 C 语言会像病毒一样流行起来。
在 Dennis Ritchie 设计和构建 Unix 的过程中,C 语言得到了发展。因为贝尔实验室(Bell Labs)不允许正式进入计算机领域,所以 Unix 也可以轻松地分发给各种不同的用户。这些其他用户帮助修补 Unix 以满足他们的需求。Dennis Ritchie 能够根据需求将这些补丁整合在一起,而不必事先考虑这些需求。
与 LISP 不同,C 仍然被大量使用。尽管高级的解释性语言,如 PHP、JavaScript 和 Python 是许多开发者的首选,但是 C 语言被用来开发很多这些高级语言。即使是像 Rust 这样的竞争对手开始崭露头角,C 仍然用于小型、低功率的设备。
因此,“更糟就是更好”的软件首先会获得接受,其次会使用户期望更少,第三个将得到改进,达到几乎是正确的程度。
——Richard Gabrie
在这一启示的几年后,Rasmus Lerdorf 开始研究个人主页/表单解释器,也就是我们现在所知的 PHP。PHP/FI 的诞生是因为 Lerdorf 需要维护他的主页,并与表单和数据库进行交互。PHP/FI 甚至不是作为一种实际的编程语言设计的,而是作为 C 语言之上的一层脚本和函数设计的。
设计一定要简单,不论它的实现还是接口,都一定要简单。
尽管 PHP 使用 C 语言,但我们认为它是“最糟糕的”。然而,这也带来了一些优势,最重要的是,更简单的底层语言可以让它更容易地扩展。虽然 Hack/HHVM 采用了更多的 C++ 方法,但 PHP 本身仍然是 C 语言。
只需短短几个小时就能完成学习这门语言的内部组织。Elizabeth Smith 发表过一篇关于 PHP 扩展的精彩演讲,可以一口气了解到,这场演讲包含了内部工作原理的丰富信息。这门语言本身借鉴了其他 C 风格的语言,使其易于阅读,并能从 C 风格的其他语言中进行转换。
PHP 的大多数接口,或者说标准库,都是非常简单的,因为大多数核心功能都仅仅包装了各种 C 语言库,并且几乎都是原封不动地公开出来。尽管这样做会导致了接口上的一些不一致,但是它为来自 C 或 C++ 的开发者提供了一个熟悉的环境。
PHP 语言也非常注重于 Web 开发。将 HTTP 中的概念提取出来并在语言中找到相似的概念通常非常简单。希望了解一个请求的头信息吗?get_headers()
就能满足你。获取请求信息就像读取 $_GET
和 $_POST
全局变量一样简单。
PHP 保持了简单的开发者接口,并且尽可能地保持内部结构的简单。
在所有可以观察到的方面,设计一定要正确。但是可以为了简单而轻微牺牲正确性。
在这里,PHP 倾向于选择“简单”而不是正确。在 HHVM 出现之前,语言的外观和特性一直没有得到规范。Zend 解释器本身就是规范,并且这门语言的行为方式总是 “正确”的(不包括实际的错误)。要想用别的东西代替 PHP 引擎,就必须实现现有引擎的所有特性。
许多核心函数的 LAX 函数参数和返回类型都使得系统的工作更容易。像 strpos()
这样的函数返回整形或布尔值,相对于返回整形或抛出异常的方法,处理要稍微容易一些。
看语言是如何发展的,几乎所有的新特性都是建立在开发人员需要的基础上的,而不是“因为它是错误的,就修复它”的严肃想法。更多地注意那些基于严格类型和错误的异常,是一种更正确的做事方法。然而,还有一些东西,比如简短的箭头函数(arrow function)、属性和枚举,都是开发者想要简化代码的东西。
设计一定不能太过不一致。某些情况下,为了保持简单可以牺牲一致性。
我甚至不打算假装 PHP 是一致的,但是它已经足够一致了。当涉及到数组与字符串函数时,人们可能会抱怨 needle/haystack 参数顺序。不过,一般而言,数组函数是一致的,而字符串函数也是一致的。与底层 C 库保持一致要比在语言中保持一致要简单得多。
PHP 在其他方面也足够一致。正如我在 strpos()
中提到的,PHP 对于遇到错误的函数往往会相当一致地返回 FALSE。这未必是正确的,但它却是一致的。带下划线和不带下划线的函数名通常都会匹配其基础库。
为了简单起见, PHP 语言牺牲了一致性,但是即使没有这个规范,它仍然需要在有意义的地方保持一致。
设计一定要尽可能多地涵盖重要的情况。
无论何时,PHP 完备的,因为它需要完成它的设计任务:编写 Web 应用程序。PHP 从未被设计成一种语言,涵盖编程世界的所有问题。尽管如此,它的简单性还是使它可以用于 Web 以外的场合。它最初的重点是与 Web 合作,帮助形成了最初需要的功能,并且这一趋势一直持续至今。
修改核心语言通常主要是由开发人员的需求驱动。全社区提出改变,社区投票,新特性被拒绝、改变或者接受。在语言上的许多创新都源于快速完成工作的需要。即便我们吸收了其它语言的功能,这也是因为它使我们的开发变得简单了,而很少是因为其他语言做得“更正确”。
今天,PHP 允许你开发 Web 应用程序。五年后,它仍然可以让你开发 Web 应用程序,只是增加了一些新特性。但是,语言本身是完整的,正如今天所需要的。如有必要,我们可以随时增加或修改语言。
Gabriel 承认,“更糟就是更好”的哲学是以这样的方式设计出来的,看起来很糟糕,也许不应该是更好的选择。唯一的问题是,当他审视这两种哲学时,与麻省理工学院/“正确的方式”的设计哲学相比,“更糟就是更好”最终仍然是更灵活的选择,“具有更好的生存特性”。如果我们看一下 PHP,就可以证实“更糟就是更好”这一观点。
这些年来,Gabriel 承认他在哪种方式更好之间摇摆不定。PHP 社区一直在争论我们是应该正确地做事还是继续简单地做事。我们有像 Laminas 这样的框架,以经典的计算机科学方式构建库,然后我们有像 Laravel 这样的框架,直接关注开发者的体验和速度。PHP 本身允许这两种情况。
下次有人想骂 PHP 的时候,那就随他喷去吧。这门语言确实很糟糕。但从许多方面来看,PHP 的长寿和广泛使用证明了这样一个事实:用“正确的方式”做事并不总是比用“最糟糕”的方式做事好。当有人抱怨你正在使用的框架时,要明白从长远来看这并不重要。选择一种你认为适合自己的设计哲学,并且高兴地知道,更糟的可能实际上是更好的。
作者介绍:
Chris Tankersley 拥有多种角色:丈夫、父亲、作家、演讲家、播客主持人和 PHP 开发者。Chris 在 12 年的编程生涯中使用 了很多种不同的框架和语言,但是他一天的大部分时间都在使用 PHP 和 Python。他是《Docker for Developers(尚无中文版)的作者,并与公司和开发者合作,将容器整合到他们的工作流中。
原文链接:
https://www.phparch.com/2021/09/education-station-php-is-the-worst/