探讨Unix Pipe对高质量软件的启示(上).md

2023年 8月 22日 80.0k 0

前言

(本文假设您对Unix Pipe和Unix/Linux的基本用法有所了解)

“Make each program do one thing well”,这是Unix的哲学中最出名的一条。这句话的作者是Doug Mcllroy,他同时也是Unix管道的发明者。

上面这句话的字面意思是,Unix建议每一个程序都只做一件事,并专注于把这一件事做好。隐含的意思是:把一个个只能做好一件事的程序进行组合,就能非常优雅地完成一些复杂的工作。

在Unix中, 管道就是用来进行做这件事的。

管道模式

多个命令组合成了一个管道,管道中**每一个命令的输出就是下一个命令的输入。**让我们从一段非常简单的Linux命令开始:

ps -ef | grep aaa | grep -v bbb | wc -l | sort -n -k 2 -r > sorted.log

这里面用到了四个非常基础的系统自带命令: ps​​, grep​​, wc​​, sort​​。 有 Linux/Unix基础的人都知道这四个命令分别是用来做什么的。

ps: 看进程信息

grep: 匹配字符串

wc: word count

sort: 排序

而如果你不知道这个命令做什么,又可以通过 man ​ 来查看其用法。

在Linux下, 如果你想对内容进行排序,首先想到的一定是sort​命令。哪怕你想要的搜索方式、条件不知道用哪个命令,比如“按第二列字段进行数字序的倒序排序”,但你知道,sort​命令大概率是可以通过某些参数的搭配来实现想要的排序效果。这时,你输入了 man sort​, 并查到了正确的参数:​ sort -n -k 2 -r​。

同样的,如果你想查看当前进程的信息,想到的一定是ps​命令,并知道一定可以通过参数实现按不同条件进行查看,或实在不行,也能通过与grepawk​等命令的搭配来实现。

这便是“Make each program do one thing well”。每一个程序都很小巧,但都有一个清晰的、聚焦的功能。而且都非常高质量地实现这个功能。

这套机制对我们实现高质量的软件也有很多启示。因此,我更希望把它认为是一种软件的设计模式,并称之为**“管道模式”**。

启示

一个好的软件架构设计往往是高内聚+低耦合的,但这还不够,从上面的管道模式中我又补充了两条:清晰的输入和输出、通用的接口。

高内聚:每个程序都聚焦于某一个特定功能,不越界。即“单一职责”。这也降低了对这些命令的学习成本。比如当需要排序时,自然而然想到sort​命令

低耦合:各程序之间没有任何依赖关系,每个都是独立的程序,都能独立运行。

清晰的输入输出:每一个软件的输入和输出的格式都是清晰明确可预知的。比如tar​命令的输出就是一个tar包。一个常见的反例是某些函数在正常时返回值是一个json, 异常时却返回一个字符串类型的错误信息。

通用的接口:还是以上面的管道为例。无论每个命令进行了什么处理,它的输出一定都是纯文本,而这就是最通用的“接口”。假如grep​现在的输出变成了json {"code":1, "result:"xxx"}​,原来的输出结果变成了json中的"result"字段,每次从grep中读取数据就需要专门为此解一次json, 就麻烦很多了; 再进一步,假如grep​输出的结果是这个命令的作者自创的一种加密格式...

实用

接下来,我们要考虑如何把启示用到实践中。实践方法有很多,我先抛砖引玉,举一个可行的方案:

首先,在软件设计之初,梳理其业务和技术上的功能点。

然后,将程序分为接口层 - 业务层 - 基础层

接口层对外提供高质量且清晰的接口,对内操作业务层。

业务层将业务功能抽象为一个个独立的子模块,各模块之间相互独立。

业务层在实现功能时,可能会用到技术层提供的功能。

最终,业务层通过一个主逻辑模块将各种子模块提供的功能进行组合。

看到这里有些人可能会说,这怎么有点像六边形架构? 可能这也是一种殊途同归吧。

下篇中我将进一步探讨管道模式在软件上的实践。

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论