软件分析、设计与建模迭代式详解

  • 1.introduction
    • 1.1 OOA/D
    • 1.2 Iterative, Evolutionary, and Agile
  • 2.Case Study and Requirement Engineering
    • 2.1 Inception and Case Studies
    • 2.2 UML
    • 2.3 OOA和OOD
  • 3.Inception
    • 3.1 Evolutionary Requirements
    • 3.2 用例
  • 4.细化迭代1——基础
    • 4.1 精化阶段
    • 4.2 领域模型
    • 4.3 System Sequence Diagrams
    • 4.4 Operation Contracts 操作契约
    • 4.5 4+1视图和软件架构
      • 软件架构
      • 软件架构的4+1视图
      • 耦合和内聚coupling and cohesion
      • 架构模式
    • 4.6 Logical Architecture and UML Package Diagrams
    • 4.7 Mapping Analysis Models to Design Models
    • 4.8 UML Class Diagram
    • 4.9 GRASP:Designing Objects with Responsibilities
      • 低耦合
      • 高内聚
      • 创建者
      • 信息专家
      • 控制器
      • Object Design Examples with GRASP
    • 4.10 可见性Visibility
    • 4.11 设计映射成代码
  • 5.细化迭代2——更多模式
    • 5.1 快速更新分析
    • 5.2 GRASP: More Objects with Responsibilities
      • 多态Polymorphism
      • 纯虚构 pure fabrication
      • 间接性indirection
      • 防止变异Protected Variations
    • 5.3 GOF设计模式
      • Adapter适配器
      • Factory工厂模式
      • Singleton单实例类模式
      • Strategy策略模式
      • Composite组合模式
      • Facade 外观模式
      • Observer/Publish-Subscribe/Delegation Event Model
  • 6.精化迭代3
    • 6.1 活动图
    • 6.2 状态图
    • 6.3 用例关联Relating Use Cases
    • 6.4 领域模型的精化refinement
    • 6.5 UML扩展:stereotypes, constraint and tag
    • 6.6 Architectural Analysis and Logical Architecture Refinement
    • 6.7 UML Deployment and Component Diagram
      • 部署图
      • 组件图
    • 6.8 更多GOF的应用
      • 代理proxy
      • 抽象工厂
    • 6.8 使用模式设计持久化框架
    • 6.9
    • 7.1
    • 7.2

1.introduction

1.1 OOA/D

什么是分析和设计?

  • 分析—做what 强调对问题和需求的调查,而不是解决方案
  • 设计—how 强调满足需求概念解决方案conceptual solution(软件和硬件),而不是其实现 如:对象设计、数据库设计、UI设计

面向对象:

  • 面向对象=对象+分类+继承+通信 它有三大属性 封装,继承和多态
  • 面向对象软件工程能够有效地减少在软件开发过程中问题域与解域的鸿沟

什么是面向对象的分析和设计?

  • 对象(事物/概念)的角度理解问题域和解决方案

    • OOA:查找和描述问题域中的概念(不是软件对象或类)。

      • 输出:领域中的概念、职责和概念之间的关系
    • OOD
      • 基于OOA中的概念定义软件对象
      • 定义软件对象如何协作满足需求

用例:只是人们如何使用应用程序的书面故事或场景

设计类图与领域模型的区别:

  • OOA/D中的不同抽象级别
  • 领域模型是领域中的概念和关系
  • 设计类图是软件的对象、属性和关系

一个OOA/D的简短过程:

  • 领域模型

    • 识别被认为值得注意的概念、属性和关联
    • 是非软件对象,是概念对象模型
  • 分配对象职责并绘制交互图: 关注对象责任和协作的OOD、使用序列图来说明这些协作
  • 定义设计类图:交互图是协作对象的动态视图使用设计类图来说明类的属性和方法。类定义的静态视图

什么是UML

  • 是一种用于指定、构建和记录系统制品的可视化语言specifying, constructing and documenting the artifacts of systems
  • 用于指定、可视化、构造和记录specifying, visualizing,constructing and documenting软件系统的行业标准图形语言
  • 在许多图表中对软件系统进行建模(用图形符号表示软件的OOA/D)

为什么建模:建模的目的是沟通

为什么使用UML:

  • 使用图形符号比自然语言(不精确)和代码(过于详细)更清楚地交流可视化建模利于沟通
  • 帮助获取系统的总体视图
  • UML不依赖于任何一种语言或技术
  • UML使我们从碎片化走向标准化

应用UML:作为草图sketch、蓝图、编程语言

1.2 Iterative, Evolutionary, and Agile

什么是软件开发过程Software Development Process(SDLC):描述构建、部署和维护软件的方法(连续步骤或子流程)

  • 软件过程是软件吗?(软件过程本身就是软件):软件过程是由人造虚拟机执行的软件(由人构成的虚拟机执行的软件)
  • 为什么软件过程如此重要?
  • 复杂软件系统
  • 软件质量

瀑布模型:
瀑布生命周期(SDLC)

  • 瀑布是软件开发的一种线性方法
  • 在编程之前,尝试定义(详细)所有或大部分需求
  • 缺点:定义太多未使用的功能,无法响应变更(冻结了需求)

什么是迭代和进化开发

  • 开发被组织成一系列短的、固定长度(例如,三周)的小型项目,称为迭代
  • 通过多次迭代不断扩大和完善系统
  • 迭代开发是敏捷方法的核心

每次迭代 选择需求的一小部分 快速设计、实施和测试 来自用户、开发人员和测试的反馈早期迭代的需求和设计可能并不准确,但经过多次迭代后,需求和设计的不稳定性会随着时间的推移而降低

迭代开发的优点:

  • less project failure, better productivity, and lower defect rates(减少项目失败可能性,提供生产率,降低缺陷率)
  • early rather than late mitigation of high risks (尽早缓解项目中存在的高风险)
  • early visible progress(能够让人明确地看到进展,给客户信心,给开发队伍成就感)
  • early feedback, user engagement, and adaptation leading to a refined system that more closely meets the real needs of the stakeholders
  • managed complexity 复杂性可控
  • the learning within an iteration can be methodically used to improve the
  • development process itself, iteration by iteration(一次迭代的经验可以用于改进开发过程,并如此反复下去)

什么是敏捷方法:对计划、需求和设计进行进化优化的短期迭代是一种基本实践方法

敏捷原则
我们的首要任务是通过尽早、持续地交付有价值的软件来满足客户
欢迎不断变化的需求,即使是在开发后期

敏捷方法和传统方法的区别:

