分离变与不变——软件设计的基本原则分析

来源:互联网 发布:查看域名是否备案成功 编辑:程序博客网 时间:2024/04/30 20:37

分离变与不变

                                                                                                                                                       ——软件设计的基本原则分析

 

        小到代码,大到模块、系统,我们都可以将其粗略的分为两个部分:变化的部分和不变的部分。有些代码,不管是维护人员来了、走了,还是版本换了、变了,它依然是那样。可怕的是另一部分,它们在不停的变化,每个新来的菜鸟都要去改一下,每个新的版本,它们都要动一下,总是让人头疼不已。更可怕的是变化的部分和不变的部分始终都纠结在一起,欲拆不能,强拆不忍,每次小小的改动都要牵连到一大片,修改这样的代码、模块,相当于将自己推入“焦油坑”,退拔皆不能,其中的痛苦只能敲掉门牙往肚里吞。

分离变与不变,是软件设计的一个基本原则。其背后蕴藏着丰富的软件工程思想,例如:信息的分装与隐藏、系统的模块化、使用分层构架等等等。其中“变”是指易变的代码或者模块,当然,“不变”就是指系统中不易变化的部分。无论是开发人员还是设计人员,使用这条原则,都可以带来可观的收益,且看以下两个本人体会到的实例。

一、代码危机

          在此,我们将一个开发员维护的代码总量看作是100,如果这些代码没有使用变与不变分离的原则,只是为了完成一定的功能而凑合在一起,那么他维护的总的代码量可能是100。实际上,代码可以分为3个部分:大概50%是不变的部分,30%是有可能会变化的部分,而剩下的20%是经常会变化的代码。也就是说,如果使用了变与不变分离的原则,将它们有效的分离开而相互不干扰,实际上维护的代码总量可能是20+30/2=35。尽管这只是理论上的分析,但是我们还是可以从中看出使用分离原则带来的好处,如图1所示。

                                    

                                                                               图1

        在代码层次,要达到变与不变分离,方法非常简单,就是使用函数或类进行功能分离,变化的部分大都和业务相关,使用单独的函数或者类将它们封装起来,同样的方法可以应用于不变的部分,这样可以达到分离的效果。在它们之间,或者使用数据结构、或者使用函数调用,或者使用消息,将它们联系起来,达到合聚的效果。其关键在于如何在设计阶段清晰地判断出变与不变的部分,不同的应用、不同的功能,并没有一致的法则,需要一定的洞察力和业务判断能力。一个比较好的方法是使用设计模式,设计模式的主旨是将接口和实现分离,其实这也就是变与不变的分离。如果不能确定变与不变,一个比较直接的方法就是编写小的函数或者类,这样可以达到一些简单的分离效果。

二、模块的版本危机

         等等,在进一步分析之前,请允许我解释一下“模块的版本危机”,毕竟这是我自创的名词。软件版本的发展有两条路线。一个是纵向路线,比如从1.0发展到2.0,然后又从2.0发展到3.0。软件版本的纵向发展对模块的维护来说相队容易。一般情况下,从低版本到高版本,不外乎两件事情:修改Bug,添加新的功能。模块维护人员的代码随着新的版本的功能变化而变化。另一条版本发展路线是横向发展。比如,在2.5版本基础上开发了多个分支,用于不同的应用或者项目:其中2.5_HUO应用于火星,2.5_MU应用于木星,2.5_DI应用于地球,2.5_JIN应用于金星等等。在这种情况下,很多模块可能会针对每个横向版本做不同的修改,来满足不同的需求,毕竟,火星不同于地球。在这种情况下,某些模块可能要随着每一个横向版本的发展,都要做代码的修改,这样,这些开发员的代码维护量随着版本的横向发展而成线性增长。我把这种现象叫做“模块的版本危机”。图2的前半部分所示。

        设想,现在有一个模块,在一次版本横向发展过程中,衍生出了四个不同的版本,这些不同的版本既有相同的部分,即公共部分,又有不同的业务处理部分。如果没有使用变与不变分离的原则,每次修改公共部分都会涉及到四个版本的修改,这是一个非常痛苦的事情,如果模块内部代码本身又没有将变与不变部分分离,那对开发人员来说更就是一场噩梦的开始,也是Bug最舒适的温床。

解决“模块的版本危机”可以从两个方面入手:

        一个方面在于设计人员。设计人员的版本横向发展的初始阶段,应该主动发现存在危机的模块,将这些模块在版本横向发展过程中的变与不变分离。使得模块的不变部分保持只有一份,而变化部分呈线性增长,这样可以大大减少维护人员的工作压力,也可以大大减少版本维护成本。图2的后半部分所示。

        另一方面在于开发人员。开发人员应该时刻使用代码危机中的分离原则,这样可以将版本横向发展带来的影响降至最小,减少自己的维护压力。

                           

                                                             图2

 

三、总结

        分离变与不变只是一个原则,不是一个具体的方法。如何使用还需要你的反思、发现和实践。原则的使用不在于有多完美,而在于你使用了没有,付出才有收获。一旦你用好、用巧,那么当别人在为代码而焦头烂额时,你却可以淡淡地泡上一杯茶。

   

 

原创粉丝点击