天天看点

复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念

961全部内容链接

文章目录

  • 软件体系结构及体系结构风格的概念
  • 设计模式的概念
  • 模块化设计的基本思想及概念
    • 抽象
    • 分解(逐步求精)
    • 模块化
    • 封装
    • 信息隐藏
    • 功能独立
      • 内聚与耦合的概念
        • 常见的内聚与耦合类型
  • 软件重构的概念(再工程)
  • 软件体系结构的UML建模
    • 包图
    • 类图
    • 构件图
    • 顺序图
    • 部署图
  • 接口的概念
  • 面向对象设计原则
    • 开闭原则
    • Liskov替换原则
    • 依赖转置原则
    • 接口隔离原则
  • 内聚与耦合的概念

软件体系结构及体系结构风格的概念

软件体系结构(architecture)并非是可运行的软件,是一种使设计师能够在更高层次分析“设计”是否满足需求的一种表示。常见的体系结构有单主机结构、B/S架构和C/S架构。

软件体系结构的风格:

  • 数据为中心的体系结构:一些数据(比如一个文件或者数据库)保存在整个结构的中心,并且被其他部件频繁地使用、添加、删除、或者修改
    复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念
  • 数据流风格的体系结构:这种结构适用于输入数据被一系列的计算或者处理部件变换成输出数据。
    复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念
  • 调用和返回风格的体系结构:这种风格使一个软件设计者设计出非常容易修改和扩充的体系结构。包含:主程序/子程序风格体系结构和远程过程调用风格的体系结构。
    复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念
    • 程序的深度:程序结构的层次数称为结构的深度。结构的深度在一定意义上反映了程序结构的规模和复杂程度。
    • 程序结构的宽度:层次结构中同一层模块的最大模块个数称为结构的宽度。
    • 模块的扇入和扇出:扇出表示一个模块直接调用(或控制)的其它模块数目。扇入则定义为调用(或控制)一个给定模块的模块个数。多扇出意味着需要控制和协调许多下属模块。而多扇入的模块通常是公用模块。
  • 面向对象风格的体系结构:系统部件封装数据和操作数据的方法。部件之间的交互和协调通过消息来传递。
  • 层次式风格的体系结构:在这种结构中,定义不同的层次,每层都完成了相对外层更靠近机器指令的操作
    复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念

设计模式的概念

在许多面向对象系统中,存在一些类和对象的重复出现的模式。这些模式求解特定的设计问题,使面向对象设计更灵活,并最终可复用。这些模式帮助设计者复用以前成功的设计,设计者可以把这些模式应用到新的设计中。

一个设计模式通常可用4个基本要素来描述:

  • 模式名称:用于描述模式的助忆符。设计模式名应具有实际的含义,能反映模式的适用性和意图。就是设计模式的名字,如工厂模式,单例模式
  • 问题:描述何时使用模式,解释设计问题以及应用模式所必须的环境和条件。
  • 解决方案:描述构成设计方案的各元素、它们之间的关系、各自的职责和协作方式
  • 效果:描述模式应用的效果以及使用模式时的折中问题

常见的设计模式有:

  • 创建型模式:工厂模式,抽象工厂,构建器,原型,单例
  • 结构型模式:适配器,桥接,组合,装饰器等
  • 行为型模式:解释器,模板方法,职责链,命令,迭代器,观察者等

模块化设计的基本思想及概念

抽象

抽象,是在软件设计的规模逐渐增大的情况下,控制复杂性的基本策略。

抽象的过程是从特殊到一般的过程,上层概念是下层概念的抽象,下层概念是上层概念的精化和细化。

软件工程过程的每一步都是对较高一级抽象的解作一次具体化的描述。

两种主要的抽象手段:

  • 过程抽象(也称为功能抽象):是指任何一个完成明确定义功能的操作都可被使用者当作单个实体看待,尽管这个操作实际上是由一系列更低级的操作来完成的
  • 数据抽象:是指定义数据类型和施加于该类型对象的操作,并限定了对象的取值范围,只能通过这些操作修改和观察数据

分解(逐步求精)

逐步求精,把问题的求解过程分解成若干步骤或阶段,每步都比上步更精化,更接近问题的解法

抽象使得设计者能够描述过程和数据而忽略低层的细节,而求精有助于设计者在设计过程中揭示低层的细节

模块化

模块化,即把软件按照规定原则,划分为一个个较小的,相互独立的但又相互关联的部件,实际上是系统分解和抽象的过程。

模块是数据说明、可执行语句等程序对象的集合,它是单独命名的,并且可以通过名字来访问。例如,过程。函数、子程序、宏等。

复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念

书上这个图主要是想说明,模块的数量也不是越多越好。适中即可。

封装

TODO

信息隐藏

每个模块的实现细节对于其它模块来说应该是隐蔽的

块中所包含的信息(包括数据和过程)不允许其它不需要这些信息的模块使用

通过信息隐蔽,则可定义和实施对模块的过程细节和局部数据结构的存取限制