什么是UP?
UP是用于构建面向对象系统的流行迭代软件开发过程。是对OOA/OOD和UML的应用结构,是一种迭代和进化式开发

统一过程(UP)的基本特征是“用例驱动以架构为中心的和受控的迭代式增量开发”。一个UP可分为若干个周期,每个周期的开发过程划分为初启阶段、精化阶段、构建阶段和提交阶段等4个阶段(见下表),每个阶段可进行若干次迭代:

  • 初启阶段(Inception) 大致的范围和版本,模糊估计业务实现可行性项目目标的稳定性,原始的项目需求和业务用例
  • 精化阶段(Elaboration) 对问题域进行分析,细化的版本、核心架构的迭代实施、高风险的解决、大多数需求和范围的确定、更现实的估计
  • 构建阶段(Construction):迭代实施剩余的较低风险和较容易的元素,并为部署做好准备
  • 提交阶段(Transition) 测试、部署,将软件产品提交用户

回忆一下下列问题:
What is analysis and design?
What is OO analysis and OO Design?
What is iterative development?
What is ®UP?
What is agile method?
What is object-oriented analysis and design?
What is Unified Process?

2.Case Study and Requirement Engineering

2.1 Inception and Case Studies

案例研究讨论的范围 是什么,为什么?
重点放在核心应用逻辑层的OOA/D上,其他的只放在设计它们与应用逻辑层的接口上

两个案例是什么?

  • 案例一:The Next-Gen POS System下一代POS系统

    • 用于零售商店,用于记录销售额和处理付款
    • 范围:
      • 硬件-计算机、扫描仪
      • 软件-接口:第三方税务计算器、库存控制系统
  • Case Two: The Monopoly Game System

什么是初始化阶段?什么不是初始化阶段? 你能列举出初始化阶段的一些陷阱吗?

2.2 UML

回顾1.1什么是UML,为什么使用UML

什么是模型

为什么建模

建模的4大原则是什么,请说明每个原则 什么是UML最适合的过程特征,请描述每个特征

2.3 OOA和OOD

OOA

  • 查找和描述问题域中的概念(不是软件对象或类)、概念的属性以及概念之间的关联—领域模型(分析对象模型)
  • 为用例场景创建系统顺序图SSD–说明与讨论中的系统相关的输入和输出事件
  • 定义系统操作。为系统操作创建合同–使用前置和后置条件表单来描述由于系统操作而对域模型中的对象所做的详细更改

OOD

  • 中心思想–抽象、分解、渐进细化和模块化(耦合和解耦)Abstract, Decomposition, Progressive Refinement and Modularity(Coupling and decoupling),大问题分解为小问题
  • 采用分层方法的逻辑架构设计
  • 动态对象设计建模,使用交互图来说明软件对象如何通过消息进行交互;发送什么消息,发送给谁,发送顺序如何
  • 静态对象设计建模–使用类图描述实现需求的软件对象、软件对象的职责以及它们之间的关联
  • OOD中的关键能力是熟练地将职责分配给软件对象
    • General Responsibility Assign Software Principles 一般软件职责分配原则:

      • 创建者、信息专家、低耦合、控制器、高内聚、多态性、间接性、纯虚构、防止变异
      • Creator, Information Expert, Low Coupling, Controller, High Cohesion,Polymorphism, Indirection, Pure Fabrication,Protected Variations
    • 应用GOF设计模式来实现GRASP原则
      • 创建型模式:Creator创建者, Factory工厂, Abstract Factory抽象工厂, Singleton单例
      • 结构型模式:Adapter适配器, Composite组合 ,Facade外观, Proxy代理
      • 行为型模式:Strategy策略, Observer观察者, Template Method模板 ,Command命令

交互图描述对象的外部行为,但有些对象很复杂,可能有复杂的算法,或者对事件有不同的内部行为-使用活动图对业务流程、工作流、数据流和复杂算法进行建模-使用状态机图来说明对象的有趣事件和状态

为什么使用分层架构?
关注点分离Separation of Concerns 一种将计算机程序分成不同部分的设计原则,以便每个部分都能解决一个单独的问题,可重用,解耦

回忆以下问题:

  • 面向对象分析模型的结构是什么?
  • 面向对象设计模型的结构是什么?
  • 面向对象分析与设计的输入和输出制品分别是什么?

3.Inception

什么制品可能在Inception中开始?

  • 设想和商业案例Vision and Business Case:描述了高层目标和约束、业务案例
  • 用例模型: 确定大多数用例的名称,可能会详细分析10%的用例
  • 补充规范Supplementary Specification:描述其他需求,主要是非功能性需求
  • 术语汇编Glossary: 关键领域术语和数据字典

3.1 Evolutionary Requirements

定义需求和需求管理

比较进化式需求和瀑布式需求

什么是FURPS+质量模型?
Functional、Usability、reliablility、performance、supportability
+是实现、接口、操作等

什么是UP需求制品?

  • 用例模型:使用系统的一组典型场景,主要用于功能(行为)需求
  • 补充规约Supplementary Specification:所有不在用例中的内容。主要针对所有非功能性需求,捕获用例或术语表中不易捕获的其他需求、信息和约束,包括系统范围的“URPS+”(可用性、可靠性、性能、可支持性等)质量属性或需求
  • 术语汇编
  • Vision设想:总结项目的高级需求和业务案例
  • 业务规则Business Rules (Domain Rules):通常描述项目需要遵守的要求或政策,如税法

3.2 用例

什么是参与者、场景和用例?

  • 参与者是指具有行为的事物,例如一个人(通过角色识别)、计算机系统或组织
  • 场景是参与者和系统之间的特定动作和交互序列;它也称为用例实例
  • 用例是相关成功和失败场景的集合,描述了参与者使用系统支持目标的情况

主成功场景:Main Success Scenario
备选场景:Alternate Scenarios

用例是功能需求吗?

  • 用例是需求,主要是指示系统将做什么的功能或行为需求
  • 用例定义了系统将如何运行的契约
  • 用例是用于发现和定义需求的中心机制。

什么是用例模型?

参与者有哪三种类型?
Primary actor、Supporting actor协助参与者(提供服务)、Offstage actor幕后参与者(Stakeholders,涉众)

如何找到用例?请列举标识用例的4个步骤 请列举用例的3种常用形式
1.choose the system boundary寻找系统边界
步骤2和3:找到主要参与者和目标
steps 4: Define Use Cases

