可维护性的含义:可轻松修改软件系统或组件,以纠正故障,提高性能或其他属性,或适应变化的环境。
可维护性的别名:可扩展性(Extensibility)、灵活性(Flexibility)、可适应性(Adaptability)、可管理性(Manageability)、支持性(Supportability)。
可维护性的度量标准:
1. 模块化编程的含义:模块化编程是一种设计技术,它强调将程序的功能分解为独立的可互换模块,以便每个模块都包含执行所需功能的一个方面。
设计目标:
(模块化降低了程序员在任何时候都必须处理的总体复杂性,因为模块化实现了分离关注点和信息隐藏)(内聚和耦合的原则可能是评估可维护性的最重要的设计原则)
2.评估模块化的五个标准
3.模块化设计的五条原则
SOLID:
含义:不应有多于1个的原因使得一个类发生变化;一个类,一个责任。(如果一个类包含了多个责任,那么将引起不良后果:引入额外的包,占据资源;导致频繁的重新配置、部署等。)
反例:
2.(OCP) The Open-Closed Principle 开放-封闭原则
含义:开发指的是对扩展性的开放,模块的行为应是可扩展的,从而该模块可表现出新的行为以满足需求的变化。封闭指的是对修改的封闭,模块自身的代码是不应被修改的,扩展模块行为的一般途径是修改模块的内部实现,如果一个模块不能被修改,那么它通常被认为是具有固定的行为。
关键解决方案:抽象技术。 使用继承和组合来改变类的行为。
反例:
*例:
// Open-Close Principle - Bad example
class GraphicEditor {
public void drawShape(Shape s) {
if (s.m_type==1)
drawRectangle(s);
else if (s.m_type==2)
drawCircle(s);
}
public void drawCircle(Circle r)
{....}
public void drawRectangle(Rectangle r)
{....}
}
class Shape { int m_type; }
class Rectangle extends Shape { Rectangle() { super.m_type=1; } }
class Circle extends Shape { Circle() { super.m_type=2; } }
上面代码存在的问题:
1.不可能在不修改GraphEditor的情况下添加新的Shape
2.GraphEditor和Shape之间的紧密耦合
3.不调用GraphEditor就很难测试特定的Shape
改进之后的代码:
// Open-Close Principle - Good example
class GraphicEditor {
public void drawShape(Shape s) {
s.draw();
}
}
class Shape { abstract void draw(); }
class Rectangle extends Shape { public void draw() { // draw the rectangle } }
3.(LSP) The Liskov Substitution Principle Liskov替换原则
含义:子类型必须能够替换其基类型。 派生类必须能够通过其基类的接口使用,客户端无需了解二者之间的差异。
(这条原则在第五章第二节中已经详细将结果,在此不再赘述)
4.(DIP) The Dependency Inversion Principle 依赖转置原则
含义:高级模块不应该依赖于低级模块。 两者都应该取决于抽象。抽象的模块不应依赖于具体的模块,具体应依赖于抽象。
*例:
改进之前的代码:
void Copy(OutputStream dev) {
int c;
while ((c = ReadKeyboard()) != EOF)
if (dev == printer)
writeToPrinter(c);
else
writeToDisk(c);
}
该用抽象技术后的代码:
interface Reader { public int read(); }
interface Writer { public int write(c); }
class Copy {
void Copy(Reader r, Writer w) {
int c;
while (c=r.read() != EOF)
w.write(c);
}
}
**例:
(改进之后,就能够将finder变成任意的EmployeeFinder,例如XmEmployeeFinder,DBEmployeeFinder,FlatFileEmployeeFinder, MockEmployeeFinder….
而在之前的代码中,就无法这么方便的改变类的属性了。)
5.(ISP) The Interface Segregation Principle 接口聚合原则
含义:客户端不应依赖于它们不需要的方法。
示例:“胖”接口具有很多缺点。胖接口可分解为多个小的接口;不同的接口向不同的客户端提供服务;客户端只访问自己所需要的端口。下图展示出了这种思想。
反例:
含义:GRASP是关于如何为“类”和“对象”指派“职责”的一系列原则。
组成: