第八章 软件设计基础
1.软件设计(名词解释)
a)为使一软件系统满足规定的需求而定义系统或部件的体系结构、部件、接口和其他特征的过程;
b)设计过程的结果。
2.软件设计的核心思想
复杂度控制
分解、抽象、层次性
第九、十章 软件体系结构设计与构建
1.体系结构概念
部件+连接件+配置
部件:承载系统主要功能,包括处理与数据
连接件:定义部件间的交互,是连接的抽象表示
配置:定义了部件和连接件之间的关联方式,将它们组织称系统的总体结构
2.体系结构的风格的优缺点
常见风格模式:
(1)主程序/子程序风格
部件:程序、函数、模块
连接件:它们之间的调用
控制从子程序层次结构顶部开始且向下移动
层次化分解:基于定义使用关系
单线程控制
隐含子系统结构:子程序通常合并成模块
层次化推理:子程序的正确性依赖于它调用的子程序的正确性
优点:流程清晰,易于理解;强控制性。
缺点:a.程序调用是一种强耦合的连接方式,非常依赖交互方的接口规格,使得系统难以修改和复用; b.基于程序调用(声明-使用)关系的连接方式限制了各部件之间的数据交互,可能会使得不同部件使用隐含的共享数据交流,产生不必要的公共耦合,进而破坏它的“正确性”控制能力。
实现:功能分解、集中控制,每个构件一个模块实现,主要是单向依赖。使用utility或tools等基础模块
(2)面向对象式风格
部件: 对象或模块
连接件: 功能或调用(方法)
数据表示对于其他对象是隐藏的
对象负责保持数据表示的完整性(例如一些不变量)
每个对象都是自主代理
优点:内部实现的可修改性;易开发、易理解、易复用的结构组织。
缺点:接口的耦合性;标识的耦合性;副作用(Ex:A和B都修改C)。
适用于核心问题是识别和保护相关机构信息(数据)的应用
数据表示和相关操作封装在抽象数据类型,例: 抽象数据类型
实现:任务分解,(委托式)分散式控制,每个构件一个模块实现,使用接口将双向依赖转换为单向依赖
将每个构件分割为多个模块,以保证单向依赖,使用utility或tools等基础模块
(3)分层风格
上层调用下层,禁止逆向调用,跨层调用
部件: 通常是程序或对象的集合
连接件: 通常是有限可见度下的程序调用或方法调用
优点:设计机制清晰,易于理解;支持并行开发;更好的可复用性与内部可修改性。
缺点:交互协议难以修改;性能损失;难以确定层次数量和粒度。
应用:适用于包含不同类服务的应用,而且这些服务能够分层组织
尤其当应用可能在某些层改变,例如交互,通信,硬件,平台等
例子:分层通信协议,每一层在某种程度的抽象上提供了通信的基底,低层定义了低层次的交互最底层是硬件连接(物理层)
实现:关注点分离(每层逐次抽象),层间接口使用固定协议(固定控制),每层一或多个模块实现,单向依赖,层间数据传递建立专门模块,使用utility或tools等基础模块
(4)MVC风格
模型——视图——控制器
Model子系统被设计成不依赖任何View或Controller子系统
它们状态的改变会传播到View子系统
部件:Model部件负责维护领域知识和通知视图变化;View部件负责给用户显示信息和将用户手势发送给控制器;Controller改变模型的状态、将用户操作映射到模型更新、选择视图进行响应
连接件: 程序调用,消息,事件
优点:易开发性;视图和控制的可修改性;适宜于网络系统开发的特征。
缺点:复杂性;模型修改困难。
适用于以下应用:在运行时,用户界面的改变很容易且是可能的
用户界面的调整或移植不会影响该应用功能部分的设计和编码
例:Web 应用
实现:特定技术,通常专用于WEB:Model与Controller单向,Controller与View双向,Model与View双向
典型实现:View:JSP,HTML;Controller:Servlet;Model:JavaBean
3.体系结构设计的过程
分析关键需求和限制条件;
通过选择体系结构风格,确定顶层架构;
实现功能需求的逻辑映射;
通过构件的逐层设计从逻辑视角向物理视角的转化;
添加辅助构件;
完善构件之间接口的定义;
完善数据的定义。
迭代过程3-8
安全与网络分布:方案比较
方案一:哪个接口更多、更复杂? 将RMI置于更少、更简单的层间接口
方案二:哪两层之间更内聚?将RMI置于更不内聚的层间接口
方案后果:更简洁、更易于修改
方案一:Mainui只包含登录
方案二:Mainui包含登录和主界面
关键区分:是否需要共同的主界面、界面一样
4.包的原则
最高原则:包与包之间不能有重复和冗余、复用发布等价原则、共同封闭原则、共同复用原则、无环依赖原则、稳定依赖原则、稳定抽象原则
(1)复用发布等价原则REP
(不要把很多用例放在一个包)为复用者聚合构件(类),单一的类通常不可复用,几个协作类组成一个包
一个包中的类应该形成一个可复用和可发布的模块,模块提供一致的功能,减少复用者的工作
(2)共同封闭原则CCP
最小化变化给程序员造成的影响
(不要把一个用例拆成多个包)当一个变化是必要的,如果该变化影响尽可能少的包,则对程序员是有利的,因为需要时间编译和链接以及重新生效
把具有相似闭包的类聚合在一起,包闭合了预期的变化
限制对一些包的修改,减少包的发布频率,减少程序员的工作
(3)共同复用原则CRP
根据公共复用给类分组,避免给用户带来不必要的依赖
常常导致细分包,获得更多更小更集中的包,减少复用者的工作
CCP和CRP原则相互排斥,例如它们不能同时被满足:CRP使得复用者的工作更简单,而CCP使维护者的生活更简单;CCP努力让包尽可能大,而CRP设法让包很小。项目的早期,架构师可能以CCP为主导来辅助开发和维护。架构稳定后,架构师可能重构包结构,为了外部复用者而最大化CRP。
(4)无环依赖原则ACP
包的依赖结构应是一个有向无环图
一块块地稳固和发布项目,以自上而下的层次结构组织包依赖
解决:分解包/抽象依赖
(5)稳定依赖原则SDP
例如:向下接口的依赖是不稳定依赖
(6)稳定抽象原则SAP
稳定包应是抽象包,不稳定包应是具体包
稳定包包含高层设计,抽象它们使得对扩展开发对修改关闭(OCP)。一些灵活性留在稳定的难以改变的包中。
对象创建:方案一: Spring方案,需要事先明确依赖关系
在程序启动时,第三方(初始化程序)一次性创建完成对象实例并set给上一层
Service:View——Logic;DAO: Logic——Data
方案二: 也适用于非层间的包依赖解除
构造一个第三方(Factory)负责创建具体对象实例
上层和下层都依赖于第三方,但第三方可以视作例外(即不影响层间独立关系)
5.体系结构构件之间接口的定义
根据分配的需求确定模块对外接口,如逻辑层接口根据界面的需求得到,数据层接口根据逻辑层调用得到
根据刺激与响应确定接口,依据详细规格明确接口内容(数据、返回值)
(1)通常情况下,VIEW的required接口可以直接作为相应Logic的Provided
(2)通常情况下,LOGIC的required接口需要分解为同层模块和不同Data的Provided
(3)Data一般没有层间依赖,接口通常来自于上一层的相应模块
【示例】saleLogic的其他接口来源 :
(1)其他被归类为saleLogic模块承担的需求,如退货用例
(2)同层模块间的依赖
解除双向依赖:需要被抽象为一个独立接口和独立包,saleLogic再导入上面的包
独立接口和独立包也属于saleLogic模块最终承担的Provide接口,也需要转化为对Data的Required接口
在分析其他模块时逐步完善,例如进行礼品赠送时查看特定客户的销售记录、库存分析时查看一定时间段内的销售记录或特定商品的销售记录
在独立接口和独立包中定义有限制的领域类供外界使用,例如对象限制为查询接口,限制数据种类等等
6.体系结构开发集成测试用例:Stub和Driver
(1)依据模块接口建立桩程序Stub——为了完成程序的编译和连接而使用的暂时代码,对外模拟和代替承担模块接口的关键类,比真实程序简单的多,使用最为简单的逻辑
【示例】P177 SalesBLService_Stub
(2)编写驱动程序,在桩程序帮助下进行集成测试
View的测试比较特殊,其他层都需要增加Driver进行测试
可以基于Junit编写Driver;基于接口规格设计测试用例
开发View层时:需要logic的stub
开发logic层时:需要模仿view的driver,需要data的stub,需要模拟同层调用的driver和stub
开发data层时:需要模拟logic的driver
(3)持续集成:逐步编写各个模块内部程序,替换相应的桩程序
真实程序不仅实现业务逻辑,而且会使用其他模块的接口程序(真实程序或者桩程序)
开始:客户端: view driver, logic stub, data stub;服务器端: logic driver, data stub
进展:客户端: (逐步替换)driver,逐步替换logic stub, data stub;服务器端: logic driver, 逐步替换 data stub
最后联调:使用真实的客户端和服务器
第11章 人机交互设计
1.可用性(名词解释)
易用性是人机交互中一个既重要又复杂的概念。它不仅关注人使用系统的过程,同时还关注系统对使用它的人所产生的作用,因为比较复杂,所以易用性不是一个单一的质量维度,而是多维度的质量属性。从易于度量的角度讲,易用性的常用维度包括:易学性、易记性、有效率、低出错率和主观满意度。
2.界面设计的注意事项及解释(至少5个)
【题型】例子违反了哪条界面设计原则
(1)不要暴露内部结构
例子:该设计明显暴露了软件结构,三个独立软件过程:创建、更新、解除
(2)展示细节——所见即所得
(3)常见界面类型:软件系统通常同时使用多种界面类型,以适应差异性的用户和任务。
3.精神模型,差异性
(1)精神模型就是用户进行人机交互时头脑中的任务模型
依据精神模型可以进行隐喻(Metaphor)设计:隐喻又被称为视觉隐喻,是视觉上的图像,但会被用户映射为业务事物。用户在识别图像时,会依据隐喻将控件功能与已知的熟悉事物联系起来,形成任务模型;隐喻本质上是在用户已有知识的基础上建立一组新的知识,实现界面视觉提示和系统功能之间的知觉联系。
(2)用户希望看到的+希望用户看到的:识别并添加哪些能够帮助用户完成任务的功能,任务的频率也要纳入考虑
常见错误:加入一些容易加入(例如正好是一个独立的软件过程)的功能,这会扰乱用户的精神模型,影响使用过程的顺利性
(3)新手用户:关注易学性,进行业务导航,尽量避免出错
专家用户:关注效率
熟练用户:在易学性和效率之间进行折中
好的人机交互应该为不同的用户群体提供差异化的交互机制。
既为新手用户提供易学性高的人机交互机制(图形界面)
又为专家用户提供效率高的人机交互机制(命令行、快捷方式、热键)
4.导航、反馈、协作式设计
(1)导航
主动将自己的产品和服务简明扼要地告诉用户,目的是为用户提供一个很好的完成任务的入口,好的导航会让这个入口非常符合人的精神模型。
全局结构按照任务模型将软件产品的功能组织起来,并区分不同的重要性和主题提供给不同的用户。全局结构常用的导航控件包括窗口、菜单、列表、快捷方式、热键等等。全局结构的设计主要以功能分层和任务交互过程为主要依据。
局部结构通过安排界面布局细节,制造视觉上的线索来给用户提供导航。局部结构常用的导航控件包括可视化控件布局与组合、按钮设置、文本颜色或字体大小等等。局部结构的设计主要以用户关注的任务细节为主要依据。
(2)反馈
让用户能够意识到行为的结果,但不能打断用户工作时的意识流
用户喜欢较短的响应时间;较长的响应时间(>15秒)具有破坏性;
用户会根据响应时间的变化调整自己的工作方式;
较短的响应时间导致了较短的用户思考时间;较快的节奏可能会提高效率,但也会增加出错率;
根据任务选择适当的响应时间:打字、光标移动、鼠标定位:50~150毫秒;简单频繁的任务:1秒;普通的任务:2~4秒;复杂的任务:8~12秒
响应时间适度的变化是可接受的;意外延迟可能具有破坏性;经验测试有助于设置适当的响应时间。
(3)协作式设计
A.简洁设计(摘要图片优于文字描述)
列举、隐藏、赋予(标签、图标等线索暗示)
B.一致性设计(确认与删除键相对位置不一致)
C.低出错率设计(用具体的指导来提示用户出错)
限制输入:列表、可选框等选择性组件代替输入框;按钮代替命令行;限定输入:类型,范围,格式…
限制范围:简单化单步操作
辅助:事前提示;事后检查;随时可以撤销
D.易记性设计
减少短期记忆负担;使用逐层递进的方式展示信息;使用直观的快捷方式。重新认知比记忆更容易;设置有意义的缺省值,可以帮助用户减少记忆负担。
链接
👉软件工程与计算II重点整理(第1-5章)
👉软件工程与计算II重点整理(第6-7章)
👉软件工程与计算II重点整理(第12-15章)
👉软件工程与计算II重点整理(第16-19章)
👉软件工程与计算II重点整理(第20-23章)