什么样的测试有助于发现有用的用例?(总而言之要合适的抽象级别):

  • Boss测试»如果用例未能通过Boss测试,它可能是某个低目标级别的用例,但不是需求分析的理想重点级别
  • EBP测试»可以增加可测量的业务价值,并使数据保持一致状态
  • 规模测试»用例很少是一个单独的操作或步骤

用例图和用例关系是用例工作中的次要部分。用例是文本文档。做用例工作意味着写文本。

活动图:使用活动图表来可视化工作流和业务流程。因此,它是编写用例文本的一个有用的替代或补充,尤其是对于描述涉及多方和并发操作的复杂工作流的业务用例。

UP鼓励用例驱动的开发:

  • 功能需求主要记录在用例(用例模型)中
  • 用例是迭代规划的重要组成部分。迭代的工作部分是通过选择一些用例场景或整个用例来定义的。用例是评估的关键输入。
  • 用例实现(一组UML图)推动了设计。

详细用例模板包含哪些部分? 用例模板的这些部分含义是什么?

用例不仅仅是需求制品(artifacts),而且是驱动需求工作的核心手段

4.细化迭代1——基础

4.1 精化阶段

构建核心架构,解决高风险因素,定义大多数需求,并估计总体进度和资源

最佳实践:

  • 进行短期的风险驱动迭代
  • 尽早开始编程
  • 自适应地设计、实现和测试体系结构的核心部分和风险部分
  • 尽早、经常、现实地进行测试
  • 根据测试、用户和开发人员的反馈进行调整
  • 通过一系列研讨会,每个精化迭代一次,详细编写大多数用例和其他需求

什么制品和活动,可能在细化阶段开始?
领域模型,设计模型,软件架构文档,数据模型

什么是迭代? 什么样的评价基准,可以用于在迭代中对用例或场景进行优先级设置?

4.2 领域模型

什么是领域模型?
领域模型是概念类或真实场景对象在对象中的可视化表示。它也称为概念模型、领域对象模型和分析对象模型,是真实情况概念类的表示,而不是软件对象的表示。

目标:

  • 确定与当前迭代相关的概念类
  • 创建初始领域模型
  • 为适当的属性和关联建模

什么是概念类
概念类是一个想法、事物或对象。更正式地说,概念类可以根据其符号、内涵、扩展定义

为什么要创建领域模型?
领域模型有助于理解实际情况中的关键概念和词汇

指南和例子:如何创建领域模型?

  • 查找概念类
  • 将它们绘制为UML类图中的类
  • 添加关联和属性

如何查找分类列表:

  • 重用或修改现有模型。
  • 使用分类列表

  • 识别名词短语

例子:领域模型的关联和属性

关联:两个类之间的语义关系:

属性是对象的逻辑数据值,/表示派生对象

精化后的领域模型:

过程:迭代和演化领域建模
UP中的领域模型只在细化阶段创建

4.3 System Sequence Diagrams

什么是系统顺序图?

系统顺序图它显示了对于用例的一个特定场景,外部参与者生成的事件、它们的顺序以及系统间事件。A system sequence diagram is a picture that shows, for one particular scenario of a use case, the events that external actors generate, their order, and inter-system events
所有系统都被视为黑箱;图表的重点是跨越系统边界从参与者到系统的事件

为每个用例的主要成功场景以及频繁或复杂的替代场景绘制SSD。

SSD显示用例的一个场景系统事件,因此它是通过检查用例生成的
SSD还可用于说明系统之间的协作,例如POS和外部信用支付授权人之间的协作

如何创建系统顺序图? 为什么创建系统顺序图?调查和定义系统行为

过程:迭代和进化式系统顺序图

UP中的SSD是用例模型一部分大部分在细化阶段创建

4.4 Operation Contracts 操作契约

用例和SSD是UP中描述系统行为的主要方式,通常已经足够了。但这可能还不够

对系统行为进行更详细或更精确的描述是有价值的。操作契约使用前置和后置条件表单来描述系统操作对域模型中对象的详细更改

定义系统操作。为系统操作创建契约

操作契约示例:

操作、交叉引用(该操作可能在那个用例中)、前置条件、后置条件

什么是系统操作?
系统作为一个整体提供的操作(例如,方法)。系统操作处理系统事件

后置条件描述域模型中对象状态的更改。域模型状态更改包括创建的实例、形成或断开的关联以及更改的属性

如何创建和编写契约?

  • 从SSD中识别系统操作。
  • 对于复杂且可能微妙的系统操作, 在其结果中,或在用例中不明确的结果中,构建一个契约。
  • 要描述后置条件,请使用以下类别:
    • 实例创建和删除
    • 属性修改
    • 形成和断开的关联

过程:UP中的操作契约
只在精化阶段用,只为最复杂和微妙的系统操作编写操作契约

4.5 4+1视图和软件架构

软件架构

软件架构(architecture)是系统的基本组织,体现在其组件、组件之间的关系、环境以及控制其设计和演化的原则中。

架构={组件、关系、环境、原则}。Architecture={component, relations, environment, principle}.

主要目标:

  • 建立一个一致的系统及其视图集,并表达为最终用户和软件设计者需要的结构形式,支持用户和设计者之间的交流与理解。
  • 分为两方面:
    • 外向目标:建立满足最终用户要求的系统;
    • 内向目标:建立满足系统设计者需要以及易于系统实现、维护和扩展的系统构件构成。–质量属性

只有复杂系统才需要架构设计

软件架构的4+1视图

  • 用例视图:用例或场景描述对象之间和流程之间的交互序列
  • 逻辑视图:逻辑视图涉及系统向最终用户提供的功能。UML图用于表示逻辑视图,包括类图和状态图
  • 进程process视图:进程视图处理系统的动态方面,解释系统进程及其通信方式,并重点关注系统的运行时行为。流程视图解决了并发性、分布、集成器、性能和可伸缩性等问题。表示流程视图的UML图包括序列图、通信图、活动图
  • 开发Development(实现)视图:开发视图从程序员的角度说明了系统,并与软件管理有关。此视图也称为实现视图,包括组件图、包图
  • 物理视图:物理视图从系统工程师的角度描述系统。它涉及物理层上软件组件的拓扑以及这些组件之间的物理连接部署图

请简要描述4+1架构视图模型
什么是软件体系架构?

耦合和内聚coupling and cohesion

耦合是软件模块之间的相互依赖程度

内聚性衡量给定模块中功能片段之间的关系强度

架构模式

4.6 Logical Architecture and UML Package Diagrams

逻辑体系结构是将软件类大规模组织到包(或名称空间)、子系统和层中

