抽象的精神

软件设计,一直是一个非常抽象的,非常难懂的领域。

然而设计,并不是科学,虽然有评价标准,却没有是非对错。好的软件,就像是艺术品,闪耀着前人智慧的结晶。

本文将探讨一下流行的软件设计,以及总结一下好的设计原则和方法。

设计的基本原则

一谈到软件设计,很多人都会讲,你要怎么怎么设计软件,怎么怎么才能面向对象,怎么样才能符合设计模式。没错,目前学软件设计,最初接触的可能就是面向对象的设计方法,23种设计模式。

但我要说,软件设计,不是死板的,不是只有这些模式的。软件设计,是更为灵活的艺术品的创作,而面向对象,可能只是其中的一个派系而已

我们所熟悉的面向对象,只是万千设计方法中的一种,23种设计模式,也只是设计中的冰山一角,我们要跳出面向对象的小圈子,去看看外面的风景。

但无论什么样的设计方式和思想,总得有一个评价标准,或者说是一个共识,来解释什么样的设计是一个好的设计,这个基本标准就是:高内聚,低耦合

所谓高内聚,是指一个功能,或一个模块,内部的封装性较好,同样的功能,尽量只存有一份代码,这样你在修改一个功能时,往往改动就很小。而且内聚性高的代码,很注重接口的稳定,在不修改接口的情况,修改内部的实现,对外部影响极小或根本无影响。

低耦合,是在说代码模块间的耦合性要低,模块能较容易的移动和替换,模块间的耦合性低,最大的好处就是可维护性强,一个模块出现问题,方便替换。而且复用性强,同一个模块,可以被多个地方引用,降低了软件的成本。

举个例子

我们现在要做一个在线购物的网站,有用户和管理员两种角色,需要维护一个商品列表,用户的购物车,有什么样的设计方式呢?

这里我们只是给出简单的例子,实际情况往往比这复杂的多。

方法1:

我们给每个页面写一段代码,假设我们用JavaEE实现,那么我们可能建立了几个页面,我们可以按照页面划分功能,然后依次实现,要完成的页面有:

  1. 登录、注册页面
  2. 查看商品列表页面
  3. 购物车页面
  4. 后台登录页面
  5. 后台管理商品列表页面

我们会用jsp写一个个页面内容,然后通过数据库操作,将对应表中的数据取出来,并格式化到前端页面上,在接受用户提交的表单时,我们为其查询数据库,并进行数据检查与过滤,然后操作对应的数据表。

经过我们苦逼程序员的一致努力,终于实现了全部的功能,网站可以使用了。

但是…客户忽然发现,他们希望再增加一种vip用户,让vip用户可以存储更多的个人信息,绑定自己的银行卡账户,这样他们能为vip用户提供更好的服务。

然而,这并不简单,由于所有的代码和页面逻辑都混在一起,虽然也有按照页面划分功能,但添加一种新的用户角色,大部分的页面都需要改动,工作量很大。

方法2:

我们先思考一下,是什么造成了改动的困难。如过单独的考虑一个用户的模型,也许就能更加简便的实现,也就是说:我们按照页面划分功能模块,这种思想太粗糙

我们设计一个用户模型,将单独的数据操作抽象出来,方便我们扩展用户类型。通过继承的方式,我们不但能实现vip用户,甚至也可以再扩展企业用户等等。

我们这里使用了面向对象的设计方式,由于Java的对象支持非常好,我们这样设计也是能很方便的用Java类来实现,这样我们不但可以方便的将模型扩展,更可以简单的复用模型中的操作。

同理,我们继续抽象整个项目的结构,像购物车,商品,都可以抽象成单独的模型类,而关键的流程控制,更是可以抽象成控制器。

这种流行的MVC架构到现在,都在软件架构中发挥着关键的作用。

这里并不想讲解MVC架构,而是要说明一个问题,软件结构直接影响软件的可维护性,可扩展性

高内聚、低耦合,这些都是良好软件设计中的基本观点,但更基本的设计考虑,则是软件是要分模块实现的,当然这个模块是一种对软件结构的抽象,可以说是类,也可以说是函数,总之是软件的组成部分。如果一个软件只有一个函数,所有功能从上到下依次完成,也就没有了所谓的软件设计。

软件设计的核心——抽象

软件设计的核心,我认为是对事物的抽象。

软件设计时,抽象是最基本的方法,来设计出高内聚、低耦合的代码。希望代码设计的更好,那么我们就需要一个好的抽象,一个对现实事物构建的合理的模型

原因也很简单,软件的是为现实世界服务的,只有良好的描述现实事物特征的模型,才能更好符合我们要让其完成的功能。

前面例子讲解了,什么是好的抽象,例如将页面中的实体抽象成数据模型,将实体相关的操作抽象成模型的方法,这直接套用了面向对象的设计模式,形成了很好的抽象。

