记忆总是会慢慢褪去,所以让文字记住一切~
分类: C/C++
2015-05-14 21:53:46
昨天下午开了一个Code Review的会议。主要Review我写的一个模块代码。此模块从设计到实现用了将近两个月的时间。本想没啥大的问题,但却讨论到了一个设计中的问题。
问题引入:
在模块中设计了一个公用的库以使多个模块使用,此库的作用是是提供一个Pool来存储所有的Server。并根据调用者的需求实时选择一个Server返回给调用者,调用者需要使用该Server来进行下一步工作(请求服务等)。 实现此Pool的一个原因是我们需要在Server之间实现fail-over和load-balance。即调用者上次使用server A 去处理事情,下一此可能会将请求提交给server B。并且在某个server down掉的情况下能够选择另一个server。大体设计如图1所示,这里选择逻辑会体现出fail-over和load-balance:
这里我们姑且将server称之为object,其有可用和不可用属性。其中一个重要逻辑上在选择过程中发现一个object不可用,需要将其加入Cache。为了便于追踪object的信息,我在模块中加入了log功能,即一个object在加入cache时就将一个log记录下来,便于用户查看。
讨论的焦点在于:
对于pool来说,加入cache属于一个事件,当事件触发时就去做某一件事情。那如果用户希望事件触发的行为不是pool提供的log呢?所以触发事件后的行为是交由pool来默认做呢,还是交由使用pool的模块来做呢?
其实各有各的好处,对于上图这样的设计,我最初的想法是使用者不需要关心pool内部的行为,不需要知道pool内部会触发事件,对其来说只是一个提供管理功能的黑箱子。这样做到的是对用户的完全封装。这样的缺点是丢掉了一些灵活性。经过最后的商量,觉得开放该灵活性给用户,这也遵循了积木式原则,充分相信使用该库的后来开发者能够自由组合发挥。所以该pool提供回调函数callback的设置接口。当事件触发时,则会回调用户定义的函数来表现不同的行为。结构如图2所示。