180

Shim的定义是什么?

4

8 回答 8

126

通过卡通片对垫片的简单解释

垫片的示例:

我的狗拉尔夫是一个幸运的 bash-tard(双关语)

概括

垫片是一些处理所要求内容的代码(通过“拦截”),没有任何人对此更明智。

垫片示例

shim 的一个例子是 rbenv(一个简洁的 ruby​​ 工具)。对 ruby​​ 命令的调用被“填充”。即,当您运行时bundle install,rbenv 会拦截该消息,并根据您正在运行的特定版本的 Ruby 重新路由它。如果这没有意义,试试这个例子,或者想想神仙母亲拦截消息并提供适当的结果。

而已!

关于这个例子的重要说明

  • 注意:像大多数类比一样,这并不完美:通常 Ralph 会得到他所要求的 - 但如何获得它的机制是 Ralph 不关心的。如果拉尔夫要狗粮,好的垫片会送狗粮。
  • 此外,我不想涉及语义论点(也不想涉及不必要的细节/复杂性 - 例如四个设计模式的适配器组和类似的)所以我故意通过卡通简化为一个一般概念,以便您可以快速/轻松地了解要点 - 那里这种方法的优点和缺点 - 如果您更喜欢百科全书式的定义,那么也许可以考虑Wikipedia 上的 shims 条目
于 2018-08-02T05:31:48.553 回答
95

Wikipedia 中定义的术语“shim”在技术上将根据其定义归类为“结构”设计模式。许多类型的“结构”设计模式在(有些人会说事实上的)面向对象软件设计模式参考“设计模式,可重用的面向对象软件的元素”中非常清楚地描述,也就是众所周知的“四人组”

四人帮”文本概述了至少 3 种成熟的模式,称为“代理”、“适配器”和“外观”,它们都提供“垫片”类型的功能。在大多数领域中,对于相同的词根概念,经常会使用或漏用不同的首字母缩写词,这会导致人们混淆。使用“shim”这个词来描述更具体的“结构”设计模式“代理”“适配器”“外观”当然是这种情况的一个明显例子。“垫片”只是更具体类型的“结构”模式“代理”、“适配器”、“外观”以及可能的其他类型的更通用术语。

于 2015-07-04T20:53:54.063 回答
17

根据微软的文章“Demystifying Shims”

这是一个基于英语单词 shim 的隐喻,这是一个工程术语,用于描述插入两个物体之间以使它们更好地结合在一起的一块木头或金属。在计算机编程中,shim 是一个小型库,它透明地拦截 API、更改传递的参数、处理操作本身或将操作重定向到其他地方。垫片还可以用于在与开发它们不同的软件平台上运行程序。

因此,shim 是任何充当中间人并部分或完全改变程序行为或操作的代码库的通用术语。像真正的中间人一样,它可以影响传递给该程序的数据,或影响从该程序返回的数据。

Windows API 就是一个例子:

应用程序通常不知道请求将发送到 shim DLL 而不是 Windows 本身,并且 Windows 不知道请求来自应用程序以外的源(因为 shim DLL 只是应用程序进程中的另一个 DLL) .

因此,制作“shim 三明治”的“面包”的两个程序应该无法区分与它们的对应程序对话和与 shim 对话。

使用垫片有哪些优点和缺点?

同样,从文章中:

您可以在不访问源代码或根本不更改它们的情况下修复应用程序。您会产生最少的额外管理开销......您可以通过这种方式修复合理数量的应用程序。缺点是支持,因为大多数供应商不支持填充应用程序。您无法使用 shim 修复每个应用程序。大多数人通常会考虑为供应商停业、软件战略性不足以需要支持或他们只是想争取一些时间的应用程序使用 shim。

于 2017-03-21T18:25:30.010 回答
16

至于这个词的起源,引用 Apple 的 Dictionary 小部件

noun
   a washer or thin strip of material used to align parts, 
   make them fit, or reduce wear.

verb ( shimmed, shimming) [ trans. ]
   wedge (something) or fill up (a space) with a shim.

ORIGIN early 18th cent.: of unknown origin

这似乎与网页设计师如何使用该术语非常吻合。

于 2010-01-22T09:15:38.427 回答
13

