博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计的核心任务之一:层次的控制
阅读量:6669 次
发布时间:2019-06-25

本文共 1733 字,大约阅读时间需要 5 分钟。

对于软件而言,层次是让人又爱又恨的东西。

 

很多问题是通过增加层次解决的,但另外一部分问题也是因为层次而导入的。我们来分别看几个例子。

 

例1:很多时候我们并不希望最终的应用绑定于某个指定平台,比如:Windows。为了达成这种跨平台的目的,就需要在OS和应用之间加入一个中间层,这个中间层负责屏蔽不同OS的差异。实际上,Java虚拟机等走的都是这样一条路线。

 

例2:当使用XML文件保存配置信息的时候,我们并不希望XML的结构在整个程序中随处可见。比如说:现在我们在Configuration/OutputFolder节点下保存了缺省保存目录,但将来很可能节点变成了Configuration/OutputFolder/Save。为了斩开与XML结构的关联,那么我们需要加入一个新的抽象层,来表征XML文件,再通过GetSaveFolder()这样的方法对缺省保存目录进行获取。

 

通过加入层次解决问题的同时,新的问题也随之发生。在眼前蒙上一层薄纱可以防止眼睛被风沙所伤害,但如果蒙上十层,那更严重的后果将会出现---你看不到路了。

 

从可理解的角度看,只有某一功能所涉及的所有层次,所关联变量的各种可能性都被澄清之后,具体的代码才可能真的被理解。在排错的时候尤其如此。我们来看一个例子:

 

在用C++创建集合类的时候,我们可能希望对集合类的内存使用方法进行更多的定制。

有时候我们可能想预先保留一块内存,接下来在这块内存上进行二次分配来存放各种小的对象。

有时候我们也可能想直接在磁盘上分配空间存放放入集合类的对象。

为了达成上面这些目的,层次又一次站出来发挥作用,我们可以建立allocator这样的类来建立一层抽象,创建集合类的时候,可以通过指定不同的allocator来控制内存使用的方法。

 

这应该是不错的设计方法,C++标准模板库里就是这么做的。

接下来我们来看一旦出了错的情形。

我们可能希望放入集合类的对象总是进行浅拷贝(swallow copy),为此重载了类的拷贝构造函数和赋值函数,但最终发现当对象被放入集合类的时候,不知道为什么总是不成功。

 

这个时候,逻辑上程序没有任何问题,因此只靠脑子想是完全解决不了问题了。为了排错,我们只能启动调试器。

调试的过程中,我们通常并不能一下就确认问题和allocator究竟有没有关联,所以为了找出问题所在,我们也要对allocator这一层次做点分析。这种分析的开销事实上就成为添加allocator这一层次的代价。

 

通过上述的例子我们可以大致体会到层次这把双刃剑的威力。

 

通过层次我们可以让软件更灵活,抽象更充分;但层次也会把达成某一功能所必须的信息进行分割,增加复杂度。所以层次的多少往往并非是一个对与错的问题,而是一个程度问题,究竟什么样的层次才合适,是需要现场的人进行判断的。

曾经有人说过这样一句话,可供我们参考,他说:如果你知道自己在做什么三层足够;如果你不知道自己在做什么,那么十七层也没用。

我个人是认同这一观点的,除非特别的情形,要努力控制层次在三层左右,否则宁愿牺牲一点抽象。

 

和层次相关的问题主要有两个:一个是层次的多少;另一个则是层次的一致性。如果说层次的多少是一个合适与否的问题,那么层次一致性则是一个是非问题。

某一个层次上所体现出来的东西应该具有层次一致性。

 

这和前面在讨论的需求中的层次问题类似。

比如说:如果有一个类叫Cat,那这个类的接口,可以有返回猫的颜色,猫的种类,这些属性是在一个抽象层面上的。但如果突然有一个接口是返回猫的个数,那么大多时候就会让人感到奇怪。

我们感觉到奇怪的本质原因是抽象的层次出现了不一致性。颜色和种类这种属性属于具体的某一只猫,而个数则属于猫的集合。

 

这种抽象层次的不一致实际上是增加耦合度的一个主要元凶。

 

很不幸的是,这又是一个要依赖于个人技能的地方。眼下还看不到自动判断抽象层次是否合适的方法。

--------------------------------------------------------------

 

理想流 + 软件 = 

理想流 + 人生 = ??
理想流 + 管理 = ??
理想流 = 以概念和逻辑推演本质,追求真理。

转载地址:http://pcoxo.baihongyu.com/

你可能感兴趣的文章
第一次作业
查看>>
linux系统——hosts文件修改
查看>>
CF1076C Meme Problem 数学
查看>>
1.6(学习笔记)Session
查看>>
oracle常用SQL——创建用户、表空间、授权(12C)
查看>>
window和document的区别理解,bom和dom的区别理解
查看>>
iml文件
查看>>
Python编码/文件读取/多线程
查看>>
自己写了一个弹出菜单,有间隙也可以
查看>>
数据的处理和特征工程
查看>>
DBMS_SCHEDULER CHAIN用法
查看>>
html之表格列标题<th>的使用...
查看>>
Delphi编写Win7屏幕保护唤醒工具
查看>>
我将在CSDN有个新家
查看>>
JS实现AOP拦截方法调用
查看>>
文件上传
查看>>
移位操作发现的悲剧
查看>>
win10 nodejs指定ionic版本安装(npm方式)
查看>>
JumpServer跳板机
查看>>
mongodb 与 c++ 的配合使用
查看>>