介绍

"Unix哲学”是将单个大系统创建为独立小软件的集合的想法。这个想法是让像 UNIX 这样大而复杂的东西变得简单,或者从技术角度来说,开发一个具有模块化、可组合程序设计的大型系统。

UNIX 哲学中没有官方定义。 Ken Thompson 和其他 UNIX 创始人通过 UNIX 的发展所展示的软件开发概念后来被称为 UNIX 哲学,并被其他人解释和解释为 UNIX 哲学。这就是为什么有几种不同的所谓 UNIX 哲学。尽管 UNIX 哲学的基本思想在今天仍然适用,但迄今为止对 UNIX 哲学的大部分解释都是基于旧技术并导致了误解。本文更新了对旧 UNIX 哲学的讨论,并使其与现代计算机和软件技术保持同步。复兴 1980 年代过时的 UNIX 哲学的现代尝试是。

按时间顺序排列的三个著名的 UNIX 哲学:McIlroy 的 UNIX 哲学 (1978)、Gunkers 的 UNIX 哲学 (1994) 和 Raymond 的 UNIX 哲学 (2003)。这些是可以称为 UNIX 另一个名称的软件工具的示例,并解释了 UNIX 哲学的思想。在本文中,根据之前的评论,三个 UNIX 哲学被解读为“软件工具哲学”、“软件工具学说”和“软件工具开发原则”,是众所周知的 UNIX 哲学的旧版本和被误解的版本。它解释了 Unix 的哲学是什么,用新词代替了旧的简短描述,解释了为什么必须修改它们,并添加了一些评论。特别是《Gunkers' UNIX Philosophy》进行了大幅度的修改。这是因为它没有《麦克罗伊的 UNIX 哲学》那种可以说是原创的简洁,而是反映了 1980 年代在 DEC 参与 UNIX 开发的 Gunkers 的原创思想。

作为记录,我不会声称本文中的解释是唯一正确的 UNIX 哲学。考虑到这三个 Unix 哲学只是他们自己的解释,而我添加了第四个。不管正确与否,我至少会尝试使它比旧的 UNIX 哲学论述更现代。此外,由于长篇文章一直很受欢迎,这篇文章只有大约 70,000 个字符。如果你制作一本书,它只是一本大约 100 页的薄书,不是吗?

关于 UNIX 哲学

UNIX 哲学是一种思维方式,而不是具体的设计策略。 UNIX 哲学诞生于 UNIX 的发展过程中,而 UNIX 是第一个将 UNIX 哲学付诸实践的系统。有一个概念认为 UNIX 是“一个充满程序员软件工具的工具箱”(参见GNU CoreUtils - 一个软件工具箱)。所以 UNIX 哲学的一个例子就是 UNIX = 软件工具。这个想法是构建一起工作的软件工具,然后一起使用它们。对于每天使用各种软件,有时甚至自己创建软件的程序员来说,UNIX 哲学是密不可分的,但我认为他们没有正确理解它的价值。

UNIX 哲学是一种“生于 UNIX”的哲学,而不是“仅限于 UNIX”的哲学。不过,也许是因为 UNIX 这个名字,或者是因为它被认为只与 UNIX 有关,又或者是因为 UNIX 哲学的很多解释都以 1980 年代的 UNIX 世界为例,旧的 UNIX 似乎使用,例如 C 语言编程、shell 脚本和掌握 UNIX shell、awk 和 UNIX 命令的技术,被误解为 UNIX 哲学,但事实并非如此。例如,Linux + fish shell script + Python command + MySQL server 的组合也是 UNIX 哲学。这只是说组合使用的工具已经更换。

UNIX 并不是唯一将 UNIX 理念付诸实践的东西。简单的例子包括使用 Docker Compose 从独立的 Docker 容器创建系统,微服务架构是 UNIX 哲学的实践(无论你是否意识到)。 UNIX 哲学在 Apache Kafka(一个用 Java 和 Scala 编写的分布式流式消息传递系统)中也很活跃。Apache Kafka、Samza 和 Unix 分布式数据哲学你可以通过阅读了解对于那些能够从其他著名的软件开发原则中学习到 UNIX 哲学实质的人来说,UNIX 哲学只是熟悉概念的代名词,并不是什么新东西要学,可能会更少。但是 UNIX 哲学仍然是一个重要的思想。

シェルスクリプトを学ぶ人のための「新しいUNIX哲学入門」 〜 ソフトウェアツールという考え方

UNIX哲学的应用范围随着计算机技术和软件技术的发展而扩大。 UNIX 哲学随着 UNIX 的发展而发展,它允许改变。使用 UNIX 旧时代没有的工具、语言和命令是 UNIX 哲学理念。继续按照 UNIX 时代的方式做事并不是 UNIX 的哲学。 UNIX 的创始人 Ken Thompson 目前正在研究 Go 语言这一事实​​清楚地表明了这一点。

比较旧 Unix 哲学和“新 Unix 哲学”

对于那些想快速了解差异而没有详细说明的人,我已经简要总结了差异。变更原因请参考评论后半部分。

麦克罗伊的 UNIX 哲学

 (i)
-個々のプログラムは1つのことをしっかりやるようにせよ。新しい仕事をするなら、
+個々のプログラムは与えられた役割をしっかりこなすようにせよ。異なる役割の仕事をするなら、
 新しい機能を追加して古いプログラムを複雑にするのではなく、まったく新しいプログラムを作れ。

 (ii)
 すべてのプログラムの出力は、他の未知のプログラムの入力になるのだということを予想せよ。
 余分な情報で出力をごちゃごちゃにしてはならない。
-縦方向の並びを厳密に揃えたり、バイナリ入力形式を使ったりすることを避けよ。
+入出力には行指向の単純なテキスト形式、または標準的なデータ形式を使用せよ。
 対話的な入力にこだわるな。

 (iii)
 オペレーティングシステムであっても、
-ソフトウェアは早く(できれば数週間以内に)試せるように設計、構築せよ。
+ソフトウェアは素早く(できれば数週間単位で)試せる仕組みを構築せよ。
+要件定義、設計、開発、構築、テスト、試用など全行程を何度も繰り返せ。
 まずい部分は捨てて作り直すことを躊躇するな。

 (iv)
 技能の低い者に手伝ってもらうくらいなら、
-プログラミングの仕事を明確にするためにツールを使え。
+ソフトウェア開発の仕事を楽にするためにツールを使い、可能な限り自動化せよ。
 ツールを作るために遠回りしなければならない場合でも、
 使ったあとで一部のツールを捨てることになることがわかっている場合でも、ツールを使え。

Gunkers UNIX 哲学 - 9 条原则

旧学说 新学说
小就是美 简单是最好的
一个节目,一件事
让它起作用
程序真正应该做什么
让它起作用
尽快制作原型 创建一个允许您尽快制作原型的系统
便携性胜过效率 实现满足要求的质量和高生产率
ASCII 平面文件中的数字数据
节省
文件有标准格式吗?
使用简单的基于文本的格式
利用软件杠杆 使用更多软件提高工作效率
通过使用 shell 脚本
提高杠杆率和便携性
简单地组合命令
利用 shell 脚本
避免过度交互的界面 用于自动处理的非交互式命令
有接口
过滤所有程序 处理数据的程序应该是
无论是过滤器

Gunkers 的 Unix 哲学 - 10 条优先原则

前准学说 新准主义
根据您的喜好自定义您的环境
允许调整
程序员的环境和工具应该是可定制的
让它更高
操作系统的
使内核更小更轻
保持内核小和用户态程序
丰富
使用小写并保持简短 长名称用于可读性,短名称用于
想玩的时候用
保护森林 保护森林和环境,减少电力消耗和二氧化碳排放
沉默是金 应该输出的数据格式一致
输出
并行思考 创建执行并行处理的程序
部分之和大于整体 通过组合多个程序创建一个大型系统
争取 90% 的解决方案 专注于你真正需要做的事情并决定不做的事情
越少越好 快速原型而不是放慢速度
制作
分层思考 为您的目的使用最好的数据结构

Raymond 的 UNIX 哲学

笔记描述没有变化

原则 解释
模块化原理 创建与干净界面相结合的简单部件
清晰原则 清楚而不是聪明
组装件原理 与其他程序相结合
分离原理 将政策与机制分开。从发动机
分离接口
简单原则 设计要简单。添加复杂的部分是
仅在绝对必要时限制
节俭原则 除非明确证明没有其他
不要写大程序
透明原则 力求清晰,使调试和调查更容易
设计
稳定原则 稳定来自透明和简单
表现力原则 巩固数据知识并简化程序逻辑
让它稳定
最小意外原则 设计界面以最大程度地减少意外
沉默原则 如果没有什么出乎意料的事情必须说,
程序什么也没说
恢复原理 如果您必须提出错误,请尽早
大错特错
经济原理 程序员的时间很昂贵。程序员时间比机器时间
省时间
产生原理 避免手动破解。如果可能的话,用于编写程序
写一个程序
优化原理 抛光前的原型。在优化原型之前
让它移动
多样性原则 不要相信“唯一正确的方式”的所有主张
可扩展性原则 未来会比预期来得更快。着眼于未来的设计

基础知识

UNIX 哲学不仅限于软件工具

软件工具是使用软件工具组合的思想,但 UNIX 哲学并不局限于软件工具。这是一个可以应用于任何软件开发的概念。正如 npm 创始人 Isaac Z. Schlueter 所说,Unix 哲学和 Node.js' 说:

很多时候,人们被 Unix 哲学的错误方面迷住了,只见树木不见森林。关于文件描述符、管道、套接字或信号。

Unix 哲学是对软件开发的展望,而不是任何特定的软件技术开发。

翻译

人们常常陷入 Unix 哲学的错误一面,只见树木不见森林。 Unix 哲学并不特定于任何特定的实现或任何 Unix 操作系统或程序。它与文件描述符、管道、套接字、信号等无关。这样的说法就像是在说“如果你不会说巴利语,你就不是佛教徒”。

Unix 哲学是软件开发的观点,而不是软件中的特定技术开发。这是一个可以达到的理想,也许具有讽刺意味的是,这个理想有时会要求放弃理想主义,转而追求实用性。

翻译至今

如果您搜索“Unix 哲学”+ 特定语言之类的内容,您会发现那些了解 UNIX 哲学的人在 UNIX 之外的各个领域的应用程序。

UNIX 哲学似乎与 UNIX 和 shell 环境联系在一起的原因仅仅是 UNIX 哲学诞生于 UNIX,而 shell 环境是当时使用计算机的唯一方式。在 UNIX 诞生的时候,人们坐在电脑前交互地使用它,现在已经很普遍了,但还不普遍,C 语言还没有诞生,软件和库也不多。在这样的时代,使用 UNIX 和 shell 环境的解释不可避免地会通过具体的例子变得容易理解。在没有人使用 GUI 的时候,以 GUI 环境为例来解释 UNIX 哲学并不能传达信息,对吧?

UNIX 哲学可以而且确实适用于其他环境和语言。然而,UNIX 哲学在开发 UNIX 时作为一种思考软件工具的方式有着悠久的历史。未来可能会有比 shell 更好的环境来组合使用不同的软件工具,但至少现在,UNIX 哲学并不局限于 shell 环境,而是 shell 环境和 shell 可以说脚本命令的组合是实践 UNIX 哲学的最合适的环境。

“使用工具”和“制作工具”的区别

UNIX 哲学有两个*。 “使用工具的*”和“制造工具的*”。我所说的工具是指所有软件。用别人做的软件好,自己做软件也好。 “使用工具”和“制作工具”是同一枚硬币的两个方面。不做工具,就不能用工具,用工具的时候不考虑,就做不出好工具。任何一个单独都行不通。 UNIX 哲学是“使用工具”和“构建工具”的结合。

“使用工具”的一个易于理解的示例是从 shell 执行命令,但编写 shell 脚本也是使用工具的行为。更准确地说,写一个shell脚本,就是提前写一个使用工具的过程手册。另一方面,“制作工具”意味着以传统的 UNIX 方式用 C 语言创建命令。当然,现在您可以使用 C 以外的任何语言。你可能认为没有创建工具,现有的命令就足够了,但由于现有的命令都是通用命令,有很多东西是不够的。当时创建自己的工具,而不是努力使用现有命令是需要的。 “编写 shell 脚本”和“编写 C 语言代码”分别对应于“使用工具”和“制作工具”,但这两个实际上是不同的动作。然而,正如稍后将讨论的,两者之间的界线是模棱两可的。现在,把这一刻想象成另一种行为。

更详细一点,“使用工具”是“使用多种工具”结合它的意思是“使用”。组合工具不仅仅是将命令连接在一起。例如,从上到下依次执行一系列命令是组合使用它们的一种方式。如果您只是从 shell 运行一个命令,那么您只需使用一个工具即可完成工作。如果仅使用一种工具无法完成工作,则将使用多种工具。当您想要执行将多个工具组合到一个过程中并一遍又一遍地重复相同事情的一系列任务时,您可以预先编写一个 shell 脚本。工作本身与在 shell 上手动执行命令相同,因此编写 shell 脚本与“使用工具”同义。

