敏捷软件开发宣言
个体和交互 胜过 过程和工具
可以工作的软件 胜过 面面俱到的文档
客户合作 胜过 合同谈判
响应变化 胜过 遵循计划
敏捷设计原则:
单一职责原则(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
分享到:
相关推荐
文档应以简洁实用为主,服务于软件开发。 - **设计与实现平衡**:敏捷开发认为设计是为了提高软件质量,但并不意味着设计比实现更重要。设计应该适时适度,以满足实际开发需求为准。 3. **敏捷开发流程与角色** -...
因此,我将基于软件开发实习生可能的工作内容和心得体会,以及常见的软件开发工具和概念,来撰写一些可能符合要求的知识点。 软件开发实习过程一般包括如下几个方面: 1. 开发环境的熟悉与使用 - 实习生在进入...
"NIIT软件开发学习心得"则突出了软件开发这一具体领域的挑战和收获。在这一阶段,学员可能经历了从编写简单的代码到解决复杂问题的转变,理解了团队协作、版本控制和敏捷开发的重要性。这些心得分享有助于后来者更好...
的面向对象代码是软件开发的核心,这涉及到对编程语言特性的深入理解、良好的设计原则和模式的应用,以及对代码质量的严格把控。面向对象设计的精髓在于将现实世界的问题映射为对象和它们之间的交互,从而提高代码的...
本文将分享过去一年中实施敏捷开发的心得体会,特别是在产品开发过程中的关键要素,如概念和架构设计、SWOT分析、业务驱动与客户导向、版本兼容性以及文档管理。 1) 注重概念和架构设计,而轻详细设计 敏捷开发倡导...
【软件开发与应用心得体会】 软件开发是一个复杂而充满挑战的过程,尤其在当今互联网时代,它已经成为推动科技进步和社会发展的重要力量。本文将从Android应用程序开发和软件工程的角度,分享一些学习和实践经验。 ...
在IT行业中,敏捷实践已经成为软件开发的主流方法论,它强调快速响应变化、迭代开发和持续交付价值。《敏捷实践的秘密(来自软件界实践者的经验心得)》这一资料集揭示了敏捷开发的核心理念和实际操作中的技巧。通过...
敏捷开发是一种强调适应性和灵活性的软件开发方法论,其核心理念是以用户需求进化为中心,通过迭代和循序渐进的方式来构建软件。与传统的瀑布式开发模式不同,敏捷开发更加注重快速响应变化、持续交付可用的产品增量...
敏捷开发是一种强调适应性和灵活性的软件开发方法论,其核心理念是以用户需求进化为中心,采用迭代、循序渐进的方式进行软件开发。这种方法使得软件项目能够在构建初期就被划分为多个小型子项目,每个子项目都可以...
敏捷开发是一种以人为本、灵活应对变化的软件开发方法论。它强调快速反馈、团队协作和持续改进,以提高软件开发的效率和质量。敏捷宣言是敏捷方法的核心指导原则,包括四个价值观:个体和交互胜过过程和工具,可以...
敏捷管理是一种以用户需求为中心,强调快速响应变化的软件开发模式。它倡导通过迭代、小步快跑的方式,不断优化产品,以确保软件始终能够满足用户的需求。相较于传统的瀑布模型、迭代式开发、螺旋开发,敏捷管理更...
在软件开发领域,经验往往是最宝贵的财富。"软件开发的经验建议15篇"这个压缩包文件,正如其标题所示,汇集了多位资深开发者的真实经历和深刻见解,旨在为正在或即将踏入这个行业的人提供宝贵的指导。这15篇文章,...
书中讲述了软件开发模型,包括瀑布模型、RUP敏捷软件开发方法、MSF(Microsoft Solution Framework)等。 知识点11:软件质量管理 书中讲述了软件质量管理的重要性和方法,包括软件质量的定义、软件质量的控制和...
软件需求工程是软件开发过程中的一关键步骤,它对软件开发的成功与否具有至关重要的影响。软件需求工程的目的是为了获取正确的软件需求,确保软件开发的正确性和可靠性。软件需求工程的过程包括需求获取、需求分析、...
这些文档包括需求规格书、设计文档、用户手册等,它们是软件开发的重要组成部分,也是测试工作的基础。良好的文档能够清晰地定义软件的功能和预期行为,有助于测试人员理解系统的工作原理,从而设计出更有效的测试...
《软件工程》是一门至关重要的学科,旨在将软件开发的过程规范化、系统化,以提高软件的质量、稳定性和生产效率。学习软件工程的目的在于应对日益复杂的软件开发挑战,通过工程化的方法来降低程序员的工作负担,提升...
【标题】2010上海 2010SD软件开发2.0大会是一次聚焦于软件开发领域的专业会议,重点探讨了软件开发的新趋势、新技术以及最佳实践。这次大会的PPT涵盖了从源码管理到开发工具的广泛议题,旨在提升软件开发的效率和...