软件开发重要思想的总结

来源:互联网 发布:关于美发的软件 编辑:程序博客网 时间:2024/05/05 19:17

 软件开发重要思想的总结

一、类——软件的细胞

正像原子是物质组成的基本单位,而细胞是生物组成的基本单位一样,软件也应该有一个基本单位。在过去,软件有两个基本单位——变量和函数。这有点像单细胞动物,对付一些小东西还行,一旦软件规模增大,这种简单的变量+函数的程序就会捉襟见肘了。一个草履虫是长不了多大的,再发展必然是向着多细胞的方向走。按照这个方向思考,面向过程思想产生的程序就是一个大大的单细胞生物,这个细胞是由变量与函数组成的,那么日后的软件发展,必然是以某种变量与函数的合体作为基本单位,这就是我们所说的类。

  变量

函数
 
变量、变量、函数、函数
 
变量

函数
 
变量

函数
 
变量

函数
 
变量

函数
 
变量

函数
 
变量

函数
 
变量

函数
 
小单细胞
 
大单细胞
 
多细胞
 
面向过程
 
面相对象
 


图1、从面向过程到面向对象

 

二、模块化与迭代开发

软件开发,降低复杂度、提高可复用性、适应变化是目的,分层、模块化、低耦合、迭代开发是手段。

 

降低复杂度、提高可复用性、适应变化
 
继承、封装、多态、接口、包等等
 
分层、模块化、低耦合、迭代开发
 
目的
 
手段
 
语言支持
 


图2、软件开发的目的与手段

软件开发在设计阶段最重要的思想是分层和模块化,并清晰的定义层间与模块之间的接口,减小各个模块之间的耦合度。这种思想的核心是减低程序的复杂度,把大事化小,同时提高软件的可复用性。

在编码阶段最重要的思想是迭代开发,也就是先开发出一个原型,然后保持持续的开发、测试和交付,使系统随时处在可用状态。与传统的瀑布模型相比,这种做法可以有效的适应变化,在开发的过程中发现了新的问题可以对原有的设计甚至是需求进行调整,逐步迭代求精,使软件日趋完美。打个比方,迭代模型好比养孩子,我们从小开始养,看到他犯了错误随时可以管教,表现不错也可以给予鼓励,孩子小时候就一定要严加管教使他养成好的习惯,不然大了就很麻烦了(《代码大全第二版》中提到的牡蛎养殖观点与此相似)。瀑布模型好比盖楼,前期的设计必须非常成熟,我们是不可能一边盖楼一边修改图纸的。《道法自然》P63-P64页的两张图就很能说明问题。

 

过度设计
 
完美设计
 
缺乏设计
 
时间
 


图3、不断趋向完美的设计(迭代开发)

世界是物质的,物质是运动的,运动是不断向前发展的,这种发展的总体形态是螺旋式上升和波浪式前进。

 

 

过度设计
 
完美设计
 
缺乏设计
 
时间
 
概要设计
 
详细设计
 
编码
 
图4、瀑布模型趋近完美的难度相当大

 

 

三、面向对象三原则:单一职责(封装)、完全替换(继承、多态)、依赖倒置(接口)

单一职责原则和完全替换原则的要求都由各种面向对象语言提供语言层面的支持。单一职责讲的是类,是语言中的封装特性。完全替换原则讲的是继承和多态的特性。

依赖倒置原则,也可以说是依赖于抽象。基类为派生类提供基础服务,派生类调用基类的方法是为正向依赖,这时我们一般直接声明和使用派生类;如果我们不直接与派生类打交道,而只是使用基类,那么基类再通过多态机制把控制权转交给相应的派生类,是为依赖倒置。这两个原则实际上也有语言层面的支持——接口(Java)或抽象基类(C++)。

我们一提到面相对象就会说继承、封装、多态,但我认为还应该加上接口,无论从语言实现还是从具体应用上来讲,这都是OO不可或缺的部分。再者,前三个特性都是说类和类的体系内部的问题,而接口则说得是类或类的体系之间的问题,它定义了一个沟通的规范。

在Bob大叔的《敏捷软件开发——原则、模式与实践》中共列举了包括以上原则在内的11项面相对象设计原则。王咏武、王咏刚所著的《道法自然——面相对象实践指南》对这些原则进行了筛选,提出了5项原则,比我上面提到的多了开放封闭原则和无循环依赖原则。大家如果有兴趣可以参考。

开放封闭原则是说软件实体对扩展是开放的,但对修改是封闭的。这里的修改指的是修改原有的程序。这很符合日常开发的经验,因为你很难完全搞清楚已经存在的代码之间的依赖关系,修改原有代码很可能牵一发而动全身,搞出很多麻烦事来。从语义上分析,它和依赖于抽象并不是相互独立的两个概念,它们之间有因果关系,如果一个系统在依赖于抽象方面做的很好,那末它将具有较好的扩展性,也将在很大程度上满足开闭原则。开始这部分是按照面向对象四原则来论述的,一顿午饭之后就变成三个了。

 

 

四、DI&AOP

J2EE领域的两个最重要的新技术或思想是:依赖注入(DI)和面向切面编程(AOP)

1、 依赖注入(DI)

依赖注入可以确保我们依赖于接口而不是具体的实现类,实现类的改变可以通过配置文件完成,接口使用者对此一无所知。工厂模式同样可以使我们只依赖于接口,但经典的工厂模式并不是一个彻底的解决方案,实现类的改变需要修改代码(见《敏捷软件开发》P283-P240),尽管接口使用者对此还是一无所知。

