3.8 模式八:接口的扩展和兼容性
对于保留至今的上古旧接口经常出现设计考虑不周的情况
在标准C库中,大量早期接口的实现必须使用全局变量,从而导致这些接口不是线程安全的(上古时候没有多线程的东西)
某些接口的参数或者返回值之参数类型设计不当
扩展方法一:新旧接口共存
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
strtok是早期C标准库里提供的字符串分割函数,然而它不是线程安全的,因为它内部使用了静态缓冲区。strtok_r是后期的线程安全版本,新老版本同时共存于标准库当中。
扩展方法二:旧接口只是新接口的包装
// 最新接口
HWND CreateMainWindowEx2(...)
{
...
}
// 次新接口是最新接口的封装
HWND CreateMainWindowEx1()
{
CreateMainWindowEx2(...);
}
// 初始接口是次新接口的封装
HWND CreateMainWindow()
{
CreateMainWindowEx1();
}
扩展方法三:强制使用新接口,旧接口标记位废弃或者移除
gpointer g_memdup(gconstpointer mem, guint byte_size);
// since 2.68
gpointer g_memdup2(gconstpointer mem, gsize byte_size);
// 使用时
#if GLIB_CHECK_VERSION(2, 68, 0)
cache->cache[pos] = g_memdup2(entry, sizeof(*entry));
#else
cache->cache[pos] = g_memdup(entry, sizeof(*entry));
#endif
扩展接口需要考虑的因素:
新增接口而非修改原有接口的语义
二进制兼容还是源代码兼容?
宏或者内联函数实现接口的向后兼容性,无法保证二进制兼容
注:
这两个术语”二进制兼容”和”源代码兼容”是分别描述了两种不同级别的兼容性。
二进制兼容(Binary Compatibility):
二进制兼容指的是不同软件项目(例如,操作系统、应用程序、库等)在二进制层面上能够相互兼容,即它们可以在同一系统上运行,而不需要进行任何修改或重新编译。
这种兼容性通常在大型系统中非常重要,例如在操作系统中,新版本的操作系统需要能够运行旧版本的二进制可执行文件,以确保系统的平滑升级。
要实现二进制兼容,可能需要付出很大的努力,例如需要确保系统能够正确地处理各种不同的数据类型、调用约定、系统调用等。
源代码兼容(Source Code Compatibility):
源代码兼容是指两个或多个版本的源代码(通常是同一项目的不同版本)能够在相同的编译环境下编译,并且生成相同的可执行文件或库。
源代码兼容是确保软件平滑升级和版本控制的关键因素。如果源代码不兼容,那么每次更新都需要对所有相关的源代码进行重新编译和测试,这会消耗大量时间和资源。
要实现源代码兼容,可能需要保持向后兼容的API(应用程序接口),确保编译器和链接器的行为一致,以及处理各种可能的源代码变化。
总的来说,二进制兼容和源代码兼容都是为了使软件系统更加稳定、易于升级和维护。在开发过程中,程序员需要考虑到这两种兼容性,以确保软件能够在不同版本和环境下正常运行。