软件架构:架构模式、特征及实践指南-读书笔记(1)

news2024/9/23 9:35:04

第二章 架构思维

2.1 架构与设计

为了使架构落地,必须打破阻碍在架构师和开发人员之间的所有障碍,从而使架构师和开发团队之间形成双向的强关联。如图2-3所示,架构师和开发人员必须在同一个虚拟团队中才能使架构落地。该模型不仅促进了架构师与开发人员之间频繁的双向沟通,而且还促使架构师为团队中的开发人员提供指导和培训。

2.2 技术广度

但是,随着开发人员过渡到架构师角色,知识的性质也会发生变化。架构师的价值很大一部分是广泛地理解技术,并且知道如何利用技术解决特定的问题。例如,作为一名架构师,知道一个问题的五种解比仅知道一种专业解更为有益。对于架构师来说,最重要的部分是金字塔的顶部和中间部分。如图2-6所示,中间部分与底部交汇处的长度代表了架构师的技术广度。
作为一名架构师,技术广度比技术深度更重要。因为架构师的职责就是根据功能做出与技术限制相匹配的决策,所以广泛了解各种解决方案是非常有价值的。因此,如图2-7所示,对于架构师而言,明智的做法是做到“博而不专”。如图所示,除了一些必要的专业知识,架构师要把时间在拓展行业内的不同知识上。

架构师应关注技术广度,以便在设计架构时有更丰富的工具箱。过渡到架构师角色的开发人员可能必须更改他们获取知识的方式。事实上,每个开发人员在职业生涯中都应该平衡知识的深度和广度。

2.3 分析权衡

程序员了解所有技术的优势是构师需要在其中找到平衡。

除了安全性问题外,图2-9中的“主题”方案仅支持同构契约。所有收到出价数据的服务必须接受相同的契约和同组出价数据。在图2-10中的队列方案中,每个使用者可以针对其所需的数据拥有自已的契约。例如,假设新的竞标历史服务需要在出价消息中加入要价信息,但是没有其他服务需要该信息。在这种情况下,需要修改契约,从而会影响使用该数据的所有其他服务。在队列模型中,由于队列是一个单独的通道,因此,单独的契约不会影响任何其他服务。
图2-9中所示的主题模型的另一个缺点是,它不支持监控主题中消息的数量以及弹性伸缩。但是,使用图2-10中的队列模型可以分别监控每个队列,并以编程方式将负载均衡应用于每个出价消费者,可以独立地进行伸缩。请注意,这种权衡是特定于某种技术的:高级消息队列协议(AMQP)可以支持程序化的负载均衡和监控,因为队列和交换(即生产者发送的内容和消费者收到的内容)是分开的。分析利弊后,现在选择哪个更好?答案仍然是看情况!表2-1总结了这些权衡。

第三章 模块化

3.2 度量模块化

模块化对架构师非常重要,研究人员创建了各种跨语言的度量标准来帮助架构师理解模块化。我们重点聚焦三个关键概念:内聚性、耦合和共生性。

3.2.1 内聚性

计算机科学家定义了一系列内聚性度量指标,将内聚性从最佳到最坏分为:

功能内聚性
        模块的每个部分都彼此相关,并且模块包含了功能所必需的所有内容。
依序内聚性/顺序内聚
        两个模块进行交互,其中一个模块的输出作为另一个模块的输入。
联系内聚性/信息内聚/通信内聚
        两个模块构成了一条通信链,其每个模块都基于信息进行操作或有助于某些输出。例如,添加一条记录到数据库和基于该信息生成电子邮件。
程序内聚性
        两个模块必须以特定顺序执行代码。
时间内聚性
        模块基于时序依赖。例如,许多系统有一些看起来不相关的东西,必须在系统启动时对其进行初始化。这些不同的任务具有时间内聚性。
逻辑内聚性
        模块内的数据在逻辑上相似,但在功能上无关。例如,存在一个模块,该模块可以从文本、序列化的对象或流中转换信息。这些操作是相似的,但功能却大不相同。每个Java项目几乎都会出现Stringutils的包(一组在String上操作但在其他情况下都不相关的静态方法)是这类内聚性的常见示例。
偶然内聚性
        除了位于相同的源文件中,模块中的元素互不相关。这是内聚性的最负面形式。

CustomerMaintenance(客户维护模块)

  • 添加客户
  • 更新客户
  • 获得客户
  • 通知客户
  • 获得客户订单
  • 取消客户订单

也可以分成两个单独的模块,比如这样:

客户维护模块

  • 添加客户
  • 更新客户
  • 获得客户
  • 通知客户

订单维护模块

  • 获得客户订单
  • 取消客户订单

哪个是正确的结构?答案仍然是:看情况:

  • 订单维护模块只有这两项操作吗?如果是这样,将这些操作归还给客户维护模块可能挺讲得通的。
  • 是否期望客户维护模块包含更多的功能,从而鼓励开发人员寻找机会提炼行为?
  • 订单维护模块是否需要掌握大量的客户信息,以至于将两个模块分开需要高度的耦合才能正常运行?这与上文LarryConstantine的引用契合。

这些问题代表了软件架构师工作的核心,是一种权衡分析。

3.2.2 耦合

幸运的是,我们有更好的工具来分析代码库中的耦合,其原理一部分基于图论:由于方法的调用和返回可形成调用图,因此使基于数学的分析成为可能。

第四章 现有的架构特征

明确非领域设计的某个注意事项
        在设计应用时,需求指定了应用应该做什么,架构特征指定了成功的操作和设计标准,涉及如何实现需求以及为何做出某些决策。例如,一个常见的重要架构特征为应用指定了一定的性能水平,而这通常不会出现在需求文档中。更相关的是,没有需求文件会指出“防止技术债务”,但这是架构师和开发人员的常见设计注意事项。我们在5.1节中深入讨论了显式特征和隐式特征之间的区别。


影响设计的某些结构项
        架构师试图在项目上描述架构特征的主要原因与设计注意事项有关:此架构特征是否需要特殊的结构才能成功?例如,安全实际上是每个项目的顾虑,所有系统都必须在设计和编码过程中符合预防措施的标准。但是,当架构师需要设计一些特殊的功能时,它会上升到架构特征的层级。在示例系统中,考虑两种围绕付款的情况:

        第三方付款处理器
        如果集成点处理付款明细,则该架构不需要特殊的结构注意事项。设计应包含标准的安全规范,例如加密和哈希,但不需要特殊的结构。

        应用内付款处理
        如果正在设计的应用必须处理付款,则架构师可以为此目的设计特定的模块组件或服务,从结构上隔离关键的安全问题。如此一来,架构特征对架构和设计就都有影响。

4.1 部分已罗列出来的架构特征

4.1.1 运营性架构特征

运营性架构特征涵盖了性能、可伸缩性、弹性、可用性和可靠性等功能。表4-1列出了一些运营性架构特征。

4.1.2 结构性架构特征

架构师还必须关注代码结构。在许多情况下,架构师应对代码质量问题(例如良好的模块化、组件之间的受控耦合、代码可读性以及许多其他内部质量评估)负全责。

4.1.3 跨领域架构特征

尽管许多架构特征属于易于识别的类别,但也有许多特征属于不合理的分类,但却构成了重要的设计约束和考虑因素。详见表4-3。

第五章 识别架构特征

5.2 从需求中提取架构特征

一些架构特征来自需求文档中的显式声明。例如,显式的预期用户数量和规模通常出现在领域问题中。其他方面则来自架构师固有的领域知识,这是领域知识始终对架构师有益的众多原因之一。例如,假设一名架构师设计了一个处理大学生班级注册的应用。为了简化计算,假设学校有1000名学生和10个小时的注册时间。架构师是否应该设计一个假设规模一致的系统,并隐式地假设学生在注册过程中会随着时间的推移平均分配自已的时间?或者,基于对大学生习惯和倾向的了解,架构师是否应该设计一个系统在最后10分钟内处理所有1000名学生的注册请求?任何了解学生是有多拖延的人都知道这个同题的答案!这样的细节很少会出现在需求文档中,但是它们确实可以为设计决策提供依据。

5.3 案例研究:硅三明治

