对于软件而言,层次是让人又爱又恨的东西。
很多问题是通过增加层次解决的,但另外一部分问题也是因为层次而导入的。我们来分别看几个例子。
例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,那这个类的接口,可以有返回猫的颜色,猫的种类,这些属性是在一个抽象层面上的。但如果突然有一个接口是返回猫的个数,那么大多时候就会让人感到奇怪。
我们感觉到奇怪的本质原因是抽象的层次出现了不一致性。颜色和种类这种属性属于具体的某一只猫,而个数则属于猫的集合。
这种抽象层次的不一致实际上是增加耦合度的一个主要元凶。
很不幸的是,这又是一个要依赖于个人技能的地方。眼下还看不到自动判断抽象层次是否合适的方法。
分享到:
相关推荐
洗衣机控制器作为洗衣机的核心部件之一,其性能直接影响着洗衣机的工作效率和用户体验。在基于VHDL的设计中,控制器被划分为多个功能模块,每个模块承担特定的任务,如状态机模块、计时控制模块、显示模块等。这种...
在当前工业自动化领域,机器人技术的应用越来越广泛,尤其在机械加工行业中,桁架机器人因具备高精度、高速度和柔性化等优势,成为了重要的自动化设备之一。本文通过《基于运动控制卡的桁架机器人控制系统设计》来...
镇流器是路灯控制系统中的关键部件之一,对于高压钠灯或金属卤化物灯等光源具有重要的作用。 1. **定义**:镇流器是一种用于控制电流并稳定灯泡电压的装置。 2. **类型**: - **电感式镇流器**:传统型,结构简单...
位置控制是整个飞行控制系统中的关键部分之一,其主要任务是确保飞行器按照预设的目标位置飞行。 **2.1 位置控制分类** - **分类依据:** 根据给定的目标轨迹,位置控制可以分为三种形式: - **定点控制**:目标...
- **核心能力**:能够运用C语言实现简单的逻辑控制任务,例如控制LED闪烁、简易的数码管显示等。 - **典型特征**:对于单片机产生浓厚兴趣,能够通过实践学习完成基本的模块驱动实验。 - **所需时间**:对于初次接触...
《Java程序设计任务驱动式教程09章》主要讲解了Java编程中的多个核心概念和实践技巧,通过一系列的任务来引导学习者深入理解Java语言。以下是关键知识点的详细说明: 1. **任务十一:用数组存储信息(使用数组)** ...
这种层次结构的设计确保了上层可以充分利用下层提供的服务,同时也可以根据需要向下层发送指令来控制其行为。例如,当应用程序需要读取文件时,它会通过系统调用接口向内核层发送请求,内核层再进一步与硬件层交互以...
7. 圆机与针织行业:圆机是一种纬编针织机械,是针织行业的核心技术设备之一。它具有产量高、工艺流程短、原料适应性广等特点。圆机主要用来生产T恤、内衣、毛衣等服装和产业用布,对于纺织制造业的发展起着关键作用...
微机原理与接口关键技术专业课程设计任务计划书是电子工程领域的一门核心课程,旨在培养学生综合数字电路和单片机知识,处理电子信息方面常见实际问题能力,并了解通常电子电路和单片机组成简单系统及较为复杂编程...
- **中图分类号TN709**:这是FPGA领域的分类代码之一,属于电路理论与技术的分类中。 ### 结论 文档提供的内容涉及到了设计和实现基于FPGA的采集控制系统的重要方面。从需求分析、方案论证到最终的设计实施,展现了...
【深入研究Windows内部原理系列之一:Windows的昨天、今天和明天】 Windows操作系统是全球最广泛使用的个人计算机操作系统,它的历史可以追溯到1980年代。这个系列将带你深入了解Windows的发展历程,以及其核心原理...
网页设计是数字时代的核心技能之一,它涉及到构建和维护网站,提供吸引人的用户体验,并有效地传达信息。在这一领域,Adobe Dreamweaver是一个重要的工具,它为网页设计师提供了强大的可视化编辑环境,结合了代码...
1. 总线式技术的选择和应用:总线技术是构建分布式系统的核心技术之一,它可以实现节点间的数据传输和控制指令的传递。在本案例中,作者选择了以ATMEGA16A型单片机为核心的节点设计,并使用特定的通信协议来实现主从...
在实际应用中,校园网络通常是层次化网络设计的经典案例之一。例如,在一个典型的校园网络中,学生宿舍楼的各个房间通过接入层设备(如锐捷S2126G)连接至楼内汇聚层设备(如锐捷S3750),再由汇聚层设备连接至校园...
- **应用场景**:在设计程序时需要考虑的因素之一。 ##### 2.3 整数算术 - **核心概念**:介绍整数加法、乘法、除法等基本算术运算。 - **应用场景**:几乎所有的编程语言都需要处理这些基本的算术运算。 ##### ...