把“制作工具”说得更详细一点,“合并零件意思是制作工具。出现了一个新术语“部件”,但部件包括面向对象语言中的函数、库和类库。工具和组件(通常制作)可能看起来相似,因为它们是可重用的代码,但区别在于它们的构造方式。工具由多个部分组成。这些部分由更小的部分组成。甚至更小的零件,这些零件层次结构它包括例如,数字闹钟由 LSI、LED、开关、电池盒、蜂鸣器等小部件组成。每个部件由更小的电子元件和金属部件组成。这与用 C 语言编写的命令是通过组合函数组成的结构相同,这些函数在内部调用较小的函数。

以分层结构创建零件的原因是,直接使用太小的零件来制作更大的零件会很复杂。通过使部件尺寸适中并允许它们在不知道部件内容和实现细节的情况下使用,我们可以避免过于复杂。这种思维方式称为抽象。工具的可靠性是通过使用高可靠性的零件来保证的。当然,零件的可靠性也得到了更小零件的可靠性的保证。这种可靠性抵押品的层次结构使我们能够构建大型工具。另一方面,“工具使用”的 shell 脚本基本上是扁平结构它包括因为如果你想要一个扁平的结构,你想知道你作为一个整体在做什么。但是,对于扁平结构,保证可靠性的唯一方法是对整个组合进行测试,因此很难创建大型 shell 脚本。在编写较大的 shell 脚本时,我建议使用函数来提供某种程度的抽象和结构化。

シェルスクリプトを学ぶ人のための「新しいUNIX哲学入門」 〜 ソフトウェアツールという考え方

使用扁平结构来了解整体要做什么,使用层次结构来忽略每个步骤的细节。这些结构上的差异使 shell 脚本更适合执行简单的任务,而其他语言更适合构建更大更复杂的脚本。

这样一来,“使用工具”和“制作工具”是完全不同的东西,但我之所以说这行模棱两可,是因为你可以用 shell 脚本创建工具,你可以用任何语言创建工具。因为你可以也使用我经常利用 shell 是一种可以安装在任何环境中的脚本语言这一事实​​,并创建可以在 shell 脚本中普遍使用的工具。但是,使用 shell 脚本中常见的样式创建大而复杂的脚本是很困难的,因此我们使用通用语言技术。例如,为了确保可移植性,我们合并了包装器以吸收每个环境中的兼容性问题。同样,这是一种逃避实现细节的抽象技术。相反,命令也可以用通用语言调用。还有一些库和框架使使用脚本语言执行命令变得容易。 “使用工具”和“制作工具”的区别,不是由使用的语言决定的,而是由思维方式的不同决定的。不管你用什么语言,扁平结构适合使用工具,层次结构适合创建工具。并且根据软件的类型,这两者可能会混合使用。我想用详细的例子来解释这些差异,但是我可以看到这篇文章的数量会增加一倍,所以非常抱歉,我省略了。

