DSSA创建过程

过程

  1. 定义领域范围
  2. 定义领域特定的元素
  3. 定义领域特定的设计和实现需求
  4. 定义领域模型的架构
  5. 产生、搜集可复用的产品单元(回到第一步,整个过程是并发的、螺旋型的、反复的、递归的)

DSSA三层模型

在整个领域开发环境—-(参考结构、参考需求、架构、领域模型(票务模型)、开发工具)—->领域特定的应用开发环境—-(实例化的体系结构)—->应用执行环境

领域实现过程

  1. 搜索可复用元件
  2. 产生可复用原件
  3. 进一步升华–螺旋式迭代

DSSA特定领域的软件架构开发

DSSA特定领域的软件架构开发

  1. What:DSSA方法论-特定问题域的应用模型
  2. Why:领域具有普遍性、抽象性、重用性
  3. How:分析、设计、实现、迭代

DSSA基本活动

  1. 领域分析(行业了解)=>得到 建立领域模型
  2. 领域设计=>获得DSSA
  3. 领域实现(功能性与分功能性的添加),逐步求精返回到领域分析=>开发和组织可复用信息

获得:建立领域模型、获得DSSA、开发和组织可复用信息

如何进行领域分析?

领域分析方法:

领域知识资源(技术文献、已完成的软件项目、用户评述、专家建议、当前及未来的需求)->领域分析

领域分析方法、管理机制->领域分析

领域专家、领域分析人员、领域设计人员、领域实现人员->领域分析

领域分析->分类方法、标准、功能模型、领域语言

领域分析需要不停地迭代

DSSA人员分工

  1. 领域专家:产品经理-需求规约、领域字典
  2. 领域分析人员:系统分析员、产品经理、企业架构师
  3. 领域设计人员:应用架构师、资深程序员-软件重用和领域设计
  4. 领域实现人员:老带新模式

ABSD方法论具体实现

ABSD方法论具体实现

体系结构6大过程

  1. 架构需求
  2. 架构设计
  3. 架构文档化
  4. 架构复审(回到架构设计,当架构复审后觉得架构设计有问题时)
  5. 架构实现
  6. 架构演进(回到架构需求,当架构发生需求变化时)

需求过程

  1. 需求库->需求获取->(生成类图->对类进行分组->把类打包成构件)(标识构件)->需求评审(评审后可能会回到需求获取步骤)

设计过程

  1. 提出架构模型(根据需求选取架构模型)->映射构件->分析构件相互作用->产生架构->设计评审(评审后可能会回到提出架构模型)

实现过程

  1. 复审后的文档化架构->分析与设计(从构件库获取构件)->构件实现->构件组装(从构件库获取构件,获取可重复用的内容)->系统测试->架构演化

演化过程

  1. 需求变化归类->架构演化计划->构件变动(从构件库获取构件)->更新构建的相互作用->构件组装和测试->技术评审(评审后有可能回到架构演化计划)->演化后的架构

ABSD架构方法论

四大基石

  1. 功能分解:使用已有的基于模块的内聚和耦合技术
  2. 结构风格:选择架构风格来实现质量和业务需求
  3. 软件模板:描述软件元素在共享服务和底层构造的基础上,如何进行交互
  4. 递归:清晰定义迭代的每一个步骤

自顶向下功能分解

  1. 系统泛化成概念子系统
  2. 概念子系统泛化成概念构件
  3. 概念构件构建形成实际构件

ABSD基于架构的软件开发

What

ABSD方法论-功能分解、软件风格、软件模板、递归

Why

什么是架构的真正驱动-业务、质量、功能需求

How

具体实现-需求、设计、文档化、复审、实现、演化

什么是架构的真正驱动?

需求是架构的真正驱动。

  1. 业务功能需求、用例
  2. 质量属性、非功能需求
  3. 企业限制、架构策略

软件架构风格