层是类、包或子系统的粗粒度分组,对系统的主要方面具有内聚责任。此外,层的组织方式使“较高”层(如UI层)调用“较低”层的服务,但反之亦然

  • UML包图通常用于说明系统的逻辑体系结构-层、子系统、包
  • UML包表示一个名称空间,可以对任何东西进行分组:类、其他包、用例等等
  • UML依赖关系行用于显示包之间的依赖关系
  • 嵌套包非常常见

分层架构优点:

  • 协作和耦合从高到低的层次;避免了从低层到高层的耦合。
  • 关注点的分离、高级服务与低级服务的分离以及特定于应用程序的服务与一般服务的分离。这减少了耦合和依赖性,提高了内聚性,增加了重用潜力,并提高了清晰度。
  • 相关的复杂性是封装和可分解的。
  • 一些层可以用新的实现替换。
  • 下层包含可重用的功能。
  • 可以分布某些层(主要是域和技术服务)。
  • 由于逻辑分割,团队开发得到了帮助

分层设计的原则:

  • 内聚职责;保持关注点的分离
  • 不将外部资源显示为底层
  • 模型-视图分离原则:不要将应用程序逻辑(如税务计算)放在UI对象方法中

领域层和领域模型之间的关系?
领域层是软件的一部分,领域模型是概念透视分析的一部分,它们不是一回事。

Model –View –Controller(MVC)

  • Model:

    • Providing the data from the database and saving the data into the datastore(负责数据存取).\
    • All the business logic are implemented in the Model(负责业务逻辑实现).
    • Data entered by the user through View are checked in the model before saving into the database(负责数据验证).
  • View
    • Taking the input from the user, (获取用户输入)
    • Dispatching the request to the controller, and then (向controller发送请求)
    • Receiving response from the controller and displaying the result to the user.(接收来自Controller的反馈并将model的处理结果发给用户)
  • Controller
    • Receiving the request from client.(接收来自客户的请求)
    • 调用model执行
    • 调用View显示执行结果

4.7 Mapping Analysis Models to Design Models

什么是静态和动态建模?

  • 动态模型,如UML交互图(序列图或通信图),有助于设计逻辑、代码行为或方法体
  • 静态模型,如UML类图,有助于设计包、类名、属性和方法签名(但不是方法体)的定义。

CRC卡:Class Responsibility Collaboration (CRC) cards
类名、职责、协作者

UML使用交互图来说明对象如何通过消息进行交互。它们用于动态对象建模

优缺点:

  • 顺序图:

    • 清楚地显示消息的顺序或时间顺序
    • 在添加新对象时,大量详细的符号选项被迫向右扩展
  • 通信图:
    • 使用水平空间通信,空间经济灵活性
    • 添加新对象更难查看消息序列符号选项更少

UML表示法:

found message
execution specification
sychronous message

具体表示法见本人文章【UML】UML交互图(顺序图和通信图) - 掘金 (juejin.cn)

问题回顾

  • 什么是交互图?
  • 顺序图和通信图的优点和缺点是什么?
  • 顺序图和通信图的UML表示法是什么?
  • 什么时候,如何使用交互图与CRC卡?
  • 从分析模型到设计模型的映射如何对类进行标识?
  • 如何确定某潜在对象值得包含进CRC索引卡?

4.8 UML Class Diagram

回顾:
我们描述了(思考一下这些是什么,为什么要用这些,怎么用)

  • 用例,补充规约
  • OOA:
    • 领域模型 domain model
    • 系统顺序图 SSD
    • 操作契约 operation contract
  • OOD
    • 架构 Architecture
    • 交互图 Interaction Diagrams

类图用来说明类、接口及其关联。

领域模型和设计模型的区别:

操作是一种行为特征,可能由接口、数据类型或类拥有

方法是操作的实现。它指定了与操作相关的算法或程序在类图中,带有用«method»构造的UML注释符号

具体的类图UML表示法见本人文章【UML】UML类图 - 掘金 (juejin.cn)

问题回顾:

  • 如何对类进行分类?
  • 哪些类的特征能帮助我们对类进行分类?
  • 如何将职责分配到类?
  • 静态建模和动态建模有哪些关系?

4.9 GRASP:Designing Objects with Responsibilities

RDD–Responsibility Driven Design职责驱动设计:强调对象角色、职责和协作的建模
DDD—Domain Driven Design
UDD- Use case Drive Design

职责:

  • 执行任务或了解信息的义务
  • 两种类型:doing(行为) 和knowing(认知)
    • doing

      • 自己做一些事情,例如创建对象或进行计算
      • 在其他对象中启动操作
      • 控制和协调其他对象中的活动
    • knowing
      • 了解私有封装数据
      • 了解相关对象
      • 了解它可以推导或计算的事物

Acronym缩写 for General Responsibility Assignment Software Patterns or Principles (GRASP)对一些基本的职责分配原则进行了命名和描述,帮助我们理解基本对象设计,以一种系统的,合理的,可以解释的方式来推导设计

模式是可以应用于新文本的问题和解决方案的命名描述,包括Name,Problem,Solution

参考的领域模型:

九个模式:

  • Low coupling:How to support low dependency, low change impact, and increased reuse 少依赖,少变化影响,提升重用性?
  • High cohesion:How to keep objects focused, understandable, and manageable对象集中、可理解和可管理, and as a side effect, support Low Coupling?
  • Creator:Who creates the Square object?
  • Information expert(职责分配的一般原则) :What is a general principle of assigning responsibilities to objects?
  • Controller:What first object beyond the UI layer receives and coordinates (“controls”) a system operation?UI层之外的第一个接收和协调系统操作的类
  • Polymorphism
  • Indirection
  • Pure fabrication
  • Protected variations

低耦合

问题:如何增加重用并减少更改的影响。
解决方案:分配职责以最大限度地减少耦合

第二个有比较少的Register知道Payment,因而降低耦合

使类独立于其他类的好处:

  • 更改局部化,避免影响其他类
  • 易于理解的代码
  • 易于重用代码

高内聚

问题:如何保持对象集中、可理解和可管理
解决方案:分配责任,以保持高度的凝聚力

具有高内聚性的类具有相对较少的方法,具有高度相关的功能,并且不会做太多工作。

提高了设计的清晰度和易理解性

  • 简化了维护和扩展。
  • 通常支持低耦合。
  • 由于内聚类可以用于非常特定的目的,因此提高了细粒度、高度相关功能的重用

创建者

