在进行软件设计时,并不能一味地站在设计者的角度去思考,而是同时需要站在模块使用者的角度去思考。设计者通常容易对自己所设计模块的使用者进行一定的使用假设,且假设使用者是完全沿着自己的设计思路去使用模块的,这种假设在现实生活中通常表现得很是脆弱,问题的发生往往就是出现在模块的使用者打破了设计者原有的假设。很有可能模块的使用者正是模块的设计者本人,在这种情形下,设计者仍应站在使用者是他人的情形进行软件设计。
     下面通过例子来说明这一原则是如何在软件设计中起作用的。现在假设需要设计一个模块,且这个模块只允许在单个的线程上下文中被使用。尽管存在这样的假设,但这一模块仍可以被运用于多线程环境中,只要保证有且只有一个线程使用这一模块就行了。如果设计者总是假设模块的使用者总是能保证模块只被唯一的一个线程使用的话,很有可能就会砬到问题。因为在现实中,当项目具备一定的复杂度时或维护周期拉长时,很有可能模块的使用者不知不觉地违背了设计者的设计假设。通常,出现多线程的问题很难找到根源,如何通过设计来规避这种问题呢?这就需要用到这里正在谈的设计原则,即通过设计来防止模块的使用者犯错。
     图1示例了如何通过设计来避免出现多线程问题。其设计思想非常简单,即为被设计模块建立一个全局变量g_module_owner以记录模块所属线程的ID。在48行如果发现g_module_owner还没有被初始化过,则调用pthread_self()函数得到当前调用函数的线程ID。程序如果运行到了51行,则说明g_module_owner被初始化过了,而要做的就是检查调用函数的线程与g_module_owner中所记录的是否是同一个,如果不是则报错并返回。显然,图中所示的这段代码可以放到模块的所有对外接口函数的开头。有了这种设计以后,一定不可能出现多线程问题,也不用担心用户不小心犯了错而没有发现且遗留到软件最终用户手中。

example.c

00044: static pthread_t g_module_owner = INVALID_THREAD;

00045: