winston 发表于 2012-1-16 10:27:45

【理想流】软件本质论 v2.0

#2003年写过一篇同名的文章,今日再看却是浅薄了,重写一篇,算是2.0版吧。
#以此作为理想流的第一篇文章   

软件是一种固化的思维。其根本组成是概念和逻辑。


软件世界中的一切的故事始于一个机器模型,而这个基本的机器模型并不复杂,甚至可以用三个关键概念来概括:指令,数据以及栈。
其逻辑也比较简单,即按照指定的顺序,逐步执行各条指令。但也就是这样一个简单的模型,支撑起了整个软件的世界。

软件构建的过程就是从客观世界中的概念和逻辑向机器模型逐步进行映射的过程。

由于编译器(或解释器)的存在,最后一重映射已经被无限简化,因此我们可以认为以编程语言为载体的代码即是固化后的思维,包含了所有固化后的概念和逻辑。


为完成这一任务,首先软件的边界必须清楚,即“要转换的究竟是什么”必须尽可能明确,此即需求开发的根本任务。
从需求向最终代码的映射可以称为软件构造。
需求开发的结果:规格说明和软件构造的结果:代码表述的实质上表述的是相同的东西,所不同的只是视角,表达方法和详尽程度。



需求开发姑且不论,软件构造即在确定的范围内打造概念的边界和定义概念间的逻辑关系的过程。


打造概念边界时原则可以有许多,但手段只有一个,即抽象。从本质上讲,抽象是一种认清事物本质,并进行归类的过程。
与抽象相对的是具体,但抽象的来源也是具体。
假使我们需要对【人】这一名词进行定义,那么必然是要从张三,李四等等具体的人身上抽取共通特征,而后才能完成定义。
最终结果是【人】这一概念来源于张三,李四,但又不是张三李四。这样一个从具体的事物中抽取共性,再进行命名的过程就是抽象。

我们常说的功能分解(Function Decomposition),抽象数据类型(ADT),面向对象(OO)都可以看做是对事物进行抽象的具体方法。



但不管使用什么样的方法,打造概念边界通常并不容易。这种困难起源于概念本身的边界并不清楚,存在模糊性。

比如:当我们描述一本书的时候,那么这本书是否被借出了这种信息,是既可以作为书的基本信息的一部分,也可以通过查阅借阅人的信息来存储的。
对此,哲学上的表述是:世上万物是运动的,联系的,而非静止的,孤立的。

更困难的是一旦切换视角,相同的概念又可以有多种划分方法。
好比说,我们可以很容易界定什么是人,什么是猿,但当我们试图把人猿归类的时候就依据我们的视角进行抉择。
因为它似乎是人,似乎是猿,却又更是人猿。打造概念边界时正是类似人猿这类概念让我们犯难。有些问题甚至只有选择而没有答案。
庄子对这种事情的观点是:自其异者视之,肝胆楚越也;自其同者视之,万物皆一也 。

也正因此编程是一种实践多于是一种理论。

我们可以抽象出一些指导性原则,比如开闭原则,比如里氏代换,比如高内聚低耦合,但一旦面对现实时却只能具体问题具体分析。
也许有人认为这里所说的澄清概念边界专属于面向对象,其实不是。
当你决定某一组函数专门负责文件操作时,你同样是定义了【文件操作】这样一个概念的边界。包,类,模块,数据结构,方法等等这些名词都可以对应到一个个具体的概念,是抽象这一工作的结果。


我们把概念之间的关系定义为逻辑。而概念间的逻辑关系可以被分为两类:
一类是概念所固有的,基本不受具体应用影响的静态关系。
比如:人是比老师或学生更为泛化的概念,老师或学生都需要有一个名字。
这就是我们常说的继承,包含聚合(整体与局部)等。需要特别一提的是框架(或设计模式)更多的体现的是一种静态关联关系。
框架把全局性,共通的部分抽象出来,固定在框架之中,把局部的,需要定制的东西开放给用户,来应对变化。

与这种静态的逻辑关系相比,具体化的概念之间的动态关系显的更为繁杂。
如果说概念间的静态关系体现的是一种预先存在的必然关联的话,那么概念间的动态关系体现的则是实现具体功能时体现出来的偶然关联关系。
假设说我们要做一个简单的监控系统。那么大致会衍生出下面几个方面的概念(模块):
l 照相机:负责拍照
2 图像处理:负责分析照片中是否有异常
3 数据库:用于存储过往的记录
4 报告功能:一旦发现异常,对相关人等进行通知
5 控制器:根据既定的处理流程,使程序动起来。
6 ... ...

这个时候,控制器和照相机(或数据库间)的关联则是一种偶然关联,是动态关联关系。把照相机替换为摄像头也无不可。
对照实现来说的话,照相机的实例可以通过控制器的接口传入,也可以在控制器的方法中创建,但如果把照相机作为控制器成员,则和这些概念间既有的关联关系向背离,耦合度会有不必要的增加。

在动态关系中第一重要的是动作的时序,即先后顺序。
时空的特征决定了这世界上大多的事情皆有因果,也决定了程序中凡事必有先后。当我们明确了先做什么,再做什么,最后做什么之后,我们才能对事情真正有所把握。不管采用什么设计方法,都要让这类路线尽可能明晰。惟其如此,程序才更容易懂,因为这是正常人最基本的认知世界的方式。

对时序影响很大的一个因素是并行,并行的一个常见实现方法是启用多线程。多线程程序之所以难写,不在于线程本身的机制或同步多么难以掌握,而在于并发使整个程序中的逻辑变的更加复杂。

最后做一点总结:软件是固化的思维,其基本组成是概念和逻辑。

在未来所有文章中,这点将作为前提(公理)而存在,不进行其他补充说明。



-------------------------------------------------------------
理想流口号:创建超一流方法论,为培育超一流软件公司贡献力量。
理想流博客:http://blog.csdn.net/leezy_2000


页: [1]
查看完整版本: 【理想流】软件本质论 v2.0