问题:谁应该负责创建某个类的新实例?
解决方案:如果下列条件其中一个为真(越多越好),则指派class B负责创建class A的实例:

  • B“包含”或聚合A
  • B记录A。
  • B密切使用A。
  • B具有A的初始化数据,该数据将在创建A时传递给A。因此,B是创建A的专家。

领域模型中Sale contains Sales LineItem,因此Sale创建Sales LineItem

  • 注意:creation复杂,建议将创建委托给称为具体工厂或抽象工厂的助手类,而不是使用创建者建议的类
  • 优点:支持低耦合
  • 相关模式或原则:
    • 低耦合
    • 具体工厂和抽象工厂
    • Whole-Part

信息专家

问题:为对象分配职责/功能的基本原则是什么?
解决方案:将责任分配给具有履行责任所需信息的类

谁应该负责了解销售总额?确定总计需要哪些信息?-行项目及其小计的总和• Sale是该职责的信息专家

为了履行了解和回答销售总额的责任,将三项责任分配给三个设计类别的对象

如下图,信息专家要求把打折操作放在持有value信息的foo当中

优点:

  • 信息封装

    • 对象使用自己的信息来完成任务
    • 支持低耦合
  • 行为分布在具有所需信息的类中
    • 轻量级类定义
    • 高内聚性

控制器

问题:谁应负责处理输入系统事件
解决方案:控制器是UI之后的第一个对象,负责接收和处理系统操作消息

将接收或处理系统事件消息的责任分配给:

  • 表示整个系统、设备、或子系统的类(facade controller外观控制器)
  • 发生系统事件的用例场景(用例控制器)
    • 相同场景中的所有系统事件使用相同的控制器类
    • 从会话的角度思考–与参与者对话的实例

谁应该是系统事件(如enterItem和endSale)的控制器?
根据控制器模式,以下是一些选择:
Register,POSSystem:表示整个“系统”、设备或子系统
ProcessSaleSession,ProcessSaleHandler:表示用例场景中所有系统事件的接收者或处理者
在系统行为分析期间识别的系统操作被分配给一个或多个控制器类

注意:

  • 通常,控制器应将需要完成的工作委托给其他对象;它协调或控制活动。它本身做不了多少工作。
  • 当没有“太多”系统事件时,Facade控制器是合适的(避免臃肿bloated)
  • 当把责任放在外观控制器中会导致低内聚或高耦合的设计时,用例控制器是一种可以考虑的替代方案,为每个用例使用不同的控制器

好处:

  • 增加了重用和可插拔接口的可能性–GUI中没有应用程序逻辑
  • 属于某些用例的专用place to place状态,例如,必须按特定顺序执行操作

Related Patterns:

  • Command
  • Façade
  • Layer
  • Pure Fabrication

Object Design Examples with GRASP

用例实现?用例实现描述了如何在设计模型中根据协作对象实现特定用例(使用类图,交互图)

将以下四个用例作为应用例子:

过程:迭代和进化式对象设计

用例实现是UP设计模型一部分,细化阶段开始,构造阶段精化

回顾:

  1. 对象设计有哪些输入、活动与制品?
  2. 什么是职责驱动设计和职责?
  3. 什么是模式?
  4. 如何在OO设计中应用下面的GRASP模式 创建者 信息专家 控制器 低耦合与高内聚

4.10 可见性Visibility

可见性是一个对象“看到”或引用另一个对象的能力。

发送方必须有接收者的可见性,即发送方必须有接收方的某种引用

属性可见性当B是A的属性时,存在从A到B的属性可见性

参数可见性当B作为参数传递给A的方法时,存在从A到B的参数可见性

局部可见性当B被声明为A的方法中的本地对象时,存在从A到B的本地可见性

全局可见性当B对A全局时,存在从A到B的全局可见性

4.11 设计映射成代码

实施顺序类需要从最不耦合到最耦合的方式实现(理想情况下是完全单元测试)

重构是一种结构化、有纪律的方法,可以在不改变外部行为的情况下重写或重构现有代码

1.如何将设计映射成代码? ⒉请举例说明什么是测试驱动的设计? 3.请举例说明什么是重构? 4.重构有哪些活动和目标?

5.细化迭代2——更多模式

5.1 快速更新分析

每次迭代,我们都应该快速更新:
需求
用例
分析模型
域模型、SSD和OC

迭代二的重点:对象设计和模式

在本次迭代中案例研究只强调

  • 基本对象设计
  • 使用模式来创建稳固的设计
  • 应用UML来使模型可视化

迭代2很大程度上忽视了案例研究的需求分析和领域分析
而是着重于使用职责和GRASP进行对象设计,并且应用一些GoF设计模式

5.2 GRASP: More Objects with Responsibilities

GRASP 多态 纯虚构 间接性 防止变异

多态Polymorphism

  • 问题:

    • 如何处理基于类型的选择(if-then-else意味着变化,但当出现新的变化时不可扩展)?
    • 如何创建可插拔的软件构件
  • 解决方案 :
    • 1.当相关选择或行为随类型(类)有所不同时使用多态操作为变化的行为类型分配职责
    • 2.推论:不要测试对象的类型,也不要使用条件逻辑来执行基于类型的不同选择

  • 1.多态是一个基本的设计原则,用于设计系统如何组织以处理类似的变化,基于多态分配职责的设计能够被简便的扩展以处理新的变化例如,增加新的具有gettaxes多态方法的计算器适配器将会对现有系统产生很小的影响。
  • 2.多态意味着在大部分面向对象语言中要使用抽象超类或接口,当你想要支持多态但是又不想约束于特定的类层次结构时,可以考虑使用接口(什么时候使用接口)

优点:可插拔(易于增加新变化所需扩展,无需影响客户就能引入新实现)

相关模式:

  • 防止变异
  • GoF设计模式依赖于多态性,包括适配器、命令、复合、代理、状态和策略。

纯虚构 pure fabrication

  • 问题:当你并不想违背高内聚和低耦合或其他目标,但是基于专家模式所提供的方案不合适时LRP(LRG)
  • 解决方案: 对人为制造的类分配一组高内聚的职责,该类并不代表问题领域的概念——虚构的事物用以支持高内聚、低耦合和复用

如persistentStorage就是领域模型当中没有,虚构出来的类


注意这里的纯虚构和C++当中的纯虚函数意义不同

  • 1.通常,此类的设计可以被广泛地分为两组:

    • 1.1通过表示解析(representational decomposition)所产生的选择
    • 1.2通过行为解析(behavioral decomposition)所产生的选择
  • 2.纯虚构通常基于相关功能性进行划分因此这是一种以功能为中心的或行为的对象

