With the prevalence of 64-bit operating systems, many applications have become 64-bit compliant. But, there is a large group of existing native applications that still run in 32-bit compatibility mode on 64-bit operating systems. While integrating 64-bit applications with 32-bit applications, we face numerous compatibility challenges relating to the size of the data type, address, pointers, binary format, and runtime dependencies. The 64-bit applications cannot load the 32-bit libraries. Therefore, no direct integration is possible with the exposed APIs of the 32-bit application. Also, if shared objects (executable and libraries) in the same process space make different assumptions about any of these compatibility issues, even if the other process is of similar architecture (64-bit only), incompatibility problems will arise.
To solve the problem of runtime incompatibility, we need to maintain two separate runtime environments with an inter-process communication mechanism between them. This allows any potential incompatibilities to co-exist, as long as each process is internally consistent. We can use a shim library that is as small as possible and with few external dependencies to achieve the process separation.
The term “shim” should technically be classified, based on its definition, as a “Structural” design pattern. The many types of “Structural” design patterns are quite clearly described in the object-oriented software design patterns reference “Design Patterns, Elements of Reusable Object-Oriented Software” better known as the “Gang of Four“. The “Gang of Four” text outlines at least 3 well-established patterns known as, “Proxy”, “Adapter” and “Facade” which all provide “shim” type functionality. It’s oftentimes the use and or misuse of different acronyms for the same root concept that causes people confusion. Using the word “shim” to describe the more specific “Structural” design patterns (Proxy, Adapter, Facade and possibly others) certainly is a clear example of this type of situation. A “shim” is simply a more general term for the more specific types of Structural patterns.
Shim vs Wrapper
A shim is typically something written specifically to maintain backwards compatibility. For example, if you have two versions of an API, version 1 and version 2. So, rather than maintaining version 1 independently of version 2, you can write a shim that intercepts calls to version 1 of the API, translates the parameters to what version 2 requires, and then returns the results. Typically, the provider of the API writes a shim, rather than the consumer.
A wrapper is written by the consumer of an API. We can switch the underlying API without the rest of your code has to know if we have written a wrapper to it.
When We Use a Shim
- Using an application from a vendor that is no longer in business. Several applications are from vendors that have since gone out of business; so clearly, support is no longer a concern. However, because the source code is not available, shimming is the only option for compatibility mitigation.
- Building the application internally. The team may not be able to fix all of the compatibility issues before the planned deployment of new versions of the application. So, they may choose to shim the applications that can be shimmed and modify the code on the remaining ones.
- When acquiring the application from a vendor that will eventually be releasing a compatible version, but support is not critical. When an off-the-shelf application is neither business-critical nor important, some customers use shims as a stopgap solution. Users could theoretically wait until a compatible version is available, and its absence would not block the deployment. But, being able to provide users with a shimmed and functional version can bridge that gap until a compatible version is available.
Why Use Shims
We can fix applications without access to the source code, or without changing them at all. We just incur a minimal amount of additional management overhead.
Shim can be used as another level of security check, done for all the services, to protect upstream systems. It will validate every incoming request, with headers user credentials, against the user credentials, which are passed in the request(SOAP/REST).
Disadvantages of Shim
The downside is the support as most vendors don’t support shimmed applications. You can’t fix every application using shims. Most people consider shims for applications where the vendor is out of business, the software isn’t strategic enough to necessitate support, or they just want to buy some time.