在软件设计和开发过程中,不管你用何中语言,也不管你用何种开发流程,只有一样是不变的,那就是“不断的变化”。需求改变,设计改变,操作系统改变,调用的库改变,编程语言的改变。。。而在设计的时候就封装这些可能的变化,则可以令自己的程序设计在面对变化的时候,改动最小。
封装听起来好像是一个面向对象设计的特性,事实上,不管用何种语言,封装都无处不在。
相信有过编程经验的人都知道,代码中,常量是不应该随便出现的,在C中一般用宏,C++中则用const定义在文件的开始处,或者公共头文件里。这如此的理所当然,以至于只能被认为是编程技巧,还上升不到设计的高度。而事实上,这就是封装变化的一种设计。
我参加的一个GUI开的项目中,在设计消息对话框的时候,设计者知道把所有的消息字符串都定义在一个消息头文件中了。消息随时变化着,今天要show“OK”明天就有可能要show“YES”,没关系,当消息变化时,只要到头文件中稍稍那么修改一下,就OK。How漂亮!可是在做图标的显示时,则把每个resource的名字写死在代码里了。当程序准备发行的时候,terrible的事情发生了,发行版的resource要全部换了,并且不同的地区发行的版本,resource都不一样。于是乎,整个team全部行动,用了一上午的时间,把所有的图标resouce找出来,重新定义到了一个新头文件中了。哎,不会触类旁通,举一反三,没有上升到理论的高度,惨痛的教训啊!
在嵌入式软件设计开发中,由于当前的软硬件平台的多样性,受性能,成本等要求的限制,底层硬件或者底层操作系统,都随时有更换的可能。所以在做设计的时候一般都会独立出一个操作系统driver层和硬件driver层。在这些driver层中,向下,对不同的平台,调用具体的库函数,系统调用,或者硬件接口,向上,则提供一个统一的服务接口。上层应用可以对底层系统或者硬件透明的调用driver层提供的接口。这样,底层的软硬件平台发生变化时,只需要改变相应的driver层,对上层应用的代码不需要,或者仅需要少量的修改就可以了。这样,对上层应用来说,driver层就封装了底层软硬件平台的变化。同样在对数据库操作时,一般也会独立出一个数据操作层,封装对数据库操作的所有SQL语句,来应对各种变化。
最后,再吼两句吧!高内聚,低耦合,永远都是软件设计所追求的目标。而封装变化,可以很好的解耦变化部分与不变的部分,使变化部分在发生变化时,对整个系统影响降到最小。封装变化的方式有多种,小到用宏定义,大到分层设计。最重要的是把封装变化这种思想灵活运用到设计中去。