优点:

  • 支持高内聚,因为职责被解析为细粒度的类这种类只着重于极为特定的一组相关任务
  • 增加了潜在的复用性因为细粒度纯虚构类的职责可适用于其他应用

相关模式:

  • 低耦合、高内聚。
  • GoF设计模式,如适配器、命令、策略等

间接性indirection

  • 问题

    • 1两个或多个事物之间直接耦合应该如何分配职责?
    • 2如何使对象解耦合,以支持低耦合开提高复用性潜力?
  • 解决方案
    • 1将职责分配给中介对象使其作为其他构件或服务之间的媒介,以避免它们之间的直接耦合
    • 2中介实现了其他构件之间的间接性(indirection),这个中介很可能是纯虚构

上面的persistentStorage就可看作Sale和数据库之间的中介

优点:实现了构件之间的低耦合

相关模式和原则:

  • 防止变异、低耦合
  • GOF:适配器、桥、外观、观察者、中介
  • 大量间接性中介都是纯虚构

防止变异Protected Variations

  • 1.问题

    • 如何设计对象、子系统和系统使其内部的变化或不稳定性不会对其他元素产生不良影响?
  • ⒉解决方案
    • 2.1.识别预计变化或不稳定之处
    • 2.2.分配职责用以在这些变化之外创建稳定接口

优点:

  • 易于增加新变化所需的扩展
  • 可以引入新的实现而无需影响客户
  • 降低耦合
  • 能够降低变化的成本或影响

5.3 GOF设计模式

23种中有15种有效

Adapter适配器

  • 1.问题

    • 如何解决不相容的接口问题或者
    • 如何为具有不同接口的类似构件提供稳定的接口
  • ⒉解决方案
    • 通过中介适配器对象
    • 将构件的原有接口转换为其他接口

适配器设计模式是一种间接性和纯虚构
并且使用了多态,支持防止变异

Factory工厂模式

工厂模式也称为简单工厂或具体工厂

  • 问题:当有特殊考虑时,例如,存在复杂创建逻辑、为了改良内聚而分离创建职责等时应该由谁来负责创建对象?
  • 解决方案:创建称为工厂的纯虚构对象来处理这些创建职责

工厂类型返回的是接口不是类

优势:

  • 将复杂创建的职责划分为内聚的辅助对象
  • 隐藏潜在的复杂创建逻辑。
  • 允许引入增强性能的内存管理策略,如对象缓存或回收

Singleton单实例类模式

  • 1.只有唯一实例的类即为“单实例类”
  • 2.问题:对象需要全局可见性和单点访问
  • 3.解决方案:对类定义静态方法用以返回单实例

尽早初始化

相关模式:单例模式通常用于Factory对象和Facade对象

具有不同接口问题的外部服务的结论:
适配器、工厂和单例模式的组合,以提供受保护的外部服务不同接口的变体

Strategy策略模式

问题:如何设计变化但相关的算法或策略?如何设计才能使这些算法或策略具有可变更的能力?
解决方案:在单独的类中分别定义每种算法/策略并且使其具有共同接口

  • 1.策略对象将依附于语境对象(context object),策略对象对其应用算法
  • ⒉策略对象对语境对象应用算法:在本例子中语境对象是Sale:当getTotal消息被送给Sale时它会把部分工作委派给它的策略对象,语境对象需要策略的属性可见性,语境对象会把自身的引用传递给策略对象,策略对象有语境对象的参数可见性

使用工厂创建策略:


策略是基于多态的,并且提供了防止变异
通常使用工厂创建策略

Composite组合模式

问题:如何能够像处理非组合(原子)对象一样(多态地)处理一组对象或具有组合结构的对象呢?
解决方案:定义组合和原子对象的类使它们实现相同的接口

外部的组合对象包含一组内部对象外部和内部对象实现相同的接口
也就是说组合类本身也要实现lSalePricingStrategy接口

相关模式:基于多态、提供防止变异,通常和策略、命令模式一块用

Facade 外观模式

  • 问题:对—组完全不同的实现或接口(例如,子系统中的实现和接口)需要公共、统一的接口可能会与子系统内部的大量事物产生耦合,或者子系统的实现可能会改变。
  • 解决方案
    • 对子系统定义唯一的接触点使用外观对象封装子系统
    • 外观对象提供了唯─和统一的接口,并负责与子系统构件进行协作

外观模式很简单并且应用广泛它将子系统隐藏在一个对象之后

相关模式:

  • 外观通常通过单例类模式进行访问它们对子系统的实现提供了防止变异,并且通过增加间接性对象有助于对低耦合的支持,外部对象只被耦合到子系统中的一个点:即外观对象
  • 正如在适配器模式中所描述的适配器对象可能用来封装对具有不同接口的外部系统的访问,这就是一种外观,但适配器强调对不同接口的适配,而外观可能单纯再封装一层,没有做适配

Observer/Publish-Subscribe/Delegation Event Model

问题:订阅者对象关注发布者对象的事件和状态变化,但要保持低耦合。
solution:定义“监听器”接口,订阅者实现接口,发布者可以动态注册关注某事件订阅者,并在事件发生时通知(类似于消息绑定)

观察者模式基于多态,一个事件可以有多个订阅者

下图中,步骤

  • 定义接口PropertyListener
  • 定义实现该接口的窗口(Saleframe1中的onpropertyEvent)
  • Saleframe1窗口初始化时,向其传递sale实例
  • Sale并不知道SaleFrame1(不知道自己被观察),只知道实现了PropertyListener的对象,降低了耦合,只对接口耦合而不是对GUI类耦合

Observer提供了一种在通信方面松散耦合对象的方法

问题回顾:

  1. 说明GRASP原则是对其它设计模式的归纳
  2. 什么是GoF的适配器工厂单例策略外观和组合设计模式?
  3. 如何使用适配器工厂单例策略外观和组合设计模式?

6.精化迭代3

6.1 活动图

显示流程中的连续和并行活动。用于建模业务流程、工作流、数据流和复杂算法,对于涉及众多参与者的非常复杂的业务过程建模具有价值

元素:

  • 活动activity

    • 表示参数化行为。
    • 可能是动作、对象、控件
    • 可能有前置和后置条件约束
  • 分区Partition:具有某些共同特征的操作的活动组,或是参加过程的不同参与者
  • 开始节点和结束节点Start node and end node
  • 动作(action) 、分叉点(fork)、连接点(join)和对象节点(object node)、菱形代表决策decision node和合并merge node
  • 当某个活动需要在另外一个活动图中展开时使用耙子(rake)符号

