`
zhaoImpulse
  • 浏览: 79047 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

读《敏捷软件开发》的一些心得

 
阅读更多

 

敏捷软件开发宣言

个体和交互 胜过 过程和工具

可以工作的软件 胜过 面面俱到的文档

客户合作 胜过 合同谈判

响应变化 胜过 遵循计划

敏捷设计原则:

单一职责原则(The Single Responsibility Principle,简称SRP);

开发-封装原则(The Open-Close Principle,简称OCP);

Liskov替换原则(The Liskov Substitution Principle,简称LSP);

依赖倒置原则(the Dependency Inversion Principle,简称DIP);

接口隔离原则(The Interface Segregation Interface,简称ISP);

单一职责原则(SRP):

就一个类而言,应该仅有一个引起它变化的原因。

开放-封装原则(OCP):

软件实体(类,模块,函数等)应该是可以扩展的,但是不可修改的。

1.对于扩展是开发的

这意味着模块的行为是可以扩展的。当应用的需求改变时,我们可以对模块进行扩展,使其具有满足那些改变的新行为。换句话说,我们可以改变模块的功能。

2.对于更改是封闭的

对模块行为进行扩展时,不必改动模块的源代码或者二进制代码。模块的二进可执行版本,无论是可链接的库、DLL或者Java的.jar文件,都无需改动。

怎么可能在不改动模块源代码的情况下去更改它的行为呢?关键是抽象!

 

public class Square(){
	public String type="square";
}
public class Circle(){
	public String type="circle";
}
public class DrawShape{
	//list为所有要画的shape的集合
	public void DrawAllShapes(ArrayList<Object> list){
		for(int i=0;i<list.size();i++){
			switch(s.type){
			case "square":
				DrawSquare(list.get(i));break;
			case "circle":
				DrawCircle(list.get(i));break;			
			}
		}	
	}
	private void DrawSquare(Object o){}
	private void DrawCircle(Object o){}
}
 

 

DrawAllShapes函数是要画出所有图形,先检查图形的类型,在判断是调用DrawSquare还是DrawCircle。该函数显然是不符合OCP,因为它对于新的形状类型的添加不是封装的。如果希望这个函数能够绘制包含有三角形的列表,就必须得更改整个函数。而要解决这个问题,就可以使用抽象

 

 public interface Shape{
		public void Draw();
	}
	public class Square implements shape{
		public void Draw(){System.out.println("Draw square");}
	}
	public class Circle implements Shape{
		public void Draw(){System.out.println("Draw circle");}
	}
	public class DrawShape{
		public void DrawAllShapes(ArrayList<Shape> list){
			for(int i=0;i<list.size();i++){
				i.draw();
			}	
		}
	}
 

 

这样想添加新图形时,只要创建这个图形的类,并implements Shape接口,并实现Draw()方法即可,无需再改动DrawAllShapes方法。它也就符合OCP了。

Liskov 替换原则(LSP)

子类型必须能够替换掉它的基类型。

正方形并不是个矩形!!!

 

 class Rectangle{
		private double width;
		private double height;
		void setWidth(double w){width = w;}
		void setHeight(double h){height = h;}
		double getWidth(){reutrn width;}
		double getHeight(){return height;}
		double Area(){
			return width * height;
		}
	}
 

正方形应该是一个矩形,所以Square应该派生自Rectangel类。不过,Square并不需要成员变量width和height。但仍会继承它们,显然这是种浪费,虽然在许多情况下这种浪费是可以忽略的,但setWidth()和setheight()这种个函数对于Square来说是不适合的,但Square仍会继承它们。当然,为了避免这个问题,我们也可以写:

 

 class Square extends Rectangel{
		void setWidth(double w){super.setWidth(w);super.setHeight(w);}
		void setHeight(double h){super.setHeight(h);super.setWidth(h);}
	}
 

这样就可以保证这个正方形的长和宽是一样的了。但对于下面这个问题

 

void g(Rectangle r){
		r.setWidth(5);
		r.setHeight(4);
		assert(r.Area()==20);
}
 

这本来是很正常的,但当r是个正方形是,这个assert就会是错误的,因为当最后调用r.setHeight(4)时,长宽都为4,Area()得到的结果就是16!所以Square并不能完全替换Rectangel,也就是说,它不符合LSP原则。

IS-A是关于行为的

对于那些不是g测试方法的编写者而言,正方形当然是个矩形,但从g的角度来看,Square对象绝对不是Rectangel对象。因为Square对象的行为方式和函数g所期望的Rectangle对象的行为方式不相容。不行为方式的角度来看,Square不是Rectangle。

对象的行为方式才是软件真正所关注的问题。

依赖倒置原则(DIP)

a.高层模块不应该依赖于低层模块。二者都应该依赖于抽象。

b.抽象不应该依赖于细节,细节应该依赖于抽象。

这是一个违反DIP原则的例子,高层的PolicyLayer 使用了低层的MechanismLayer,而MechanismLayer又使用了更低层的UtilityLayer。那么UtilityLayer一些很小的改动都将影响高层的PolicyLayer。而低层的类又是容易改变的,为了解决这个问题,我们可以将这些类低速于抽象。每个较高层次都为它所需要的服务声明一个抽象接口,较低的层次实习了这些抽象接口,每个高层类都通过该抽象接口使用下一层,这样高层就不依赖于低层。低层反而依赖于在高层中声明的抽象服务接口。

要依赖于抽象,于是可知三个原则:

1.任何变量都不应该持有一个指向具体类的指针或者引用。

2.任何类都不应该从具体类派生

3.任何方法都不应该复写它的任何基类中的已经实现了的方法。

一个简单的例子

 

public class Button{
 private Lamp lamp;
 public void poll(){
  if(/*some condition*/)
   lamp.turnOn();
 }
}

     这个方案违反了DIP,Button类直接依赖于Lamp类,当Lamp改变时,高层的Button类也会受到影响,此外,想重用Button类来挖掘一个Motor对象是不可能的。在这个设计中,Button控制着Lamp对象,并且也只能控制Lamp对象。

找出潜在的抽象

这样,Lamp依赖于ButtonServer,但ButtonServer没有依赖于Button,任何知道如果去操作ButtonServer接口的对象都能够控制Lamp。

接口隔离原则(ISP)

接口应该是高内聚的,一个接口应该尽量只为一种客户服务,而不是为了几个客户,否则,就会出现接口污染。

不应该强迫客户依赖于它们不用的方法。

如果强迫客户程序依赖于那些它们不使用的方法,那么这些客户程序就面临着由于这些未使用方法的改变所带来的变更。这无意中导致了所有客户程序之间的耦合。换句话说,如果一个客户程序依赖于一个含有它不使用的方法的类,但是其他客户程序却要使用该方法,那么当其他客户要求这个类改变时,就会影响到这个客户程序。我们希望尽可能地避免这种耦合,因此我们希望分享接口。

  • 大小: 32.7 KB
  • 大小: 86.7 KB
  • 大小: 15.9 KB
  • 大小: 36.2 KB
分享到:
评论

相关推荐

    敏捷软件开发敏捷软件开发

    敏捷软件开发敏捷软件开发敏捷软件开发敏捷软件开发敏捷软件开发敏捷软件开发敏捷软件开发敏捷软件开发

    Scrum敏捷软件开发过程.pdf

    Scrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程.pdfScrum敏捷软件开发过程....

    敏捷软件开发原则、模式与实践.pdf

     ·讲述在预算和实践要求下,软件开发人员和项目经理如何使用敏捷开发完成项目。  ·使用真实案例讲解如何用极限编程来设计、测试、重构和结对编程。  ·包含了极具价值的可多次使用的C++和JAVA源代码  ·重点...

    Scrum敏捷软件开发

    《Scrum敏捷软件开发》是敏捷联盟及Scrum联盟创始人之一、敏捷估算及计划的鼻祖Mike Cohn三大经典著作中影响最为深厚的扛鼎之作,也是全球敏捷社区中获得广泛肯定的企业敏捷转型权威参考。作者花四年时间,把自己近...

    敏捷软件开发.pdf

    敏捷软件开发.pdf 凝聚了世界级软件开发大师Robert C. Martin数十年软件开发和培训经验,Java版曾荣获计算机图书最高荣誉——Jolt大奖,是广受推崇的经典著作,自出版以来一直畅销不衰。要想成为一名优秀的软件开发...

    敏捷软件开发:原则、模式与实践(全)

    敏捷软件开发:原则、模式与实践(全) 敏捷软件开发:原则、模式与实践(全) 敏捷软件开发:原则、模式与实践(全) 敏捷软件开发:原则、模式与实践(全) 敏捷软件开发:原则、模式与实践(全)

    敏捷软件开发_java

    敏捷软件开发 敏捷软件开发 敏捷软件开发 敏捷软件开发

    敏捷软件开发.doc

    敏捷软件开发.doc敏捷软件开发.doc

    敏捷软件开发:原则、模式与实践.pdf

    敏捷软件开发:原则、模式与实践.pdf 敏捷软件开发:原则、模式与实践.pdf 敏捷软件开发:原则、模式与实践.pdf

    敏捷软件开发:原则、模式与实践(高清PDF)

    敏捷软件开发:原则、模式与实践(高清PDF)

    敏捷软件开发方法与实践

    第6章从组织变革实施模型的角度分析了软件开发组织(全企业或企业中的一些部门)如何进行敏捷转型;第7章介绍了在分布式开发环境和团队中如何采用敏捷实践。, 《敏捷软件开发方法与实践》的目标读者包括软件行业从业...

    敏捷开发-敏捷软件开发:原则、模式与实践

    在本书中,享誉全球的软件开发专家和软件工程大师Robert C.Martin将向您展示如何解决软件开发人员、项目经理及软件项目领导们所面临的最棘手的问题。这本综合性、实用性的敏捷开发和极限编程方面的指南,是由敏捷...

    敏捷软件开发:原则模式与实践

    《敏捷软件开发:原则模式与实践》是综合性、实用性的敏捷开发和极限编程方面的指南,讲述了在预算和时间要求下软件开发人员和项目经理如何使用敏捷开发完成项目:使用真实案例讲解如何用极限编程来设计、测试、重构...

    敏捷软件开发精要.pdf

    敏捷软件开发精要,讲述敏捷开发方法、介绍、实施内容。

    敏捷软件开发书籍 pdf

    敏捷软件开发书籍合集,包括: [Scrum敏捷软件开发] [The.Pragmatic.Bookshelf开发丛书-敏捷开发回顾:使团队更强大] [The.Pragmatic.Bookshelf开发丛书-敏捷开发指导] [敏捷开发修炼之道] [用户故事与敏捷方法]

    敏捷软件开发实践估算与计划 Mike Cohn

    敏捷软件开发实践估算与计划 Mike Cohn,2016年版,清华大学出版社

    敏捷软件开发实践

    敏捷软件开发实践,一本好书

Global site tag (gtag.js) - Google Analytics