Future Portability
A simple but solid goal when developing software should be to remain as independent as possible from third-party software, so that your project does not depend on any one vendor or environment. However, you should not reinvent the wheel and write your own libraries. Instead you should isolate all of your library-specific code in a few modules, including all references to a library's functions, data structures, classes, header files, constants, and global variables.When you isolate all system-dependent code in a few modules, porting to new environments in the future might be as easy as rewriting the wrapper modules to support a new library. There is no guarantee that your new library can be mapped onto the function calls of the old library, but chances are most of it will.
Don't be tempted to ignore this argument, even if you can write compatible wrappers on future systems to make them emulate your current environment. This can be a trap. No matter how much time you allocate for a future port, you will never implement all of the options of your current library. By taking the time to isolate your system-dependent code now, parameter checking can be tightened in the future to prevent use of features that are not implemented in all of your environments.
While you are wrapping third-party library functions, you will probably also want to wrap the file- and memory-access functions that you use. Even though the ANSI file-access functions may be all you need right now, there is a good chance that a future environment (a network, Windows, OS/2, etc.) will require you to use some special access functions. For memory access, you may want to use a handle for major data structures to allow future porting to virtual-memory environments. A simple, easy-to-maintain handle table allows for future migration.
New-Version Protection
No one can predict how a future release of a commercial library will behave. There will always be bug fixes and enhancements that change the behavior of the library, for better or for worse. If your application depends on the behavior of the old version, you may be able to correct for the changes in the wrappers. For example, Microsoft changed the return value of the fputs function in Microsoft C between versions 4.0 and 5.0. Although the new return value is now an ANSI-standard function, no one expected fputs to change. An application developed with a wrapper for fputs could probably have been revised to accommodate this change with minimal effort.
Better Parameter and Return Value Checking
In a perfect world, programmers check the values of all parameters before passing them to functions. They also check all function return values to catch any errors. In the real world, many junior-level programmers don't know all of the conditions they should check for. Even senior-level programmers may overlook unlikely error conditions, especially under the stress of a deadline.Wrapper functions can check for any unlikely conditions and call a global error-reporting function. The application can determine where such error messages should be directed, depending upon the current state.
For instance, when retrieving a database record you normally write application code that handles only two conditions. If the call fails, it was most likely caused by a missing record. In the wrapper, you can take care of checking for unusual conditions like a corrupted database and branch to an appropriate routine to shut down and perform an integrity check on the database.
This approach allows you to write your code checking software in increments. As you gain experience with a library and discover new conditions that merit checking, you can add these checks without modifying all of your application code.
Programming for the Lowest Common Denominator
While checking parameters, you can also check for options that are not available on all the platforms your software supports. If a future port determines that an option should not be used, the wrapper can provide a warning for programmers in the old environment as well as the new one. This will stop future programmers from using options that can't be supported on all systems.
Simplification
If you have six programmers on a team developing a Windows application, should you train all six in Windows development? Not necessarily. By assigning two or three members to write the wrappers and document the available options, you can decrease the learning curve for the remaining team. The remaining team can then focus on problems they are better qualified to solve. The team's database experts, for instance, can concentrate on database issues.Documentation for the wrappers can be as simple as, "This duplicates the functionality of the xyz function in library ABC, with the following changes..." However, the documentation for library ABC will change from one release to another, but your wrapper's interface should not. If time permits, you should write complete documentation for the wrapper. Otherwise, the library's release number should be noted and the old manuals retained for reference.
If you have the time to properly document your work, you might as well try to simplify the application developer's job. If you find that calls to a library function are always preceded by one or more "setup" functions, it may make sense to combine the functions into a single wrapper call. Also, if you find yourself always initializing data structure members to a certain value before calling a function, this can easily be placed in the wrapper.
Enforced Corporate Standardization
By limiting parameter choices and function calls in the wrappers, you can make a more consistent application. The look and feel of the application should not be a decision left to junior-level programmers, but rather should be a matter of corporate policy. Wrappers are the perfect place to enforce this policy.
Uniformity of Naming Standards
Instead of using whatever naming standards are used in a third-party library, the wrappers can be written to conform to your company's naming standards. This shortens the learning curve for new programmers, and makes code easier to read. For instance, if your company does not normally use Hungarian notation, calls to Windows API functions probably look out of place.