软件组件

2015年9月13日

将软件开发从费力地编写代码转变为通过简单地组装组件来构建强大系统的理念,一直是我进入这个行业以来的目标。这是一个有时能瞥见,但从未真正实现的目标——尽管许多技术都曾打着工业化重用的旗号。

当我们谈论软件组件时,最难的一步往往是定义它们是什么。我最喜欢的定义仍然是这个:

组件不是技术。技术人员似乎很难理解这一点。组件是关于客户希望如何与软件交互。他们希望能够一次购买一部分软件,并能够像升级音响系统一样升级软件。他们希望新组件能够与旧组件无缝衔接,并能够按照自己的时间表进行升级,而不是按照制造商的时间表。他们希望能够将来自不同制造商的组件混合搭配。这是一个非常合理的要求。只是很难满足。

-- 拉尔夫·约翰逊

我将此总结为:软件组件是可以独立替换和升级的

我将今天的组件视为两种形式:库和服务。库包含一些在运行时链接到进程的代码,成为客户端进程的一部分。例如,Java 的 jar、C# 的程序集、Ruby 的 gem 和 Javascript 的模块。为了成为一个合适的组件,库用户应该保留何时以及是否升级供应商库的决定权。因此,如果我选择使用一个 6 个月前的库版本,那取决于我。

服务是一个独立存在于其自身进程中的组件,[1] 客户端通过一些进程间通信机制与它进行通信:RPC、通过 HTTP 的 RESTful 调用、消息传递等。服务可以按照自己的时间表进行升级,无需与客户端协调,但要做到这一点,它们必须保留现有的客户端契约,以便客户端可以选择何时升级他们对服务的利用。为了使服务成为组件,你永远不需要协调一个服务的升级与另一个服务的升级。

我认为组件是模块的一种特殊形式。我将模块定义为软件系统的划分,它允许我们通过仅理解系统中一些定义明确的子集来修改系统——模块就是这些定义明确的子集。组件是模块的一种形式,它具有独立替换的附加属性。

修订

2020-11-05:我在翻阅我的文件时发现了这篇 bliki 文章,我已经写完了,但从未发表。因此,我在我的 bliki 中添加了它,并附上了我写它的日期。

备注

1: 此处的服务与 EvansClassification 中的服务对象不同。