框架 vs 工具包 vs 库

331

框架、工具箱和库之间有什么区别?

12个回答

490
最重要的区别,实际上是库和框架之间的定义性区别,就在于控制反转
这是什么意思呢?这意味着当您调用库时,处于控制状态。但是对于框架,控制被反转了:框架会调用您。(这就是所谓的好莱坞原则:不要打电话给我们,我们会打电话给你。)这基本上就是框架的定义。如果没有控制反转,它就不是一个框架。(我在看着你,.NET!)
基本上,所有的控制流程已经在框架中了,只有一堆预定义的白色空白可以用您的代码填充。
另一方面,库是一个您可以调用的功能集合。
我不知道术语工具包是否真正被定义清楚。仅仅是"kit"这个词似乎表明了某种模块化,即一组独立的库,您可以从中挑选和选择。那么,工具包与仅仅是一堆独立的库有何不同呢?集成:如果您只有一堆独立的库,那么不能保证它们能很好地协同工作,而工具包中的库已经被设计为可以很好地协同工作,您只需要使用其中的一部分就可以了。

但那只是我对这个术语的解释。与库和框架不同,它们有明确定义,我认为没有一个被广泛接受的工具包定义。


4
这可能是不正确的。框架可以执行控制反转,但并非必须如此。你对CSS框架有什么看法?框架会在你不知不觉中为你完成很多事情,这就是它们不能与同类框架组合使用的原因(如果你将两个CSS框架组合在一起,准备好迎接惊喜吧)。其中一个它们可以在你不请求的情况下完成的事情就是拥有应用程序的控制流。我认为@Sridhar-Sarnobat的答案可能更好。 - neuron
作为一个可靠的参考,GoF 的《设计模式》书中的第 1.6 节将 toolkit 定义为一个 class 库,即面向对象的 subroutine 库的等价物:‘通常,应用程序将包含来自一个或多个预定义类库(称为 toolkits)的类。工具包是一组相关且可重用的类,旨在提供有用的通用功能。工具包的一个示例是一组集合类,用于列表、关联表、堆栈等。C++ I/O 流库就是另一个示例。 - Géry Ogam
1
工具包不会对您的应用程序施加特定的设计;它们只提供可以帮助您的应用程序完成其工作的功能。它们让您作为实现者避免重新编码常见功能。工具包强调代码重用。它们是子程序库的面向对象等效物。 - Géry Ogam

131
马丁·福勒在他的控制反转文章中讨论了库和框架之间的区别:

控制反转是一个框架与库不同的关键部分。 库本质上是一组可以调用的函数,这些天通常被组织成类。每次调用都会执行一些操作并将控制权返回给客户端。

框架体现了一些抽象的设计,并内置更多的行为。为了使用它,您需要在框架的各个位置插入自己的行为,可以通过子类化或插入自己的类来实现。然后框架的代码在这些点调用您的代码

总之:你的代码调用库,而框架则调用你的代码。

75

框架的一个假定好处是可以在不同平台上移植它,这样就会有更少的问题。但在实践中,将应用程序从一个平台移植到另一个平台似乎是一种不太可能发生的情况,因此我不想面临它带来的头痛。 - Sridhar Sarnobat
对于鸟瞰式的方法,你做得很好。 - Jacksonkr

73

Barrass提供的答案可能是最全面的。不过,解释可以更加清晰易懂。大多数人忽略了这些都是嵌套的概念。所以,让我为您列出来。

编写代码时:

  • 最终你会发现程序中有一些重复的代码,于是你将其重构为函数/方法
  • 最终,在编写了几个程序之后,你会发现自己在新程序中复制已经制作好的函数。为了节省时间,你将这些函数打包成
  • 最终你发现每次使用某些库的时候都要创建相同类型的用户界面。因此,你重构了工作并创建了一个工具包,它允许您通过通用方法调用更轻松地创建UI。
  • 最终,你已经编写了很多应用程序,它们都使用相同的工具包和库,于是你创建了一个框架,其中已经提供了通用版本的样板代码,所有你需要做的就是设计UI的外观并处理用户交互产生的事件。

总的来说,这完全解释了这些术语之间的区别。


这个答案是对包含IoC的前两个答案的补充,但是由于省略了IoC并将框架与“样板代码”混淆在一起,因此这个答案不足以严格正确。 - Timothee Howland
鉴于控制反转(IoC)既不是框架的要求,也不是框架所独有的,而且考虑到框架的主要作用是提供类似样板文件的代码(即经常在多个应用程序中重复使用的代码,但每种情况需要进行微小修改,并且可以通过重构将这些修改视为参数或配置),我认为我的通用答案非常全面和正确。 - Arkain

72

介绍

与相关代码集合有关的术语有很多,它们具有历史意义(本答案的目的是指1994/5年之前的历史时期)和现实意义。读者应该了解这两者,特别是在阅读关于计算机/编程的经典文本时。

