试想一下Windows 之前之前的个人电脑硬件市场。例如,在那些日子里,每个应用程序都需要有自己的驱动程序。这意味着如果一台打印机没有WordStar 和Lotus 1-2-3 的驱动程序,那么它在办公环境中几乎毫无用处。如果您的打印机可以同时使用这两个应用程序,但您现在还需要来自Harvard Graphics 的输出,该怎么办?您需要确保应用程序本身知道如何处理您的特定打印机。
也就是说,N 个应用程序和 M 个打印机意味着需要 N×M 个驱动程序。
使用 Windows,硬件制造商可以为 Windows 编写驱动程序,只要应用程序知道如何通过 Windows 提供的接口与打印机通信,它就不需要知道任何有关特定硬件的信息。
这使得硬件和软件都更便宜。具体来说,应用程序程序员不需要对现有的特定硬件有太多了解。而且,在编写应用程序时不存在的硬件仍然可以与应用程序一起使用,如果它们都通过相同的驱动程序接口进行通信。
当然,这是一个相当简化的情况。即使使用 DOS,也有 ESC/P、PCL,当然还有 PostScript,所以并不是每台打印机都是独一无二的,但应用程序仍然需要了解这些细节。
这里的情况类似。在大多数情况下,知道如何与DBI 对话的 Perl 应用程序不需要关心每个特定数据库的大部分各种细节。为 Perl 程序提供一个特定的数据库只需要为它编写适当的DBD::* 模块。来自DBI documentation 的下图说明了这一点:
||
.-. .-------------。 .-------------。
.--------。 | |---| XYZ 驱动器 |---| XYZ 引擎 |
|珀尔 | | | `-------------' `-------------'
|脚本| |一个| |D| .-------------。 .-------------。
|使用 |--|P|--|B|---|Oracle 驱动程序 |---|Oracle 引擎|
| DBI | |我| |我| `-------------' `-------------'
| API | | |...
|方法| | |... 其他驱动程序
`-------' | |...
`-'
一旦出现DBI,为给定引擎编写或使用特定专用模块的动力就会降低。当然,拥有一个独立模块来单独与某处的 ABC 引擎进行通信可能有某些好处,但必须权衡这些好处与成本。其应用程序需要访问数据库的程序员需要了解陌生 API 的来龙去脉。如果访问ABC 引擎的唯一方法是通过DBI 以外的方式,那么ABC 引擎不允许程序员利用他们已经知道的东西。使用ABC 引擎的专用API 的应用程序无法与其他引擎一起使用,或者应用程序程序员必须提供自己的数据库独立接口,并对其进行编程,并将DBD 复制到DBI 层。但是,既然已经建立了独立于数据库的接口及其随附的数据库驱动程序,为什么还要为此烦恼呢?
看看DBIx::Class 的引擎特定部分,想象一下如果我们还没有为每个引擎提供DBD 会做多少工作。然后,想象一下如果Rose::DB 也必须复制整个驱动程序集。
或者,您可以想象如果每个房子都有自己喜欢的墙壁插座类型并且每个电器都有自己喜欢的电源插头会发生什么。每台笔记本电脑都可以有自己的变压器,但我们都受益于标准插头和插座,它们可以从中获取电力。 DBI 处于即插即用级别。