专栏名称: 逸言
文学与软件,诗意地想念。
目录
相关文章推荐
码农翻身  ·  为何 Linus ... ·  昨天  
程序猿  ·  450万虚假Star曝光,最低0.7元/个? ... ·  3 天前  
OSC开源社区  ·  DeepSeek-V3满血版在国产沐曦GPU ... ·  3 天前  
51好读  ›  专栏  ›  逸言

软件架构预述

逸言  · 公众号  · 程序员  · 2021-03-14 12:24

正文

《软件架构编年史》

作品连载


《软件架构编年史》是Herberto Graca的系列作品,我在ThoughtWorks的同事覃宇在征得作者同意与授权后,在简书陆续发布了该系列的译文。该系列回眸了软件架构的发展历程,对主流的架构模式与设计方法进行了系统的梳理和介绍,可以作为架构师的入门读物。


我见之心喜,认为这样的好文章不可错过,赶紧联系覃宇兄,得到了他的授权,允许在我的公众号「逸言」上首次发布这一高价值的系列文章。


从2021年3月11日开始,每周一、周四的上午九时,我会准时发布《软件架构编年史》的系列文章,欢迎关注和分享,借此机会感谢Herberto Graca和覃宇的无私奉献!



覃宇,(曾经的)Android开发者/ThoughtWorks技术教练//译者,热衷于探究软件开发的方方面面,从端到云,从工具到实践。喜欢通过翻译来学习和分享知识,译作有《Kotlin实战》、《领域驱动设计精粹》、《Serverless架构:无服务器应用与AWS Lambda》和《云原生安全与DevOps保障》。



这篇文章是软件架构编年史(译)的一部分,这部编年史由一系列关于软件架构的文章组成。在这一系列文章中,我将写下我对软件架构的学习和思考,以及我是如何运用这些知识的。


在这篇文章中,我将总结一些关于软件架构的最基本的概念,了解它们才能更好地理解后续的文章。


◐ 没有银弹


无论你如何理解我在软件架构编年史(译)中谈到的内容,首先要理解的是没有银弹,没有“普适性”的解决方案。尽可能地了解不同的方法,理解每一种方法的优劣,和它们解决的特定技术问题。


然后,当接受新的挑战时,先从理解业务和最终用户的需求开始。在搞清楚这些需求之后,你才能思考应该采用哪些架构风格和模式来更好地解决这些问题。


最后,自己做出选择,是实现一种已知的解决方案,还是创造适合自己的特定问题的独特设计。


有些架构风格号称是所有形式的软件的“银弹”。然而,优秀的设计这应该选择最符合解决特定问题需要的风格。——Roy Fielding, 2000 [1]


术语


在软件开发的世界中使用的术语很多都模棱两可,因此,我必须澄清一些我使用的术语的含义,然后继续。


功能性(Functional)


在应用中纯粹发挥技术作用的代码片段、方法、类、类的组合。它们和(业务)领域无关,仅仅代表应用中的一种技术能力。例如:

  • 层次(Layer)

  • 工厂(Factory)

  • 资源库(Repository)

  • 值对象(Value Object)

  • 视图(View)

  • 视图模型(ViewModel)

概念性(Conceptual)


在应用中标识一个(业务)领域概念的代码片段、方法、类、类的组合。它们和领域相关,代表应用中的一种业务能力。例如:

  • 用户

  • 产品

  • 库存管理

  • 产品变体

  • 结帐

  • 销售


这种划分并不是说一个代码单元不能同时具备两种能力(功能性和概念性)。例如,“Money”对象可以表示一个领域概念,同时也被设计成一个值对象。如果我把它当成领域概念,我指的就是领域内的金钱概念,但如果我涉及的是这个类中的功能性方面时,我指的就是值对象的技术特性(没有ID、可以是不变的等等)。


包(Package)


划分在一起的类组成的集合,理想情况下遵循一组规则进行划分。


模块(Module)


我使用Software Architecture in Practice[7]给出的定义,模块就是一个功能性包,它体现了应用中的一种技术能力。它是解耦的并且能够被其他的实现替换。我的理解是,模块即存在与较低的粒度级别,比如,“安全模块”或者“ORM”,也可以存在于像客户端和服务器这样的应用块。模块提供的是功能性内聚。


组件(Component)


我使用Software Architecture in Practice[7]给出的定义,作者将组件定义为一个代表业务能力的概念性包。理想情况下,它也是和其他组件和模块解耦的。例如“用户”、“产品”或“结帐”。


然而,最重要的是要记住,理想情况下,它代表了一个限界上下文(Bounded Context)。组件提供了概念性内聚。


应用(Application)


我将面向用户的代码即 UI 视为应用,它建立在组件之上。例如,我们可以基于一组组件构建网络商店。不管怎样,这个网络商店会提供一个(店面) UI 让用户浏览和购买商品和另一个(管理) UI 让商店管理员管理商品、库存、支付供应商,等等。这是在同样的业务组件之上构建的两个独立的应用。


系统(System)


我认为系统是一组以某种方式在一起工作,为各种企业必需品提供功能,形成一个企业范围内的系统,即企业应用。这些应用可能构建在相同或不同的组件上。在之前网络商店的例子中,系统就是作为一个整体的网络商店,包括两个基于同样业务组件构建的两个应用(店面和管理),还有其他像支付供应商或货运供应商这样的第三方应用。


架构(Architecture)


软件架构的简单定义有很多,我觉得都不错,但我认为理解它是什么很简单,而更重要的是,定义架构的产出,它应该给项目带来什么。


软件架构[…]是系统需要考虑的一组结构,它们包括软件元素和它们之间的关系,以及这些元素和关系的属性。—— Clements et al, 2010 [6]


下面是我考虑架构的方面:

  • 横跨所有特性开发的技术决策,例如,框架、代码标准、文档、流程,...;

  • 这是存在于项目中的一组很难在后期改变的技术决策 [3];

  • 它是系统的全景图[5]:pp.2,粗略的描绘,结构,组件及其关系[4] [6];

  • 它使项目做好变化的准备[5]:pp.30,常常是将决策推迟到最后允许的时刻[5]:pp.32;

  • 它让项目做好重用组件和模块的准备[7]:pp.29–35;

  • 它制定出结果的一致性标准并建立轻量的流程,比如编码规范、开发阶段、持续交付和持续部署;

  • 它不是某一个人的职责,而是由来自项目中不同特性团队的开发者组成的行会的职责。


如果你不熟悉行会的概念,可以观看下面关于Spotify 工程师文化的视频:

Spotify Engineering Culture part 1

Spotify Engineering Culture part 2


视频链接请点击文末“阅读原文”,在原文中打开视频。


架构师(Architect)


他是由行会讨论和决定的架构的发起人和守护者。他是部门/团队中经验最丰富的开发者之一,恰好承担着分析高层次问题和解决方案的额外职责。在做出架构决策时,他还拥有“质量票”(He also benefits from a “quality vote” when making an architectural decision.)。


可是,有一点值得注意,所有开发者某种程度上都是架构师,因为他们都要了解架构,他们都会议某种形式参与架构,他们都适当地承担着维护架构的职责。


象牙塔架构师(Ivory Tower Architect)


有一种架构师会做出和架构有关的所有决定,这种万能的象牙塔架构师是一种架构师的反模式。他对其他干系人对架构的贡献既不开放,也不轻易接收,而是阉割了这些贡献。


◐ 架构的坏味道 [8]


僵化(Rigidity)


如果软件难以修改是因为修改会导致更多关联修改,软件就是僵化的。它就会变成兔子洞:当我们以为修改快要完成时,突然发现还有更多的代码需要修改,把我们拉进无止尽的轮回之中。







请到「今天看啥」查看全文