架构设计风格

  1. What:主流软件架构风格-数据流、调用返回、独立构件、虚拟机、仓库
  2. Why:风格影响架构质量和实现效率
  3. How:理论结合面试题实战
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
graph LR
A[软件架构风格] -->B(数据流风格)
A --> C(调用返回风格)
A --> D(独立构件风格)
A --> E(虚拟机风格)
A --> F(仓库风格)
B --> B1(批处理序列)
B --> B2(管道过滤器)
C --> C1(主程序子程序)
C --> C2(面向对象)
C --> C3(层次结构)
D --> D1(进程通信)
D --> D2(事件驱动)
E --> E1(解释器)
E --> E2(规则系统)
F --> F1(数据库系统)
F --> F2(黑板系统)
F --> F3(超文本系统)

数据流风格

批处理序列

批处理风格通常会由总体协调安排批处理过程,保证其每一步处理都是独立的,并且顺序执行。具体来看有以下特点:

  • 强时间顺序: 只有当前一步的计算任务处理完成后,后一步处理才能开始。计算任务前后顺序明确
  • 强完整性:数据传送在计算单元之间通过指定的数据交互方式传递。每一步要确保数据完整,才可以向下一步发起数据传送。
  • 强控制力度:有独立的顺序控制和时间把控机制,并辅以数据检查等功能。

批处理序列,作为常见的架构风格,案例很多:

  • 传统定制批处理任务: 比如银行的夜间批量结算和大小额清算,券商的夜间交易结算和证券系统对账等。特点是通常运行在指定时间,数据流庞大,每一步有精确的数据处理要求和校验机制,顺序逻辑清晰。
  • Hadoop大数据处理: Hadoop在处理过程中有明确的步骤安排,比如map几次,shuffle几次,再reduce完成数据处理。
  • Apache Beam大数据处理: 当前比较火的批量处理工具是Apache Beam。虽然它同时支持批处理和流处理,但是在日常使用中其批处理的优势更加明显。它定义类专门的数据集计算过程、管道和执行器。能够形成有向无环图,来保证数据流的方向和结果输出。
管道过滤器

管道过滤器风格,由管道和过滤器两部分组成。

  • 过滤器:是其中的核心构件,负责业务的处理。它从用户或者上游管道获得输入数据,进行数据的变换及增量计算,处理完成后,通过下游管道传递给另一个过滤器。过滤器是独立的实体,它不能与其他的过滤器共享数据,而且一个过滤器不知道它上游和下游的其他过滤器信息。
  • 管道: 是一种数据传输途径。可以是Unix/Linux操作系统的管道文件,也可以是消息队列,只要能确保数据的先进先出,单向进出就可以了

管道-过滤器的经典案例也很多,比如:

  • 编译器: 在编译器系统中,一个阶段(包括词法分析、语法分析、语义分析和代码生成)的输出是另一个阶段的输入,处理阶段是是以数据流进行编译过程驱动流转的。
  • 操作系统管道过程: 比如经典的Linux命令ps -ef | grep java,就是在系统中检查java进程信息,其中的ps -efgrep java就是两个过滤器,各自处理相关流程步骤,中间的|标识,就是管道,负责在两个过滤器之间进行有向传输。
  • Streaming流处理: 比如经典的Spark Streaming、Storm、Apache Flink、 Kafka Streams等流式处理框架,或者是完整的流数据管道式处理方式,或者是将数据流进行微小的窗口切分,再采用超小批量处理方式进行数据处理和向后传递。这些技术整体来看,都属于管道-过滤器架构风格。

数据流风格总结
数据流的两种子风格的相似点如下:

  • 解耦: 将每个阶段的处理过程进行了隔离,使得软件构件具有良好的隐蔽性和高内聚、低耦合的特点; 每个批处理过程或者过滤器独立管理,可以方便地进行替换。
  • 复用: 支持软件重用,只要提供适合数据处理的需求,任何两个批处理过程和过滤器都可有序被连接起来。
  • 高吞吐: 数据流风格在5大风格中是最适合大数据的架构风格。它可以完成各种大量数据互通、传递、处理的过程。