暂时我在这里想说的是,“使用工具”和“制作工具”是两个不同的东西。要了解 UNIX 哲学,您需要了解两者关于它。如果你不知道如何使用它,你就无法构建一个好的工具,如果你不构建一个工具,你最终会用糟糕的 UNIX 命令编写生涩的 shell 脚本。 “使用工具”和“构建工具”都是 UNIX 哲学。顺便说一句,UNIX 哲学的起源之一,“软件礼仪“ (原来的软件工具(1976) P.J. Kernighan, Brian W. Plauger) 是一本为那些“制造工具”以及如何制造工具的人写的书(大鼠它是用一种不寻常的语言写成的,叫做这本书讨论了管道,这是一种“使用工具”的技术,但几乎不讨论 shell 脚本。原因之一是在 Bourne shell 之前的 Thompson shell 时代,几乎没有脚本语言能力,没有什么可写的,希望你能找到它。

我经常听到有人说停止使用 shell 脚本并使用 Python,但 shell 脚本和 Python 是结合使用的,而不是使用任何一个。与其编写 1000 行 Python 脚本,不如编写 200 行 Python 脚本和 200 行 shell 脚本,Oil shell,一个旨在继承 bash 的新 shell。在说话.从“使用工具(编写shell脚本)”和“创建工具(用C语言、Python等编写程序)”的思路不同,我认为可以理解shell脚本和其他语言。想想。这就是为什么无论有多少“工具构建”语言,“工具使用”shell 脚本都不会消失。

自 UNIX 诞生以来,C 语言和 shell 脚本就已经存在。这两种语言不是可以根据自己的喜好选择的两种语言,而是因为两者都需要。创建工具的 C 语言可以被其他编译或脚本语言替代,但使用工具的 shell 脚本的唯一替代方法是 shell 脚本(具有不同的语法,例如 fish)。有一些库和框架尝试使用脚本语言来做类似于 shell 脚本的事情,但是它们越是易于使用,它们就越会成为具有 shell 脚本式语法或 shell 脚本的薄包装器的 DSL。最好从一开始就使用 shell 脚本,而不是学习如何使用类似 shell 脚本的库。

“UNIX 哲学 - 做与不做”和不断变化的工具

由于许多人误解了 UNIX 哲学(软件工具),我们整理了一份您不应该犯的常见错误列表。

  • 不要挂断在 UNIX 上。
    • 它只是 UNIX 哲学诞生的一种操作系统。
  • 不要沉迷于 UNIX 命令。
    • 这只是 UNIX 开发早期的一小部分命令。
  • 不要沉迷于 POSIX 命令。
    • 它是在每个 UNIX 上兼容的 UNIX 命令的子集。
  • 不要坚持创建自己的命令。
    • 查找可用命令。世界上有许多命令。
  • 不要挂断现有的命令。
    • 如果找不到可以使用的命令,请创建自己的命令。
  • 不要拘泥于C语言。
    • 它只是另一种创建命令的语言。在正确的地方选择正确的语言。
  • 不要挂在 Bourne shell 上。
    • 它只是实践 UNIX 哲学的众多 shell 之一。
  • 不要坚持标准安装。
    • 任何语言和任何命令都可以通过简单的安装工作。

这很简单。UNX 哲学不是扼杀 UNIX 未来发展的哲学.坚持旧的 UNIX 命令会否定 UNIX 未来可能出现的新命令。自从原始 UNIX 的开发结束以来,UNIX 命令的数量并没有增加,但在另一个未来,可能会诞生新的 UNIX 命令。 Unix 命令不能充分利用 Unix,因此需要新的命令。它不应该被禁止。 UNIX 哲学对创建新工具没有任何限制。我只是在陈述以更好的方式制作新工具的想法。

与 UNIX 哲学一样,POSIX 和 POSIX 命令经常被误解。 UNIX 不是根据 POSIX 制作的操作系统。 UNIX 诞生于 1969 年,POSIX 诞生于 1988 年。创建 POSIX 是因为它与原始 UNIX 不同,许多原始 UNIX 诞生了,并且很难创建高度可移植(在任何 UNIX 上运行)的应用程序。因此,首先创建了许多 UNIX 风格,UNIX 供应商采用 POSIX 作为 UNIX 的一部分。此外,POSIX 并未标准化操作系统所需的所有功能。例如,包管理系统超出了 POSIX 标准化的范围,并且对于每个操作系统都不同。

并且 POSIX 并不禁止实现扩展。相反,该标准的制定并不妨碍扩展的实施。 POSIX 命令只是 POSIX 认为具有高度可移植性的命令和选项的列表,实现(扩展)其他命令和选项并不违反 POSIX。 POSIX 与 UNIX 哲学一样,对创建新工具没有任何限制。例如bash 是一个符合 POSIX shell 标准并具有 POSIX 允许实现的扩展的 shell,而不是具有不符合 POSIX 特性的 shell。这才是正确的解释。

可在任何地方运行的软件不仅限于标准的 OS shell 和命令不要忽视这样一个事实许多语言和命令只需安装它们即可工作。 POSIX 最初是为了“安装和工作”而创建的。这就是 C 编译器(c99 命令)被标准化的原因。C 编译器标准化的事实并不意味着 C 是 POSIX 允许的唯一语言。这意味着只要你有一个 C 编译器,你就可以轻松地编译任何语言或命令并使用它。.与过去不同,安装工作不需要自己构建,只需从包中添加即可。在 UNIX 开发的早期,在 AT&T 之外的各个地方创建了很多软件并使其有用,那么锁定现代软件的使用有什么意义呢?我正是这个意思。

只使用 UNIX 和 POSIX 命令的想法与 UNIX 哲学和 POSIX 策略无关,或者说相反。如果你真正研究它,你可以发现它。 UNIX 哲学和 POSIX 标准都没有规定您应该只使用 UNIX 命令或只使用 POSIX 命令。因此,使用所有语言、所有命令、所有中间件和所有软件并不违背 UNIX 哲学或 POSIX,而是应该用于推进软件技术。

了解当今 UNIX 哲学家的想法

了解 UNIX 的创始人将要做什么以及他们现在正在做什么也有助于我们理解 UNIX 哲学。 UNIX 的创始人正在开发一种名为 Plan 9 的新操作系统。由于政治或实际原因,该项目几乎完成(还是有一些动静),Plan 9 是从头开始设计的,不是基于 UNIX,而且 shell 也有遥控壳开发了一个更简单的外壳。如果计划 9 的开发成功,那么 UNIX 世界的工具可能会大不相同。

UNIX 创始人 Ken Thompson 和 Rob Pike 现在在 Google围棋语言(可以肯定的是,我没有开发 Iyaiya Go,因为谷歌在恐吓我)。 Go 非常适合云和网络服务,也可用于创建命令行工具。文档或者常问问题,可以看到 Go 是一门并发性强、多核并行性强的语言,并且可以充分利用联网机器,让程序员的工作效率更高。换句话说,它是一种填补 UNIX 所没有或缺乏的东西的语言。 Go 是必要的,因为 shell 脚本和 UNIX 命令无法发挥多核性能并且无法很好地处理网络。

遵循 UNIX 理念的工具不断变化。 Go 是新时代 UNIX 哲学的一种新工具(语言)。

用法 Unix时代 在互联网的曙光之后 现代(云后)
系统描述语言 C语言 C语言 C 语言,铁锈
命令控制语言 伯恩,克什 伯恩,rc,破折号,ksh,bash,zsh 破折号,bash,ksh,zsh,鱼
命令开发语言 C语言 C 语言、C++、Perl、Python C 语言、Python、Rust、
网络系统开发语言 - Perl、Python、PHP、红宝石 蟒蛇,PHP,红宝石,
数据处理语言 AWK AWK、Perl、Python、SQL Python、SQL、R

笔记上述分类是基于教条主义和偏见的图像。我接受反对。我省略了某些区域。

Go 有一些在过去的 UNIX 时代没有的特性。例如,go 命令使用子命令。标准选项解析模块flag 支持长选项。它有一种语法,可以提高多核性能。兼容网络功能。有用于使用 RDBMS 的标准模块。它进行静态构建并生成较大的二进制文件以获得更好的兼容性。这些在 Unix 时代很不方便,Ken Thompson 和其他遵循 Unix 哲学的人对其进行了改进。如果你了解 UNIX 哲学,你应该积极使用 Go。当然,您可以使用任何其他语言。我认为 Go 是用于应用程序开发的,Rust 将是 C 的更好替代品。

开发 Go 的原因之一是可以轻松利用多核性能。前一阵子,自动并行化(管道部分)shell脚本的神秘技术成为了一个热门话题,但说白了就是没用。我想我了解一般机制,但在大多数情况下,由于开销很大,它相当慢,而且“手动编写自动并行化所需的定义”只是一件麻烦事。通过xargs -P 或后台进程执行 (&) 进行的并行化是唯一可以有效利用多核性能的 shell 脚本。并行化流水线的想法正在迅速达到极限,除了精心设计的情况外,无法利用多核性能。这就是为什么 Ken Thompson 和其他人开发了一种称为 Go 的新语言的原因。

最了解 UNIX 哲学的人生活在现实中,并看到了未来。固守 UNIX 命令的人,不了解 UNIX 哲学的精髓,停留在过去。是。

如何找到好的工具以及工具的发展政策和未来潜力

Shell 脚本可以快速完成工作。这并不是因为shell脚本优越,而是因为提前准备了方便的工具(命令)。 Shell 脚本非常擅长将命令链接在一起,但生产力不是 Shell 脚本的功劳,而是工具的功劳。工具以多种语言制作。

与所有小工具都随 UNIX 一起提供的日子不同,我们现在拥有很多小工具。但是,现在每个人都可以轻松开发工具,但并非所有工具都是好工具。有一些好的也有一些不好的。好的工具带来巨大的价值,但如果你选择了不好的工具,你就会被工具所左右。

找到好的工具的关键是理解 UNIX 的思维哲学。我相信这篇文章会帮助你理解 UNIX 哲学。如果 UNIX 哲学对您仍然没有意义,请选择一个很多人已经使用了很长时间的工具。很多人使用的工具都在OS包管理系统中注册,评论文章很多,GitHub star也很多。当然,如果您无法自己决定,这是最后的手段。就算是在包管理系统注册了,也有可能因为没有维护而濒临被删除,而且就算文章多,也可能不会再用了,GitHubstars也有话题度。爆发式增长。最终你必须使用它并自己评估它。即使只是使用工具,您也需要慢慢了解 UNIX 哲学。

还应注意项目性质的差异。例如,GNU 项目强调稳定性和兼容性,因此您可以长时间继续使用它,而不必担心添加新功能或改进它。反之,在积极添加新功能并对其进行改进的项目中,可能无法经常维护兼容性,可能难以应对版本升级。商业和专有软件使用起来可能很昂贵,或者在合同到期时可能变得无法使用。

另一个考虑因素是该工具的通用性。确定某物是否通用的诀窍是考虑它是否可以在其他地方使用或与其他工具结合使用。例如,当您离开当前项目或搬到另一家公司时,您会在其他地方使用这些工具吗?相反,是否有可能来自其他地方的人正在使用相同的工具?您可以将该工具与完全由其他人制造的工具结合使用吗?如果您对这些问题的回答是肯定的,那么您就有了一个多功能工具。通用性低的工具再好,寿命也会很短。但是,这并不意味着您不能使用通用性低的工具。至少,只要您继续当前的工作,这将是值得的。

重要的是选择适合您项目的那一款,而不是哪一款更好或更差。无论如何,你不应该做的是不幸选择了一个不适合你的工具,然后出于厌恶而停止使用其他人制作的工具。并不是所有的工具都不好,只是你选择的工具不好。工具必须逐个工具进行评级。如果你停止使用工具,你能用自己的力量做什么将是你的极限。你一个人做不了太多事情。如果你自己做所有事情,无论你有多少时间,这都不够。

来自“新 Unix 哲学”的三大修复

流行的 Unix 哲学说“做一件事”和“使用文本格式”,但我对 Unix 哲学的解释没有这样的原则。我不是说完全错误,而是因为没有完全把握本质,所以存在矛盾。因此,我正在纠正它们,但我讨厌人们说,“这就是 UNIX 哲学所说的。你不了解 UNIX 哲学。”,了解 UNIX 哲学后特意修改我想澄清原因。

组合小程序可能既困难又复杂

工具(命令)是否简单和如何使用工具(自己写的shell脚本)简单,完全是两码事。组合了许多命令的 Shell 脚本往往很复杂。进行同样的流程时,如果使用的工具小而简单,那么使用工具的代码就会大而复杂。例如,齿轮是一种简单的工具,但组合了许多齿轮的 karakuri 人偶是复杂的。总体而言,较小的工具并不总是最好的。为简单起见,请减少组合工具的数量。例如,使用sort -u 比组合sortuniq 命令更简单。

小工具为“工具制造者”高兴是。 UNIX 哲学是 UNIX 开发的哲学,所以“工具制造者”的逻辑是 UNIX 命令应该简单。使用小工具的组合是一种专业而困难的行为。由于 UNIX 是面向程序员的操作系统,因此能够组合困难的工具是很自然的。如果你想简单地编写一个大型的 shell 脚本,你需要一些技巧。微服务的一个众所周知的缺点是,即使小服务本身很简单,但它们组合起来也会变得复杂。小程序没有快速或高效的优势.

即使您想使用工具使事情变得更容易,但如果您需要培训和教育来掌握工具,那就是本末倒置。大型复杂的 shell 脚本也需要测试。使用经过测试的大型程序编写简短的 shell 脚本更加可靠和高效。

面对所有这些问题,为什么“小程序”的想法会成为流行的 UNIX 哲学?我在 1974 年关于 UNIX 的第一篇论文中发现了 UNIX 和小程序之间的联系。UNIX 分时系统在Ken Thompson 在其中指出,UNIX 设计中的下一个考虑因素是:

  1. 一个交互式系统,可以轻松编写、测试和运行程序
  2. 由系统和软件大小限制驱动的经济而优雅的设计
  3. 可以自己维护UNIX

    这2,“由大小限制驱动的经济和优雅的设计”与小程序有关。 “经济”似乎意味着它不消耗系统资源,但在谈到软件设计问题时,我对使用“经济”一词感到不舒服。 。原因是 1978 年的论文UNIX 分时系统:正向从 写于 中的 Small Is Beautiful 和经济学家舒马赫之间的联系中可以清楚地看出。显然是 1973 年的经济学家恩斯特·弗里德里希·舒马赫由...出版小就是美:研究经济学好像人很重要1973 年,在第一次石油危机期间,“经济”一词成为人们关注的焦点。

    换句话说,我认为小就是美的想法只是被应用到了当时的流行语上,从一开始就不是 UNIX 哲学的恰当表达。当时的计算机性能很低,虽然不是 UNIX 哲学的精髓,但它必须是一个小程序。从那里开始,编写小程序是 Unix 哲学的想法传播开来。现在小程序没有任何好处。由 Ken Thompson 设计的 Go 不会生成小程序。我认为大小限制确实会导致更精简、更简单和更优雅的设计,但我认为这与 UNIX 哲学没有直接关系。

    首先UNIX 的创始人之一麦克罗伊在他的 UNIX 哲学中说过,“一个程序应该做一件事”,而不是“让它成为一个小程序”。. Gunkers UNIX 哲学告诉您编写小程序。做一件事和把它变成一个小程序是完全不同的事情。

    那么究竟什么是“一件事”呢?有许多 unix 命令不做一件事.例如,sed 命令执行多项操作,例如追加 (a)、替换 (s) 和删除 (d) 字符串。 rm 命令不能正常删除目录,但是使用-r 选项,它会删除包括目录在内的所有文件。更新修改日期的touch 命令将在文件不存在的情况下创建该文件而不会出错。 ls 命令也进行排序,find 命令做了很多工作。甚至test ([ ]) 命令也会执行多项操作,例如文件存在检查以及数字和字符串比较。如果您不知道“一件事”是什么意思,并且您正在考虑错误的事情来做好“一件事”,那么您只是在浪费时间。

    所以我正在纠正这个词,这实际上是没有意义的。然而,这并不意味着你应该漫无目的地做大事。就是要摒弃“一件事”这种模糊的、没人遵守的标准和“小程序”这种没有好处的标准。 UNIX 哲学的核心是模块化和可组合性。只要能实现,程序就可以大。如果你想让程序保持简单,模块化程序的内部就足够了。我们现在应该怎么做才能让使用该程序的人使用它变得简单?应该被考虑。

    我说要明确解决这个问题的原因是因为有人滥用它。现在系统因其实用性而被广泛采用,但最初因与 UNIX 哲学相悖而引起争议。我也觉得 Systemd 有点太大了,还可以做得更简单些。这是错误的。” UNIX 本身具有不做“一件事”的有用命令,所以这不是借口。如果“一件事”是正确的做法,那么在不依赖 UNIX 哲学权威的情况下这样做是有好处的。 Systemd 最终变得普遍,因为“一件事”没有优点。

    一个简单的小工具易于使用,但这并不意味着您使用该工具创建的内容会很简单。使用简单的工具可能很复杂这就是你需要知道的。仅使用 shell 脚本创建大型软件需要一定的技能。我们不希望 shell 脚本很大,所以我们需要使工具(命令)变大以保持工具(shell 脚本)很小。顺便说一句,简单和容易是具有不同含义的词。我不会在本文中详细介绍,但这是一个重要的想法。简单的需要” 以及更多信息。

    禁止基于二进制的数据格式是不切实际的

    作为一般原则喜欢文本格式不改变。但与 1980 年代甚至不存在 zip 和 gif 格式不同的是,现在有许多标准化和事实上的标准格式,即使它们是基于二进制的。澄清您可以使用它们的二进制形式以及文本形式。事实上,这些二进制格式被广泛使用、高度可移植,并且具有种类繁多的命令和库。

    人们常说文本格式易于人类读写,但实际上只是因为有文本编辑器使人类易于阅读和编写文本格式。这并不容易,因为它是一种文本格式,只是有许多工具与文本格式兼容。使用图形软件可以轻松读取和写入标准图像格式。如果你有合适的工具来处理它,即使是二进制格式也很容易读写。在过去,您必须专门为软件创建自己的二进制格式,但现在情况正好相反,有一种软件支持的标准二进制格式。

    您可能需要文本格式何时合适以及二进制格式何时合适的标准。例如,基于文本的格式适用于人们(不仅仅是计算机)想要使用文本编辑器读写的数据。图像数据、视频数据、音频数据(不能用乐谱表示)等不需要格式化为文本,因为您不想使用文本编辑器对其进行读写。对于像 Markdown 这样的简单文档,文本格式就可以了。富文本格式如果是这样,人类可能仍然希望直接使用文本编辑器进行读写。但是当涉及到像 MS Word 这样的东西时,即使它是纯文本格式 (XML),人类也不想在文本编辑器中读写。没有人能够理解 XML 标记的含义并在脑海中想象结果。

    乍一看,数据库之类的东西似乎应该是文本格式。例如基于文本的记录文件使用格式文件处理数据库GNU 实用程序有一个项目叫简单的例子如果是这样,您当然可以使用文本编辑器进行读写,完整规格在不知道和犯错误的情况下手动重写会有点棘手。 Recfile 是文本文件,但很难使用常见的 UNIX 命令正确编辑。一个小错误很容易破坏数据库。毕竟,如果你想要方便作为一个工具,你需要一个专用于 Recfiles 的命令。如果您需要专门的读写命令,则没有理由选择文本格式。它是您想要在数据库中以文本形式出现的“数据”,而不是“数据库文件”。总之,只要你有文本格式的导入导出功能,数据库文件就可以是二进制格式。事实上,在锁定、索引和可靠性方面,二进制数据库文件更好。

    McIlroy 的 UNIX 哲学和 Gunkers 的 UNIX 哲学都指的是文本格式和二进制格式,但它们非常不同。在 McIlroy 的 UNIX 哲学中,程序输入/输出基于文本的界面Gunkers说要使用基于文本的文件这是它说使用的地方。 McIlroy 的 Unix Philosophy 谈到程序可组合性,Gunkers 谈到数据可移植性,所以这是一个完全不同的故事。最初,UNIX 是一个不可移植的操作系统,可移植性是事后才想到的。因此,可移植性对于软件很重要,可移植性与 UNIX 哲学无关而已。即使您使用基于二进制的文件,如果输入/输出是基于文本的,与其他程序链接的便利性也不会改变。 SQLite 是一个使用基于二进制文件的数据库软件,但它的输入和输出是基于文本的并且完全可配置的。

    但是,shell 脚本和 UNIX 命令处理的格式应该基于文本格式。因为 shell 和 unix 命令有时不处理二进制文件(确切地说是\0)。实际上,这只是 shell 脚本和 unix 命令的一个缺点。一个更重要的问题是文本格式没有严格定义。例如,如果数据包含换行符怎么办?一个快速的解决方法是转义这些字符。例如油壳在项目中 ”QSN:一种熟悉的字符串交换格式'' 建议作为字符文字。但是当前的 shell 和 UNIX 命令不能正确支持 QSN 之类的东西。如果一开始就很好地定义了转义规则,那就太好了,但不幸的是,UNIX 命令的开发没有定义这样的规则。这导致了 shell 脚本的陷阱。这是一个需要解决的 shell 脚本问题,但故事范围太窄,无法在此介绍。

    这个话题没完没了,但暂时我要明确一点,虽然本文更喜欢基于文本的格式,但标准二进制格式也是可以接受的。

    即使使用高性能硬件也能实现高便携性和长寿命

    “可移植性高于效率”,我认为 Gunkers 可能是唯一这样说的人,这是一种可能被误解为“更高效(性能)的系统更不便携”的学说。。这是一个完全依赖于当时的历史背景,不适用于现代的学说,所以我会更正一下。

    我之所以说要强调可移植性,并不是“因为一个高效的系统的可移植性低”,而是“因为使用特殊的硬件功能提高了效率,可移植性就会降低”。是否高效不是争论的焦点,而“使用特殊的硬件功能”才是争论的焦点。但即使这意味着它,它也不适用于现代。原因是不同的抽象层使我们不太关心实现细节,即我们使用什么样的硬件。抽象层具体是介于两者之间的软件层,称为驱动程序、库(如OpenGL)、语言、包装器等,作为操作系统的一部分,通常用于解决兼容性等问题。目前操作系统几乎所有的高可移植性和兼容性都是通过这个抽象层来实现的。

    Gunkers(属于 X Window System 的开发团队)关心的性能主要(仅?)与图形加速器有关。到了 1980 年代,甚至连 OpenGL(1992 年出生)都还没有出现,为了实现高绘图性能,硬件的特殊功能直接从操作系统不支持的接口中使用,因此便携性低。这就是“可移植性高于效率”的真理。图形加速器或 GPU 领域在今天仍然在发生比较大的变化,但尤其是从 1980 年代到 2000 年代,从简单的 2D 图形功能如画线和矩形到多边形和纹理映射,这是一个 3D 图形功能如因为在很短的时间内得到了很大的发展。操作系统跟不上日新月异的变化,图形操作系统的标准接口还没有建立起来。尤其是在 1980 年代,在 OpenGL 诞生之前。

    现在操作系统已经成熟,大部分硬件已经被抽象出来,可移植性超过效率已经成为过去。抽象意味着您不必担心具体的实现。换句话说”如果安装了高性能硬件,它将利用该性能。“关于它。再次,如果没有一种称为抽象层的机制,就不可能发挥硬件的性能。.这是因为无论如何安装高性能硬件,都只能使用适用于任何硬件的常用功能。这样一层软件,可以说是一种抽出计算机性能的机制。

    抽象的概念不仅仅与硬件有关。语言、库和包装器吸收了 Windows 和 Linux 之间的差异,以及 MySQL 和 PostgreSQL 等数据库之间的差异,并吸收了各种环境中的差异,并且可以使用单个源代码原样使用。该应用程序现在可以在另一个环境中运行。如果没有这样的东西,你会过度依赖特定的软件或技术,最终会被供应商锁定。如果现有软件没有完全吸收环境差异,最好自己吸收差异。例如,当在 shell 脚本中从 Internet 检索文件时,通过创建一个名为 get 函数的包装器,该函数与wget 命令和curl 命令一起使用,增加了操作环境,shell 脚本的可移植性你可以改善你的生活。

    尽管抽象层是一种具有很大优势的机制,但它在 1980 年代未被大量使用的原因之一是包含包装器导致的速度变慢。那个时候,是一个我们担心在中间插入这样一层软件会降低效率的时代。在当今计算机性能有所提高的世界中,没有必要取得如此大的进步。从这个意义上说,如果您说“可移植性比效率(减少)(通过包装器)更重要”,它仍然适用。如果没有抽象,您将直接使用具体的硬件和操作系统接口(API 和命令),这将大大降低可移植性。

    软件工具的哲学

    以下内容基于“McIlroy's Unix Philosophy”并进行了修改以提供更恰当的解释。 McIlroy 是 AT&T 的 UNIX 创始成员之一,因此它是最接近 UNIX 哲学原著的。虽然是最古老的 UNIX 哲学,但它是一种抽象的表达方式,不太可能受到时代潮流的影响,因此没有与原意大相径庭的修改程度。

    i. 程序必须很好地履行其指定的角色。

    (i) 每个程序都应该很好地履行其指定的角色。如果您想做不同的工作,请构建一个全新的程序,而不是通过添加新功能使旧程序复杂化。

    原来的

    (i) 让每个程序做好一件事。如果您想从事新工作,请构建一个全新的程序,而不是用新功能使旧程序复杂化。

    变更原因及说明

    正如我已经写过的,只要没有明确的标准,坚持一件事是没有意义的。很少有命令实际上做一件事,所以说“给定角色”更合适。角色由名称给出。 sed 是一个流编辑器,所以他的角色是编辑流。 awk 是给定 awk 编程语言执行的角色。使用子命令与 UNIX 理念一致。例如,git 是一个角色,用于使用 git 处理版本控制子命令。一个子命令按照它的名字做它应该做的事情。

    如果它所做的工作与其名称所赋予的角色不同,那么您应该编写一个全新的程序。比如yes命令是重复输出y的命令,而yes n是一直嘀咕n的废话命令。这是一个我必须创建一个新程序的示例,因为重复输出指定的字符串与名称 yes 给出的角色不同。 yes 这个命令可能确实做了“一件事”,但它是一个命名不当的命令,它做的不是它的“指定角色”。

    新功能应该添加到旧程序中,即使它可以作为一个单独的程序实现,如果它适合给定的角色。即使添加了新的功能,如果程序的内容被适当地抽象和结构化,源代码也可以保持简单。

    ii. 让它与其他程序一起工作

    (ii) 期望每个程序的输出都成为其他未知程序的输入。不要用额外的信息使输出混乱。使用简单的面向行的文本或标准数据格式进行输入和输出。不要沉迷于交互式输入。

    原来的

    (ii) 期望每个程序的输出都成为其他未知程序的输入。不要用额外的信息使输出混乱。避免严格的垂直对齐和二进制输入格式。不要沉迷于交互式输入。

    变更原因及说明

    与其他程序互操作性的真正要求是采用标准数据格式。如果一个程序以 PNG 格式输出数据,而另一个程序接受 PNG 格式的输入,则这些程序可以一起工作。在没有标准数据格式的时候,使用易于解释的简单文本格式是与其他程序链接的最佳方式,但现在二进制格式有很多标准化的数据格式,可以使用库来轻松处理此类数据格式.

    我认为严格对齐垂直对齐意味着不为美观而调整位置与空格数,但原因尚不清楚。 cut命令不会将连续的空格解释为一个,所以如果调整空格的个数就会有问题,有时候还可以。 awkread 可能是在“McIlroy 的 UNIX 哲学”被记录后诞生的,所以当时只有 cut,如果有正当理由,这将是一个问题。但是,有像ls 这样的命令可以调整位置和输出,所以我猜想避免在垂直方向上严格对齐是一个相当古老的故事,但很明显我不知道我在做什么,留下这个解释只会让我感到困惑,所以我把它删除了。

    请注意,这个想法与存储数据的文件格式无关。这仅限于流(标准输入/输出)。程序内部使用的文件格式与程序输入输出数据的格式无关。即使数据存储在专有的数据库文件中,如果有办法从程序中以简单的文本格式输出数据,它可以与另一个支持文本格式的程序链接。唯一重要的一点是让它与其他程序一起工作。

    iii. 快速重复原型

    (iii) 建立一个允许软件快速测试的系统(最好在几周内)。重复整个过程,包括需求定义、设计、开发、构建、测试和试用。不要犹豫,扔掉不好的部分,重新​​开始。

    原来的

    (iii) 设计和构建软件,以便它可以快速测试(如果可能的话,在几周内),即使它是一个操作系统。不要犹豫,扔掉不好的部分,重新​​开始。

    变更原因及说明

    我将其更改为“快速”,因为它需要重复多次,而不仅仅是“快速”。重复所有步骤。为了快速尝试,我们需要建立一个允许它的机制。单靠心理学是解决不了问题的。

    作为旁注,“不要犹豫,扔掉不好的部分并重新制作它”是一个好主意,但每次修改时都扔掉所有东西并重新制作它并不好。只有“坏部分”被丢弃,所以即使一个简单的修复重新创建整个文件,基本设计也是糟糕的。

    iv. 使用该工具,即使这意味着将其丢弃。

    (iv) 使用工具使软件开发工作变得更容易和尽可能自动化,而不是依靠技能较低的人来提供帮助。即使您必须花费很长的时间来制作工具,即使您知道使用后会丢弃一些工具,也要使用这些工具。

    原来的

    (iv) 使用工具来阐明编程任务,而不是让技能较低的人帮助您。即使您必须花费很长的时间来制作工具,即使您知道使用后会丢弃一些工具,也要使用这些工具。

    变更原因及说明

    软件开发不仅仅是编程。使用工具使您的工作更轻松是很自然的,但重要的是尽可能自动化以节省昂贵的人力时间。工具被更方便的工具取代,旧的工具有时会被扔掉。尽管如此,“即使你知道你会扔掉它们,也要使用这些工具。”

    对软件开发的需求越来越多,而我自己一个人完成这一切的时间非常紧迫。您必须使用各种工具来完成工作。 “帮助不太熟练的人”被工具所取代。不要手动做可以被工具代替的事情。

    软件工具主义

    以下内容基于“Gunker's Unix Philosophy”的教义,是旧解释的改进版。我将原始的 Gunkers 学说写为“旧”以供参考。 《UNIX 的思想》主要设定在 1980 年代和 1990 年代初,那时没有开源、没有互联网、没有 Linux,人们梦想着 UNIX 世界的到来。通俗易懂而具体的句子成了大敌,成了一个问题多多、容易引起误解的学说。因此,对其进行了全面修改和解释。

    Gunkers 是一家名为 DEC(现已不存在)的公司的员工,该公司销售用于 UNIX 开发的小型计算机(PDP 系列)。我不认为 Gunkers 和 UNIX 创始人之间有直接联系,但是 DEC 在 1980 年代通过为他们的计算机开发自己的基于 BSD Unix 的 UNIX 参与其中。 《Gunkers 的 UNIX 哲学》总结了 Gunkers 通过 UNIX 开发所理解的 UNIX 哲学。

    也许,但与其他 UNIX 哲学不同,Gunkers 的 UNIX 哲学不是给读者“这样做”的建议,而是说“这就是我们 DEC 的 UNIX 开发团队的想法。我们将尽最大努力实现这些目标!”传达我们想法的事情和决定我想是的。其依据是,旧的准教条 2:让操作系统的内核更小更轻是一个教条,我们(不是操作系统开发人员)即使被告知这样的事情也无济于事。因此,例如,“使用文本文件”的真正含义是声明“我们作为 UNIX 开发人员,将文本文件用于 OS 配置文件等等!“使它成为过滤器”可能是达到的理想状态, “开发 UNIX 以便它可以实现(尽管在当前的 UNIX 中是不可能的)!”简而言之,我认为最初的教义可能没有被创造为我们遵循的教义。教义的改变。

    Gunkers 的 UNIX 哲学发表于 1994 年(日文翻译:2001)。UNIX的思想” 被定义在2003年修订版《Linux 和 Unix 哲学”已出版,但尚未翻译成日文。顺便说一句,在《The idea of​​ UNIX》的日文翻译中,“tenets”被写成“theorem”。但是,我认为它在 UNIX 社区中并没有被广泛接受(DEC 除外?),所以我将其更改为“学说”的原意。在《UNIX的思想》的P9中,关于学说(定理)写成如下,

    前面的项目与 UNIX 开发人员的原则相当。它可能包含在其他 UNIX 书籍中,并且被广泛接受为 UNIX 的基石。如果您知道这些定理,您将被视为“UNIX 人”。

    这个学说本身是冈克斯发明的,无非是冈克斯的说法,没有证据证明它是真的。请不要认为这是理所当然的。

    信条 1:简单就是最好的

    • 老:小就是美

    当计算机功能不那么强大时,更小的可执行映像(= 更少的内存使用)也可以通过减少交换和分页来提高性能。但是,现在安装了大量的内存,减少程序的可执行映像的大小几乎没有什么好处,相反,甚至存在更大的内存和磁盘空间在性能方面更好的情况和便携性。比如依赖庞大的数据库、视频编辑软件或者算法,可以通过使用大量内存来加速,使用虚拟机镜像或者使用容器会增加磁盘使用率,但是便携性和便携性高。成为。

    更小的源代码的好处不是大小,而是复杂性,这意味着简单。当程序看起来更小没有意义时,简单是最好的,而不是小是美丽的。我们现在需要的工具是不是“小工具”,而是“实现简单的工具”是。即使工具本身很大,但如果它实现简单,它就是最好的工具。

    简单的正确含义是“不纠结”,而不是“容易”。例如,涉及与其本质无关的过程的过程流称为复杂的。例如,在 shell 脚本中,与吸收每个环境的基本处理和命令之间差异的代码“纠缠”的 shell 脚本称为复杂的。太长的管道也可能很复杂,因为不同的过程可能“交织在一起”。缠结的绳索更难去除。逃避复杂性的关键词是抽象。抽象就是隐藏具体的实现(每个环境的命令和进程),实现它的常用方法是将其分离为函数和外部命令。简单和容易是具有不同含义的词。 “简单”和“复杂”是客观概念,“容易”和“困难”是因人而异的概念。详细是"简单的需要“请参阅。

    原则 2:让程序做它应该做好的事情

    • 旧:一个程序做好一件事

    更改的原因与 McIlroy 的 UNIX Philosophy 中的 i. 相同。 “一件事”是一个模糊的定义,很少有命令实际上做一件事。如果硬要一个程序做一件事,会给用户带来麻烦。你算什么?只是从头到尾进行无用的讨论,什么都不会诞生。那么“真正”要做什么呢?更值得考虑。真正需要做什么应该由程序的角色决定。每个人都知道这一点,所以即使他们说“一件事”,他们也不会保留它。

    当然,我们应该小心“Shibiyori multifunctionalism”。它具有很少需要的功能不要做关于它。作为另一个命令已做在这种情况下,它最终成为冗长的多功能主义的牺牲品。我只是创造了一些东西,如果它可以在不组合的情况下使用会很方便,但是以一种不方便的形式,这样它就不能在不组合的情况下使用。 UNIX 的理念是使工具“可以组合”,而不是工具“必须组合”。

    具有讽刺意味的是,设计用于组合使用的工具往往是多功能的。这是因为将添加功能,以便可以与任何工具结合使用。 ls 命令在打印到终端时会自动显示在多列中。如果您从 ls 命令中删除多列功能并使用 ls | column ,则 column 命令具有多个选项,例如更改分隔符以便它可以与任何命令组合。是否要将多列显示功能合并到ls 命令中?在另一个命令中实现?两者兼而有之更方便。内置的ls 命令是一个简化版本,如果你想做一些更方便的事情,想法是把它和column 命令结合起来。您可以保持简单,因为在大多数情况下简化版本就足够了。

    有些人不喜欢在一个程序中做很多事情。如果你想让它成为“一件事”,你可以*地那样做。不过,想想看。实现很多特性的唯一问题是实现者可能很难实现它。即使有不必要的功能,用户也不必担心,因为他们根本不使用它们。也就是说,我想说的是,如果别人说“我想要一个◯◯的功能”,实现起来可能会觉得麻烦,但是实现者要自己实现,说明你可以实现.实施者有权*创建自己的程序。没有理由被某人所说的“一件事”剥夺*。

    原则 3:创建一个允许尽快重复原型制作的系统

    • 旧:尽快原型

    更改的原因与 McIlroy 的 UNIX Philosophy 中的 ii. 相同。这个想法也适用于敏捷。重要的是在早期快速迭代许多原型,而不是只迭代一个原型。为了高速开发一个系统,我们必须创建一个机制。例如,创建机制意味着自动化构建和测试。如果它是一个 Web 应用程序,它还包括部署到服务器,因此需要与版本控制工具(如 git 和 CI 服务)链接。结合提供这些机制的“软件工具”正是 UNIX 哲学的理念。如果没有机制,制作许多原型并返回瀑布思维方式将是乏味的。

    顺便一提”敏捷软件开发宣言没有说“没有工具”或“没有文档”或“没有计划”。敏捷使用工具、文档和计划。不要误会“如何阅读敏捷软件开发宣言请仔细阅读《敏捷软件开发宣言》中的“误解与现实”。

    原则 4:协调质量以满足要求和高生产率

    • 旧版:便携性高于效率

    是 Gunkers 说使用硬件特殊功能来提高效率意味着更少的便携性,但这是 1980 年代的旧想法。当今主流的思维方式是使用驱动和封装来吸收硬件和环境的差异,实现效率和可移植性并重。这个想法无处不在。使用可用的特殊硬件功能,并在没有它们的情况下工作效率满足便携性去做。包装器的开销很小,但如果“可移植性高于效率”这句话适用于今天,“优先考虑使用包装器的可移植性,而不是消除包装器以提高效率'应该说。

    需要注意的是,当 Gunkers 谈到“可移植性”时,他指的是移植到具有不同架构的计算机,而不是不同的操作系统。在 1980 年代,争夺霸主地位的计算机公司比今天更多,软件公司专门为少数计算机移植软件。但是现在硬件差异被操作系统吸收了,我们所要做的就是为特定的操作系统编写软件。此外,随着网络的普及,即使您专门为一种操作系统开发软件,您现在也可以与多种类型计算机的用户开展业务。便携性仍然很重要,但它的价值已不如从前.即使它只支持特定的操作系统,能够立即使用它会更有用。

    另外,如果是通用软件,选择合适的语言和库即可。便携性是免费的已经成为任何人都可以通过编写单个源代码轻松获得最低限度的可移植性,而不必担心移植性,因此高移植性不再是技术能力的差异,它已经过去了。这个时代可移植性低的语言是你自己解决兼容性问题的同时还要自己编程的语言,而shell脚本就是移植性低的语言之一。

    还要注意 Gunkers 对“效率”一词的使用。 “高效”表示 CPU、内存和磁盘资源使用率低,但 Gunkers 使用“效率”表示“性能好”。 “高效”不仅仅是“低资源使用”,而是“在一定条件下的低浪费”。例如,如果有一种算法使用大量内存进行高速处理,则在可以实现性能的条件下,如果使用的内存量很小,则说它是有效的,但即使性能无法实现 即使使用的内存量很小,也不能说是高效的。在计算机内存很少的时代,使用大量内存由于交换和分页导致读写慢磁盘,性能下降,所以“效率”=“内存使用率低”=“((因为交换和分页)不会发生)”成立,但现在“高效”和“良好性能”并不相等。

    请注意,“使用硬件特殊功能 =表现“更好=更不便携”与效率无关。如果我们在这里将性能和效率等同起来,效率好=不那么便携”。 “可移植性高于效率”的原始学说是基于这个错误的公式。高效(性能)的方法不一定不那么可移植.现在我们尝试在效率和便携性之间取得平衡。“选择一种高度便携的方法,即使这意味着牺牲效率(性能)。”这是一种过时的思维方式。

    Gunkers 便携性故事的真相是

    • 效率(性能)在 1980 年代之前一直非常重要,当时计算机速度非常慢。使用特殊的硬件功能来提高性能是有效的,但是操作系统没有吸收硬件差异,所以我们不得不自己编写一个包装器来吸收硬件差异。。此外,计算机的性能如此之低,以至于包装器本身导致效率下降。那也是一个硬件性能在短时间内大幅度提升的时代,高性能但不兼容的新硬件层出不穷。在这个时代,效率和可移植性很难兼顾,考虑到开发成本,不值得,便产生了可移植性比效率更重要的想法。

    就是这样。

    现在情况完全不同了。除了一些例外,现在可以开发软件而不用担心使用什么样的硬件。如果操作系统有硬件的特殊功能,它会使用它,否则它会被软件模拟,从而可以提取计算机的性能而不用担心便携性。因此,说我们不应该使用硬件的特殊功能是不合时宜的,因为在当今时代,便携性比效率更重要。仍然有一些专门的硬件功能很重要的领域(例如高级 3D 游戏、机器学习、大数据等)。在这样的领域中,硬件的特殊功能极其重要,所以即使说便携性很重要,如果放弃性能,也无法满足实用水平的要求。仍然有一些领域唯一的选择是使用特殊的硬件功能,因为软件仿真无法达到实用的性能水平。

    现在,软件需要的不仅仅是效率和可移植性。效率和便携性现在被视为质量的一部分。质量被定义为“功能适用性”、“性能效率“兼容性”“可用性”“可靠性”“安全性”“可维护性”“可移植性” 被细分为(参考国际音标“互联世界的软件质量指南”)

    シェルスクリプトを学ぶ人のための「新しいUNIX哲学入門」 〜 ソフトウェアツールという考え方

    这种质量概念似乎自 1990 年代就已经确立。所以 Gunkers 的 Unix Philosophy(出版于 1994 年,但主要是在 1980 年代)是在质量概念尚未完全发展的时候。在那个年代,计算机的能力如此之低,以至于除了效率和便携性之外,他们可能没有时间考虑其他任何事情。质量的历史是“回顾软件质量技术的历史 - 专注于软件质量测量 -”以通俗易懂的方式进行了总结。

    软件所需的质量水平因项目而异,但无论如何,虽然软件所需的质量很高,但要达到高质量需要时间。几乎没有一个项目不需要生产力,所以我们必须同时实现高质量和生产力。为此目的使用正确的工具组合非常重要。好消息是今天有很多高质量的软件可用,甚至是开源的。将这些语言、库、命令和中间件结合起来,是一种导致 UNIX 哲学思想的思维方式。

    今天的可移植性技术是驱动程序和包装器的抽象。您可能认为拥有包装器会降低效率,但在当今时代,效率降低可以忽略不计,通过删除它来关注性能是没有意义的。从这个意义上说,“可移植性高于效率”这句话在某种意义上可能是正确的。如果您选择合适的语言或库,例如 Go,则无需执行任何操作,因为内置了等效的包装器(如果需要)。简而言之从一开始就“可移植性高于效率”生产力也很高。可移植性只是质量要求,而不是重中之重。因此,如果您认为出于业务战略原因需要处理其他环境,则可以处理它们。还有很多其他的事情要考虑。只需要考虑两个选择的日子已经一去不复返了:“软件需要效率还是可移植性?”

    原则 5:对文件使用标准或简单的基于文本的格式

    • 旧版(第一版):数字数据存储在 ASCII 平面文件中
    • 旧版(修订版):将数据存储在纯文本文件中

    这一原则与 McIlroy 的 UNIX 哲学一样,即使基于文本的界面与其他程序一起工作。您需要与其他程序一起工作的是接口(标准输入/输出),而不是文件格式。所以“数据存储在平面文件中”是 Gunkers UNIX 理念所独有的。

    如果未知程序可以读取和写入文件,则该文件是可移植的。这样做的先决条件是使用标准文件格式。它是文本还是二进制都没关系。我认为 text 使用起来更方便,但它与文件可移植性无关,并且不足以使二进制文件无法使用。如果您使用标准文件格式,则可以使用陌生人制作的程序。如果您使用非标准文件格式,您最终会得到一个专用工具来处理该文件格式。其他程序必须支持该特定文件格式。

    与 1980 年代甚至不存在 zip 和 gif 格式不同,现在有许多标准化的、甚至基于二进制的格式已成为事实上的标准。如果一种文件格式不被特定公司垄断,其规范是开放的、严格定义的,并且在世界范围内得到广泛支持,则可以说是一种高度可移植的文件格式。二进制但高度可移植的格式示例包括 SQLite 数据库格式和 Excel 文件格式。 (旧的 xls 格式的规范也向公众开放,Microsoft Office Excel 97-2007 二进制文件格式 (.xls) 规范(此规范根据 Microsoft 开放规范承诺提供。)

    反之,即使是基于文本的,也没有明确的文件格式规范,有特殊的数据结构和目录结构,有特殊的文件放置和访问方式规则,反之则完全没有规则。如果规格是任意的,则为低。这是因为现有的程序都不支持它,而且复杂的格式很难正确处理。另请注意,即使是基于文本的文件格式也有公司拥有的专有格式。举个例子FBX我将介绍格式。仅仅因为它是基于文本的格式并不意味着它一定是可移植的。

    如果没有合适的标准化数据格式,则保持它尽可能简单,采用面向行的文本格式会更安全。简单的面向行的文本格式是这样一种格式,其中一行是一个数据,或者数据排列成一行,由空格等字符分隔的格式(所谓的SSV格式)。如果是简单的文本格式,应该不难处理。除非尽可能简单,否则很难从其他程序中读写。但是,在这种情况下,可能会出现问题,具体取决于数据的性质,因为当数据包含空格和换行符等特殊字符时,没有标准规则。除了一些例外,shell 脚本和 UNIX 命令基本上只能处理简单的面向行的文本格式,并且没有处理特殊字符的标准规则。这是未来必须改进的shell脚本的问题之一。

    人们经常误解“UNIX 命令可以处理任何基于文本的格式”。比如 JSON 格式是一种基于文本的格式,但是我们不了解它的结构,所以只能将其视为“无结构的文本格式”。即使您不理解结构的含义也可以处理它的原因与说二进制文件具有高度可移植性是一样的,因为您可以使用二进制编辑器读取和写入所有二进制文件。结构化(或半结构化)基于文本的数据格式也在 UNIX 时代之后出现。换句话说,一种 UNIX 命令无法处理的基于文本的新格式诞生了。对 UNIX 命令的正确解释是“简单的面向行的文本格式也可以处理 UNIX 命令”。处理其他格式需要非 UNIX 命令,例如 jq 命令。

    如果一个独特的格式是绝对必要的,我认为保持原始格式基于文本会更好,但高数据可移植性的标准不是基于文本或基于二进制,而是一个标准的文件格式。如果您不能使用标准文件格式甚至简单格式,您可以定义一个新的文件格式规范并发布它,或者您可以轻松读取、写入并将其转换为标准格式。库或命令(如果可能,开源)。如果该格式在世界范围内传播,它将加入标准文件格式的行列。当然,如果文件格式只供程序内部使用,则无需为原始格式定义规范。只要标准输入/输出接口易于理解,就足够了。

    原则 6:使用更多软件来提高生产力

    • 旧版:利用软件优势

    当我第一次读到这篇文章时,我不明白“软件杠杆”是什么意思。杠杆是杠杆原理的杠杆。利用英语。杠杆经常被用作投资术语,但我不太了解它是杠杆还是杠杆。这句话的意思是“一个人的力量是小而有限的,但是如果你把别人做的软件当成一个杠杆,你可以用它把小力量变成大力量。意思是你可以成就一些事情。”你不能或不能在他人的帮助下创造。换句话说,“有效利用软件的杠杆作用”是什么意思?“利用现有软件资产提高生产力”这就是它的意思。

    然而,即使我们使用软件资产,不要复制和粘贴代码(剪切和粘贴现有代码).连shell脚本都有版权,众所周知,剪切粘贴现有代码的行为(不理解含义)会导致质量下降,所以不好增加。我之所以写这个,是因为它是以 Gunkers 推荐的复制和粘贴的方式编写的。首先要做的是使用通用库而不进行修改。这个明显的故事之所以没有出现在《UNIX 的思想》中,大概是当时“通用库”的思想比较薄弱。其依据是《详细正则表达式第三版》P86上写的以下句子。

    同样在 1986 年首次引入的,也许比 POSIX 更重要的是由 Henry Spencer 用 C 语言编写的正则表达式包。该软件包可供其他程序员免费整合到他们自己的程序中,当时它是同类中的第一个。使用亨利包的程序(有很多)都以相同的方式运行,除非作者故意重写它们。

    当我第一次阅读这篇文章时,我意识到我没有意识到有一段时间没有通用库(除了OS标准库)。仔细想想,C 语言本身就是从 UNIX 的发展中诞生的,所以在 UNIX 面世的时候,自然不会有 C 语言的通用库。当世界开始使用 UNIX 时,人们都在编写自己的代码。

    设计一个通用库非常困难。在没有通用库的时代,唯一的选择是从现有代码中找到并复制粘贴似乎可用的代码。因此,我认为只使用 UNIX 提供的标准函数(C 语言标准库和命令),其余的复制粘贴是当时普遍的开发风格。嗯,那是很久以前的事了。现在每种语言都有一个高质量的通用库。 (我没有很多shell脚本......)

    软件利用不仅仅是 UNIX 原生的基本功能。任何语言、任何库、任何框架、任何命令、任何中间件、任何软件,而不仅仅是 C 或 shell 脚本。现在的程序非常庞大,其中很多都需要操作系统不提供的图像处理和音频处理等高级和高难度的算法,因此一个人很难创建有价值的软件。我是。高价值的图书馆有成千上万行,创建类似的东西需要大量的时间。

    利用现有软件现在很普遍。现在很多软件都是开源的并且可以免费使用。相反,我必须警告你不要过分依赖过于简单的库。软件的质量取决于它所依赖的软件,所以你要选择质量。看穿这样高质量的软件是我们的技术能力之一。

    原则 7:利用 shell 脚本简单地组合命令

    • OLD:使用 shell 脚本获得更大的影响力和可移植性

    有两件事必须首先明确。一是 Gunkers 只说 shell 脚本比 C 更便携,并没有将它们与其他较新的语言如 Rust、Go、Python、Perl 等进行比较。另一个是移植 shell 脚本到其他操作系统时可移植性低。它不必是一个 shell 脚本才能有效地利用杠杆作用。

    关于第一个,Gunkers之所以不将其与其他语言进行比较,是因为在UNIX全盛时期,其他语言还没有诞生或流行,而UNIX开发人员是一种不属于UNIX的语言对于一些枪手来说,这不是一个选择。 C 和 shell 脚本是在 UNIX 的发展过程中诞生的,是 UNIX 的一部分,但其他语言则不是。作为补充,awk 也是诞生于 UNIX 的语言,sed 也类似于一种语言,但在通用性方面不如 shell 脚本。

    关于第二点,Gunkers 表示,shell 脚本的可移植性很高,因为当他们公司的 UNIX 移植到新架构的计算机上时,如果是用 shell 脚本编写的,就不需要修改它们了。由于移植的 UNIX 与以前的 UNIX 相同,或者相同 UNIX 的后续版本,在这种情况下,shell 脚本的可移植性肯定很高。但是,在将shell脚本移植到其他公司的UNIX时,由于环境依赖性强,shell脚本的可移植性较低。

    既然 POSIX 已经标准化了 UNIX 规范,那么如果它们遵循 POSIX,shell 脚本不是更便携吗?你可能会这么想,但有一个陷阱。事实上,POSIX 并不打算完全消除 UNIX 命令实现中的差异。粗略地说,如果您通过将应用程序分为“1. 与任何实现兼容的部分”、“2. 行为略有不同的部分”和“3. 不兼容的部分”来开发具有高可移植性的应用程序,兼容''。我只是做了一个开发指南,同时注意2和3。 Unix 供应商不会改变他们的实现方式来保持向后兼容性,POSIX 说这很好(接受 POSIX 一致性)。由于 POSIX 是一个实现优先的概念,如果认为它与许多实现兼容,它会对其进行标准化,但不会主动统一规范或制定新的规范。基本上,它留给 UNIX 供应商,而 UNIX 供应商不会为了向后兼容而改变行为。不能)。但是,对于 C 语言部分ANSI C政策是采用 中标准化的内容,并且 ANSI C 在 POSIX 之外定期进行改进。简而言之只有与 shell 脚本相关的部分是不可移植的是目前的情况。

    这很突然,但这里有一个测验。以下 1 或 2 中哪一个通常是最便携的 shell 脚本?这里的可移植性是指对其他 UNIX 或类 UNIX 操作系统的可移植性。

    1. Shell 脚本仅使用标准安装的 UNIX (POSIX) 命令
    2. Shell 脚本仅使用默认未安装的非 unix (POSIX) 命令

      正确答案是 2。 1 依赖于与每个 UNIX 略有不兼容的命令。就像很多浏览器和Java实现存在兼容性问题一样,UNIX命令实现越多,兼容性越低。另一方面,除了 2 个 UNIX 命令外,基本上只有一个开发人员,而且由于该命令经常按原样使用,因此不存在兼容性问题。当然,这仅限于命令在任何环境下都可以工作并保持兼容性的情况,但是具有许多用户的命令通常会满足该条件。如果您在这里回答 1,您可能“以最少的操作系统配置运行”和“可移植性”之间的混淆正在做。如果没有安装,只需安装它。 1980 年代“用 C 编写的命令很难构建和安装”的想法已经一去不复返了。现在,您可以使用包管理器轻松安装命令和安全更新。甚至 shell 和 UNIX 命令的兼容性问题也可以通过简单地安装 GNU bash 或 GNU CoreUtils 来解决。大多数命令只需安装即可使用,无需设置任何服务器软件。即使没有包,使用 Go 制作的软件也是作为静态构建分发的,因此您可以像复制 shell 脚本一样复制可执行文件来使用它。

      好的,到此为止Shell 脚本的可移植性较差澄清。后来出现的较新的语言优于 C 和 shell 脚本。没有理由坚持使用 shell 脚本,因为软件杠杆(命令和库)的效果可以在其他语言中使用。此外,其他语言可以高度便携,没有太大的困难。使用 shell 脚本开发应用程序是 1980 年代的一个想法,当时只有 C 语言而没有库。是。这在当时可能是一个有趣的想法,但这是一个 30 或 40 年前的想法。其他语言更快更容易,即使在处理基于文本的文件时也是如此。

      在 shell 脚本中开发应用程序本质上是有问题的。与 C 相比,不编译是一个优势,但其他脚本语言也是如此。虽然在脚本语言的时候无法达到高性能,但是由于是频繁调用外部命令并立即终止的风格,所以会出现多次命令执行和数据重读,从而导致性能不佳。玩大量数据通过管道进行进程间通信也会影响性能,如果通过管道连接的命令较多,会在内存中多次创建临时中间数据,导致效率低下。由于它不支持复杂的数据结构,所以不能直接处理合适的数据结构,需要转换,不能直接调用OS自带的API,各种进程都是通过其他语言的程序来执行的,你必须这样做,所以高架。到底如果您以另一种语言调用程序并对其进行处理,那么从一开始就使用该语言执行它会更有效和更高效。关于它。如果很简单,如果你想在一个shell脚本中做各种事情,你将不得不组合很多命令,所以它很快就会变得复杂。

      简单来说,高级数据处理最好使用其他语言而不是shell脚本。对于其他语言,awk 和 Perl 已经使用了很长时间,但现在 Python 和 Go 是不错的选择。当然,如果简单的文本处理就足够了,你可以使用sedgrep,但是如果你最终通过将许多命令以复杂的方式组合起来进行“单一数据处理”,你可以使用那部分。用一个简单的“另一种语言的命令”替换它。这并不是说 shell 脚本没有作用。 shell 脚本的作用是“协调命令”,执行多个独立的数据处理。

      shell 脚本适合链接命令的原因是它们被设计成可以像函数一样使用命令。这在其他语言中很麻烦,因为你必须使用语言的函数来间接调用命令。还有,命令输出数据到标准输出,但是其他语言的函数基本不使用标准输出,返回数据作为返回值,所以函数和命令的接口完全不同。由于这些差异,没有其他语言可以替代 shell 脚本,而 shell 脚本是协调命令的最佳脚本语言。这里提到的 shell 脚本不限于 Bourne shell 或 POSIX shell。包含在交互式 shell(例如 csh 或 fish)中运行的所有 shell 脚本。 (在更广泛的意义上,Windows 批处理文件也包括在内。)

      嗯,时间有点长,简单总结一下。没有理由仅仅为了利用和可移植性而使用 shell 脚本。与其通过组合多个数据来强制一个数据处理,不如让我们创建一个用另一种语言进行数据处理的命令。如果你想坚持使用 unix 命令,你可以使用 awk 作为你的语言,但是看看你是否可以使用更合适的命令。 Shell 脚本用于链接命令。但是,shell 脚本和 UNIX 命令不可移植,所以要小心。可移植性不是必需的,因此您可能会放弃。另外,安装和使用 GNU bash、GNU CoreUtils 等将在一定程度上解决可移植性问题。安装工具来解决问题正是 UNIX 的哲学,因为 UNIX 的哲学是使用工具的组合。

      原则 8:命令应具有用于自动化处理的非交互式界面

      • 旧:避免过度交互的界面

      “避免过度交互的界面”没有太大的意义,但我不知道它是什么程度的过度。还有,重点不是要避免交互界面,而是要有一个交互花界面。因此,虽然可以实现交互界面,但我们对其进行了修改,使其也具有可以非交互方式使用的界面,从而可以进行自动处理。

      交互式界面是假设人类可以与计算机交互的界面,例如“你想运行它吗?(Y/N)”。另一个示例是使用光标键选择菜单的界面。不仅是操作,还有ls的列显示和对输出进行着色等供人类使用的输出功能,可以说是一个交互界面。当人类(而不是 shell 脚本)使用 shell 时,我们也说我们以交互方式使用它。如果您实现交互式功能,您应该提供禁用它的选项或机制(例如当输出不是终端时自动禁用它)。

      避免交互界面的原因是它们使 shell 脚本的自动化变得困难。使用yes 命令可以绕过(Y/N) 之类的问题,但这是行为不良程序的最后手段,应避免使用yes 命令。不要这样做。例如,在命令中实现一个选项,该选项自动为所有问题选择“是”。

      请注意,CLI 命令并不是在 CLI 环境中运行的唯一程序。有些程序有一个基于文本的用户界面,称为 TUI(文本用户界面)(顺便说一下,CUI 是日语英语)。例如vimemacs,它们使用文本字符但使用整个屏幕来提供类似GUI 的界面。没有必要为打算用作这样的 TUI 的程序提供非交互式界面。与其通过添加一个 CLI 友好的界面来使 TUI 复杂化,不如让它作为一个单独的 CLI 命令独立存在。即使将其作为单独的命令分开,在其中执行的处理也可以通过使其成为库来共享,因此不会增加重复代码。

      原则 9:处理数据的程序应尽可能成为过滤器

      • 旧:过滤所有程序

      在 UNIX 命令的上下文中,过滤器是从标准输入输入数据并将数据输出到标准输出的命令。 UNIX 命令不一定是过滤器。我没有准确计算,但可能只有大约一半充当过滤器。

      UNIX 命令是文本和数据处理命令的过滤器。此类命令包括sedawkcutgrep。还有一些不完善的过滤器,例如diffjoin,其中一个数据来自标准输入,另一个来自文件。

      另一方面,文件和进程管理命令不是过滤器。例如dfdulsps。他们直接从文件系统或进程信息而不是标准输入中获取输入数据。因此,并非所有程序都可以成为过滤器。

      许多命令不需要数据输入。例如echoprintfseqyesdatedirnamebasename。这些命令通过命令行参数改变它们的行为。您可以将命令行参数视为输入,但根据定义它们不是过滤器,因为它们不从标准输入中获取数据。这样的程序可以被认为是带有人类指令(参数)的“程序创建数据”。这也是为什么不是每个程序都可以成为过滤器的另一个原因,因为并不总是程序可以首先读取数据。

      有些命令既没有标准输入也没有标准输出。例如chmodchownkillwait。它们在参数中接受人工指令,并直接影响文件系统和进程信息。

      如您所见,许多现有的 UNIX 命令不是过滤器。在这种情况下,说“让所有程序成为过滤器”并不是很有说服力。如果您尝试将其强制转换为类似过滤器的形式,您也许可以做到,但这不是 UNIX 的直观界面。 (个人觉得我们可以通过强行做成过滤器的形式来做一些有趣的事情,但是我还没有决定。)

      什么是数据?也许它可以表示为“文件的内容”?在过滤器之前的日子里,即在管道之前,相当于将一个程序的输出打印到文件中,然后下一个程序处理该文件。管道可以做到这一点,并允许您将一个程序的输出直接连接到另一个程序的输入。这意味着只有处理“文件内容”的程序才能成为过滤器。像chmod 这样的东西处理的是“文件元信息”而不是“文件内容”,所以它不能是一个过滤器。如果所有程序都将成为过滤器,则必须创建一个将所有信息表示为“文件内容”的操作系统作为先决条件。 UNIX 不是这样的操作系统,因此并非所有程序都可以成为过滤器。

      软件工具准学说

      “Unix 思想”介绍了九个学说,以及不太重要的信条,如“十次小信条”。本文将这些称为准教义。但是,由于只是简单地写成一个与“UNIX的思想”相对应的准学说,所以本文的解释不包括lesser(劣等)的细微差别。

      在“The Unix Thinking”的第 105 页,Gunkers 强烈地论证了“教义”的重要性:

      到目前为止,对于 UNIX 开发人员来说,这些定理是不费吹灰之力的。如果受到攻击,请全力反击。

      不过,这只是 Gunkers 的断言,这里的 UNIX 开发者大概是“DEC 的 UNIX 开发团队”所以,我认为可以说我们带着这种感觉开发 UNIX 是合理的。再次,

      我在下面讨论的想法或多或少是“好吧,我有点同意”。 “并非 UNIX 阵营中的每个人都同意,但我想说整个社区都同意。

      因为“即使在 DEC 的 UNIX 开发团队中,意见也存在分歧。”我想这就是它的意思。这并不意味着 Gunkers 的主张是错误的,而是应该将其视为与原始 UNIX 哲学不太接近的个人主张,将其解释为唯一正确的 UNIX 哲学是错误的。

      子原则 1:为程序员提供高度可定制的环境和工具

      • OLD:允许自己根据自己的喜好调整环境

      (GUI 桌面)环境不是唯一应该可定制的东西。对于 shell 执行环境和命令选项等自定义也是如此。你有没有注意到,这种能够调节环境的想法与“小就是美”和“一个程序做好一件事”的旧信条相矛盾?这是因为能够调整环境意味着你可以做很多事情,程序也会随之增长。但是我已经修改了旧的学说,没有必要把它变小,所以没有矛盾。

      应该理解,高度可定制的工具的想法对于程序员来说是一个有价值的想法,而不是计算机用户。对于对编程不感兴趣的一般用户来说,高可定制性可以看作是一个难用的工具。甚至 Windows 和 macOS 也不会尝试在自定义方面走得太远,并且某些功能只能通过高级方法(注册表或 CLI 命令)进行配置。 UNIX 哲学主要是针对程序员的哲学。

      这里有些例子。

      Windows 记事本被认为是可定制性很小的最终用户应用程序。像 Sakura 编辑器这样的东西提供了一定程度的可定制性,但范围很小,按照当前的标准,对于程序员的工具来说还不够。 VSCode 具有高度可定制性,适合作为程序员的工具,通过扩展添加功能的能力与 UNIX 结合使用工具的理念是一致的。在我刚刚列出的三个文本编辑器中,VSCode 是最适合程序员的,它可能很难使用,但它的生产力很高。但是,记事本和樱花编辑器对一般用户来说更容易。 (当然,vim 和 emacs 也是程序员高度可定制的工具。)

      作为另一个例子,高度可定制的命令增加了它们与其他工具结合使用的能力。例如,如果一个命令可以选择以 JSON 格式而不是纯文本格式输出,它可以与其他处理 JSON 的命令结合使用。更多的选择是一件好事(如果你能克服复杂性)。

      shell 环境也应该是可定制的。例如,有些人使用 macOS,但更喜欢使用随 Homebrew 安装的 bash 和 GNU CoreUtils。不要妨碍用户想要使用他们的定制环境。最好创建一个高度可移植的 shell 脚本,以便它可以在这样的环境中工作(使用的命令是 GNU 版本,即使它是 macOS)。

      子原则 2:保持内核小而用户态程序丰富

      • 旧版:更小更轻的操作系统内核

      只有 UNIX(内核)开发人员才能“使操作系统的内核更小更轻”,所以从这里开始,“Gunkers 的 UNIX 哲学”是“UNIX 开发人员应该遵循的学说”,而 UNIX 我决定它不是作为开发上述软件的开发人员将遵循的原则。

      只有内核说比原来的学说更小。我并不是说要缩小内核以外的任何东西,即 UNIX 命令和许多其他用户态程序。修改后的描述增加了“丰富的用户空间”以阐明非内核程序不需要很小。用户态是内核和驱动程序以外的部分,UNIX 命令和大多数程序都运行在用户态。

      请注意,UNIX 命令是标准的操作系统命令,但它们与其他命令没有区别。甚至 shell 也只是一个在用户空间中运行的程序,就像任何其他命令一样。由于这是一个 UNIX 命令(广义上的 OS 命令),它不具有速度快的特性。在用户态程序中,内核(或狭义的操作系统)代码仅在调用系统调用时才会执行。缓慢的系统调用调用是导致 shell 脚本缓慢的一个已知原因。任何使用系统调用的东西,无论是调用外部命令还是通过管道进行进程间通信,都很慢。因此,如果速度很重要,那么使用另一种语言会更快。

      这个学说并没有说 UNIX 命令,用户态操作系统的基本命令(包括 shell)应该很小,但它们通常更小。它旨在在最小的计算机上运行。我不知道操作系统将在什么样的环境中使用。它可能在具有多核 CPU 和大量内存的计算机上运行,​​但它可能在物联网或嵌入式等较差的环境中运行。即使 CPU 性能低下,只要慢一点,程序也可以执行,但如果内存不够,程序就无法运行。虚拟内存在嵌入式环境中并不总是可用(尤其是在需要实时控制时),因此操作系统通常会优先考虑节省内存。操作系统和基本命令应该在内存较少的情况下工作,但内存较少的软件可能性能不佳。理想情况下,操作系统的基本功能应该很小,而高性能软件应该来自附加包。

      Linux 是一种使操作系统保持小型化的操作系统。您可能认为 GNU 命令很大,但对于 Linux 内核,GNU 命令只是在用户空间中运行的一个命令集。如果 GNU 命令很大,您可以使用另一个命令集。不是真正的 GNU 命令,而是带有 BusyBox 的 Alpine Linux,它是一小组命令。即使在 Alpine Linux 中,也为每个命令提供了 GNU 命令,并且可以根据需要进行替换。顺便说一句,它不包括 shell 或命令免发行版还有一个 Linux 容器镜像叫做您甚至不需要 shell 或命令来运行程序。

      子原则 3:使用长名称以提高可读性,使用短名称以获得乐趣

      • 旧:使用小写,短

      使用大写字母时要遵守约定。文件名通常是小写的,但 README 传统上是大写的。以ASCII字符码的顺序排列时出现在前面是有原因的,但是当en_US.UTF-8等用于locale时就不会出现这种情况,所以习惯上使用大写字母。按照惯例,环境变量使用大写字母,shell 变量使用小写字母。命令名、函数名、类名等根据语言有不同的约定,所以使用合适的。

      过去,电传打字机的键输入和输出(打印)都很慢,这样做可以使程序更小,但现在却没有了。不要仅仅因为它们很短就盲目地模仿 UNIX 命令或其选项。

      缩写和太短的命令名称很难记住并且没有好处。一个可以被没有先验知识的人识别的名字更好。因为 UNIX 命令使用短名称,所以短名称是 UNIX 哲学只是一种误解。我们保留短名称只是因为我们认为短名称有更多优点。经常在任何地方使用的通用命令很难记住,但您会记住它们,因为您会多次使用它们。如果你还记得的话,做空是有好处的。但是,不经常使用的命令不会被记住并且只是晦涩难懂。

      只有当它们是通用的、可重用的,并且您确信即使它们晦涩难懂,它们也值得记住时,才允许使用短命令名称。例如jq 命令。通用命令广泛用于许多不同的项目。嗯,创造了他们引以为豪的产品的程序员通常认为这太棒了,从现在开始它会被大量使用,而且短名称很容易输入,所以我理解缩短它们的愿望。但是一个简短的名字很有价值,因为它很容易和别人一起穿。短名称是程序员的共同财产,因此请注意它们。即使你成名了也可以缩短你的名字,如果你只是想亲自缩短它,只需使用alias。如果您需要像git 这样的一系列命令,请考虑使用子命令。 go 命令也使用子命令。

      建议基本上为命令选项创建长选项。无论如何,单字母选项将用完数字。应将单字母选项分配给 shell 中常用的选项,以使输入更容易。从 shell 脚本调用命令时,更长的选项更利于可读性。 POSIX 命令的选项除外。如果你想运行一个需要可移植性的 shell 脚本,并且作为标准安装在操作系统中的命令,你别无选择,只能使用短选项。短选项如果使用频率足够高以被记住,则可以使用它们,但基础是长选项。 Go 在其标准选项解析库中支持长选项。

      另外,编程语言有较大作用域名称较长、局部变量名称较短等规则,请参考各语言的编码风格。

      子原则 4:保护森林和环境,减少电力消耗和二氧化碳排放。

      • 旧:保护森林

      老实说,为什么这在 UNIX 哲学中是一个谜。因为浪费纸张与 UNIX 哲学无关。当时的热潮之一无纸化社会Gunkers 似乎是在“.起初我想删除它,但我保留了它,因为我能够将它与 UNIX 哲学联系起来。

      原来,这个学说是在过去,长的源代码被打印在纸上并被调试。旧显示器能显示的面积很小,可能做小功能的风格还不够流行,长代码看不懂。在过去,打卡数据录入浪费的纸张更多。这些问题通过大型图形显示器得以解决。其他各种系统也上线了,虽然速度很慢,但我们仍然在无纸化。

      森林不是唯一应该保护的环境。例如,有能源问题。这可以从虚拟机技术、容器技术、云等“使用工具”的思想与UNIX哲学联系起来。计算机具有省电功能,但即使它们不进行任何处理,它们只要打开它们就会消耗电力。现在电脑的功率越来越大,甚至单台电脑的功率也太大了,通过使用虚拟机技术、容器技术等工具将多台电脑合并为一台来节省电量是可以做到的。

      在云(数据中心)中,许多用户可以做同样的事情,因此可以更有效地使用能源。您可能认为手边有一台计算机(例如在您公司的机房中)和远程位置的计算机没有区别,但在数据中心中,有许多计算机是集体空调,需要特殊电源供应。它可能有系统,可以说是环保的。

      数据中心消耗大量电力,因此我们正在尝试尽可能减少它。例如,作为降温措施,可以在凉爽的地方建一个数据中心,用海水降温,高压直流 (HVDC)(参考直流电时代的到来! <Part 1> Sakura Internet 的直流供电系统(HVDC))。看起来它实际上正在得到回报。 "数据中心会耗尽全球电力吗?为避免这种情况需要解决的问题“比

      2018 年,数据中心的工作量比 2010 年高出 6 倍以上,但能耗相对保持不变。

      如果没有大型数据中心,这些努力是不可能的。我不是说你什么都应该用云服务,但是有了云,你就不用一台一台去买电脑了,你也可以换一台更多规格的电脑。通过在高峰时段根据服务器负载增加虚拟机数量并在非高峰时段减少虚拟机数量的工作自动化,您可以降低成本和劳动力。这不像您过去购买功能强大的计算机,但您在非高峰时间做的很少。有云特有的问题,但如果你提到它,硬件也会发生故障,因此恢复工作会比那些更容易。通过使用虚拟机技术、容器技术、云技术等工具,可以在保护环境的同时降低成本,一石两鸟。

      子原则 5:在应该输出时以一致的格式输出数据

      • 老:沉默是金

      “沉默是金”的正确解释会在流程正常结束时输出“处理完成”等“状态信息”,在没有数据返回时会输出“数据未找到”等“状态信息”,表示不应该输出任何内容(沉默)而不是这样做。这并不意味着发生错误时最好保持沉默。确保错误正确打印到标准错误输出。

      该原则是适用于原则 8 没有输出数据时的特殊规则:命令应具有用于自动处理的非交互式界面。一个命令的输出可以输入到另一个程序中,所以输出的格式可以很容易地被另一个程序处理。顺便说一句,早期的 UNIX 没有标准错误输出,而且错误信息也是输出到标准输出,所以看起来很麻烦。

      状态消息旨在供人阅读,而不是输出数据以输入到其他程序。因此,不需要输出。但是,如果您被问到是否应该永远显示它,则不一定如此,只要输出格式一致就没有问题。例如,如果规范仅在没有数据返回时才输出消息“No data found”,则很难将其作为数据处理,而是始终输出找到的项目数,例如“total 0” “。如果规范是这样做的,没有问题,因为它可以用作数据。这实际上是来自 POSIX 的 ls -l 规范。

      如果没有可以作为数据的信息,就不需要输出任何指示状态的消息,但是如果真的要输出指示状态的消息,可以加一个选项来抑制它,还有一个方法输出到标准错误输出。

      该学说的真正意义不是保持沉默,而是以一致的格式输出可处理数据的信息。

      子原则 6:创建执行并行处理的程序

      • 旧:平行思考

      这个学说的旧解释是原著中的“平行思考”。如果我正常翻译,我认为它的意思是“并行思考”而不是“并发”,但我不明白为什么要改为“并发”。如果一切都改成并行,我还是明白的,但是有一个词“并行”和一个词“并行思想”,所以并行和并行是混杂的。可能所有的原件都是平行的。并发和并行在中途混合,所以很混乱,但我认为他们没有单独使用它们。

      在计算机术语中,“并发”意味着执行多个进程,就好像它们同时运行一样。在只有一个 CPU 的环境中,在执行多个进程的同时以小间隔切换 CPU。这是一种通过在 CPU 等待慢速磁盘读/写、网络处理、等待人工输入等时执行其他处理来有效使用 CPU 的方法。另一方面,“并行”是指使用多个 CPU 或 CPU 内核同时执行处理。

      解释“并行思考”的不好的部分是没有写出主题。是计算机并行思考,还是人类并行思考?众所周知,如果人类并行思考,即把工作分成小块时间,通过多任务处理同时进行多个任务,效率就会下降。人类必须异步思考,而不是同时思考。异步思考意味着你可以在后台运行你的程序并且在它完成之前忘记它。

      在 CLI 环境下,除非使用支持并发的程序,否则需要有意识地在后台运行程序,方法是在 shell 中的命令末尾附加&。 GUI 桌面环境只是在应用程序之间切换。在 1980 年代,UNIX 是唯一可以进行体面的多任务处理的操作系统。现在任何操作系统都支持多任务,通过图形用户界面,自然可以在后台运行程序,所以大家都在不知不觉中练习“并行思考”。

      《UNIX的思想》的解说内容是关于让计算机的CPU工作繁忙,还是关于在后台运行一个程序,到底是关于人的,还是关于计算机的,我不确定。我想了很久,但我明白我想谈谈如何在不中断的情况下使用你的电脑,而不用担心它会被如何使用。

      有几种方法可以进行并行处理。 (概念上应该分开处理的东西混在一起了)

      1. 多处理的 CPU 并行性
      2. 多线程的 CPU 并行性
      3. 使用 GPU 进行并行处理
      4. 与 Elixir 和 Erlang 等轻量级进程并行处理
      5. 使用 Haskel 和 Go 等轻量级线程进行并行处理

        传统 UNIX 上只有 1 个可用。此方法用于通过使用 shell 脚本后台进程启动或xargs -Pmake -j 启动多个进程来进行并行处理。

        2中的多线程并行处理的特点是在一个进程中使用多个CPU共享内存,这与使用多个进程的并行处理不同。例如,多进程中使用管道进行进程间通信需要内存复制,但使用线程可以避免这种情况。因此,多线程比多处理效率更高,但由于实现原因并不总是更快,所以要小心。

        使用 3 个 GPU 的方法是最近流行的一种方法,用于机器学习和大数据处理。使用擅长并行处理的 GPU 执行计算需要兼容的硬件。由于用法与使用 CPU 的并行处理完全不同,因此需要编写一个用于 GPU 处理的程序。 Python等库丰富方便。

        4和5是一些语言中可用的方法,据说擅长并行处理。与其直接使用操作系统的多处理和多线程功能,不如使用该语言的内置并行功能。顾名思义,可以创建数以百万计或数以千万计的进程和线程,这在 OS 功能中是不可能的。

        这样,在 UNIX 的全盛时期不存在的新的并行处理方法正在增加。您选择哪种方法取决于具体情况,但除 1 之外的所有方法都不能直接从 shell 脚本或 UNIX 命令中使用。换句话说,shell 脚本和 UNIX 命令不太适合通过并发和并行处理来发挥计算机的性能。为了充分利用您的计算机,您需要使用其他语言和新命令。这就是 Ken Thompson 创建 Go 的原因。然而,并行处理也是一个困难的领域,因此并行处理是在每个进程的基础上执行的。您应该在 shell 脚本中寻找的是便利性,而不是性能。

        子原则 7:通过组合多个程序创建一个大系统

        • OLD:部分之和大于整体

        作为旁注,“部分之和大于整体”似乎是基于亚里士多德的话“整体大于部分之和”。

        这个原则是,当创建一个大型系统时,与其将其创建为单个大型软件,不如将其创建为多个程序的集合以提高可维护性。比如将大型集成应用配置为多个组件的集合,将大型服务器配置为多台前端服务器和一台后端服务器,将多个服务组合为微服务来创建大型服务,都是一样的思路。的这种思维在软件开发中无处不在。有这么多可重用的软件,你不太可能用一个软件来构建所有东西。

        将一个大型系统组合成多个程序的组合就是我们所说的松散耦合。通过这样做,可以更容易地逐个程序地并行开发和测试,并且可以逐个程序地替换程序。此时重要的是适当地决定接口。仅仅说文本格式是不够的,例如,如果是JSON格式,它是一个接口,包括有什么样的键。用今天的话来说,这意味着定义一个 Web API。诸如管道和套接字(通常是文件)之类的进程间通信用于在程序之间传递数据。

        组合多个程序也有其缺点。即,复杂性随着要组合的程序数量的增加而增加。即使每个程序本身都很简单,但它们组合起来并不一定简单。组合的行为是一种越来越复杂的行为。当您在 shell 脚本中传递许多命令时,同样的情况会变得复杂。降低这种复杂性的方法是减少组合程序的数量。例如,应用程序容器技术可用于通过将由多个程序组成的复杂软件放入一个简单的容器中来降低复杂性。这个想法是通过分层构建软件来减少组合的数量。

        子信条 8:专注于你真正需要做的事情并决定不做的事情

        • OLD:争取 90% 的解决方案

        “追求 90% 的解决方案”并不意味着“90% 的一切都恰到好处”。即使您犯了错误,也请不要将其解释为“不完美是正确的!”或“以不完美为目标!”这个教义的真正含义是你不应该是一个完美主义者,而不是你不应该是完美的。做什么和做多少取决于项目的重要性和政策。现在有很多软件必须以 100% 为目标。

        这个教义是雅尼也称为原理例如,您的软件会在任何基于 UNIX 的操作系统上运行吗?只支持Linux还不够吗?关于它。即使您预测它可能稍后会起作用,但它通常并没有实际使用,并且花费在处理它上的时间被浪费了。这样的对应会使代码复杂化。保持设计简单比这更重要。

        当发现程序缺陷或错误时,不应以“争取 90% 的解决方案”为借口。这并不是要挑衅和挑衅地指出并说:“我的目标是90%的解决方案,所以有错误是很自然的。”如果你不提出一个合理的理由,如果它被称为一个错误是无济于事的。应妥善处理错误。处理它并不意味着修复错误,它意味着承认它是一个错误并决定是否修复它。如果您决定不修复它,您应该记录它并说明原因。你不仅要决定做什么,还要决定不做什么。

        “瞄准 90% 的解决方案”是一个误导性的句子。我们将更改措辞,以便在发现错误时不会将其用作借口。

        子原则 9:快速制作原型,而不是随着时间的推移完善它

        • 旧:越差越好

        不要使用诸如“越差越好”之类的朗朗上口的短语来吸引读者的注意力。主旨是解释或理解天魔这句话的意思,并没有传达任何真正需要说的话。当然,低级永远不可能是高级。当我说它有缺陷、难以使用或劣质时,这就是我通常的意思。该学说被滥用为“越少越好”。

        没有开发人员可以想象出理想的软件成品形式。如果它是没有人创造的原创和开创性的软件,那就更是如此。如果您不知道它的外观,请制作原型。只担心少数开发人员不会给您一个好的答案。通过原型,您可以收集更多意见。

        “Worse is better”的意思是虽然发布出来的功能比理想中的少或者处于未完成的状态,但我能够从中吸取教训,最终导致开发出优秀的软件。劣质是原型版的故事,优秀的终将完成。

        如果您对“越差越好”这样的短语感到困惑,例如 Gunkers,“如果 UNIX 在各方面都变得非常出色,那么它将不得不处于灭绝的边缘。”我将不得不说出来。 Richard P. Gabriel 创造了“Worth is Better”一词。 Gunkers也是这个朗朗上口的短语的受害者。 (参考“越差越好”的概念和敏捷/精益)

        子原则 10:为你的目的使用最好的数据结构

        • 旧:分层思考

        作为《UNIX的思想》中层次结构的例子,从P11开始,文件系统、网络服务中的命名法、窗口管理、面向对象开发,从P122开始,列出了进程树和GUI界面。其他层次结构包括子命令、结构化编程、函数调用树、库名称空间、JSON、YAML、XML,无处不在的层次结构。然而,层次结构不一定是最佳的数据结构。

        一个著名的非分层示例是该命令使用的平面文件。因此,分层思维是一种与 Gunkers 的“将数据存储在平面文本文件”原则相矛盾的思维方式。不过,我已将教义改正为“使用标准形式”,因此并无矛盾。从“分层思考”学说与“保存在平面文件”学说的矛盾中可以看出,分层结构在某些情况下是合适的,平面结构在某些情况下是合适的,而其他数据结构是合适的。关于它。

        平面文本文件在大型机平面数据库中具有历史渊源。回溯历史,它制表机用于打卡是。一张卡片对应一行数据。那么,如果大型机只有一个平面数据库就足够了,当然不是这样。数据库历史到 1969 年,当 UNIX 诞生时,结构化数据库、网络数据库和关系数据库(RDB)等结构的数据库诞生了。

        从数据库的历史看,你会发现最优的数据结构不止一种,而是很多。毕竟层次结构是重要的数据结构之一,但它并不是唯一正确的数据结构。有适合您的目的的数据结构。但是,由于 shell 脚本和 UNIX 命令只能轻松处理平面数据,因此需要使用其他语言和非 UNIX 命令来处理分层数据。

        软件工具开发原则

        主要是制作工具(软件工具)时的一个开发原则。我想说它是根据“Raymond's UNIX Philosophy”修改的,但这只是一个引用,没有任何修改。原因是它足够抽象,原理没有过时,文字没有误导。尽管如此,它还是包含在本文中,因为它作为开发软件工具的更具体的原则是必要的。 “软件工具的思想”和“软件工具的学说”都是模糊的内容,不可能学会自己制作工具的思维方式。似乎这还不够,本文将“Raymond 的 UNIX 哲学”称为“软件工具开发原则”。

        然而,内容并非没有争议。有一些地方让我很困扰,但至少从原理的文字上看,误解的可能性很小,所以我不编辑它,因为我认为保持原样也可以。 .我还没有读到足够多的内容来指出更细微的地方。页数是“UNIX 概念”的近四倍,体积大。

        有关“Raymond 的 UNIX 哲学”的更多信息,请参阅UNIX 编程艺术“请参阅。如果英文版是作者的官方网站你可以免费阅读它不仅比其他文档更新(尽管它是在 2003 年出版的),而且还提供了详细的 UNIX 历史、具体案例研究、与其他操作系统的思维差异以及 UNIX 哲学。还写了优缺点,而如果你想学习UNIX哲学,它涵盖的内容比《UNIX的思想》更广泛推荐《UNIX 编程艺术》是。

        顺便说一句,《The Art of UNIX Programming》的日文翻译写成《Unix 思想》Unix 哲学基础从原文可以看出,是“UNIX哲学”。

        最后

        当我写完正文,在想怎么写完的时候,我在找一本旧书的时候发现了,”软件开发的黄金法则 201”正好在我手里。本书第一版于 1996 年出版,原版“201 软件开发原理”是 1995 年 3 月。 The Unix Thinking 于 1994 年 12 月出版,因此只有四个月的时间。虽然这本书的目的不同,但我有点惊讶我读它时感受到的时代氛围是如此不同。毕竟,“Unix 理念”是在 1980 年代设定的。

        《软件开发201铁律》的P2是这样写的。

        一套原则随着学科的发展而发展。现有的原则被修改,新的原则被添加,旧的原则被丢弃。 .这是为之不惜一切的原则)。相似地,今天的原则在 30 年后看起来很荒谬。.

        在写这篇文章的时候,2022 年,距离 30 周年只有三年的时间。这是正确的。 30 年后,那些日子的原则将会改变。 UNIX 哲学保持不变?它还会按原样工作吗?并不真地。原则必须修改。这就是我们在本文中所做的。

        我怀疑有些人可能不喜欢我对 UNIX 哲学评论的修订。他们认为到目前为止对 UNIX 哲学的解释是正确的,并且认为他们过去所学的知识就足够了,他们不需要学习新的东西,也不需要改变任何东西。现在,当我翻页时,我在第 142 页发现了一些关于哲学的有趣内容,“原则 129:不要相信你所读的一切”,所以我将引用它。

        作为一般规则,相信特定哲学的人会寻找支持该哲学的数据并丢弃不支持该哲学的数据。那些相信另一个立场的人对明显不支持它的数据不感兴趣,而使用支持它的数据。假设您遇到这样的短语,“使用方法 x,您可以将生产力(或质量)提高多达 93%”。在这种情况下,最好假设该方法可能确实达到了该结果,但这将是一个例外情况。大多数项目的结果远非戏剧性的。这是很常见的。此外,在某些项目中,使用方法 x 可能会导致生产力损失。

        参考:Fenton, N.,“软件工程方法的有效性如何?”系统与软件杂志,22, 2(1993 年 8 月),第 141-146 页。

        201 条基本规则中的一些感觉已经过时,但在我看来,原则 129:不要相信你读到的所有内容仍然适用。换句话说,不要相信你读到的所有关于 UNIX 哲学的东西。

        那些相信旧 UNIX 哲学解释的人必须放弃(不考虑)本文中不支持它的“新 UNIX 哲学”解释。但在瞬息万变的计算机和软件领域,无法想象 30 多年前的思想在今天仍然以同样的形式有效。这是。UNIX 哲学没有改变,只是没有改变是。即使 UNIX 哲学没有改变,世界的软件技术也发生了很大变化。没有得到更新的 UNIX 哲学是一种落后于世界的思维方式。不要让对程序员很重要的 UNIX 哲学思想过时。

        最后但并非最不重要的一点,我将再次解释它。 UNIX 的理念是开发具有模块化、可组合程序设计的大型系统。实践中的一个例子是软件工具。其思想是不仅要创建 UNIX shell 和 UNIX 命令,还可以创建各种 shell、各种命令、各种语言、各种中间件等各种软件,并将它们组合使用。 UNIX 哲学不是坚持使用旧工具和坚持 UNIX 时代的开发方法。最初的 UNIX 理念是创造新的工具并随着时代的变化而变化。


原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308624375.html

相关文章: