分层架构最佳实践
分层架构是常用的架构设计方法,本文探讨了分层架构的概念、优势、最佳实践,并给出了在架构设计中常用的命名约定。原文: Layered Architecture in Software Architecture: Concept, Benefits, and Best Practices
Kimon Maritz @Unsplash
分层架构是软件开发中广泛使用的结构化设计方法,该方法将系统划分为不同的层,每个层都有特定用途并与其他层交互。本文将探讨分层架构的概念、优点以及实施的最佳实践。
分层架构以四个关键问题为指导:用户(who)、功能(what)、部署(where)和实施(how)。
用户(Who) —— 开发满足用户需求的产品或系统。
客户互动 —— 积极与使用产品的客户或顾客接触。设计人员和开发人员需要收集需求、召开会议并征求反馈意见,以确保最终产品符合客户的期望和目标。
确定用户角色 —— 用户角色是根据用户的职称、职责或特定标准分配给他们的预定义类别。
定义界面 —— 界面是用户与系统或产品之间的交互点。界面设计要考虑信息架构、视觉设计、交互模式和可用性原则等因素。原型设计、线框设计和用户测试通常用于完善和验证界面设计。
考虑可用性 —— 易于使用。可用性测试包括任务、场景和真实用户,以评估产品的可用性。
功能(What) —— 定义系统的功能、特点和高级模块。
系统功能 —— 定义系统能做什么以及如何与环境互动以实现目标,概述了系统的具体操作、输入、输出和限制。
业务功能 —— 代表系统的具体功能或特征,为用户提供价值。根据系统的性质和复杂程度,可以是基本功能,也可以是高级操作。通常源于系统功能,旨在满足特定的用户需求。业务功能通常作为系统需求或规格的一部分记录在案,并作为开发和测试的基础。
高级模块 —— 封装相关功能或特性,代表了可独立开发、部署和管理的内聚功能单元。
部署(Where) —— 侧重于系统的基础设施方面,涉及利用网络工具和服务、设计网络基础设施、考虑分布式网络架构、利用基础设施即代码实践以及优化网络性能。
Azure 网络架构 —— Microsoft Azure 提供各种网络工具和服务,如 Azure 虚拟网络、Azure 虚拟广域网、Azure 专用链接和 Azure 防火墙,以支持工作负载和服务。
谷歌云网络设计 —— 谷歌云提供虚拟专用云(VPC)的使用、网络安全管理以及评估全球或地区服务的应用需求。
分布式网络架构 —— 为关键任务应用提供可靠的基础,易于扩展,并能适应不断变化的应用和服务流。
网络架构物理域 —— 网络架构正在不断发展,以支持具有认知管理功能的高度自动化网络。这种转变涉及动态适应性、云资源分配、联合数据管道和开放式 API,目标是优化性能、成本和业务敏捷性。
基础设施即代码(IaC) —— 基础设施即代码(IaC)是一种 DevOps 实践,通过描述性模型管理基础设施,涵盖网络、计算服务、数据库、存储和连接拓扑。实施 IaC 有很多好处,如增强部署信心、管理多个环境以及更好的了解基础架构状态。
实施(How) —— 实施细节,包括架构模式和层与层之间的通信机制。
架构信息传递模式 —— 用于促进应用程序不同部分或不同系统之间的信息交换,可分为信息交换架构和路由。
信息交换架构 —— 一个发送方和多个接收方之间采用不同的方法或模式传输信息。
Pub-Sub(发布-订阅) —— 信息由一个发布者根据感兴趣的主题发送给多个接收者(订阅者)。发布者发布特定主题的信息,对这些主题感兴趣的订阅者会收到这些信息,而发送者并不知道具体的接收者是谁。
Fanout —— 向所有订阅者广播消息,不考虑主题。在这种模式下,发送者发送信息,信息会同时传递给所有连接的订阅者。
单向流 —— 信息流单向流动,通常是从发送方到接收方,不需要任何确认或回复。这是一种单向通信,发送方持续向接收方发送信息流,而不期待接收方回复。
双向流 —— 信息在发送方和接收方之间双向流动。
路由 —— 确定系统中发送方和接收方之间如何传递信息。
Unicast(单播) —— 信息从单个发送者发送到特定接收者。
Broadcast(广播) —— 向所有连接的接收器广播信息。
Multicast(组播) —— 向一组特定的接收者发送信息。
Anycast(任播) —— 信息从一组潜在接收者中发送到最近的可用接收者。
架构层 —— 组织分布式系统的组件。
显示/用户界面层 —— 处理用户交互、向用户显示信息并捕捉用户输入。
应用层 —— 包含系统的业务逻辑,并协调表现层和领域层之间的数据流,实施业务规则和流程,这些规则和流程定义了系统如何运行以及如何与用户交互。
业务/领域层 —— 封装系统核心业务逻辑和规则,代表业务领域的概念模型,并包含根据业务需求定义系统运行方式的逻辑。该层侧重于特定业务的操作和规则。
持久层/数据访问层 —— 管理数据库或其他数据源的数据存储和检索,提供与底层数据存储系统交互的必要机制,如执行 CRUD (创建、读取、更新、删除)操作和数据查询。
数据库层 —— 代表实际的数据存储和管理系统,如数据库服务器,处理数据的物理存储。
通过提出并回答这四个问题,架构师可以全面了解系统,确保在设计过程中考虑到所有相关方面,有助于明确界定不同层或组件之间的界限,并厘清责任。
关键最佳实践
波动性递减原则(The Principle of Diminishing Volatility)
根据系统层的不稳定性或变化的可能性来组织系统层。
根据这一原则,可变性或可改变性应随着设计良好的系统层数的减少而降低。
客户端层被认为是最不稳定的,因为直接与用户交互,会根据用户的要求频繁更改。
应用层的变化基于特定的使用场景,相对来说比客户端层更稳定。
引擎层甚至比应用层更稳定,因为变化通常涉及基本的业务行为或规则。
预计数据访问层的修改最少,因为处理的是原子操作,如添加、删除、修改和查询数据,这些操作不会经常变化。
增量构建原则(Incremental Construction Principle)
开发过程分为若干阶段或迭代。增量构建原则主张逐步构建系统,在每次迭代中增加新的特性和功能,而不是试图在前期完成整个系统的设计和实施。
初步设计和实施的重点是创建一个满足核心需求的系统基本版本,然后对该版本进行测试、评估和审查,以收集反馈意见并确定需要改进的地方。根据反馈和评估结果,进行后续迭代,为系统添加新的或增强功能。
增量构建原则通常与 Scrum 或 Kanban 等敏捷方法有关,在这些方法中,工作被划分为较小的增量或用户故事,可在短时间内(通常为几周)完成。每次迭代都建立在前一次迭代的基础上,逐步扩展系统功能。
命名约定
服务(相当于类)的命名约定,推荐几条可以提高软件设计清晰度和交流性的准则。
服务名称应遵循 Pascal 命名法,也称为"大写驼峰式",即每个单词的第一个字母大写,不使用空格、连字符或下划线。例如,UserService、PaymentManager、OrderEngine 和 ResourceAccessController。
服务名应至少由两部分组成,以便更具体的表达服务目的。
服务名的后缀应指明服务类型,如管理器(Manager)、引擎(Engine)、接入(Access)或资源访问(ResourceAccess)。
服务名的前缀因服务类型而异:
对于管理器(Manager)类型,前缀应是名词,包含一个可改变的用例。
对于引擎(Engine)类型,前缀应为定义封装事件的名词。
对于资源访问(ResourceAccess)类型,前缀应指明访问的数据资源。
动名词(以"ing"结尾的动词)可用作服务名的前缀,但仅限于引擎类型。动名词应代表与协调和访问可变性有关的功能分解。
Get 和 Put 等原子操作动词不应作为服务前缀使用,但可用作数据访问层的接口名称。
参考资料
Programming Naming Conventions - Camel, Snake, Kebab, and Pascal Case Explained
Snake Case VS Camel Case VS Pascal Case VS Kebab Case - What's the Difference Between Casings?
Pascal case vs. camel case: What's the difference? | TheServerSide
What Is Pascal Case? Definition & Alternatives (with Examples)
Architecture styles - Azure Application Architecture Guide
你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
版权声明: 本文为 InfoQ 作者【俞凡】的原创文章。
原文链接:【http://xie.infoq.cn/article/9f4c3e9ac779835d89464d5ac】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论