用 Unix 的设计思想来应对多变的需求
程序员文章站
2022-05-26 20:40:50
...
在软件设计领域,有很多设计模式可以参考。但本文作者另辟蹊径,从UNIX设计思想的角度来阐述什么是好的软件设计,什么样的设计可以把需求变更对软件开发的影响降到最低。
以下为原文文章:
我曾经在《UNIX传奇》的下篇中写过一些关于UNIX的设计哲学和思想(这里重点推荐大家看一下《The Art of UNIX Programming》),以前也写过一篇《一些软件设计的原则》。不过,这些内容都太多了,记不住。其实,这么多年来,我的经验告诉我,无论是UNIX设计,还是面向对象设计,还是别的什么如SOA、ECB、消息、事件、MVC、网络七层模型、数据库设计等等,他们都在干三件事——解耦,解耦,还是解耦!所谓解耦,就是让软件的模块和模块间尽量少地依赖起来。
一、现实当中的例子
让我先举几个现实生活中的例子:
1、现实社会中,制造灯具的工厂完全不关心制造灯泡的工厂,制造灯泡的工厂也完全不关心制造灯具的工厂。但是,灯泡和灯饰可以很完美地组合成用户所喜欢的样子。他们是怎么做到的?
2、互联网上,网站开发者完全不用关心用户在用什么样的操作系统,什么样的客户端浏览器 (当然事实上,浏览器的不标准也让网站开发者很头痛,这里只是举个例子)。反过来,用户也不关心网站开发者在用什么技术来开发网站。但是大家在完全不关心对方的情况下,却可以很正常地协同工作在一起。为什么?
这样的例子太多了。为什么可以做成这样呢?因为大家依赖的是同一个接口。灯具和灯饰并不互相依赖,它们依赖的是一个接口;网站开发者和网站的用户依赖的还是接口——HTTP协议。这就是面向对象的核心思想——依赖于接口而不是依赖实现,这也就是解耦。当你看过这两个例子以后,我希望你以后设计的软件至少不能比我们现实社会中的这些方法要差。不然,你就是在让社会倒退了。
你可能会说,这与UNIX和应对需求变化有什么关系?下面让我们再来看一下UNIX的设计。
二、UNIX设计的例子
下面是几个UNIX下的例子:
1、UNIX下,所有的硬件都可以通过文件的方式存取。于是,软件和硬件的耦合被解开了,操作系统只需要把硬件统统变成文件即可。而程序也只需要使用三个工具:一个是fd,一个是read(),一个是write(),就可以来操作任意的硬件了,这就是抽象,简单到不行。
2、UNIX下,所有的命令都可以用管道串起来(管道绝对是个伟大的发明),这样,所有的命令间的交互全部解耦到只依赖于STD_IN和STD_OUT设备上。最酷的是,用户可以使用管道任意地拼装那些命令,以完成各式各样的功能。管道这个设计思想可以映射为今天的Web Service,你可以任意地拼装各种Web Service。
看到这里,你会发现,这还是解耦,本质上来说,也是一种依赖倒置——OOD的精髓。但是,UNIX还不仅仅是这些。我们再来看几个例子:
1、UNIX下,软件都是绿色地安装。在iOS上更明显——各个程序间基本上互不干扰,这个程序产生的垃圾文件不会影响到另一个程序。你删除一个程序不会影响到另一个程序。你也可以删除这些程序,只要把内核留着,系统依旧可以启动。
2、UNIX下,你可以通过设置一些环境变量,让多种环境同时存在。例如,某个LAMP 用的是Apache 2.0、Mysql 4.0、PHP 4.0,而另一个个LAMP用的是Apache 2.2、Mysql 5.0、PHP 5.3,你不但可以方便地在系统中切换这两个环境,你甚至还可以同时启动它们。
3、UNIX下,你可以随意地替换你想要的程序。例如,你不喜欢bash,你可以替换成ksh/csh;你不喜欢awk,你可以替换成gawk;所有的东西都像零件一样,你不喜欢什么,你就可以替换什么。
这三个例子告诉了我们——当你把你的软件设计的耦合度非常低时,你就可以随意地组合,随意地安排你的系统。相当的灵活,灵活到Windows到今天都学不会。
三、应对需求变化
看到这里,你可能明白我想说的是什么了。你可能开始觉得怎么样的系统设计会更有效了。如果你还记得《Steve Y 对平台的长篇大论》,你就会知道我想说什么了。是的,我想说的就是,当你真正了解了UNIX的设计思想后,你会觉得今天的这些设计理念都是对UNIX设计思想的一种传承或是变种。这些设计理念就是:
你可能会说我说得太简单了,或者,你可能觉得有一些系统这样做没必要。不错,我承认这一点。不过,你可以有选择的或多或少地试试(其实,我相信你已经在不自觉的或多或少的在使用这种方式开发软件了)。
以下为原文文章:
我曾经在《UNIX传奇》的下篇中写过一些关于UNIX的设计哲学和思想(这里重点推荐大家看一下《The Art of UNIX Programming》),以前也写过一篇《一些软件设计的原则》。不过,这些内容都太多了,记不住。其实,这么多年来,我的经验告诉我,无论是UNIX设计,还是面向对象设计,还是别的什么如SOA、ECB、消息、事件、MVC、网络七层模型、数据库设计等等,他们都在干三件事——解耦,解耦,还是解耦!所谓解耦,就是让软件的模块和模块间尽量少地依赖起来。
一、现实当中的例子
让我先举几个现实生活中的例子:
1、现实社会中,制造灯具的工厂完全不关心制造灯泡的工厂,制造灯泡的工厂也完全不关心制造灯具的工厂。但是,灯泡和灯饰可以很完美地组合成用户所喜欢的样子。他们是怎么做到的?
2、互联网上,网站开发者完全不用关心用户在用什么样的操作系统,什么样的客户端浏览器 (当然事实上,浏览器的不标准也让网站开发者很头痛,这里只是举个例子)。反过来,用户也不关心网站开发者在用什么技术来开发网站。但是大家在完全不关心对方的情况下,却可以很正常地协同工作在一起。为什么?
这样的例子太多了。为什么可以做成这样呢?因为大家依赖的是同一个接口。灯具和灯饰并不互相依赖,它们依赖的是一个接口;网站开发者和网站的用户依赖的还是接口——HTTP协议。这就是面向对象的核心思想——依赖于接口而不是依赖实现,这也就是解耦。当你看过这两个例子以后,我希望你以后设计的软件至少不能比我们现实社会中的这些方法要差。不然,你就是在让社会倒退了。
你可能会说,这与UNIX和应对需求变化有什么关系?下面让我们再来看一下UNIX的设计。
二、UNIX设计的例子
下面是几个UNIX下的例子:
1、UNIX下,所有的硬件都可以通过文件的方式存取。于是,软件和硬件的耦合被解开了,操作系统只需要把硬件统统变成文件即可。而程序也只需要使用三个工具:一个是fd,一个是read(),一个是write(),就可以来操作任意的硬件了,这就是抽象,简单到不行。
2、UNIX下,所有的命令都可以用管道串起来(管道绝对是个伟大的发明),这样,所有的命令间的交互全部解耦到只依赖于STD_IN和STD_OUT设备上。最酷的是,用户可以使用管道任意地拼装那些命令,以完成各式各样的功能。管道这个设计思想可以映射为今天的Web Service,你可以任意地拼装各种Web Service。
看到这里,你会发现,这还是解耦,本质上来说,也是一种依赖倒置——OOD的精髓。但是,UNIX还不仅仅是这些。我们再来看几个例子:
1、UNIX下,软件都是绿色地安装。在iOS上更明显——各个程序间基本上互不干扰,这个程序产生的垃圾文件不会影响到另一个程序。你删除一个程序不会影响到另一个程序。你也可以删除这些程序,只要把内核留着,系统依旧可以启动。
2、UNIX下,你可以通过设置一些环境变量,让多种环境同时存在。例如,某个LAMP 用的是Apache 2.0、Mysql 4.0、PHP 4.0,而另一个个LAMP用的是Apache 2.2、Mysql 5.0、PHP 5.3,你不但可以方便地在系统中切换这两个环境,你甚至还可以同时启动它们。
3、UNIX下,你可以随意地替换你想要的程序。例如,你不喜欢bash,你可以替换成ksh/csh;你不喜欢awk,你可以替换成gawk;所有的东西都像零件一样,你不喜欢什么,你就可以替换什么。
这三个例子告诉了我们——当你把你的软件设计的耦合度非常低时,你就可以随意地组合,随意地安排你的系统。相当的灵活,灵活到Windows到今天都学不会。
三、应对需求变化
看到这里,你可能明白我想说的是什么了。你可能开始觉得怎么样的系统设计会更有效了。如果你还记得《Steve Y 对平台的长篇大论》,你就会知道我想说什么了。是的,我想说的就是,当你真正了解了UNIX的设计思想后,你会觉得今天的这些设计理念都是对UNIX设计思想的一种传承或是变种。这些设计理念就是:
- 解耦、解耦、解耦。尽量地让你的模块不要在实现上耦合,而是耦合某个规范,某个标准。
- KISS、KISS、KISS。要做到高度解耦,你的模块就一定要很简单。当然不是说简单到只有几行代码,而是简单到只做一件事,并把这件事做到极致,然后通过某个标准拼装起来。
- 拼装、拼装、拼装。我想不起来是谁曾说过这样一句话:“当我想用一个模块的时候,我直接调用就好了,没有必要像C或Java一样,还要编译”。是的,拼装需要一个框架,需要一种标准协议,然后让所有的系统都耦合在这种规范上,各自独立运行。就像一个机器上的各个部件,当我觉得这个部件性能不好,换一个部件就是了(例如,当我们在尝试不同的算法的时候)。
你可能会说我说得太简单了,或者,你可能觉得有一些系统这样做没必要。不错,我承认这一点。不过,你可以有选择的或多或少地试试(其实,我相信你已经在不自觉的或多或少的在使用这种方式开发软件了)。
上一篇: 使用 UNIX 的 10 个良好习惯
下一篇: C语言、UNIX之父丹尼斯·里奇去世