使用于UP中的业务建模(Business Modeling),其用途是去理解和沟通”将要部署系统的组织的结构和动态特征”【RUP】,业务建模科目的关键制品是业务对象模型(UP中领域模型的超集)

本质上,业务对象模型使用UML类图、顺序图和活动图对业务如何运转进行了可视化

有哪些UML活动图?
在活动图建模方面,有哪些准则?
什么是UP过程的业务建模?
什么是业务对象模型?

6.2 状态图

通过有限状态转换显示设计系统部分的离散行为显示对象的生命周期:它经历的事件、它的转换以及它在这些事件之间的状态仅适用于核心对象、关键对象和复杂对象

元素:State、event、transition、transition actions and guards、Nested States

UP中任何模型都可以使用状态图

6.3 用例关联Relating Use Cases

简单的组织机制,能够(理想地)促进对用例的理解和沟通、减少文本重复改善用例文档的管理

使用包含<<inculude>>和扩展<<extend>>关联

包含关系:多个用例中存在部分相同的行为,将这部分行为分离为子功能用例,然后使用包含关系指示

用例文档用下划线表示被包含的用例

用途2:描述异步事件的处理

用例文档用例如a*这种星号表示,意味着扩展或事件可以在任何时候发生

或者用例非常冗长,分解成便于理解的子单元

扩展关系:
基础用例(处理销售)对扩展用例(处理债券支付)没有任何引用扩展关系的最重要特征,因此,基础用例不需要定义或处理扩展触发的条件,处理销售用例自身是完备的,它不需要知道扩展用例的信息。区别于包含关系,重点在于不能修改原来的用例

触发条件和扩展点:

具体concrete用例是由参与者发起,完成了参与者所期望的完整行为[RUP],它们通常是基本业务过程用例。例如,处理销售用例是具体用例

抽象用例永远不能被自己实例化,是其他用例的子功能。用例处理信用卡支付是抽象用例,它不能够单独存在,只能是其他用例,如处理销售用例的一部分

基础base用例包含其他用例的用例,或者是被其他用例扩展或者泛化的用例。处理销售用例包含处理信用卡支付子功能用例,因而它是基础用例。

附加用例被其它用例包含的用例或者扩展、泛化其他用例的用例。

UML表示法:
扩展关系:扩展用例指向基础用例,可以在线上标条件和扩展点
包含关系:基础用例指向扩展用例

6.4 领域模型的精化refinement

泛化(超类和子类)、关联(量化或受限关联、自反关联、聚合、组合)

用包图来组织领域模型(Payment、Products、Sales)

何时定义概念超类?
如何标记组合关系
什么是量化关联?
什么是自反关联?
如何区别销售发生时的历史价格和当前价格?
如何划分领域模型?

6.5 UML扩展:stereotypes, constraint and tag

构造型表示对现有建模概念的细化,并在UML概要文件中定义,与关键字一样,如«authorship»,也允许用户自定义

UML约束是对UML元素的限制或条件。在{}(大括号)之间的文本中可视化,例如:{size>=0}

UML标记和标记值:构造型可以具有称为标记定义的属性。当构造型应用于模型元素时,属性的值称为标记值

6.6 Architectural Analysis and Logical Architecture Refinement

架构分析是在功能性需求的语境中,识别和处理非功能性需求的活动

架构分析中的常见步骤:

  • 识别和分析对架构(architecture)有影响的非功能性需求(架构因素),写在补充规约当中

    • 可以采用Architectural Factor Table架构因素表
    • 变化点variation point
    • 进化点evolution point
  • 分析备选方案并制定解决方案以解决影响

Facade模式通常用于从较高层到较低层的“向下”协作

什么是架构分析? 请举例说明架构分析的4个主题在分层架构中如何应用外观、观察者和控制器模式?

6.7 UML Deployment and Component Diagram

部署图

UML部署图:部署图显示了具体软件构件(如可执行文件、实体) 到计算节点(处理服务)。它显示了软件元素在物理体系结构中的部署以及物理元素之间的通信(通常在网络上)

部署图最基本的元素是节点(node),有两种类型的节点:

  • 1设备节点device node(或设备)具有处理和存储能力可执行软件的物理计算机资源
  • 2执行环境节点execution environment node(EEN)在外部节点(例如计算机)中运行的软件计算资源,其自身可以容纳和执行其他可执行软件元素(操作系统虚拟机数据库引擎)

使用构造型来标记节点类型<<server>>``<<OS>>

元素:

  • Artifact制品表示物理世界中的具体元素,这些元素是开发过程的结果。制品的示例包括可执行文件、库、归档、数据库模式、配置文件
  • 通信路径:节点之间的连接,可以用协议标记。这些通常表示网络连接

组件图

组件图显示组件、提供和需要的接口、端口, 以及它们之间的关系
Component diagram shows components, provided and required interfaces, ports(端口), and relationships between them

UML组件图:UML组件是设计级透视图;它们不存在于具体的软件透视图中,而是映射到具体的工件,例如一组文件

6.8 更多GOF的应用

在用例实现的设计中应用GoF和GRASP:
远程服务失败时故障切换到本地服务
本地缓存
支持第三方POS设备,如不同的扫描仪
处理贷记、借记和支票付款

故障切换到本地服务;本地缓存的性能例如,访问产品信息 出于性能原因和可恢复性,使用产品描述对象的本地缓存–内存中的产品目录对象–本地产品服务维护更大的持久(基于硬盘)缓存 在尝试远程访问之前,应始终在本地缓存中搜索“缓存命中”

代理proxy

使用代理从外部服务访问失败中恢复

首选远程服务而非本地服务

问题:不希望也不可能直接访问真实的主题对象
解决方案:使用代理代理对象添加间接级别,代理对象实现与主题对象相同的接口,并负责控制或增强对其的访问

  • 优点:

    • 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
    • 同时代理对象可以扩展目标对象的功能
    • 代理模式能将客户端与目标对象分离,降低了系统的耦合度
  • 缺点: 增加代理对象,会造成请求处理速度变慢,同时系统复杂性增加

代理是封装内部对象的外部对象,两者实现相同的接口。客户端不知道它引用了代理

抽象工厂

相关对象族Families of Related Objects的抽象工厂

  • 抽象产品为一组不同但相关的产品定义接口
  • 具体产品是抽象产品的各种实现,按族分组
  • 抽象工厂接口声明了一组用于创建每个抽象产品的方法
  • 具体工厂实现抽象工厂的创建方法
  • 客户可以使用任何具体的工厂/产品变体,只要它通过抽象接口与其对象通信

