`
foo
  • 浏览: 25119 次
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

设计的核心任务之一:层次的控制

阅读更多


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

 

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

 

例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,那这个类的接口,可以有返回猫的颜色,猫的种类,这些属性是在一个抽象层面上的。但如果突然有一个接口是返回猫的个数,那么大多时候就会让人感到奇怪。

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

 

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

 

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

分享到:
评论

相关推荐

    软件工程之专题十一: 系统工程知识

    需求分析是对处理对象进行系统调查,在完全弄清楚用户对新系统的确切要求后,用统一、规范的图表和书面语言表达出来,它是系统开发工作中最重要的环节之一。 ①系统范围和系统目标分析: 确定系统的范围、定义业务...

    《面向对象程序设计java)》课程整体教学设计.docx

    并行课程:数据库设计与应用 后续课程: :《JSP动态网站设计开发》、《安卓手机应用开发》 二、课程概述 课程定位 《面向对象程序设计》是计算机类专业的核心课程之一,也是基础课程之一, 在整个课程体系中起专业...

    计算机网络课程设计.doc

    根据需求分析,以层次化的网络设计方法,选择合适的网络技术,设计一个性能价格比相对优化的网络解决方案,网络要提供尽可能高的可靠性、有效性、可扩展性和安全性。设计内容包括、网络拓扑设计、IP寻址模式、路由...

    计算机硬件组成教学设计.docx

    学习任务1 任务:以2人为小组通过搜索等技术手段,请将计算机硬件结构与部件功能收集归类,并通过思维导图工具绘制出层次结构图,绘制好后分享交流。 任务驱动,支持学生自主学习,推动小组合作完成任务,让学生将...

    某大学校园网络设计方案.doc

    远程访问技术:远程访问也是园区网络必须提供的服务之一。它可以为家庭办公用 户和出差在外的员工提供移动接入服务。远程访问有三种可选的服务类型:专线连接、 电路交换和包交换。不同的广域网连接类型提供的服务...

    软件设计规范

    完整把握,从头设计是第一原则。因为软件世界自己并不能统一,还有继续分化的趋势。没有根本一致的基础可能是软件的本性。退回到一无所有是处理软件问题的根本。 在这样的视野下,操作系统只是一个部分,一个模块,...

    计算机要学哪些东西----(还有附赠哦)

    每个领域由一个两个字母的缩写词表示,比如OS代表操作系统,PL代表程序设计语言,领域之下又被分割成更小的单元(units),代表领域中单独的主题模块。每个单元都用一个领域名加一个数字后缀表示,比如OS3是关于并发...

    毕业设计基于Opencv的车牌识别系统.zip

    OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV...

    OCR:基于OpenCV和TesseractOCRiOS的银行卡号识别.zip

    OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV...

    软件工程-理论与实践(许家珆)习题答案

    比较复杂的系统不能画在一张纸上,逐层分解的画法可以控制每一层的复杂度。 顶层:将整个系统作为一个加工,描述系统边界(输入与输出)。 中间层:表示某个加工分解为一组子加工,其中的子加工还需进一步分解。 ...

    毕业设计项目(基于opencv车牌识别的停车场收费系统).zip

    OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV...

    2016年校电子设计竞赛,基于树莓派,OpenCV的零件形状识别装置.zip

    OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV...

    计算机二级C语言考试题预测

    (55) 在设计程序时,应采纳的原则之一是(A) 注:和设计风格有关 A. 程序结构应有助于读者理解 B. 不限制goto语句的使用 C. 减少或取消注解行 D. 程序越短越好 (56) 下列不属于软件调试技术的是(B) 注:P98 A. 强行...

    WEB设计大全

    前言 <br>第一部分 Web设计核心问题 <br>第1章 什么是Web设计 <br>1.1 Web设计的金字塔 <br>1.2 建设Web站点 <br>1.3 为用户建设 <br>1.4 从纸张到软件 <br>1.5 Web的图形用户界面传统 ...

    基于opencv+pyqt5开发的美颜化妆软件,功能包括:图像锐化、亮睛、红唇、瘦脸、美肤等.zip

    OpenCV(Open Source Computer Vision Library)是一款开源的计算机视觉库,专门为图像和视频处理任务设计,广泛应用于学术研究、工业应用以及个人项目中。以下是关于OpenCV的详细介绍: 历史与发展 起源:OpenCV...

    asp.net知识库

    深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托...

    MFC深入浅出带目录完整版(李久进chm版)

    并且进一步阐述MFC的核心概念之一:状态(模块状态、线程状态、模块线程状态),揭示MFC对多线程的支持机制,MFC实现规则DLL和扩展DLL的内幕。 第十章,阐述MFC下的调试手段。 第十一章,讨论CFile类,主要分析了...

    二级C语言公共基础知识

    (7) 在软件开发中,下面任务不属于设计阶段的是______。(D) A. 数据结构设计 B. 给出系统模块结构 C. 定义模块算法 D. 定义需求并建立系统模型 (8) 数据库系统的核心是______。(B) A. 数据模型 B. 数据库管理系统 C....

Global site tag (gtag.js) - Google Analytics