当前位置:
文档之家› 软件设计的五大原则ppt课件
软件设计的五大原则ppt课件
软件设计中的5大原则
.
1. 单一职责原则(SRP)
• 陈述:
– 就一个类而言,应该只有一个导致其变化的原因
• 分析:
– 一个职责就是一个变化的轴线 – 一个类如果承担的职责过多,就等于将这些职责耦合在
一起。一个职责的变化可能会虚弱或者抑止这个类完成 其它职责的能力 – 多职责将导致脆弱性的臭味
.
• 示例1:
见下页程序
.
2. 开放封闭原则(OCP)
– 例子1(续)
class client{ server& s;
public: client(server& SER):s(SER){} void useServer(){ s.ServerFunc(); }
};
class client{ server1& s;
.
– 什么是职责? 职责是“变化的原因”。
– 上面的例子可能存在两种变化的方式:
• 连接和通信可能独立变化 在这种情况下,应该将职责分开。例如,应用的变化导致了连接部分 方法的签名(signature)发生了变化,那么使用数据连接的部分也 需要重新编译、部署,这会相当麻烦,使得设计僵化。
• 连接和通信同时变化 这种情况下,不必将职责分开。反而分离可能导致“不必要的复杂性” 的臭味
刻舟求剑是错误的。 ——王亚沙
.
– 修改后的设计如下:
<<interface>> Data Channel
+send(:char ) +recv():char
<<interface>> Connection
+dail(pno:String ) +hangup()
Modem Implementation
public: client(server& SER):s(SER) {} void useServer(){ s.ServerFunc(); }
};
class server{ int serverData;
public: void ServerFunc();
};
.
– 例子1(续) 这个程序出了什么问题? client和server都是具体类,接口与实现没有实现分离。如果我们 想要让client调用一个新的server类,那么我们不得不修改client 的源代码 从而带来编译、链接、部署等一系列的问题。
.
– 修改后的设计如下:
Computational Geometry Application
Graphical Application
Geometric Rectangle
Rectangle
GUI
+area( ):double
+draw( )
.
• 示例2:
一个Modem的接口: Class Modem{
public: virtual void dail(char* pno)=0; virtual void hangup( ) =0; virtual void send(char c) =0; virtual void recv( ) =0; };
Modem类(可能)有两个职责: 1. 拨号 2. 通信
Computational Geometry Application
ห้องสมุดไป่ตู้
Rectangle + draw( ) +area( ):double
GUI
Rectangle类具有两个职责: 1. 计算矩形面积的数学模型 2. 将矩形在一个图形设备上描述出来
.
Graphical Application
– Rectangle类违反了SRP,具有两个职能——计算面积和 绘制矩形
有一点需要注意:在 ModemImplementation中 实际还是集合了两个职 责。这是我们不希望的, 但是有时候却是必须的。
但是我们注意到,对于 应用的其它部分,通过 接口的分离我们已经实 现了职责的分离。
ModemImplementation已 经不被其它任何程序所 依赖。除了main以外, 其他所有程序都不需要 知道这个函数的存在。
• 分析:
– 世界是变化的(而且变化很快),软件是对现实的抽象 软件必须能够扩展
– 如果任何修改都需要改变已经存在的代码,那么可能导致牵一发动 全身现象,进而导致雪崩效应,使软件质量显著下降
.
• 实现OCP的关键是抽象:
– 例子1
client
server
class client{ server& s;
.
• 常见错误提醒:
– 持久化与业务规则的耦合。 例如:
Persistence Subsystem
Employee
+CalculatePay +Store
业务规则经常变化,而 持久化方法却一般不变。 将这两个职责耦合在一 起,将导致每次因为业 务规则变化调整 Employee类时,所有持 久化部分的代码也要跟 着变化
.
2. 开放封闭原则(OCP)
• 陈述:
– 软件实体(类、模块、函数等)应该是可以扩展的,同时还可以是 不必修改的,更确切的说,函数实体应该: (1)对扩展是开放的 当应用的需求变化时,我们可以对模块进行扩展,使其具有满足改 变的新的行为——即,我们可以改变模块的功能 (2)对更改是封闭的 对模块进行扩展时,不必改动已有的源代码或二进制代码。
public: void ServerFunc();
};
.
2. 开放封闭原则(OCP)
– 例子1(续) 修改后的设计
– 这种对SRP的违反将导致两个方面的问题:
• 包含不必要的代码
– 一个应用可能希望使用Retangle类计算矩形的面积,但是却被迫 将绘制矩形相关的代码也包含进来
• 一些逻辑上毫无关联的原因可能导致应用失败
– 如果GraphicalApplication的需求发生了变化,从而对Rectangle 类进行了修改。但是这样的变化居然会要求我们重新构建、测试 以及部署ComputationalGeometryApplication,否则其将莫名其 妙的失败。
public: client(server& SER):s(SER){} void useServer(){ s.ServerFunc(); }
};
class server{ int serverData;
public: void ServerFunc();
};
class server1{ int serverData;