当然,还有很多种抽象方法,例如在大名鼎鼎的LISP语言中,函数就是第一等公民,将各类方法抽象成函数就是他的做法,甚至是数据的定义,也可以抽象成模型构造函数。这样就又换了个角度,从另外一个方面来审视整个项目,得出的软件结构,也大不相同。

在LISP语言中,抽象方式变了,不再那么关注数据模型,而是关注每一个功能的输入输出,将不同的功能组合在一起,形成新的功能,就是函数式编程的基本思想。

好的抽象,往往和软件是无关的,是在人脑中,将事物的特征归类,形成的有效的概念。而一种好的抽象,往往会影响一个时代的设计风格。在Unix系统中,有一个非常棒的设计,将一切抽象为文件,设备驱动也是文件,IO操作也是文件,系统的监控,也是靠文件。这种设计影响了整个业界,人们惊奇的发现,原来操作系统将一切抽象为文件后,所有的操作都变得统一和方便了。我们添加新的硬件驱动,不需要修改系统接口,用设备文件的方式就可以访问,包括进程间通信,也用的是内存共享文件,监控系统参数,只需要打开文件就可以。

编程范式对人思考的影响

我一直说,千万不要局限在设计模式中。原因很简单,固定的设计模式往往会阻碍你对更好的设计的追求。有时会有种一叶障目的感觉。

判断一款软件是否设计的较好,最简单的方式是这样,先看有没有冗余代码,消除冗余是代码优化的第一步。

一般情况,总会有办法能将冗余代码合并在一起。但是不是没有冗余就是好的设计了呢?这可不一定。因为很有可能你虽然消除了冗余代码,但引入了复杂的结构,这样是得不偿失的。还有,就是要看可读性,如果消除冗余代码时,降低了代码的可读性,本来功能很清楚的一个函数,经过冗余消除后,反而看不懂是在做什么了,这时,就要避免代码整合。

或者说,这时的另外一种方式就是,构建新的抽象方式,抽象新的概念,这样就能让思考转换,构建出既没有冗余,又容易理解的代码。

我很喜欢多范式编程语言,这类语言不规定你具体要使用什么样的编程模型,你自由发挥的空间就广,代表就是C++、LISP、Scala等,都是十分优秀的语言。

如果你只属性面向对象的设计,那么我强烈建议你去看一看函数式设计和面向方面的AOP编程,往往会对你的设计具有启发式的意义。

分层是解决软件设计问题的有力方法

其实分层的思想和抽象是一脉相承的,一批软件功能的整体抽象,往往就能形成一个中间层,绝大部分复杂问题,都可以通过分层的思想,逐层分而治之,将任务不断简化,最后问题得解。

例如我们的互联网,互联网就是分层解决问题的典范,在TCP/IP协议下,有对等层的概念。我们知道,TCP/IP协议族采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。

协议分为:网络接口层、网络层、传输层、应用层。网络接口层就解决两个硬件设备直连的通信的问题,通过出错重传机制,保障直连信息的可靠传输;网络层则负责寻找目标地址,分组转发和路由,将数据填上ip报文段,发送到目标机;传输层则复杂格式化信息流,并提供稳定可靠传输,为此,传输必须通过三次握手才能开始,而且每个报文包更是要经过接收方发回确认才算安全传输。

如此复杂的互联网,通过分层的解决方案,得到了可靠有效的实现。现如今互联网的蓬勃发展,也证明了当年的设计确实是灵活合理的。

软件设计领域,有这样一句著名的命题:

任何一个软件设计的难题,都可以通过增加一个中间层来实现。

我们这里不去论证这个命题是否合理,但分层确实是人类这么多年设计经验的精华。分层体现了两个重要的思想,分治和抽象,这是解决问题的关键。

本文属 西风逍遥游 原创, 转载请注明出处: 西风世界 http://blog.csdn.net/xfxyy_sxfancy

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-16 15:34:04

抽象的精神的相关文章

DAL,IDAL,BLL,Factory作用

业务逻辑层(BLL):主要是针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理.如果说数据层是积木,那逻辑层就是对这些积木的搭建. 数据访问层(DAL):主要是对原始数据(数据库或者文本文件等存放数据的形式)的操作层,而不是指原始数据,也就是说,是对数据的操作,而不是数据库,具体为业务逻辑层或表示层提供数据服务. (IDAL)它体现了“抽象”的精神,或者说是“面向接口编程”的最佳体现.抽象的接口模块IDAL (Model)实体和数据库表映射类(Web)web网站项目. 并不是每

关于在.NET中 DAL+IDAL+Model+BLL+Web

其实三层架构是一个程序最基本的 在.Net开发中通常是多层开发比如说    BLL 就是business Logic laywer(业务逻辑层) 他只负责向数据提供者也就是DAL调用数据 然后传递给 客户程序也就是UI    DAL就是(data access laywer)数据访问层 ,负责 对实体也就是数据库相应表的增删改查    IDAL它体现了“抽象”的精神,或者说是“面向接口编程”的最佳体现.抽象的接口模块(IDAL)    Model: 实体层数据库中表的映射,一般有几个表就有几个实