同时,批处理序列风格与管道过滤器风格的不同点也很多:

  • 计划性: 批处理通常由时间规划和任务调度统筹安排,而管道过滤器是递增式处理过程是由数据驱动的处理流程
  • 敏捷性: 批处理需要完成前序任务,再进行后续任务,通常整个任务处理周期较长,通常以分钟、小时、天为单位,管道过滤器在传输过程中没有整体处理的概念,可以快速将-份小的数据变动流过相关的过滤器和管道,实现秒级、分钟级的快速响应。

调用返回风格

主程序/子程序

主程序子程序风格是面向过程的经典架构风格。一般采用单线程控制,把问题划分为若干处理步骤,分别由主程序和子程序完成。主程序调用子程序,子程序将调用结果返回给主程序。同时,子程序通常也可以合成为模块,增加调用过程的层次性。主程序最终结果的正确性,取决于其下属的模块和子程序的执行结果。

这一风格基本上涵盖了所有面向过程的开发模式,作为程序开发的最经典模式,被普遍使用。主要特点:

  • 简单明了: 符合传统的商业行为过程: 浏览->添加购物车->购买->支付->收货->评价等
  • 架构清晰: 可以和程序流图、泳道图、状态机模型等架构图一一对应,方便开发和验证这一风格基本上涵盖了所有面向过程的开发模式,作为程序开发的最经典模式,被普遍使用。
面向对象风格

这种风格是主程序子程席风格的进化,它随时面向对象语言的产生而同步出现。它将数据的表示方法和它们的相应操作封装在一个抽象数据类型或对象中。由对象来负责保持资源的完整性(成员变量)和程序之间的过程调用关系 (方法)。

这一风格基本上涵盖了所有面向对象的开发模式,是高级语言程序开发的最经典模式。

主要特点,非常鲜明:

  • 完整性:每个对象独立负责维护其本身的完整性,比主程序子程序的紧耦合方式,更容易实现应用体完整性
  • 隐蔽性: 对象的表示对其他对象而言是隐蔽的,对象可以不影响它的客户就能改变其实现方法。
  • 面向对象编程的优势:可以充分利用高级语言的优势来实现封装、聚合、继承、接口、多态、依赖、抽象、复用等特质。和现实生活中的实体逻辑可以一一映射地进行实现。
层次结构风格

分层是软件架构设计的主流方法之一,将应用设计成一个层次系统,每一层为上层服务,并作为下层客户。每一层最多只影响上下两层,同时允许每层可以用不同的方法来实现应用逻辑和功能。这对于解决软件的复杂性和重用性,提供了强大的支持。

经典模式比如:

  • OSI网络7层模型,TCP/IP网络4层模型:确保每一层可以采用不同的技术栈和设计思路,所有数据会根据网络层次结构进行数据包的封装,不会出现层次的跳跃现象。
  • 操作系统内核和用户态管理: 操作系统从核心的内核层,到外围的工具、用户系统,类似一个洋葱模型,所有的过程调用只在相邻两层之间进行。
  • 应用分层模型:比如MVC三层模型、领域驱动4层模型等。我们将在后续的领域驱动章节详细介绍4层领域模型。可以想见,层次结构风格极大化地抽象了软件架构,摆脱了编程语言的限制。其他如C/S、B/S、SOA应用架构等,横跨了软件、系统和网络范畴。但它们有一个共同点,都采用了层次化的描述方式,所以可以看成是层次结构风格的延伸。

主要特点:

  • 隐藏复杂性:每一层可以独立设计、开发,只要满足和上下层的接口定义即可。同一层可以实现架构重用和借鉴,从整体上将应用实现了分层解耦。
  • 邻居互动性:每一层至多和相邻的上下层交互,因此功能的改变最多影响相邻的上下层。

调用返回风格总结

