翻译转帖
原文链接https://herbertograca.com/2017/07/05/software-architecture-premises/
软件架构前提
这篇文章是软件架构编年史的一部分,这是一系列关于软件架构的文章。在它们中,我写了我在软件架构方面学到的东西,我如何看待它,以及我如何使用这些知识。如果您阅读本系列之前的文章,这篇文章的内容可能会更有意义。
在这篇文章中,我建立了关于软件架构的第一个概念,这是为了更好地理解以下文章所必需的。
没有银弹!
无论您如何理解我在《软件架构编年史》中所说的内容 ,首先请理解没有灵丹妙药,也没有“一劳永逸”的解决方案。尽可能多地了解不同的方法,了解每种方法的优缺点,它们解决的具体技术问题。
然后,在接受新挑战时,首先要了解业务和最终用户的需求。只有在清楚地理解了这些需求之后,您才能推断出应该使用哪些架构风格和模式来更好地解决手头的问题。
最后,做出您自己的选择,也许实施已知的解决方案之一,也许创建适合您特定问题的自己的设计。
一些架构风格通常被描述为适用于所有形式软件的“银弹”解决方案。然而,一个好的设计师应该选择一种与正在解决的特定问题的需求相匹配的风格。
罗伊·菲尔丁,2000 [1]
术语
在软件开发领域,使用的术语有很多歧义,因此,在继续之前,澄清我想赋予我使用的几个术语的含义很重要。
功能性
它是在应用程序中具有纯技术作用的任何代码、方法、类、类组。它与领域无关,它只是代表应用程序中的一种技术能力。例子:
- 图层
- 工厂
- 存储库
- 值对象
- 观看次数
- 视图模型
概念性的
它是反映应用程序中的域概念的任何代码、方法、类、类组。它与领域直接 相关,它代表了应用程序中的一种业务能力。例子:
- 用户
- 产品
- 库存管理
- 产品变体
- 查看
- 加售
这种分离并不意味着不能以两种方式(功能和概念)引用代码单元。例如,“Money”类可以表示域概念并被设计为值对象。如果我将它称为一个概念,我的意思是域货币概念,但如果我指的是类的功能方面,那么我的意思是 ValueObject 的技术特征(没有 ID,可能是不可变的,等等)。
包裹
任何组合在一起的类,最好遵循一些规则
模块
我使用了Software Architecture in Practice [7] 中给出的定义 ,它说模块是一个功能包,它反映了应用程序中的技术能力。它是解耦的,可以由另一个实现交换。对我来说,模块存在于低粒度级别,例如“安全模块”或“ ORM ”,但也存在于更高粒度级别,如 应用程序的客户端和服务器块。模块提供功能内聚。
组件
我还使用了实践中的 软件架构[7]中给出的定义,其中作者将组件定义为反映业务能力的概念包。理想情况下,它还与其他组件和模块分离。示例可以是“用户”、“产品”或“结帐”。
不过,要记住的最重要的事情是,理想情况下,它反映了一个有界上下文。组件提供概念内聚。
应用
我将应用程序视为面向用户的代码,即 UI,它构建在组件之上。例如,我们可以有一组组件,我们可以在这些组件上构建一个网上商店。然而,这个网上商店有一个用户界面,消费者浏览和购买产品(店面)使用它,还有另一个独立的用户界面,商店管理员使用它来管理产品、库存、支付提供商等(管理员)。这是两个独立的应用程序,构建在相同的业务组件之上。
系统
我认为系统是一组应用程序,它们以某种方式协同工作,为广泛的企业必需品提供功能,形成一个企业范围的系统,即企业应用程序。这些应用程序可能会也可能不会建立在相同的组件之上。在前面的网店示例中,系统是整个网店,包括构建在相同业务组件(店面和管理)之上的两个应用程序,还包括其他 3rd 方应用程序,如支付提供商或发货提供者。
建筑学
软件架构有很多简单的定义,我认为有它们很好,但我认为更容易理解它是什么,更重要的是,定义架构的可交付成果,它应该为项目交付什么。
软件架构 […] 是对系统进行推理所需的一组结构,它包括软件元素、它们之间的关系以及两者的属性。
克莱门茨等人,2010 [6]
这就是我对架构的推理方式:
- 所有的技术决策是 跨领域的所有功能开发,即。框架、编码标准、文档、流程……;
- 这是一组技术决策是难以改变后的项目[3] ;
- 它是系统的大图[5]:pp.2,大纲,结构,组件及其关系 [4] [6];
- 它使项目为变更做好准备 [5]:pp.30,通常只是将决策延迟到最后一个可接受的时刻 [5]:pp.32;
- 它为组件和模块的重用做准备[7]:pp.29–35;
- 它建立标准为进程轻质结果的一致性和,如编码标准,开发阶段,连续输送和展开;
- 这不是一个人的责任,而是 属于项目中不同功能团队的经验丰富的开发人员行会的责任。
如果您不熟悉公会的概念,请查看Spotify 工程文化视频:
建筑师
他是作为公会讨论和决定的架构的守护者和推动者。他是团队/部门中最有经验的开发人员之一,恰好有分析高层问题和解决方案的额外责任。在做出架构决策时,他还受益于“质量投票”。
需要注意的是,所有开发人员在某种程度上最终都会成为架构师,因为他们都需要了解架构,他们都以某种方式为架构做出贡献,最终,他们都有责任维护架构到位。
象牙塔建筑师
全能的象牙塔建筑师是建筑师的反模式,一个让他决定与建筑有关的所有问题的人。他通过不公开也不容易获得这些贡献来阉割其他利益相关者对架构的贡献。
糟糕的架构(和糟糕的代码)的味道 [8]
刚性
僵化的软件是难以更改的软件,因为一次更改将引发越来越多的更改需求。它变成了一个兔子洞:当我们认为我们快完成时,我们发现更多需要更改的代码,将我们拖入一个看不到尽头的循环中。
脆弱性
当更改时,脆弱的软件会在意想不到的、不相关的和不可预测的地方崩溃。
不动
当一个设计包含在其他系统中可能有用的部分时,它是不可移动的,但将它们与原始系统分离的工作量和风险太大了。
粘度
在粘性系统中,做错事比做正确的事容易得多。这意味着通过 hack 来实现更改比正确开发它要容易得多。
如果运行单元测试和/或编译需要大量时间,就会发生系统范围的粘性,这使得开发人员很可能绕过程序并在不运行所有自动化测试的情况下实施黑客攻击。
不必要的重复
这种情况发生在没有进行必要的抽象时,要么是因为时间不够,要么是经验不足。代码可能没有从字面上复制粘贴,但在多个地方定义了相同的业务规则。
不透明度
代码以一种不透明且令人困惑的方式编写,我们需要深入研究方法实现以了解它们的作用。
不必要的复杂性
为了避免其他 6 种异味,开发人员引入了各种抽象概念,并为未来可能发生的变化做准备。好的软件设计轻巧、灵活、易于阅读和理解,最重要的是易于更改,因此您不必尝试预测未来的所有潜在变化。
来源
[1] 2000 – Roy Fielding – 架构风格和基于网络的软件架构设计
[2] 2000 – Robert C. Martin – 设计原则和设计模式
[3] 2006 年 - Booch,在[5 pg.2]
[5] 2010 – James Coplien、Gertrud Bjornvig – 精益架构
[6] 2010 – Paul Clements、Felix Bachmann、Len Bass – 记录软件架构
[7] 2012 年 – Len Bass、Paul Clements、Rick Kazman – 实践中的软件架构
[8] 2014 – MH Jongerius – 腐烂软件的七种设计味道
[9] 2017* – 维基百科 – 软件架构