张恭庆院士: 数学是一种精神追求

沉醉其间半世纪,数学已经不再单纯是张恭庆为之奋斗.求索的事业选择,更是他为人.为师.为友的一种精神追求. 10月30日晚,北京大学一间可容纳300余人的阶梯教室里座无虚席,就连过道和台阶也被挤得水泄不通,除了学子们一张张年轻的面孔,人群中几位头发花白的老者显得格外醒目. 他们的到来,或许是为时常萦绕心头的这样一个问题寻求答案——数学究竟有什么用?年近八旬的数学家.中科院院士张恭庆在众人的期待中走上讲台,没有多余的寒暄和客套,他直奔主题向台下听众娓娓道来“数学的价值”. 两个小时的时间,张恭庆贯通

谈一谈:抽象工厂+反射+配置文件 实现数据访问程序

<大话设计模式>中第15章中<就不能不换DB吗?>引出了我今天要谈论的主题:抽象工厂+反射+配置文件 实现数据访问程序.当时也不甚理解啊!到了机房收费的亲身实践中,终于体会到了这对组合的奥秘. 抽象工厂模式(Abstract Factory) 提供一个创建一系列相关或相互依赖对象的接口,而无需制定它们具体的类.知道它是用来创建工厂的就OK了. 反射 提供了封装程序集.模块和类型的对象.这里仅仅用到反射的一部分功能.且记住它的格式: Assembly.Load("程序集名称

C语言精神

国际标准化组织与1990年发布了第一个ANSI/ISO C标准 在该委员会制定的指导原则中,最有趣的可能是:保持C的精神.委员会在表达这一精神时列出了一下几点: 信任程序员: 不要妨碍程序员做需要做的事: 保持语言精练简单: 只提供一种方法执行一项操作: 让程序运行更快,即使不能保证其可移植性. 在最后一点上,标准委员会的用意是:作为实现,应该针对目标计算机来定义最合适的特定操作,而不是强加 一个抽象.统一的定义.在学习C语言的过程中,许多方面都反映了这一哲学思想.

Linux路由表的抽象扩展应用于nf_conntrack

思想 标准IP路由查找的过程为我们提供了一个极好的"匹配-动作"的例程. 即匹配到一个路由项.然后将数据包发给该路由项指示的下一跳.假设我们把上面对IP路由查找的过程向上抽象一个层次,就会发现,事实上它还能够有别的用.抽象后的表述为:以数据包的源地址或者目标地址为键值去查询一张表.查到结果项以后运行结果项指示的一个动作.一个结果项为: struct result_node { uint32 network; uint32 netmask; void *action; }; 以上这个思想

湮没在先秦的【文士道】精神

道墨结合:道借墨之行,墨享道之思.(下) [思想]湮没在先秦的[文士道]精神--                         士道:做一个独立声音型知性贵族(时代的紧迫需要) 结尾我们来简单介绍一下我个人对[文士道]的肤浅理解. 1:什么是士?什么是士道? 士,是指古代职业政治家.士是由一些秉承思想贵族精神的知识分子组成.现代社会即使也存在着职业政治家,但是其意境与气度以及气节不可同日语.这就是仕人与士人的微妙区别--士人是狼独立而自由:仕人是犬傍依于屋檐. 士道,则是士人的人格理想与行为规

从云计算谈精神世界的本质

对于精神世界里出现的神秘事件,科技人员总是采用研究物质的方法来解释,并且固执地认为这样的解释是科学的,结论是正确的.比如轮回记忆,专家 从细胞.物质功能的角度来分析生命的过程,然后认为轮回是不可能存在的.得出这种结论是草率的,和下结论的人本身的社会地位及知名度没有关系,因为轮回属 于精神世界里发生的事件,和物理世界的身体没有直接的关系,不能把对身体的研究结果直接套用到不同类型的事物上.比如不能因为研究了鹿,就认为马不需要研 究了,指鹿为马. 人类因为大脑精神世界的无限能力而变得固执狂妄,忘记了人

《人类意念力》正式发布,从精神层面解开大脑的奥秘

人类意念力 谨记收藏,勿散播 李炎 2015-1 本文可能获得诺贝尔生物学奖,因为揭开生命的奥秘:人类意念力.当然本文不是为了得到诺贝尔学奖而写,可能为了人工智能,可能只是为了存档,因为不写下来就不知道曾经有过. 用脑洞大开,闻所未闻来形容本文可能比较贴切.我一直在想要不要发布这篇文章,最后我想,还是不要带进坟墓去比较好.因为过了今天,我可能就不写了. 我写了我知道的,剩下的是人们想象的空间,或者说给人们发挥的余地,让大家继续补充. 我和气功有个约会 我出生在广西一个小山村,建村有200多年.我