调用返回风格是5大架构风格中最润物细无声的一种。它几平自然而然地被运用在了所有开发设计过程中:

  • 在面向过程的开发中,通常都采用了主程序/子程序风格
  • 在面向对象的开发中,几乎都是用了面向对象风格
  • 在应用的分层设计中,几乎都采用了层次结构风格

它们组合起来,真正实现了软件构件的解耦和互动。

独立构件风格

进程通信

构件之间通过独立的进程来实现消息传递。比较经典的例子包括:

  • 应用之间的RPC调用: 通常采用同步或异步方式,远程调用其他模块的接口程序。
  • 应用之间的RestAPl调用: 通过规定的消息传输机制(REST接口规范)来实现同步或异步方式的进程间通信。
  • 点对点通信: 比如像区块链、BitTorrent等的点对点通信,也是进程通信风格的延伸

主要特点:

  • 目标明确: 远程通信具有清晰的指向性,目标明确0。
  • 同步为主: 通常以同步调用为主,辅以异步交互式通信方式。
事件驱动系统

事件驱动系统风格是基于事件的隐式调用风格,构件不直接调用一个过程,而是触发或广播一个或多个事件。后续执行过程会被注册在一或多个事件,当对应的事件被触发或者广播时,系统会自动调用该事件中注册的过程,执行相应的模块功能支持基于事件的隐式调用的应用系统很多:

  • 调试器: 在IDE工具中设置断点,当触发断点后,IDE工具处理程序在断点处停下,变量监视器自动刷新变量数值。整个过程IDE工具和调试模块之间没有直接的进程通信,而是采用事件驱动的机制实现过程调用。
  • 消息队列: 消息队列通常用于应用间的通信和业务流的峰填谷,当消息被发送到消息队列后,对应的消息监听应用会自动消费该消息,并进行相应数据和业务处理操作。整个过程中消息的生产者和消费者之间没有直接的互动和了解,完全由消息队列来驱动数据流的指向。
  • 事件驱动设计: 事件驱动设计(Event Driven Architecture)是当今很火的话题,结合CQRS读写分离等技术,可以实现完整的业务分解和设计。我们会在后续的领域驱动设计章节来详细讨论事件驱动系统风格。

事件驱动系统风格的主要特点:

  • 隐式调用,匿名互动:事件的触发者并不知道哪些构件会被这些事件影响。这样不能假定构件的处理顺序,甚至不知道哪些过程会被调用,体现了极强的低耦合性。
  • 广播机制: 通常事件驱动的接受者不止一个,会采用广播方式进行信息传输,方便实现一对多的过程调用和应用交。

独立构件风格总结

独立构件风格是5大架构风格中,最偏重沟通的一种风格。它描述了在一个应用系统中,各个构件是如何进行通信的:

  • 可以是点对点的、指定方向的进程通信风格
  • 也可以是广播的、隐式调用的事件驱动系统风格

他们组合起来,真正实现了进程与进程、模块与模块、系统与系统间的互动。

虚拟机风格

解释器

解释器通常包括:完成解释工作的解释引擎,被解释代码的存储区、记录解释警当前工作状态的数据结构、记录源代码被解释执行进度的数据结构等。

解释器可以仿真硬件的执行过程和一些关键应用,通常被用来弥合程序语义与硬件语义之间的差异。其缺点是执行效率较低。

比较经典的例子包括:

  • 编程语言解释器: 如Java语言解释器JVM。它负责Java语言的解释和虚拟机运行环境。
  • 容器运行解释器:像Docker Daemon等容器运行环境,也可以理解为容器的解释器和虚拟机,完成了自定义的容器内应用的解释和管理。
  • CAD仿真环境: 电路前端后端仿真运行环境,负责解释电路设计程序,并提供运行仿真环境。
  • 专家系统:基于经验的大数据推理系统。将专家推理逻辑和程序,转换成决策平台的解释系统。