为了说明几个概念,我们使用架构kata。为了展示架构师如何从需求中获取架构特征我们将举例介绍硅三明治卡塔(Silicon Sandwiches kata)。
描述
        一家全国连锁的三明治店希望开启在线订购(除了当前的呼叫服务之外)。
用户
        目前数千,也许一天可达到百万级别。
需求

  •         用户将会下订单,然后给定一个取三明治的时间,以及展示一个去商店的路线(商店必须集成多个包含交通信息的外部地图服务)。
  •         如果商店提供送货服务,请向用户发送配送司机和三明治的信息。
  •         移动设备可访问性。
  •         提供全国每日促销/特价。
  •         提供当地每日促销/特价。
  •         接受在线付款、当面付款以及交货时付款。

其他内容

  •         三明治店专营权,每个店主拥有不同的所有者。
  •         母公司近期计划向海外扩张。
  •         公司目标是雇用廉价劳动力以最大限度地提高利润。

在这种场景下,架构师将如何得出架构特征?需求的每个部分都可能对架构的一个或多个方面有影响。架构师不会在这里设计整个系统(解决领域问题仍需要花费大量精力来编写代码)。相反,架构师需要寻找影响设计的架构特征,尤其是结构上的影响。首先,将候选架构特征分为显式特征和隐式特征。

5.3.1 显式特征

显式的架构特征出现在需求规范中,作为设计的必要部分。例如,购物网站可能希望支持特定数量的并发用户,这是领域分析师在需求中指定的。架构师应考虑需求的每个部分,以了解其是否有助于架构特征。但是首先,架构师应该考虑关于预期指标的领域级别的预测,如卡塔的“用户”部分所述用户数量应该引起架构师的注意,其中最重要的细节之一是:目前有数于名用户,也许有一天会达到百万人(这是一家雄心勃勃的三明治店!)。因此,可伸缩性(在不严重降低性能的情况下处理大量并发用户的能力)是最重要的架构特征之一。请注意,问题说明并未显式要求可伸缩性,而是将该要求表示为预期的用户数量。架构师必须经常将领域语言解码为等效的工程技术。
但是,我们可能还需要弹性(处理突发请求的能力)。这两个特征通常看起来是混在一起的,但是它们有不同的约束。可伸缩性看起来如图5-1所示。

另一方面,弹性可衡量流量的突发,如图5-2所示。
一些系统是可伸缩的,但不是弹性的。以一个旅馆预订系统为例。如果没有特别的销售或活动,用户数量可能会保持一致。相反,考虑音乐会门票预订系统。随着新门票的发售,狂热的粉丝将涌入该场地,这需要高度的弹性。弹性系统通常还需要可伸缩性:处理突发事件和大量并发用户的能力。

弹性要求未出现在“硅三明治”要求中,但架构师应将其识别为重要的考虑因素。需求有时会直接说明架构特征,但有些潜伏在向题域内。例如,一个三明治店整天的流量是否一致?还是进餐时间会十分拥挤?儿乎可以肯定是后者。因此,好的架构师应该能够识别这种潜在的架构特征。

架构师应依次考虑所有这些业务需求,以查看架构特征是否存在:

1.用户将会下订单,然后给定一个取三明治的时间,以及展示一个去商店的路线(商店必须集成多个包含交通信息的外部地图服务的选项:
外部地图服务暗示集成点,这可能会影响可靠性等方面。例如,如果开发人员构建的系统依赖于第三方系统,但是调用失败,则会影响调用系统的可靠性。但是,架构师还必须警惕过度指定的架构特征。如果外部交通服务中断了怎么办?硅三明治网站是否应该失败,还是提供一个没有交通信息的低效率产品?架构师应始终防止在设计中带入不必要的脆弱性。


2.如果商店提供送货服务,请向用户发送配送员和三明治的信息。
似乎不需要特殊的架构特征来支持此要求。


3.移动设备的可访问性。
此要求将主要影响应用的设计,需要构建一个可移植的Web应用或几个原生Web应用。考虑到预算的限制和应用的简单性,架构师可能会认为构建多个应用过于刻薄,因此设计改为了对移动设备进行优化的Web应用。因此,架构师可能希望为页面加载时间和其他移动敏感特性定义一些特定的性能架构特征。请注意,架构师不应在这种情况下独自行动,而应与用户体验设计师、领域利益相关者以及其他有关部门合作,共同审核此类决策

4.提供全国性的每日促销/特价。


5.提供当地每日促销/特价。
这两个要求都指定了促销和特价中的可定制性。请注意,促销要求还隐含了基于地址的自定义交通信息。基于所有这三个要求,架构师可以将可定制性视为架构特征。例如,微内核架构等架构风格通过定义可插件架构,可以很好地支持自定义行为。在这种情况下,默认行为会出现在核心中,并且开发人员将根据位置通过插件编写可选的自定义部件。但是,传统设计也可以通过设计模式(例如模板方法[Template Method))来满足此要求。这种难题在架构中很常见,要求架构师在各种竞争方案之间不断取舍。关于特定权衡的讨论详见5.3.2节。


6.在线、当面或在收货时付款。
在线支付暗含安全性,但此要求中没有任何一项表明需要特别高级别的安全性。

7.三明治店是专营店,每个店都有不同的所有者。
此需求可能会对架构增加成本限制一一架构师应检查可行性(诸如成本、时间和员工技能等约束)以查看是否需要简单架构或牺牲某些特质的架构。

8.母公司有近期向海外扩张的计划。
此需求意味着国际化。有许多设计技术可以满足这一要求,这些技术不需要特殊的结构即可适应。但是,这肯定会推动设计决策。

9.公司的目标是雇用廉价的劳动力以使利润最大化。
该需求表明易用性将很重要,但同样,它更关注设计而不是架构特征。

我们从上述需求得出的第三个架构特征是性能:没有人愿意从性能不佳的三明治店购买,尤其是在高峰时段。但是,性能是一个微妙的概念一一架构师应设计什么级别的性能?我们在第6章中介绍了性能的各种细微差别。

我们还希望结合可伸缩性数字定义性能数字。换句话说,我们必须建立一个没有伸缩的性能基准,并确定给定数量的用户可接受的性能水平。通常,架构特性会相互影响,从而迫使架构师在架构特质之间进行来回定义。

5.3.2 隐式特征

许多架构特征并不会在需求文档中指定,但它们对设计有重要的影响。该系统可能要支持的隐式架构特征是可用性:确保用户可以访问三明治站点。可靠性与可用性密切相关:可靠性确保网站在交互过程中保持正常运行一没有人愿意从总是断开连接的站点购买产品。

安全性是每个系统中的隐式特征:没有人愿意创建不安全的软件。但是,可以根据重要程度对其进行优先级排序,这说明了我们定义的内在联系。如果安全性影响了设计的某些结构并且对应用至关重要,则架构师会将安全性视为架构特征。

对于“硅三明治”,架构师可能会假设付款应由第三方处理。因此,只要开发人员遵循一般的安全习惯(不将信用卡号作为纯文本传递,不存储太多信息,等等),架构师就不需要任何特殊的结构设计来确保安全性,在应用中进行良好的设计就足够了。每个架构特征相互影响,其常见的陷阱是过度指定架构特征,这与未充分说明架构特征一样有害,会使系统设计变得过于复杂。

“硅三明治”需要支持的最后一个主要架构特征是可定制性,它包括需求中的儿个细节,请注意,向题域中提供了自定义行为:配方、本地销售和可能在本地被覆盖的指示。因此,架构应支持自定义行为的能力。通常,这属于应用设计的范围。但是,正如我们的定义所指出的那样,部分依赖自定义结构的问题域可以将其移入架构特征领域。但是,此设计元素对于应用的成功并非至关重要。重点是,选择架构特征时没有正确的答案只有错误的答案(正如Mark在他的著名语录之一中指出的那样):


在架构中没有错误的答案,只有昂贵的答案。

架构师可以设计一种无法在结构上适应可定制性的架构,需要应用本身的设计才能支持该行为。架构师不应该过分强调发现一组完全正确的架构特征一一开发人员可以通过多种方式实现功能。但是,正确识别重要的结构元素可能有助于产生简化或更优雅的设计。架构师必须记住:没有最佳的架构设计,只有最差可用的权衡取舍。

架构师还必须考虑这些架构特征的优先级,以尝试找到最简单的必需集合。一旦团队在确定架构特征上走出了第一步,一个有用的练习就是尝试确定最不重要的一个一一向一下自已,如果必须消除一个,那会是什么?通常,由于许多隐式架构影响应用的成功,因此架构师更倾向于剔除显式架构特征。我们通过定义什么对应用的成功至关重要,可以帮助架构师确定应用是否真正需要某种架构特征。通过尝试确定最小应用,架构师可以帮助确定其关键需求。对于“硅三明治”,我们确定的哪个架构特征最不重要?同样,不存在绝对正确的容案。然而,在这种情况下,自前解决方案可能会放弃可定制性或性能。我们可以消除可定制性,并将这种行为实现为应用设计的一部分。在运营性架构特征中,性能对于成功的影响最小。当然,开发人员并不是要构建具有糟糕性能的应用,而是要建立一个不将性能置于其他特征的优先级(例如可伸缩性或可用性)之上的应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2050770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于使用conda安装opencv-python失败的解决方法

当你想使用conda环境安装opencv-python时,会弹出: conda install opencv-python Collecting package metadata (current_repodata.json): done Solving environment: failed with initial frozen solve. Retrying with flexible solve. Collecting packa…

【网络】网络基础概念背景TCP/IP 五层模型跨网络传输详解

主页:醋溜马桶圈-CSDN博客 专栏:计算机网络原理_醋溜马桶圈的博客-CSDN博客 gitee:mnxcc (mnxcc) - Gitee.com 目录 1.计算机网络发展 1.1 独立模式 1.2 网络互联 1.3 局域网 LAN 1.4 广域网 WAN 2.协议 2.1 初识协议 2.2 协议分层 2…

应急响应:挖矿木马-实战 案例一.【Linux 系统-排查和删除】

什么是挖矿木马 挖矿木马是一种恶意软件,它在未经用户许可的情况下,利用用户的计算资源来挖掘加密货币,从而为攻击者带来非法收益。这类软件通常通过多种手段传播,例如利用系统漏洞、弱密码爆破、伪装正常软件等方法感染目标设备…

TI官网下载芯片原理图文件和封装文件导入Altium Designer 21.0.9

1、TI文件下载以 UCC27614为例 打开TI官网直接找到元器件资料界面 在设计与开发栏中找到封装模型文件下载 确认封装 选择封装导出的目标软件–AD 2、文件导入AD软件中 解压压缩包找到项目文件使用AD打开 导入AD输出芯片封装 打开UL_Import.pas然后点击Run 出现UL Import 选择…

20240818 每日AI必读资讯

3人干翻谷歌!免费学术搜索比谷歌学术相关性高5倍,已获YC投资 - 三人团队打造的学术搜索引擎:Lumina - 目前已处理了超30万次查询,支持24种语言 - 号称搜索结果相关性平均比谷歌学术高5倍,能搜索超1亿个研究对象&…

类和对象(下)(1)

类和对象(下) 再探构造函数 我们之前在实现构造函数的时候,初始化成员变量使用的方式都是在函数体内进行赋值,其实构造函数初始化成员变量还有一种方式:初始化列表。 初始化列表不只是为了写得方便,还能解…

信用贷款“并发”能做多少?“并发”前,得做好几件事

最近,咱们聊聊一个挺热门的话题——信用贷的“并发”现象,还有大家最关心的,信用贷款并发能做多少?“并发”操作过程中哪些是需要注意的。 信用贷款并发能做多少? 信用贷能贷多少,这事儿得从俩角度考虑&am…

问题: vue--elementUI 关于 Drawer 抽屉能打开而受蒙版影响不能正常关闭问题解决

对于一个后端为主的小白来说,刚接手Element 遇到的第一个大问题。 vue–elementUI 关于 Drawer 抽屉能打开而受蒙版影响不能正常关闭问题解决> 分享并且记录一下下 其实问题很简单。我们既然能打开。先定位问题。 当我们发现到问题的时候,我觉得应该 …

基于javaEE的校园二手书交易平台的设计与实现

TOC springboot287基于javaEE的校园二手书交易平台的设计与实现 第1章 绪论 1.1 研究背景 互联网概念的产生到如今的蓬勃发展,用了短短的几十年时间就风靡全球,使得全球各个行业都进行了互联网的改造升级,标志着互联网浪潮的来临。在这个…

NGINX 基础参数与功能

章节 1 NGINX 的源码安装 2 NGINX 核心配置详解 3 NGINX 之 location 匹配优先级 4 NGINX 基础参数与功能 目录 1 实现 Nginx 账户认证功能 1.1 创建htpasswd 认证文件 1.2 创建数据目录 1.3 指定认证文件路径 1.4 测试效果 2 定义重定向错误日志 2.1 指定错误日志访问路…

深度学习的量化和剪枝

一:背景 如果要将深度学习的AI模型部署到受限设备(FPGA)上,往往需要更小的存储需求和最低的计算复杂度。当然,还得保持一定的性能(下降在能够接受的范围)。受限设备资源的环境,一般是…

掌握ChatGPT写作艺术:从入门到精通的四个层次

这些周末我仔细研究了如何通过优化提示词提升ChatGPT输出内容的质量。 关于如何使用ChatGPT辅助我们的写作,我归纳了以下规律,希望能为你带来启发。 一、写作步骤 撰写一篇文章,思路上必须是从抽象到具体逐步深入。 首先我们需要明确写什么…

【数据结构与算法】冒泡排序

冒泡排序目录 一.冒泡排序原理二.图示三.冒泡排序具体实现四.冒泡排序升级版五.完整代码 一.冒泡排序原理 还是老样子,我们如何对这个进行排序呢? 冒泡排序的原理是,将两两进行比较,如果前面较大的我们就进行交换到后面. 然后再对交换后的这个和下一个进行比较,一轮过后,最大值…

spfa()算法(求最短路)

spfa算法是对bellman_ford算法的优化,大部分求最短路问题都可以用spaf算法来求。 注意: (1)如若图中有负权回路,不能用spfa算法,要用bellman_ford算法;若只有负权边,则可以用 spf…

Feign的基本使用

一、在项目中引入相关的依赖 创建两个微服务,分别为userservice、orderservice 现在需要在orderservie中查询用户相关的数据,所以需要使用feign进行远程调用userservice 1.1、在orderservice的pom.xml文件中添加下面的依赖 <dependency><groupId>org.springfram…

疫情居家办公系统--论文pf

TOC springboot394疫情居家办公系统--论文pf 第1章 绪论 1.1 课题背景 伴随着科技的进步&#xff0c;电子计算机已经成为人们日常生活不可或缺的办公工具。在这样的背景下&#xff0c;互联网技术被用于各个领域。为了能提高日常生活高效率&#xff0c;互联网信息技术性蓬勃…

Linux 网络套接字解析:实现网络通信

目录 一.网络基础1.协议2.OSI与TCP/IP模型3.网络通信流程4.IP与Mac地址 二.网络编程套接字1.端口号2.网络字节序3.tcp、udp协议4.socket编程5.sockaddr结构解析6.实现Udp_socket7.实现Windows与Linux通信8.Linux下远程执行指令9.实现tcp_socket10.守护进程 一.网络基础 1.协议…

IDEA中的 Maven 项目打包成Jar依赖,如何发布到本地仓库、远程仓库?

IDEA中的 Maven 项目打包成Jar依赖&#xff0c;如何发布到本地仓库、远程仓库&#xff1f; 默认读者都已经安装好 maven环境&#xff0c;如有不知道如何安装 maven 环境的&#xff0c;请先进行 maven 环境的安装学习教程&#xff01; 一、创建 maven 项目 按照图中方式&#xf…

python:画由两条抛物线所围成的图形

《高等数学》同济大学版 P338 编写 test_diff_2_area.py 如下 # -*- coding: utf-8 -*- """ 画由两条抛物线: ysqrt(x) , yx^2 所围成的图形的面积 """ import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import…