如何使用代理从外部服务访问失败中恢复? 如何处理故障? 如何使用适配器访问外部物理设备?如何使用多态和Do lt Myself模式处理 支付?

6.8 使用模式设计持久化框架

与RDB一起工作的持久性服务称为O-R映射服务

持久化对象:需要持久存储,如产品描述实例

使用Facade访问持久性服务

使用模板方法模式设计持久性框架,模板方法是框架设计的核心,在一个超类中定义一个方法(模板方法),该超类定义了算法的框架及其变化和不变的部分 可以在子类中重写不同的部分,以添加它们自己独特的行为

事务状态和状态模式
背景/问题:对象的行为取决于其状态,其方法包含反映条件状态相关操作的case逻辑。是否有条件逻辑的替代方案?
解决:为每个状态创建状态类,实现一个公共接口。代表(委派) 从上下文对象到其当前状态对象的状态相关操作。确保上下文对象始终指向反映其当前状态的状态对象

使用命令模式设计事务事务是原子的,其任务必须全部成功完成,否则任何任务都不能完成

问题;如何处理需要排序(优先级排序)、排队、延迟、日志记录或撤消等功能的请求或任务?
解决:使每个任务成为实现公共接口的类

什么是持久化对象? 什么是框架?什么是虚代理?什么是事务?

6.9

什么是架构视图?什么是部署图?什么是构件?

7.1

1.如何规划UP中的迭代? 2.如何标记场景?3.如何组织项目制品?4.什么是阶段计划和迭代计划?5.在UP中,如何实现可靠的估计?

7.2

1什么是软件架构?2什么是设计模式?3什么是框架?4什么是架构模式?5什么是进程?什么是线程?6什么是系统的并发性和分布性? 7有哪些架构活动? 8什么是软件架构影响周期?

【软件分析】软件分析、设计与建模迭代式详解相关推荐

  1. 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记

    01.软件项目管理与敏捷方法--敏捷项目生命周期详解笔记 00.与其说是船还不如说是熟练的航行技术保证了成功的航行.--George William Curtis 01.敏捷项目是一个按照敏捷宣言宗旨 ...

  2. 视频教程-沐风老师3DMAX室内建模挤出法详解-3Dmax

    沐风老师3DMAX室内建模挤出法详解 沐风课堂创始人,专栏作家,独立媒体人,资深互联网从业者. 沐风老师 ¥12.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 APP ...

  3. 数学建模——主成分分析算法详解Python代码

    数学建模--主成分分析算法详解Python代码 import matplotlib.pyplot as plt #加载matplotlib用于数据的可视化 from sklearn.decomposi ...

  4. 数学建模——支持向量机模型详解Python代码

    数学建模--支持向量机模型详解Python代码 from numpy import * import random import matplotlib.pyplot as plt import num ...

  5. 数学建模——线性规划模型详解Python代码

    数学建模--线性规划模型详解Python代码 标准形式为: min z=2X1+3X2+x s.t x1+4x2+2x3>=8 3x1+2x2>=6 x1,x2,x3>=0 上述线性 ...

  6. 经验积累①:关于设备程序的版本迭代方案详解

    关于设备程序的版本迭代方案详解 一.案例描述 对于嵌入式应用层来说,需要对设备的很多参数进行保存,为了使得这些配置参数掉电不丢失,因此在flash中生成配置文件用于保存设备参数,每当设备重启后,将参数 ...

  7. C#,生信软件实践(03)——DNA数据库GenBank格式详解及转为FASTA序列格式的源代码

    1 GenBank 1.1 NCBI--美国国家生物技术信息中心(美国国立生物技术信息中心) NCBI(美国国立生物技术信息中心)是在NIH的国立医学图书馆(NLM)的一个分支.它的使命包括四项任务: ...

  8. 从源码分析RocketMQ系列-Remoting通信架构源码详解

    导语   这篇博客要从官方给出的一张图开始说起,之前的分析我们都是简单的分析了一下消息传递的流程,以及消息传递流程过程中出现的一些类的封装,并且提出,所有的封装操作都是为了更加高效的服务于NameSe ...

  9. 新电脑装机——配置硬件、软件安装卸载、注册表、路径——介绍详解

    装机工具.配置.路径,介绍详解 电脑配置信息 电脑历史记录 黑色 Window Top 加入黑色(微信不能调成黑色背景) edge浏览器的配置(被edge恶心过的必看,有方法解决edge被管理.不能新 ...

最新文章

  1. php 偷偷转移别人权重,判断百度蜘蛛偷偷进行301转移权重 给新站提权
  2. 网络编程学习笔记(SIGPIPE信号触发)
  3. 阿里七层流量入口 Tengine硬件加速探索之路
  4. TensorFlow2-自编码器
  5. SAP 电商云 Spartacus UI Checkout 页面的三个 page guards
  6. error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“MD_DynamicRelease”...
  7. luoguP3799 妖梦拼木棒 [组合数学]
  8. Shell编程之通配符
  9. linux 挂起后无法唤醒屏幕
  10. 解决使用七牛CDN导致AJAX评论报错{“ERROR”:”GET FROM IMAGE SOURCE FAILED: E405″}
  11. 计算机软考初级题库,‎App Store 上的“软考题库-最全最新历年真题”
  12. Quartz表达式详解
  13. 关于 U盘被写保护的问题
  14. 开发人员的 Chrome 翻译设置
  15. Excel 2010 SQL应用022 查询满足条件的记录
  16. php 调用mp3,使用PHP合并MP3文件的类,兼容php4、php5(2)
  17. C语言实验——圆周率 sdut oj
  18. Android系统充电指示灯无响应
  19. ANSYS Electronics Suite 2021 R2
  20. 奇迹MU服务端架设——拓展功能技术分享

热门文章

  1. 机器人编程与python语言的区别_少儿编程和机器人编程的区别有哪些?
  2. PDManer[元数建模]-v4.1.0发布:一款简单好用的数据库建模平台
  3. 无人机机载LiDAR数据应用之电力线路巡检
  4. python内置函数布尔值bool用法详解
  5. 2PSK的调制解调,编码解码,还有它的误码率,功率谱(语音信号的)
  6. GMS地下水数值模拟实践技术应用
  7. flash 图片剪切 php,flash + php头像上传预览裁剪组件1.8发_php
  8. SiamFC论文学习笔记
  9. 惠普83752B高功率合成扫频器,20 GHz
  10. wkhtmltopdf 网页转换为pdf