主要特点:

  • 虚拟环境: 提供虚拟运行环境
  • 程序解释: 解释程序代码、运行状态等
基于规则的系统

基于规则的系统包括规则集、规则解释器、规则/数据选择器及工作内存等。

比较经典的例子如:

  • 业务规则引擎:像Drools开源规则引擎、IBM iLog商业规则引擎,都是业务人员的好伙伴。业务人员不能像程序员一样精通if/else逻辑开发,但是又需要可以随时进行业务逻辑的修改和优化。业务规则引擎提供了有效的途径,它可以采用图形化的方式,让业务人员拖拖拉拉地指定业务逻辑。比如优惠券的计算逻辑、产品的价格制定逻辑、仓储系统的内部流转逻辑等。
  • 大数据分析引擎: 大数据分析通常满足82原则,80%的数据分析仍然是有规律可循,可以采用一定的规则引擎来处理,另外的20%数据才需要A人工智能的强大分能力来完成。在规则化的处理过程中,通常数据科学家不会直接编程来完成逻辑规则的指定,所以大数据环境,分析规则引擎也被广泛使用,来协助数据工程和数据分析。
  • 网络防护系统: 比如WAF应用防火墙、机器人识别防护、IDS/IPS入侵检测和防御,通常都依赖于规则的设定
  • 运维自动化: 在IT运维和数据中心运维中,越来越多的采用了规则类的工具和系统来实现自动化。

基于规则引擎的系统的主要特点:

  • 规则决策:规则的细节被引擎所解析,来决定业务、监控等策略和措施的制定。
  • 人工智能:简化人工智能、加速自动化和逻辑处理

虚拟机风格总结

虚拟机风格是5大架构风格中,最偏重运行环境的一种风格。它描述了在一个应用系统中,程序代码是如何被解释和用于决策的:

  • 虚拟机方式提供解释引擎和中间数据存储过程
  • 规则引擎来匹配和解释规则集,指定最终决策

它们组合起来,真正实现了程序产生智能,IT掌控世界。

仓库风格

数据库系统

数据库架构是仓库风格最常见的形式,所有的关系型和非关系型数据库的使用都可以归为这一风格。它有一个中央数据库或者数据仓库,作为共享数据源,保存当前系统的数据状态:大量的分布式和不同业务逻辑的系统,作为独立处理元素,对数据元素进行操作。

主要特点:

  • 共享数据源:集中式的共享数据库
  • 独立处理单元:分布式的独立处理节点
超文本系统

超文本系统风格主要是用于共享静态网页

比较经典的例子如:

  • CMS内容管理系统:保存有JavaScript、CSS、HTML等静态网页,用于让不同领域的前端节点来共享地访问静态页面元素和框架。
  • 分布式文件互通: 节点各自存储部分文档,通过节点跳跃、网状链接等方式共享静态文件。

主要特点:

  • 多种共享形式:超文本系统可以是集中式的文件资源方式,也可以是网状互通的分布式资源共享方式。
  • 非结构化文件: 适合管理非结构化文件,如静态文件、对象存储等。
黑板

黑板是所有软件架构风格里最复杂的一套风格。通常只在特定领域使用,比如语音识别、模式识别、信号处理等。黑板系统是一种问题求解模型。以语音识别为例,通常一段语音的识别没有必然正确的最优解,只有根据现有知识和模型的匹配近似解。将原有问题通过变换、分割等方式转换为多个子问题,并将原始数据也相应地转换为高级数据结构。1000个人心中有1000个哈姆雷特,同样地,1000个专家(或专家系统)也会有1000个不同的子问题解。用一个黑板,让这些专家将已经获得的信息、已经处理完的数据、已经完成的子问题都写到同一个黑板上。其他专家可以通过这个共享的里板的数据变更,很快地作出反应,优化自己手上的子问题计算,这个黑板,就是用于记录组织推理步骤、控制状态数据和问题求解之领域知识的框架。它将问题的解空间组织成一个或多个应用相关的分级结构。这些分级结构将由不同的专家(系统),通过不同知识表达方法、推理框架和控制机制的组合来形成各自的知识源。知识源之间没有直接的数据传输,所有交互都通过共享的黑板的数据更新来完成。