无论是历史上还是现在,库都是与特定任务或一组紧密相关任务有关的代码集合,这些任务在大致相同的抽象级别上运行。它通常没有自己的目的或意图,并旨在由客户端代码使用(消耗)并与客户端代码集成,以帮助客户端代码执行其任务。

工具包

从历史上看,工具包是一个更专注的库,具有明确定义和特定的目的。目前,这个术语已经不再流行,并且几乎只用于当前时代的图形小部件和GUI组件(据本文作者所知)。工具包通常在比库更高的抽象层次上运作,并且通常会消耗和使用库本身。与库不同,工具包代码通常用于执行客户端代码的任务,例如构建窗口、调整窗口大小等。工具包内较低的抽象级别要么是固定的,要么可以按照规定的方式由客户端代码操作。(想想窗口样式,它可以是固定的,也可以在客户端代码预先更改。)

框架

在历史上,框架是一套相互关联的库和模块,分为“通用”或“特定”类别。通用框架旨在通过提供通用功能(例如跨平台内存管理、多线程抽象、动态结构(以及通用结构)等)来提供全面集成的应用程序平台。历史上的通用框架(不包括依赖注入,请参见下文)已经几乎被面向对象语言中的多态模板化(参数化)打包语言提供所取代,例如C++的STL,或非面向对象语言的打包库(保证Solaris C头文件)。通用框架在不同的抽象层面上运作,但通常是低级别的,像库一样依赖于客户端代码来执行其特定任务。

历史上,'特定'框架是为单个(但通常是庞大的)任务开发的,例如用于工业系统的"命令与控制"系统和早期网络堆栈,并在高层次的抽象层面上运作,就像工具包一样用于执行客户端代码的任务。

目前,框架的定义变得更加专注,并采用了“控制反转”原则作为指导原则,因此程序流程以及执行由框架完成。然而,框架仍然针对特定的输出进行定位;例如,针对特定操作系统的应用程序(例如MS Windows的MFC),或者针对更通用的工作(例如Spring框架)。

SDK:“软件开发工具包”

SDK是一组工具,可帮助程序员创建和部署非常特定于某个平台或以非常特定方式运行的代码/内容。 SDK可以仅由一组库组成,客户端代码必须以特定方式使用这些库,并且可以像正常编译一样编译,也可以由一组二进制工具组成,这些工具创建或调整二进制资产以生成其(SDK的)输出。

引擎

引擎(在代码集合术语中)是一个二进制文件,将运行定制内容或以某种方式处理输入数据。游戏和图形引擎可能是最普遍使用此术语的用户,并且几乎普遍与SDK一起使用以针对引擎本身,例如UDK(虚幻开发工具包),但还存在其他引擎,例如搜索引擎和RDBMS引擎。

一个引擎通常允许客户端访问它的一些内部,但并非总是如此。最常见的情况是为了针对不同的架构、改变引擎输出的呈现方式或进行调整。开源引擎是指可以根据需要自由更改和修改的引擎;某些专有引擎则是完全固定的。然而,在全球范围内使用最广泛的引擎几乎肯定是 JavaScript 引擎。JavaScript 引擎嵌入到所有浏览器中,有许多 JavaScript 引擎将 JavaScript 作为输入进行处理,然后输出渲染。

API:应用程序编程接口

我要回答的最后一个术语是我的个人痛点:API。历史上,API用于描述应用程序或环境的外部接口,它本身能够独立运行,或者至少在初始执行后无需任何必要的客户端干预即可执行其任务。诸如数据库、文字处理器和Windows系统之类的应用程序会向外部接口公开一组固定的内部钩子或对象,客户端可以调用/修改/使用等来执行原始应用程序可以执行的功能。API的功能因API提供的功能量以及客户端代码重用了多少核心应用程序而异。(例如,文字处理API可能需要在每个客户端代码实例运行时加载完整的应用程序背景,或者只需加载其中一个链接库;而运行的窗口系统将创建由自己管理的内部对象,并返回句柄给客户端代码来代替使用。)

目前,API这个术语的范围已经变得更加广泛,并且通常用于描述本答案中几乎所有其他术语。实际上,应用于此术语的最常见定义是API向另一段软件(客户端代码到API)提供了一个收缩的外部接口。在实践中,这意味着API是语言相关的,并且具有由上述代码集合之一提供的具体实现,例如库、工具包或框架。

备注

如上所述,上述术语的历史和当前定义已经发生了转变,这可以看作是基础计算原理和范例的科学理解的进步以及特定软件模式的出现所致。特别是,90年代早期的GUI和窗口系统帮助定义了许多这些术语,但自从操作系统内核和窗口系统的有效混合化(除了Linux可能),以及依赖注入/控制反转作为消费库和框架的机制被大规模采用后,这些术语不得不改变它们各自的含义。


附言(一年后)