经典的工厂模式+反射=依赖注入的实现机制。Spring中Bean工厂的核心反射代码如下:

Class cls =  Class.forName("net.xiaxin.beans.User");

Method mtd = cls.getMethod("setName",new Class[]{String.class});

Object obj = (Object)cls.newInstance();

mtd.invoke(obj,new Object[]{"Erica"});

return obj;

这段代码摘自夏昕的《Spring开发指南V0.8》,代码中用双引号括起来的都是可以从配置文件中读取的数据。

依赖注入在Spring中用Bean工厂实现。AOP在Spring中是通过工厂Bean实现的,这两个很容易搞混。

2、 面向切面编程

面向切面编程是与面向对象编程同一层面的概念。它根本无法纳入到面向对象的体系之中。如果说OO是点组成的层级模型,那AOP就是面组成的网状模型。OO与AOP一纵一横交织而成一个完整的系统。还有一种说法是OO面向名词领域,AOP面向动词领域,面向的是方法,也就是图4中的Target Method。

AOP运用了动态代理(JDK1.3引入)的特性(AOP可以有很多实现方式,但动态代理的实现应用最广)。它的模型如下图所示。这个图取自《J2EE Development without EJB中文版》P194。

 


图5、AOP模型

这里要注意一个问题,AOP代理在调用Advisor/Interceptor时不是把Advisor/Interceptor放到一个List里,然后对List循环。而是采用的Intercepting Filter模式,也就是多次的回调(我们以前只有“传参数”的说法,我认为回调就是“传方法”,它是以传对象之名行传方法之实)。Webwork拦截器,Servlet Filter也都是这种实现方式。Webwork的代码实现如下,摘自《Spring开发指南V0.8》中XWork拦截器体系一节。

Interceptor 的调度流程大致如下:

1.  ActionInvocation初始化时,根据配置,加载 Action相关的所有 Interceptor

参见ActionInvocation.init方法中相关代码:

private void init() throws Exception {

  ……

    List interceptorList = new 

ArrayList(proxy.getConfig().getInterceptors());

interceptors = interceptorList.iterator();

}

 

2.  通过ActionInvocation.invoke方法调用 Action实现时,执行 Interceptor:

下面是DefaultActionInvocation中 Action调度代码:

public String invoke() throws Exception {

  //调用intercaptors

  if (interceptors.hasNext()) {

    Interceptor interceptor = 

(Interceptor) interceptors.next();

    resultCode = interceptor.intercept(this); //注意

  } else {

   if (proxy.getConfig().getMethodName() == null) {

      resultCode = getAction().execute();

    } else {

      resultCode = invokeAction(

getAction(), 

proxy.getConfig()

);

    }

  }

……

}

3.Interceptor的intercept方法实现如下

  public String intercept(ActionInvocation invocation) throws

Exception {

    String result = null;

 

    before(invocation);

    result = invocation.invoke(); //回调

    after(invocation, result);

 

   return result;

  }

 

五、大师说软件设计原则和方法

 


 

 


 

 

 

 

 

 

 

 

 


以上摘自《敏捷软件开发——原则、模式与实践》

 

 

 

 

 

 


以上摘自《Unix编程艺术》

笔者用了半天的时间把长久以来在脑子里的东西整理出来,文中肯定会有不稳妥甚至是错误的地方,恳请大家的批评指正。

 

参考文献

1、夏昕《Spring开发指南V0.8》满江红2004.09

2、 Robert C.Martin 著  邓辉 译 孟岩 审《敏捷软件开发——原则、模式与实践》清华大学出版社 2003.09

3、王咏刚 王咏武 著《道法自然——面向对象实践指南》电子工业出版社2004.10

4、Rod Johnson、Juergen Hoeller 著  JavaEye 译《J2EE Development without EJB中文版》电子工业出版社2005.09

5、Eric S. Raymond 著  姜宏、何源、蔡晓骏 译《Unix编程艺术》电子工业出版社2006.03

 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 微信支付被投诉怎么办 微信q币充值错误怎么办 微信充值流量充错了怎么办 微信延迟到账怎么办 移动流量充错了怎么办 qq充话费等待发货怎么办 qq充值话费没到账怎么办 电信话费冲错了怎么办 微信手机充错话费充空号怎么办 京东地址写错了怎么办 京东售后不退款怎么办 冲了话费不到账怎么办 币安维护充值怎么办 微信话费未到账怎么办 微信话费交错了怎么办 北京移动查话费余额怎么办 淘宝卖家客服无法联系怎么办? 微信支付月限额怎么办 微信超额20万怎么办 微信支付超额了怎么办 微信零钱超额了怎么办 微信的充值冲错了怎么办 有流量还扣话费怎么办 自动取款机充值到电子账户怎么办 淘宝qb充错了怎么办 q币冲错了人家不给怎么办 qq充值话费错号怎么办 qq充错号码了怎么办 qq交话费不到账怎么办 充错手机号码而且是空号怎么办 微信钱包充错话费怎么办 QQ充值话费充到空号了怎么办 给别人充错话费怎么办 用qq交错话费对方是空号怎么办 号码变成空号了怎么办 qq冲流量冲错了怎么办 流量冲错了套餐怎么办 微信流量充错号码怎么办 微信支付不进账怎么办 充话费充不进去怎么办 用支付宝充话费没到账怎么办