功能独立

功能独立是模块化、抽象、信息隐藏和局部化等概念的直接结果。开发功能专一的且避免与其他模块过多交互的的模块可以实现功能独立。

功能独立的重要性:

  • 功能被分隔且接口被简化使得软件更容易开发
  • 由于因修改设计或修改编码引起的副作用被限制,减少了错误扩散,且模块复用成为可能,因而使得软件更易于维护和测试。

内聚与耦合的概念

功能独立性可以由两项指标来衡量:内聚度与耦合度

内聚(cohesion)是一个模块内部各个元素彼此结合的紧密程度的度量。

耦合(coupling)是模块之间的相对独立性(互相连接的紧密程度)的度量

模块之间的连接越紧密,联系越多,耦合性就越高,而其功能独立性就越弱

一个模块内部各个元素之间的联系越紧密,则它的内聚性就越高。

功能独立性比较强的模块应是高内聚低耦合的模块

常见的内聚与耦合类型

一般模块的内聚性分为七种类型:

复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念
  • 巧合内聚(偶然内聚):将几个模块中没有明确表现出独立功能的相同程序代码段独立出来建立的模块称为巧合内聚模块
  • 逻辑内聚:指完成一组逻辑相关任务的模块,调用该模块时,由传送给模块的控制型参数来确定该模块应执行哪一种功能
  • 时间内聚:指一个模块中的所有任务必须在同一时间段内执行。例如初始化模块和终止模块
  • 过程内聚:指一个模块完成多个任务,这些任务必须按指定的过程(procedural)执行。
  • 通信内聚:指一个模块内所有处理元素都集中在某个数据结构的一块区域中。
  • 顺序内聚:指一个模块完成多个功能,这些功能又必须顺序执行。
  • 功能内聚:指一个模块中各个部分都是为完成一项具体功能而协同工作,紧密联系,不可分割的。

一般模块之间可能的耦合方式有七种类型:

复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念
  • 内容耦合:如果一个模块直接访问另一个模块的内部数据;或者一个模块不通过正常入口转到另一模块内部;或者两个模块有一部分程序代码重迭;或者一个模块有多个入口,则两个模块之间就发生了内容耦合。
  • 公共耦合:若一组模块都访问同一个公共数据环境,则它们之间的耦合就称为公共耦合。公共的数据环境可以是全局数据结构、共享的通信区、内存的公共覆盖区等。
  • 外部耦合:指模块间通过软件之外的环境联结(如I/O将模块耦合到特定的设备、格式、通信协议上)时,称为外部耦合。
  • 控制耦合:如果一个模块传送给另一个模块的参数中包含了控制信息,该控制信息用于控制接收模块中的执行逻辑,则称为控制耦合。
  • 标记耦合:两个模块之间通过参数表传递一个数据结构的一部分(如某一数据结构的子结构),就是标记耦合。
  • 数据耦合:两个模块之间仅通过参数表传递简单数据,则称为数据耦合。
  • 非直接耦合:如果两个模块之间没有直接关系,即它们中的任何一个都不依赖于另一个而能独立工作,这种耦合称为非直接耦合。

软件重构的概念(再工程)

考纲中说的软件重构应该就是指书上的再工程技术,语文不好不太确定。但是也没其他的了。

逆向工程(reverse engineering):指在软件生存周期中,将软件的某种形式描述转换成更抽象形式的活动。

重构(restructuring):指在同一抽象级别上转换系统的描述形式,如把C++ 程序转换成Java程序

设计恢复(design recovery):指借助工具从已有程序中抽象出有关数据结构设计、总体结构设计和过程设计的信息。

再工程(reengineering):指在逆向工程所获信息的基础上修改或重构已有的系统,产生系统的一个新版本

再工程的主要目的:为遗留系统转化为可演化系统提供一条现实可行的途径

再工程包含:

  • 业务过程再工程
  • 软件再过程:软件再过程又包括:
    • 库存目录分析:分析一下系统的基本情况,便于后期维护
    • 文档重构:重要的业务重新写文档,不重要的业务就用之前的文档
    • 逆向工程:用程序生成代码,用代码生成ER图,UML图等,帮助理解程序。
    • 代码重构:把看不懂的代码重构一下,可以用工具。
    • 数据重构:分解原有复杂的数据结构。
    • 正向工程:对某个现有功能重新开发,也可以同时加入新功能。

软件体系结构的UML建模

包图

包(package)就是java中的包。包图,就是把在图中把包体现出来

复旦大学961-软件工程-第三章-软件设计与构造软件体系结构及体系结构风格的概念设计模式的概念模块化设计的基本思想及概念软件重构的概念(再工程)软件体系结构的UML建模接口的概念面向对象设计原则内聚与耦合的概念

如图,java.lang包中包含这几个类。

类图

类图在上一章有详细讲解。

构件图

TODO

顺序图

这个上一章说过了

部署图

TODO

接口的概念

面向对象设计原则

面向对象设计原则参考