经过一年的深思熟虑,我拒绝将IoC原则作为框架和库之间的定义性差异。确实有很多知名作者认为它是,但也有几乎同样数量的人认为它不是。现在有太多“框架”没有使用IoC,无法说它是定义性原则。搜索嵌入式或微控制器框架会发现许多不使用IoC的框架,我现在相信.NET语言和CLR是“通用”框架的可接受后代。对我来说,说IoC是定义性特征太过死板,我无法接受,这也排斥了任何自称符合上述历史表述的框架。

有关非IoC框架的详细信息,请参见上面提到的许多嵌入式和微框架,以及任何不通过语言提供回调的历史框架(好吧,回调可以针对具有现代寄存器系统的任何设备进行黑客攻击,但普通程序员做不到),显然还有.NET框架。


根据您的更新,您是否有更精细的区分?还是您暗示“框架”只是一个模糊的依赖项,可以为您执行某些操作?我想作为应用程序开发人员,您不必担心嵌入式程序员的词汇。 - Sridhar Sarnobat
请问您能否详细说明一下,在您对API的解释中,“外部接口”是什么意思? - Syed Shaharyaar Hussain
我认为驳斥控制反转(IoC)论点的更好方式是提出“库或工具包是否也可以从消费者处接管控制?”我认为答案是肯定的。 - rfportilla

13

一个库就是将多个方法/函数打包成一个可以被导入到代码项目中并可重复使用的包。

框架是一组强大的库或者库集合,为你的代码提供了“基础”。框架遵循控制反转模式。例如,.NET框架是一个由协同库构成的巨大集合,你可以在其上构建应用程序。当人们说“框架”时,你可以认为它意味着更大、更强大的库套件,这些库将成为应用程序中不可或缺的一部分。

我将工具箱和SDK看作是同样的东西。它附带有文档、示例、库、封装等。同样地,你可以说这和框架一样,你也可能是正确的。

它们几乎可以互换使用。


5

非常相似,框架通常比库更发达和完整,而工具包可以简单地是类似库和框架的集合。

这是一个非常好的问题,可能稍微有点主观性,但我认为这是我能给出的最好答案了。


4

我认为大家都一致认为,库是已经编写好的代码,可以供你使用,以免再次编写。代码必须以一种允许你查找所需功能并从自己的代码中使用它的方式进行组织。

大多数编程语言都带有标准库,特别是一些实现某种集合的代码。这总是为了方便,使您不必自己编写这些内容。同样,大多数编程语言都有构造函数,允许您从库中查找功能,例如动态链接、命名空间等。

因此,经常需要重复使用的代码非常适合放在库中。

工具包

用于特定目的的一组工具。这是一致的。问题是,什么被认为是工具,什么不是。我会说没有固定的定义,这取决于称自己为工具包的事物的上下文。工具的例子可能包括库、小部件、脚本、程序、编辑器、文档、服务器、调试器等。

另一个需要注意的是“特定目的”。这个总是正确的,但工具包的目的范围可以根据制作工具包的人很容易地改变。所以它可以很容易地成为程序员的工具包,或者它可以成为字符串解析的工具包。一个工具包可以广泛地涉及所有与编程有关的工具,而另一个则更加精确。

SDK通常是工具包,因为它们试图将一组工具(通常是多种工具)捆绑成单个软件包。

我认为共同点在于工具可以为您完成某些事情,完全地或者帮助您完成它。而工具包只是一组所有执行或帮助您执行特定一组活动的工具。

框架

框架没有被明确定义。它似乎是一个可以为您的代码构建框架的任何东西的概括性术语。这意味着您会针对框架构建您的代码,而您会针对您的代码构建库。

但是,有时看起来框架这个词是和工具包甚至库使用相同的意思。.Net Framework主要是一个工具包,因为它由FCL(库)和CLR(虚拟机)组成。因此,您可以将其视为在Windows上进行C#开发的工具包。Mono是Linux上进行C#开发的工具包。然而,他们称之为框架。这样考虑也是有道理的,因为它对您的代码进行了框架设置,但框架应该更多地支持和保持事物在一起,而不是做任何工作,所以我的观点是这不是您应该使用这个词的方式。

我认为这个行业正在努力让框架意味着已经编写好了的程序,其中缺少必须提供或自定义的部件。我认为这是一件好事,因为“框架”这个词在其他用途上的“工具包”和“库”都是很好的精确术语。


3

框架:安装在您的计算机上并允许您与之交互。没有框架,您无法向计算机发送编程命令。

库:旨在解决某个问题(或多个与同一类别相关的问题)

工具包:由许多代码片段组成,可以解决多个问题和多个问题(就像一个工具箱一样)


2

我认为这有点主观。工具包最容易使用。它只是一堆可以使用的方法和类。
关于库和框架的问题,我根据它们的使用方式作出区分。我在很久以前读到过一个完美的答案。框架调用你的代码,但是你的代码调用库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接