主要特点:

  • 分布式知识源:不同的子问题采用不同的数据集、推理框架和控制机制,生产分布式的知识源。
  • 集中式的数据共享:通过黑板这个集中式逻辑系统完成所有知识源的数据共享。
  • 集中式控制: 通过黑板的数据更新,通知各数据源,从而驱动分布式计算的进行。

它们组合起来,真正实现了分布式世界中数据的存储和共享。

架构是可传递可复用的模型

架构复用

  1. 方法论复用(ABSD、DSSA、AT、EA、TOGAF)
  2. 模型服用(UML、SOA、CBM)
  3. 工件复用(素材、图片、表格、图标、文件)
  4. 剪裁(三七原则,保留30%其他项目结构或者内容)
  5. 架构资产更新(内部资产库、外部架构社区)

OpenGroup架构认证

  1. TOGAF企业架构(广度、知识点、案例分析、笔试)
  2. Master Architect主架构师认证(应用架构、数据架构、集成架构、技术架构)

主架构师认证

  1. 三个完整方法论案例(需求、设计、风险、决策、结果)
  2. 20+架构师评测点(各2-3个案例论证)
  3. 评测重点:方法论、模型的复用,架构资产的贡献

架构与组织结构

康威定律Conway’s law

organizations which design systems … are constrained to produce designs which are copies of the communication structures of these organizations.

设计系统的架构受制于产生这些设计的组织的沟通结构。即,沟通方式(组织结构)决定系统设计,有什么样的组织结构就有什么样的系统,所以要有一个好的系统就要先从组织结构入手。

贝佐斯的“两个披萨”原则

一个团队接近12个人,一共有12*11/2的沟通线。太多会导致信息失真。

架构师需要考虑问题

  1. 如何解决环境问题:开发、QA和生产的不匹配
  2. 如何解决耦合问题:凤凰项目和传统系统耦合
  3. 如何决绝资源共用问题:关键人员疲于在多项目中切换
  4. 如何满足峰值需求:突发性业务需求、性能测试需求
  5. 如何解决安全问题:最小代价完成安全合规审计

明确系统设计约束条件

架构明确了系统设计的约束条件。

ADEMES矩阵

架构面临当前各种问题的矩阵,相较于RAID比较静态。

广义功能 质量 约束
业务级需求 业务目标 快、好、省 技术性约束
法规性约束
技术趋势
竞争因素与竞争对手
遗留系统集成
标准性约束
分批实施
用户级需求 用户需求 运行期质量 用户群特点
用户水平
多国语言
开发级需求 行为需求 开发期质量 开发团队技术水平
开发团队磨合程度
开发团队分布情况
开发团队业务知识
管理:保密要求
管理:产品规划
安装、维护

RAID矩阵

Risk风险 Assumption假设 Issue问题 Dependency依赖
架构决策1
架构决策2
架构决策3

架构制约系统质量属性

  1. 核心质量属性:
    1. 扩展性、可用性、性能、安全性、耦合性;
    2. 伸缩性、易用性、可维护性、可移植性;
    3. 可操作性、可重用性

Android Studio问题集

Android Studio 2022.3.1版本修改maven下载路径

  1. 找到settings.gradle.kts输入如下的信息中的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    pluginManagement {
    repositories {
    // add maven url
    maven(url = "https://maven.aliyun.com/repository/google")
    maven(url = "https://maven.aliyun.com/repository/public")
    google()
    mavenCentral()
    gradlePluginPortal()
    }
    }
    dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    // add maven url
    maven(url = "https://maven.aliyun.com/repository/google")
    maven(url = "https://maven.aliyun.com/repository/public")
    google()
    mavenCentral()
    }
    }