开闭原则

开闭原则(Open Closed Principle, OCP)是指对扩展开放,对修改关闭。通俗的话说,当你需要对功能进行变化时,可以在不更改原有源代码的情况下扩展新的代码。

实现开闭原则的常用方法:

  • 抽象约束、封装变化:通过接口或者抽象类为软件实体定义一个相对稳定的抽象层,而将相同的可变因素封装在相同的具体实现类中。
  • 使用继承:通过继承原有类,扩展其方法。
  • 使用接口:调用时尽量调用接口而非调用类。如调用排序方法时,调用 Sort接口,而非调用具体的BubbleSort类。
  • 使用设计模式:如代理模式,装饰器模式等。比如可以使用Spring的AOP功能来遵循开闭原则。
  • 其他各种各样的方法,开闭原则是一个原则,不同的情况使用不同的方式来遵循这个原则,考试中应该会让举几个例子,或者给出例子让考生描述如何遵循开闭原则。

开闭原则的作用:

  • 对软件测试的影响:软件遵守开闭原则的话,软件测试时只需要对扩展的代码进行测试就可以了,因为原有的测试代码仍然能够正常运行。
  • 可以提高代码的可复用性:粒度越小,被复用的可能性就越大;在面向对象的程序设计中,根据原子和抽象编程可以提高代码的可复用性。
  • 可以提高软件的可维护性:遵守开闭原则的软件,其稳定性高和延续性强,从而易于扩展和维护。

Liskov替换原则

Liskov替换原则(Liskov Substitution Principle,LSP)也称为里氏替换原则。里氏替换原则是针对继承提出的,原则为:子类可以扩展父类的功能,但不能改变父类原有的功能。也就是说:子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法。

总结为以下几点:

  • 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法
  • 子类中可以增加自己特有的方法
  • 当子类的方法重载父类的方法时,方法的前置条件(即方法的输入参数)要比父类的方法更宽松(比如父类中的方法参数为Map,则子类中就要用HashMap)
  • 当子类的方法实现父类的方法时(重写/重载或实现抽象方法),方法的后置条件(即方法的的输出/返回值)要比父类的方法更严格或相等(比如父类方法返回Map,则子类实现父类时,该方法也返回Map,或者可以更严格,返回HashMap)

里氏替换原则的作用:

  • 里氏替换原则是实现开闭原则的重要方式之一。
  • 它克服了继承中重写父类造成的可复用性变差的缺点。
  • 它是动作正确性的保证。即类的扩展不会给已有的系统引入新的错误,降低了代码出错的可能性。
  • 加强程序的健壮性,同时变更时可以做到非常好的兼容性,提高程序的维护性、可扩展性,降低需求变更时引入的风险。

依赖转置原则

依赖倒置原则(Dependence Inversion Principle,DIP)定义为:高层模块不应该依赖低层模块,两者都应该依赖其抽象;抽象不应该依赖细节,细节应该依赖抽象。核心思想为:要面向接口编程,不要面向实现编程。

依赖转置的实现方式有:

  • 每个类尽量提供接口或抽象类,或者两者都具备。
  • 变量的声明类型尽量是接口或者是抽象类。
  • 任何类都不应该从具体类派生。
  • 使用继承时尽量遵循里氏替换原则。

依赖转置原则的作用:

  • 依赖转置原则可以降低类间的耦合性。
  • 依赖转置原则可以提高系统的稳定性。
  • 依赖转置原则可以减少并行开发引起的风险。
  • 依赖转置原则可以提高代码的可读性和可维护性。

接口隔离原则

接口隔离原则(Interface Segregation Principle,ISP):尽量将臃肿庞大的接口拆分成更小的和更具体的接口,让接口中只包含客户感兴趣的方法。这里的客户指的是使用该接口的人。

接口隔离原则的实现方式:

  • 接口尽量小,但是要有限度。一个接口只服务于一个子模块或业务逻辑。
  • 为依赖接口的类定制服务。只提供调用者需要的方法,屏蔽不需要的方法。
  • 了解环境,拒绝盲从。每个项目或产品都有选定的环境因素,环境不同,接口拆分的标准就不同,深入了解业务逻辑。
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。

接口隔离原则的优点:

  • 将臃肿庞大的接口分解为多个粒度小的接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。
  • 接口隔离提高了系统的内聚性,减少了对外交互,降低了系统的耦合性。
  • 如果接口的粒度大小定义合理,能够保证系统的稳定性;但是,如果定义过小,则会造成接口数量过多,使设计复杂化;如果定义太大,灵活性降低,无法提供定制服务,给整体项目带来无法预料的风险。
  • 使用多个专门的接口还能够体现对象的层次,因为可以通过接口的继承,实现对总接口的定义。
  • 能减少项目工程中的代码冗余。过大的大接口里面通常放置许多不用的方法,当实现这个接口的时候,被迫设计冗余的代码。

内聚与耦合的概念

这个在上面的功能独立中已经说明

961

继续阅读