在 .net 4.5 Microsoft Fakes 框架中使用垫片 将您的应用程序与其他程序集隔离开来进行单元测试。Shims 将调用转移到特定方法到您在测试中编写的代码

于 2012-10-20T12:43:42.907 回答
10

垫片的另一个例子

当我还是个孩子的时候,我的祖母住在同一个城市。那是一个小镇。每个人都互相认识。

我曾经给她写信:

To:   Grand Ma
From: Ben

并将它投递到邮箱中…………那些用来寄给她的信件,没有失败。

我不知道也不关心它是怎么发生的。

问:这就引出了一个问题:这些信件是如何送达的?

A:这很简单:消息被填充了。因为是小镇,邮局的人知道这封信是谁写的(来自 Woop Woop 的 Ben),也知道奶奶的地址,因此修改并填充地址,以便将消息正确地传递给她。

# shimmed msg thanks to Post Office operator
To:   Mrs Ammama Kutty, 1 PA Avenue.... 
From: Ben

这是相同的基本概念,除了应用于代码。你发信息。该消息被拦截,结果如预期。那是一个垫片。

于 2020-12-03T00:57:15.147 回答
4

正如我们在这里的许多响应中看到的那样,shim 是一种在 API 级别提供功能的适配器,它不一定是该 API 的一部分。这个线程有很多好的和完整的响应,所以我不会进一步扩展定义。

但是,我想我可以添加一个很好的例子,那就是 Javascript ES5 Shim ( https://github.com/es-shims/es5-shim ):

Javascript 在过去几年中发生了很大的变化,在语言规范的许多其他变化中,许多新方法已添加到其核心对象中。

例如,在 ES2015 规范(又名 ES5)中,该方法find已被添加到Array原型中。因此,假设您正在使用此规范之前的 JavaScript 引擎运行您的代码(例如:Node 0.12),该引擎尚不提供该方法。通过加载 ES5 shim,这些新方法将被添加到Array原型中,即使您没有在更新的 JavaScript 规范上运行,您也可以使用它们。

您可能会问:为什么有人会这样做而不是将环境升级到较新的版本(比如说 Node 8)?

有很多真实案例场景表明这种方法是有意义的。一个很好的例子:

假设您有一个在旧环境中运行的遗留系统,并且您需要使用这些新方法来实现/修复功能。您的环境升级仍在进行中,因为存在需要大量代码更改和测试(关键组件)的兼容性问题。

在此示例中,您可以尝试制作您自己的此类功能版本,但这会使您的代码更难阅读、更复杂、可能引入新的错误并且需要大量额外的测试才能覆盖您知道的功能在下一个版本中可用。

相反,您可以使用此填充程序并利用这些新方法,利用此修复/功能将在升级后兼容的事实,因为您已经在使用已知在下一个规范中可用的方法。还有一个额外的原因:由于这些方法是下一个语言规范的本机方法,因此它们很有可能比您尝试制作自己的版本时可以完成的任何实现都运行得更快。

另一个欢迎这种方法的真实场景是在浏览器级别。假设您需要支持旧浏览器并希望利用这些新功能。Javascript 是一种允许您在其核心对象中添加/修改方法的语言(例如向 Array 原型添加方法),并且这些 shim 库足够聪明,只有在当前实现缺少这些方法时才添加这些方法。

PS:1)您将看到与这些 Javascript 垫片相​​关的术语“Polyfill”。Polyfill 是一种更专业的填充程序,用于在不同的浏览器级别规范中提供前向兼容性。顺便说一句,我上面的例子正是指这样的例子。

2) 垫片不限于此示例(添加将在未来版本中可用的功能)。有不同的用例也被认为是垫片。

3) 如果您对这个特定的 polyfill 是如何实现的感到好奇,您可以打开 Javascript Array.find规范并滚动到页面末尾,您将在其中找到该方法的规范实现。

于 2018-05-02T17:45:17.877 回答
-1

SHIM 是对所有服务进行的另一级安全检查,以保护上游系统。SHIM 服务器根据请求中传递的用户凭据(SOAP / RESTFUL)使用标头用户凭据验证每个传入请求。

于 2018-12-14T05:07:20.813 回答