C#9 和 .NET5 软件架构(一)

原文:zh.annas-archive.org/md5/83D8F5A1D11ACA866E980121BEEF9AAA

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

本书涵盖了现代基于云和分布式软件架构中涉及的最常见设计模式和框架。它通过提供实际的现实场景,讨论了何时以及如何使用每种模式。本书还介绍了 DevOps、微服务、Kubernetes、持续集成和云计算等技术和流程,以便您可以开发并交付给客户最佳的软件解决方案。

本书将帮助您了解客户想要的产品。它将指导您在开发过程中解决可能遇到的最大问题。它还涵盖了在云环境中管理应用程序时需要遵循的注意事项,以及您需要遵循的做和不做。您将了解不同的架构方法,如分层架构、面向服务的架构、微服务、单页应用程序和云架构,并了解如何将它们应用于特定的业务需求。

最后,您将使用 Azure 在远程环境或云中部署代码。本书中的所有概念都将通过实际的实际用例来解释,其中设计原则在创建安全和健壮的应用程序时起到关键作用。通过本书,您将能够开发和交付高度可扩展和安全的企业级应用程序,满足最终客户的业务需求。

值得一提的是,本书不仅涵盖了软件架构师在开发 C#和.NET Core 解决方案时应遵循的最佳实践,还讨论了我们需要掌握的所有环境,以便根据最新趋势开发软件产品。

这第二版在代码和解释方面得到了改进,并且根据 C# 9 和.Net 5 提供的新机会进行了调整。我们添加了去年出现的所有新框架和技术,如 gRPC 和 Blazor,并在专门的章节中更详细地描述了 Kubernetes。

这本书是为谁写的

这本书适用于任何希望提高与 C#相关的 Azure 解决方案知识的软件架构师。它还适用于渴望成为架构师或希望使用.NET 堆栈构建企业应用程序的工程师和高级开发人员。需要具备 C#和.NET 的经验。

本书涵盖了什么

第一章《理解软件架构的重要性》解释了软件架构的基础知识。本章将为您提供正确的思维方式来面对客户需求,然后选择合适的工具、模式和框架。

第二章《非功能需求》指导您在应用程序开发的重要阶段,即收集和考虑应用程序必须满足的所有约束和目标,如可伸缩性、可用性、弹性、性能、多线程、互操作性和安全性。

第三章《使用 Azure DevOps 记录需求》描述了记录需求、错误和应用程序其他信息的技术。虽然大部分概念是通用的,但本章重点介绍了 Azure DevOps 和 GitHub 的使用。

第四章《选择最佳基于云的解决方案》为您提供了云中可用工具和资源以及 Microsoft Azure 的广泛概述。在这里,您将学习如何搜索合适的工具和资源,以及如何配置它们来满足您的需求。

第五章,将微服务架构应用于企业应用程序,提供了微服务和 Docker 容器的广泛概述。在这里,您将了解基于微服务的架构如何利用云提供的所有机会,并了解如何使用微服务在云中实现灵活性、高吞吐量和可靠性。您将学习如何使用容器和 Docker 在架构中混合不同的技术,以及使您的软件平台独立。

第六章,Azure Service Fabric,描述了微软特定的微服务编排器 Azure Service Fabric。在这里,您将实现一个简单的基于微服务的应用程序。

第七章,Azure Kubernetes Service,描述了 Kubernetes 的 Azure 实现,它是微服务编排的事实标准。在这里,您将在 Kubernetes 上打包和部署微服务应用程序。

第八章,使用 C#与数据交互-Entity Framework Core,详细解释了您的应用程序如何借助对象关系映射(ORM)以及特别是 Entity Framework Core 5.0 与各种存储引擎交互。

第九章,如何在云中选择数据存储,描述了云中和 Microsoft Azure 中可用的主要存储引擎。在这里,您将学习如何选择最佳的存储引擎以实现所需的读/写并行性以及如何配置它们。

第十章,使用 Azure Functions,描述了计算的无服务器模型以及如何在 Azure 云中使用它。在这里,您将学习如何在需要运行某些计算时分配云资源,从而仅支付实际计算时间。

第十一章,设计模式和.NET 5 实现,描述了常见的软件模式,并提供了.NET 5 的示例。在这里,您将了解模式的重要性以及使用它们的最佳实践。

第十二章,理解软件解决方案中的不同领域,描述了现代领域驱动设计软件生产方法,如何使用它来应对需要多个知识领域的复杂应用程序,以及如何利用基于云和微服务的架构。

第十三章,使用 C# 9 实现代码重用,描述了在.NET 5 应用程序中最大化代码重用的模式和最佳实践,以及代码重构的重要性。

第十四章,使用.NET Core 应用服务导向架构,描述了服务导向架构,它使您能够将应用程序的功能公开为 Web 或私有网络上的端点,以便用户可以通过各种类型的客户端与它们交互。在这里,您将学习如何使用 ASP.NET Core 和 gRPC 实现面向服务的架构端点,并如何使用现有的 OpenAPI 包自行记录它们。

第十五章,介绍 ASP.NET Core MVC,详细描述了 ASP.NET Core 框架。在这里,您将学习如何基于模型-视图-控制器(MVC)模式实现 Web 应用程序,以及如何根据领域驱动设计的规定组织它们,该设计在第十二章“理解软件解决方案中的不同领域”中有描述。

第十六章,Blazor WebAssembly,描述了利用 WebAssembly 在用户浏览器中运行.NET 的新 Blazor 框架。在这里,您将学习如何使用 C#实现单页应用程序。

第十七章,C# 9 编码最佳实践,描述了在使用 C# 9 开发.NET 5 应用程序时应遵循的最佳实践。

第十八章,使用单元测试用例和 TDD 测试您的代码,描述了如何测试您的应用程序。在这里,您将学习如何使用 xUnit 测试.NET Core 应用程序,以及如何轻松地开发和维护满足您规范的代码,借助测试驱动设计的帮助。

第十九章使用工具编写更好的代码,描述了评估软件质量的度量标准,以及如何借助 Visual Studio 中包含的所有工具来衡量它们。

第二十章理解 DevOps 原则,描述了 DevOps 软件开发和维护方法论的基础。在这里,您将学习如何组织应用程序的持续集成/持续交付周期。它还描述了如何自动化整个部署过程,从在源代码库中创建新版本,经过各种测试和批准步骤,到在实际生产环境中部署应用程序的最终部署。在这里,您将学习如何使用 Azure Pipelines 和 GitHub Actions 来自动化整个部署过程。

第二十一章应用 CI 场景的挑战,补充了对 DevOps 的描述,介绍了持续集成场景。

第二十二章功能测试的自动化,专门讲述了自动功能测试 - 也就是自动验证整个应用程序版本是否符合约定的功能规格的测试。在这里,您将学习如何使用自动化工具模拟用户操作,以及如何与 xUnit 一起使用这些工具编写功能测试。

充分利用本书

  • 本书涵盖了许多主题。请将其视为您可能需要在不同情况下多次查看的指南。

  • 不要忘记安装 Visual Studio Community 2019 或更高版本。

  • 确保您理解 C# .NET 原则。

下载示例代码文件

该书的代码包托管在 GitHub 上,网址为github.com/PacktPublishing/Software-Architecture-with-C-9-and-.NET-5。我们还有其他书籍和视频的代码包,可在github.com/PacktPublishing/上找到。请查看!

下载彩色图片

我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图片。您可以在这里下载:static.packt-cdn.com/downloads/9781800566040_ColorImages.pdf

使用的约定

本书中使用了许多文本约定。

CodeInText:表示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄。例如:“当您调用sb.ToString()获取最终结果时,它们只会在最终字符串中复制一次。”

代码块设置如下:

[Fact]
public void Test1()
{
    var myInstanceToTest = new ClassToTest();
    Assert.Equal(5, myInstanceToTest.MethodToTest(1));
} 

任何命令行输入或输出都是这样写的:

kubectl create -f myClusterConfiguration.yaml 

粗体:表示新术语、重要单词或屏幕上看到的单词,例如菜单或对话框中的单词,也会在文本中出现。例如:“在解决方案资源管理器中,右键单击即可选择发布…”。

警告或重要提示是这样的。

提示和技巧是这样的。

第一章:理解软件架构的重要性

软件架构是当今软件行业中讨论最多的话题之一,它的重要性将来肯定会增长。我们建造的解决方案越复杂、奇妙,我们就越需要出色的软件架构来维护它们。但是,新功能被添加到这��软件解决方案的速度不断增加,新的架构机会也不断出现。这就是你决定阅读这本书的原因;也是我们决定写第二版的原因。

写这个重要的话题并不是一件简单的任务,因为它提供了许多替代技术和解决方案。本书的主要目标不是建立一个详尽而永无止境的可用技术和解决方案清单,而是展示各种技术家族是如何相关的,以及它们如何在实践中影响可维护和可持续解决方案的构建。

我们需要将注意力集中在创建实际、有效的企业解决方案上的需求不断增加;用户总是需要他们的应用程序中的更多新功能。此外,由于市场变化迅速,需要频繁交付应用程序版本的需求增加了我们对复杂软件架构和开发技术的义务。

本章将涵盖以下主题:

  • 对软件架构的理解

  • 一些可能对软件架构师有帮助的软件开发过程模型

  • 收集设计高质量软件所需的正确信息的过程

  • 帮助开发过程的设计技术

  • 需求影响系统结果的情况

  • 本书案例研究的介绍

本书的案例研究将带你了解为名为World Wild Travel ClubWWTravelClub)的旅行社创建软件架构的过程。这个案例研究的目的是帮助你理解每一章节中解释的理论,并提供一个如何使用 Azure、Azure DevOps、C# 9、.NET 5、ASP.NET 和其他本书中介绍的技术开发企业应用的示例。

在本章结束时,你将能够准确理解软件架构的使命。你还将学习 Azure 是什么,以及如何在平台上创建你的账户。你还将获得关于软件流程、模型和其他技术的概述,这些将使你能够管理你的团队。

什么是软件架构?

如果你今天在阅读这本书,你应该感谢那些决定将软件开发视为工程领域的计算机科学家。这发生在上个世纪,更具体地说,是在六十年代末,当他们提出我们开发软件的方式很像我们建造建筑物的方式时。这就是为什么我们有了软件架构这个名字。就像建筑师设计建筑并监督其建造一样,软件架构师的主要目标是确保软件应用程序的良好实施;而良好的实施需要设计一个出色的解决方案。

在专业开发项目中,你必须做以下几件事情:

  • 定义解决方案的客户需求

  • 设计一个出色的解决方案来满足这些要求

  • 实施设计好的解决方案

  • 与客户验证解决方案

  • 在工作环境中交付解决方案

软件工程将这些活动定义为软件开发生命周期。所有的理论软件开发过程模型(瀑布、螺旋、增量、敏捷等)都与这个周期有某种关联。无论你使用哪种模型,如果你在项目期间不使用前面提到的基本任务,你将无法交付可接受的软件解决方案。

设计出色解决方案的主要点是本书的目的。您必须了解伟大的现实世界解决方案伴随着一些基本的约束:

  • 解决方案需要满足用户需求

  • 解决方案需要按时交付

  • 解决方案需要符合项目预算

  • 解决方案需要提供良好的质量

  • 解决方案需要保证安全和有效的未来发展

出色的解决方案需要可持续发展,您必须了解没有伟大的软件架构就没有可持续的软件。如今,出色的软件架构取决于现代工具和现代环境,以完美地满足用户的需求。

因此,本书将使用微软提供的一些优秀工具。该公司已宣布.NET 5 作为软件开发的统一平台,这为我们创造了一个巨大的机会来创建出色的解决方案。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.1:.NET 5 平台

.NET 5 与 C# 9 一起发布。考虑到.NET 面向如此多的平台和设备,C#现在是世界上使用最多的编程语言之一,并在不同的操作系统和环境中运行在小型设备上到大型服务器上。

本书还将使用Azure,这是微软的云平台,在那里您将找到公司提供的所有组件,用于构建先进的软件架构解决方案。其中之一是Azure DevOps,这是一个应用程序生命周期管理环境,您可以在其中使用最新的软件开发方法构建解决方案。

作为软件架构师意味着理解上述技术,以及其他许多技术。本书将指导您进行一次旅程,在这次旅程中,作为团队中的软件架构师,您将使用所列工具提供最佳解决方案。让我们通过创建您的 Azure 账户开始这次旅程。

创建 Azure 账户

Microsoft Azure是目前市场上最好的云解决方案之一。重要的是要知道,在 Azure 内部,我们将找到一系列组件,可以帮助我们定义 21 世纪解决方案的架构。

如果您想了解 Microsoft Azure 拥有的各种组件,只需查看 Alexey Polkovnikov 开发的这个令人难以置信的网站:azurecharts.com/

本小节将指导您创建 Azure 账户。如果您已经有一个,可以跳过这部分。

使用网站地址azure.microsoft.com开始访问 Azure。在那里,您将找到开始订阅所需的信息。通常会自动设置为您的母语翻译。

  1. 一旦您访问了这个门户,就可以注册。如果您以前从未这样做过,可以选择免费开始,这样您就可以在不花钱的情况下使用一些 Azure 功能。请查看azure.microsoft.com/en-us/free/上的免费计划选项。

  2. 创建免费账户的过程非常简单,您将通过一个表格进行引导,该表格要求您拥有Microsoft 账户GitHub 账户

  3. 在过程中,您还将被要求提供信用卡号,以验证您的身份并防止垃圾邮件和机器人。但是,除非您升级账户,否则不会收取费用。

  4. 要完成任务,您需要接受订阅协议、优惠详情和隐私声明。

一旦您填写完表格,您就可以访问 Azure 门户。正如您在下面的截图中所看到的,面板显示了一个您可以自定义的仪表板,以及左侧的菜单,您可以在其中设置您将在解决方案中使用的 Azure 组件。在本书中,我们将回到这个截图来设置组件,以帮助我们创建现代软件架构。要找到下一页,只需选择左侧菜单图标(汉堡菜单)并单击所有服务

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.2:Azure 门户

一旦您创建了 Azure 账户,您就可以了解软件架构师如何引导团队利用 Azure 提供的所有机会来开发软件。然而,重要的是要记住,软件架构师需要超越技术,因为这个角色是由人来扮演的,他们被期望定义软件的交付方式。

如今,软件架构师不仅要设计软件的基础,还要确定整个软件开发和部署过程的进行方式。下一个主题将涵盖全球范围内使用最广泛的软件开发范式之一。我们将首先描述社区所称的传统软件工程。之后,我们将介绍改变了我们如今构建软件方式的敏捷模型。

软件开发流程模型

作为软件架构师,了解当前大多数企业中使用的一些常见开发流程是很重要的。软件开发流程定义了团队中的人员如何生产和交付软件。一般来说,这个流程与一个被称为软件开发流程模型的软件工程理论相关。自软件开发被定义为工程过程以来,已经提出了许多用于开发软件的过程模型。让我们回顾一下传统的软件模型,然后再看看目前常见的敏捷模型。

审查传统软件开发过程模型

软件工程理论中引入的一些模型已经被认为是传统的和相当过时的。本书并不旨在涵盖所有这些模型,但在这里,我们将简要解释一些仍然在一些公司中使用的模型-瀑布和增量模型。

了解瀑布模型原则

这个主题在 2020 年的软件架构书中可能看起来有些奇怪,但是是的,您可能仍然会发现一些公司仍然将最传统的软件过程模型作为软件开发的指导方针。这个过程按顺序执行所有基本任务。任何软件开发项目都包括以下步骤:

  • 需求,创建产品需求文档,这是软件开发的基础

  • 设计,根据需求开发软件架构

  • 实施,编写软件

  • 验证,应用测试

  • 维护,在交付后再次开始循环

让我们看一下这个图表的表示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.3:瀑布式开发周期(https://en.wikipedia.org/wiki/Waterfall_model)

通常,瀑布模型的使用会导致与软件功能版本交付延迟相关的问题,以及由于期望与最终交付的产品之间的差距而导致用户不满。此外,根据我的经验,只有在开发完成后才开始应用测试总是让人感到非常有压力。

分析增量模型

增量开发是一种试图克服瀑布模型最大问题的方法:用户只能在项目结束时测试解决方案。这种模型的理念是尽早给用户与解决方案互动的机会,以便他们能够提供有用的反馈,这将有助于软件的开发。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.4:增量开发周期(https://en.wikipedia.org/wiki/Incremental_build_model)

在前面图片中介绍的增量模型被引入作为瀑布方法的一种替代方案。该模型的理念是为每个增量运行一组与软件开发相关的实践(沟通规划建模构建部署)。尽管它减轻了与客户沟通不足相关的问题,但对于大型项目来说,较少的增量仍然是一个问题,因为增量仍然太长。

当增量方法被大规模使用时——主要是在上个世纪末——由于需要大量文档,报告了许多与项目官僚主义相关的问题。这种笨重的情况导致了软件开发行业中一个非常重要的运动的兴起——敏捷

理解敏捷软件开发过程模型

在本世纪初,开发软件被认为是工程中最混乱的活动之一。软件项目失败的比例非常高,这一事实证明了需要一种不同的方法来处理软件开发项目所需的灵活性。

2001 年,敏捷宣言被引入世界,从那时起,各种敏捷过程模型被提出。其中一些一直存活至今,并且仍然非常普遍。

敏捷宣言已被翻译成 60 多种语言。请查看其链接agilemanifesto.org/

敏捷模型和传统模型之间最大的区别之一是开发人员与客户互动的方式。所有敏捷模型传达的信息是,你把软件更快地交付给用户,就越好。这个想法有时会让软件开发人员感到困惑,他们会把这理解为——让我们试着编码,然后就这样了,伙计们!

然而,敏捷宣言中有一个重要观察,许多人在开始使用敏捷时没有读到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.5:敏捷软件开发宣言

软件架构师始终需要记住这一点。敏捷过程并不意味着缺乏纪律。此外,当你使用敏捷过程时,你会很快意识到,没有纪律就无法开发出优秀的软件。另一方面,作为软件架构师,你需要明白意味着灵活性。一个拒绝灵活的软件项目往往会随着时间的推移而毁掉自己。

敏捷背后的 12 个原则是这种灵活方法的基础:

  1. 持续交付有价值的软件以满足客户的需求必须是任何开发人员的最高优先级。

  2. 需求的变化需要被理解为使客户更有竞争力的机会。

  3. 使用每周的时间表来交付软件。

  4. 软件团队必须由商业人员和开发人员组成。

  5. 软件团队需要被信任,并且应该有正确的环境来完成项目。

  6. 与软件团队沟通的最佳方式是面对面。

  7. 你可以理解最伟大的软件团队成就是当软件真正在生产中运行。

  8. 敏捷在可持续发展时是有效的。

  9. 你投入的技术和良好设计越多,你就越敏捷。

  10. 简单至关重要。

  11. 团队自组织程度越高,交付的质量就越好。

  12. 软件团队倾向于不断改进他们的行为,分析和调整他们的流程。

即使在敏捷宣言发布 20 年后,其重要性和与软件团队当前需求的联系仍然保持完好。当然,有许多公司不接受这种方法,但作为软件架构师,您应该将其视为改变实践和与您一起工作的团队发展的机会。

有许多技术和模型被提出给敏捷方法的软件社区。接下来的子主题将讨论精益软件开发、极限编程和 Scrum,以便您作为软件架构师决定您可能使用哪些来改进软件交付。

精益软件开发

在敏捷宣言之后,精益软件开发方法被引入社区,作为汽车工程中一个著名运动——丰田汽车制造模式的一种适应。全球精益制造方法即使资源有限也能提供高质量。

Mary 和 Tom Poppendieck 列出了软件开发的七个精益原则,与敏捷和本世纪许多公司的方法真正相关。我在这里列出了它们:

  1. 消除浪费:您可能认为浪费是任何可能干扰实际客户需求交付的事物。

  2. 内建质量:一个希望保证质量的组织需要在从一开始构建代码的过程中促进质量,而不仅仅是在代码被测试后考虑它。

  3. 创造知识:取得卓越成就的公司通常通过有纪律的实验、记录和确保知识在整个组织中传播来生成新知识。

  4. 推迟承诺:在造成项目损害之前,计划决策到最后一刻。

  5. 快速交付:软件交付得越快,浪费就会越少。竞争频率高的公司比竞争对手具有明显优势。

  6. 尊重人:给团队合理的目标,以及指导他们自组织日常工作的计划,是尊重你一起工作的人的问题。

  7. 优化整体:精益公司改进整个价值循环;从接收新需求的时刻到软件完成交付的时刻。

精益原则导致团队或公司的方法改进客户真正需要的功能的质量。它还减少了在软件交付给客户时不会使用的功能上花费的时间。在精益中,决定对客户重要的功能指导团队交付重要的软件,这正是敏捷宣言在软件团队中意图促进的内容。

极限编程

就在敏捷宣言发布之前,一些设计该文件的参与者,特别是肯特·贝克,向世界展示了开发软件的极限编程XP方法论

XP 基于简单性、沟通、反馈、尊重和勇气的价值观。根据贝克在他关于这个主题的第二本书中的说法,它后来被认为是编程中的社会变革。它确实促进了开发流程的巨大变革。

XP 指出每个团队都应该有简单性,只做被要求的事情,每天面对面交流,早期演示软件以获得反馈,尊重团队每个成员的专业知识,并有勇气就进展和估计告诉真相,将团队的工作视为一个整体。

XP 还提供了一套规则。如果团队发现某些规则不起作用,可以进行更改,但始终保持方法论的价值观是很重要的。

这些规则分为规划、管理、设计、编码和测试。唐·韦尔斯在网站www.extremeprogramming.org/上绘制了 XP。尽管这种方法论的一些想法受到许多公司和专家的强烈批评,但今天仍有许多好的实践:

  • 使用用户故事编写软件需求:用户故事被认为是描述用户需求的敏捷方法,以及用于保证正确实施的验收测试。

  • 将软件分成迭代并交付小版本:在瀑布模型之后,所有方法论都支持软件开发的迭代实践。更快地交付版本降低了未能实现客户期望的风险。

  • 避免加班并保证可持续速度:尽管这可能是软件架构师所面临的最艰巨的任务之一,加班工作表明流程中有些地方出了问题。

  • 保持简单:在开发解决方案时,很常见地试图预测客户想要的功能。这种方法增加了开发的复杂性和解决方案上市的时间。采用不同的方法会导致高成本,可能在你正在开发的系统中使用的功能水平较低。

  • 重构:持续重构代码的方法很好,因为它能够使软件不断发展,并保证由于你用来开发的平台的正常技术变化而真正需要的设计改进。

  • 始终保持客户可用:如果你遵循 XP 的规则,你应该在团队内有一个专家客户。这当然是难以获得和处理的,但这种方法的主要思想是确保客户参与到开发的所有部分中。另外,让客户接近你的团队意味着他们了解团队所面临的困难和专业知识,从而增加了双方之间的信任。

  • 持续集成:这种实践是当前 DevOps 方法的基础之一。你个人的代码库和主要代码库之间的差异越小,越好。

  • 先编写单元测试代码:单元测试是一种方法,你可以为测试项目的单个单元(类/方法)编写特定的代码。这在一种当前的开发方法论中被称为测试驱动开发TDD)。这里的主要目标是确保每个业务规则都有自己的单元测试用例。

  • 编写的代码必须符合约定的标准:确定编码标准的需要与这样一个想法相关联,即无论你有哪个开发人员在项目的特定部分工作,代码必须编写得让他们中的任何一个都能理解。

  • 配对编程:配对编程是另一种在软件项目的每一分钟都难以实现的方法,但这种技术本身——一个程序员编码,另一个积极观察并提供评论、批评和建议——在关键场景中是有用的。

  • 验收测试:采用验收测试来满足用户故事是确保新发布版本的软件不会损害其当前需求的好方法。更好的选择是将这些验收测试自动化。

值得一提的是,这些规则中的许多今天被认为是不同软件开发方法论中的重要实践,包括 DevOps 和 Scrum。我们将在本书的后面讨论 DevOps,在第二十章理解 DevOps 原则。现在让我们进入 Scrum 模型。

进入 Scrum 模型

Scrum 是用于管理软件开发项目的敏捷模型。该模型源自精益原则,是当今广泛使用的软件开发方法之一。

请查看此链接以获取有关 Scrum 框架的更多信息:www.scrum.org/

正如你在下图中所看到的,Scrum 的基础是你有一个灵活的用户需求待办事项(产品待办事项),需要在每个敏捷周期(称为冲刺)中讨论。冲刺目标冲刺待办事项)由 Scrum 团队确定,由产品负责人、Scrum 大师和开发团队组成。产品负责人负责确定在该冲刺中将交付什么。在冲刺期间,这个人将帮助团队开发所需的功能。在 Scrum 过程中领导团队的人被称为Scrum 大师。所有的会议和流程都由这个人进行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.6:Scrum 过程

重要的是要注意,Scrum 过程不讨论软件需要如何实现,也不讨论将完成哪些活动。再次强调,你必须记住软件开发的基础,这是本章开头讨论的;这意味着 Scrum 需要与一个过程模型一起实施。DevOps 是一种可能帮助你将软件开发过程模型与 Scrum 一起使用的方法之一。查看第二十章了解 DevOps 原则,以更好地理解它。

收集正确的信息来设计高质量的软件

太棒了!你刚刚开始了一个软件开发项目。现在,是时候利用你所有的知识来交付你能做到的最好的软件了。你的第一个问题可能是 - 我该如何开始? 好吧,作为软件架构师,你将成为回答这个问题的人。你可以肯定,你的答案将随着你领导的每个软件项目的发展而不断发展。

定义软件开发过程是第一个任务。这通常是在项目规划过程中完成的,或者可能在项目开始之前完成。

另一个非常重要的任务是收集软件需求。无论你决定使用哪种软件开发过程,收集真实的用户需求都是一个困难且持续的工作的一部分。当然,有一些技术可以帮助你,你可以肯定,收集需求将帮助你定义软件架构的重要方面。

这两个任务被大多数软件开发专家认为是开发项目旅程结束时成功的关键。作为软件架构师,你需要使它们能够尽可能避免尽可能多的问题,同时指导你的团队。

了解需求收集过程

有许多不同的方式来表示需求。最传统的方法是在分析开始之前你必须写出完美的规范。敏捷方法建议,你需要在准备开始开发周期时立即编写用户故事。

记住:你不仅为用户编写需求;你也为你和你的团队编写需求。

事实上,无论你决定在你的项目中采用什么方法,你都必须遵循一些步骤来收集需求。这就是我们所说的需求工程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.7:需求工程过程

在这个过程中,你需要确保解决方案是可行的。在某些情况下,可行性分析也是项目规划过程的一部分,当你开始需求获取时,你已经完成了可行性报告。因此,让我们检查这个过程的其他部分,这将为软件架构提供许多重要信息。

检测确切的用户需求

有很多方法可以检测特定情景下用户的确切需求。这个过程被称为引出。一般来说,这可以通过帮助您理解我们所说的用户需求的技术来完成。在这里,您有一个常见技术清单:

  • 想象力的力量:如果您是在您提供解决方案的领域的专家,您可以使用自己的想象力来发现新的用户需求。可以一起进行头脑风暴,这样一群专家就可以定义用户需求。

  • 问卷调查:这个工具对于检测常见和重要的需求非常有用,比如用户数量和类型,系统的高峰使用情况,以及常用的操作系统OS)和 Web 浏览器。

  • 面试:与用户进行面试可以帮助您作为架构师发现用户需求,也许问卷调查和您的想象力无法覆盖的需求。

  • 观察:了解用户的日常工作方式最好的方法就是和他们一起度过一天。

一旦您应用了这些技术中的一个或多个,您将获得关于用户需求的重要和有价值的信息。

记住:您可以在任何需要收集需求的情况下使用这些技术,无论是为整个系统还是为单个故事。

在那时,您将能够开始分析这些用户需求,并检测用户和系统需求。让我们在下一节看看如何做到这一点。

分析需求

当您发现用户需求时,就是开始分析需求的时候了。为此,您可以使用以下技术:

  • 原型制作:原型制作非常好,可以澄清和实现系统需求。今天,我们有许多工具可以帮助您模拟界面。一个很好的开源工具是Pencil Project。您可以在pencil.evolus.vn/找到更多信息。

  • 用例:如果需要详细的文档,统一建模语言UML)用例模型是一个选择。该模型由详细规范和图表组成。ArgoUML是另一个可以帮助您的开源工具。您可以在图 1.8中看到创建的模型:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1.8:用例图示例

当您分析系统的需求时,您将能够准确澄清用户的需求。当您不确定需要解决的真正问题时,这是很有帮助的,比起直接开始编程系统并希望一切顺利,这要好得多。在需求分析上投入的时间是以后编写更好代码的时间。

编写规范

完成分析后,将其记录为规范很重要。规范文档可以使用传统需求或用户故事来编写,在敏捷项目中通常使用。

需求规范代表用户和团队之间的技术合同。这份文件需要遵循一些基本规则:

  • 所有利益相关方都需要确切理解技术合同中的内容,即使他们不是技术人员。

  • 文件需要清晰明了。

  • 您需要对每个需求进行分类。

  • 使用简单的将来时代表每个需求:

  • 不好的例子:普通用户注册自己。

  • 好的例子:普通用户应该注册自己。

  • 需要避免模棱两可和争议。

一些额外的信息可以帮助团队了解他们将要处理的项目的背景。以下是一些关于如何添加有用信息的提示:

  • 编写一个引言章节,以便全面了解解决方案。

  • 创建术语表以便更容易理解。

  • 描述解决方案将覆盖的用户类型。

  • 编写功能和非功能需求:

  • 功能需求相当容易理解,因为它们准确描述了软件将要做的事情。另一方面,非功能性需求确定了与软件相关的限制,这意味着可扩展性、健壮性、安全性和性能。我们将在下一节中涵盖这些方面。

  • 附上可以帮助用户理解规则的文件。

如果您决定编写用户故事,一个好的建议是按照以下方式编写短句,代表系统中每个用户的每个时刻:

As <user>, I want <feature>, so that <reason> 

这种方法将准确解释为什么要实现该功能。这也是帮助您分析最关键的故事,并优先考虑项目成功的好工具。它们也可以很好地通知应该构建的自动验收测试。

理解可扩展性、健壮性、安全性和性能的原则

检测需求是一个让您了解您将要开发的软件的任务。然而,作为软件架构师,您必须关注不仅仅是该系统的功能需求。理解非功能性需求很重要,也是软件架构师最早的活动之一。

我们将在第二章 非功能性需求中更详细地讨论这一点,但在这一点上,重要的是要知道可扩展性、健壮性、安全性和性能的原则需要应用于需求收集过程。让我们来看看每个概念:

  • 可扩展性:作为软件开发人员,全球化为您提供了让您的解决方案在全球范围内运行的机会。这很棒,但作为软件架构师,您需要设计一个能够提供这种可能性的解决方案。可扩展性是应用程序在必要时增加其处理能力的可能性,这是由于正在消耗的资源数量。

  • 健壮性:无论您的应用程序有多可扩展,如果它无法保证稳定和始终可用的解决方案,您将无法获得任何平静。健壮性对于关键解决方案非常重要,因为您没有机会随时进行维护,因为应用程序解决的问题类型。在许多行业中,软件不能停止,许多例行程序在没有人员可用时运行(过夜、假期等)。设计一个健壮的解决方案将使您在软件运行良好时获得自由。

  • 安全性:这是另一个非常重要的领域,在需求阶段之后需要讨论。每个人都担心安全性,并且世界各地都有不同的法律与之相关。作为软件架构师,您必须了解安全性需要通过设计提供。这是应对安全社区目前正在讨论的所有需求的唯一途径。

  • 性能:了解您将要开发的系统的过程可能会给您一个很好的想法,您需要做些什么才能从系统中获得所需的性能。这个话题需要与用户讨论,以确定在开发阶段将面临的大部分瓶颈。

值得一提的是,所有这些概念都是世界所需要的新一代解决方案的要求。优秀软件与令人难以置信的软件之间的区别在于满足项目要求所做的工作量。

审查规范

一旦编写了规范,就是时候与利益相关者确认他们是否同意了。这可以在审查会议中完成,也可以使用协作工具在线完成。

这时,您将展示您收集到的所有原型、文件和信息。一旦每个人都同意了规范,您就可以开始研究实施项目的最佳方式。

值得一提的是,你可以使用这里描述的过程来完成整个软件或其中的一小部分。

使用设计技术作为一个有用的工具

定义解决方案并不容易。确定其技术增加了这样做的难度。在你作为软件架构师的职业生涯中,你会发现许多项目,你的客户会给你一个“准备开发”的解决方案。如果你把这个解决方案视为正确的解决方案,情况可能会变得非常复杂;大多数时候,会有架构和功能上的错误,这将在未来导致解决方案出现问题。

有些情况下问题更严重——当客户不知道问题的最佳解决方案时。一些设计技术可以帮助我们解决这个问题,我们将在这里介绍其中的两种:设计思维和设计冲刺。

你必须明白的是,这些技术可以是发现真实需求的一个绝佳选择。作为软件架构师,你有责任帮助你的团队在正确的时间使用正确的工具,而这些工具可能是确保项目成功的正确选择。

设计思维

设计思维是一个允许你直接从用户那里收集数据,专注于实现最佳结果来解决问题的过程。在这个过程中,团队将有机会发现将与系统互动的所有人物。这将对解决方案产生美妙的影响,因为你可以通过专注于用户体验来开发软件,这对结果可能会产生美妙的影响。

这个过程基于以下步骤:

  • 共情:在这一步中,你必须进行现场调研,以发现用户的关注点。这是你了解系统用户的地方。这个过程有助于让你理解为什么以及为谁开发这个软件。

  • 定义:一旦你了解了用户的关注点,就是时候定义他们的需求来解决它们了。

  • 构思:需求将提供一个机会,来对一些可能的解决方案进行头脑风暴。

  • 原型:这些解决方案可以���发成模型,以确认它们是否是好的解决方案。

  • 测试:测试原型将帮助你了解最符合用户真实需求的原型。

这种技术的重点是加速发现正确产品的过程,考虑到“最小可行产品”(MVP)。原型过程将帮助利益相关者理解最终产品,并同时鼓励团队提供最佳解决方案。

设计冲刺

设计冲刺是一个专注于通过设计在五天冲刺中解决关键业务问题的过程。这个技术是由谷歌提出的,它是一个允许你快速测试和学习一个想法的替代方案,需要构建和推出一个解决方案到市场上。

这个过程是基于专家们致力于解决所提到的问题的一周时间,在一个为此目的准备的战争室中进行的。这一周分为以下几个部分:

  • 星期一:这一天的重点是确定冲刺的目标,并将挑战映射到实现它的地方。

  • 星期二:在了解了冲刺的目标之后,参与者开始勾画可能解决问题的解决方案。现在是时候找到客户来测试新的解决方案了。

  • 星期三:这是团队需要决定哪些解决方案有最大机会解决问题的时间。此外,星期三团队必须将这些解决方案绘制成故事板,为原型制定计划。

  • 星期四:现在是在故事板上计划的想法的原型制作时间。

  • 星期五:完成了原型后,团队向客户展示它,通过从客户对设计的反应中获取信息来学习。

正如你在这两种技术中所看到的,从客户那里收集反馈的加速来自原型,这将使你的团队的想法更具体化,更贴近最终用户。

需求收集过程影响系统结果的常见情况

到目前为止在本章讨论的所有信息对于想要遵循良好工程原则设计软件是有用的。这个讨论与使用传统或敏捷方法开发无关,而是专注于专业或业余地构建软件。

了解一些未能执行你所读的活动导致软件项目出现问题的案例也是一个好主意。以下案例旨在描述可能出现的问题,以及先前的技术如何帮助开发团队解决问题。

在大多数情况下,简单的行动可能会保证团队和客户之间更好的沟通,这种简单的沟通流程将把一个大问题转化为一个真正的解决方案。让我们来看看三种常见情况,需求收集如何影响了性能、功能和可用性的结果。

案例 1 - 我的网站打开那个页面太慢了!

性能是你作为软件架构师在职业生涯中将要处理的最大问题之一。任何软件的这一方面如此棘手的原因在于我们没有无限的计算资源来解决问题。此外,计算成本仍然很高,特别是当你谈论具有大量同时用户的软件时。

你不能通过编写需求来解决性能问题。然而,如果你正确地书写它们,你就不会陷入麻烦。这里的想法是需求必须呈现系统的期望性能。一个简单的句子,描述这一点,可以帮助整个项目团队:

非功能性需求:性能 - 该软件的任何网页在有 1,000 个用户同时访问时,至少应在 2 秒内响应。

前面的句子只是让每个人(用户、测试人员、开发人员、架构师、经理等等)确信任何网页都有一个要达到的目标。这是一个良好的开始,但还不够。一个既能开发又能部署你的应用程序的良好环境也很重要。这就是.NET 5 可以帮助你的地方;特别是如果你谈论的是 Web 应用程序,ASP.NET Core 被认为是今天提供解决方案的最快选项之一。

如果你谈论性能,作为软件架构师,你应该考虑使用以下部分列出的技术以及特定测试来保证这一非功能性需求。同时,重要的是要提到 ASP.NET Core 将帮助你轻松使用它们,以及微软 Azure 提供的一些平台即服务PaaS)解决方案。

理解缓存

缓存是一种很好的技术,可以避免可能消耗时间并且通常会给出相同结果的查询。例如,如果你在数据库中获取可用的汽车型号,数据库中的汽车数量可能会增加,但它们不会改变。一旦你有一个不断访问汽车型号的应用程序,一个好的做法是对这些信息进行缓存。

重要的是要理解缓存存储在后端,并且缓存由整个应用程序共享(内存缓存)。一个要关注的重点是,当你在开发可扩展的解决方案时,你可以使用 Azure 平台配置分布式缓存来解决问题。事实上,ASP.NET 提供了两者,因此你可以选择最适合你需求的那个。第二章非功能性需求,涵盖了 Azure 平台的可扩展性方面。

应用异步编程

当您开发 ASP.NET 应用程序时,需要记住您的应用程序需要设计为能够同时被许多用户访问。异步编程让您可以简单地做到这一点,给您提供了asyncawait这两个关键字。

这些关键字背后的基本概念是,async使任何方法能够异步运行。另一方面,await允许您同步调用异步方法,而不会阻塞调用它的线程。这种易于开发的模式将使您的应用程序在没有性能瓶颈和更好的响应性的情况下运行。本书将在第二章 非功能性需求中更多地涵盖这个主题。

处理对象分配

避免性能不足的一个很好的提示是了解垃圾收集器GC)的工作原理。当您使用完内存时,GC 是会自动释放内存的引擎。由于 GC 的复杂性,这个主题有一些非常重要的方面。

如果您不释放它们,某些类型的对象将不会被 GC 收集。这个列表包括与 I/O 交互的任何对象,比如文件和流。如果您没有正确使用 C#语法来创建和销毁这种对象,您将会有内存泄漏,这将损害您的应用程序性能。

处理 I/O 对象的不正确方式是:

System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\sample.txt");
file.WriteLine("Just writing a simple line"); 

处理 I/O 对象的正确方式是:

using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\sample.txt"))
{
file.WriteLine("Just writing a simple line");
} 

值得注意的是,这种正确的方法还确保文件被写入(它调用 Flush)。在不正确的示例中,内容甚至可能都没有被写入文件。尽管对 I/O 对象来说,前面的做法是强制性的,但强烈建议您在所有可处置的对象中继续这样做。事实上,在解决方案中使用警告作为错误的代码分析器将防止您意外地犯这些错误!这将有助于 GC,并将使您的应用程序以正确的内存量运行。根据对象的类型,这里的错误可能会滚雪球,您最终可能会遇到其他不良情况,例如端口/连接耗尽。

另一个重要的方面是,GC 花费在收集对象上的时间会干扰应用程序的性能。因此,避免分配大型对象;否则,它可能会导致您等待 GC 完成其任务。

改进数据库访问

数据库访问是最常见的性能弱点之一。为什么这仍然是一个大问题是因为在编写查询或 lambda 表达式以从数据库获取信息时缺乏注意。本书将在第八章 使用 C#与数据交互-Entity Framework Core中涵盖 Entity Framework Core,但重要的是要知道如何选择以及从数据库中读取正确的数据信息。对于希望提供性能的应用程序来说,过滤列和行是必不可少的。

好消息是,与缓存、异步编程和对象分配相关的最佳实践完全适用于数据库环境。只需要选择正确的模式,就能获得更好的性能软件。

情况 2-用户的需求没有���到正确实现

技术在各种领域的广泛应用,使得精确满足用户需求变得更加困难。也许这句话对您听起来很奇怪,但您必须明白,开发人员一般来说学习如何开发软件,但很少学习如何满足特定领域的需求。当然,学习如何开发软件并不容易,但要理解特定领域的特定需求更加困难。如今,软件开发为所有可能的行业提供软件。问题在于开发人员,无论是软件架构师还是其他人,如何能够进步到足以在他们负责的领域交付软件?

收集软件需求将帮助你完成这项艰巨的任务;编写它们将使你理解和组织系统的架构。有几种方法可以最小化实施与用户真正需求不同的风险:

  • 原型界面以更快地理解用户界面

  • 设计数据流以检测系统和用户操作之间的差距

  • 经常开会以了解用户当前的需求并对增量交付进行调整

同样,作为软件架构师,你将不得不定义软件的实现方式。大多数情况下,你不会是编程的人,但你始终是负责的人。因此,一些技术可以帮助避免错误的实现:

  • 与开发人员一起审查需求,以确保他们理解他们需要开发什么。

  • 代码检查以验证预定义的代码标准。我们将在第十九章使用工具编写更好的代码中介绍这一点。

  • 开会消除障碍。

记住,实现符合用户需求是你的责任。利用你能够满足它的每一个工具。

案例 3-系统的可用性不符合用户需求

可用性是软件项目成功的关键点。软件的呈现方式以及它如何解决问题可以帮助用户决定他们是否想要使用它。作为软件架构师,你必须记住,现在交付具有良好可用性的软件是强制性的。

本书不打算涵盖可用性的基本概念,但在涉及可用性时满足正确的用户需求的一个好方法是了解谁将使用软件。设计思维可以在这方面帮助你很多,正如本章前面讨论的那样。

了解用户将帮助你决定软件是否将在网页上运行,还是在手机上,甚至在后台。这种理解对于软件架构师非常重要,因为如果你正确地映射谁将使用它,系统的元素将呈现得更好。

另一方面,如果你不在乎这一点,你只会交付能够运行的软件。这在短期内可能是好的,但它不会完全满足让一个人要求你设计软件的真正需求。你必须记住选项并理解,优秀的软件是设计用于在许多平台和设备上运行的。

你会很高兴知道,.NET 5 是一个令人难以置信的跨平台选择。因此,你可以开发解决方案在 Linux、Windows、Android 和 iOS 上运行你的应用程序。你可以在大屏幕、平板电脑、手机甚至无人机上运行你的应用程序!你可以将应用程序嵌入到自动化板上,或者在 HoloLens 上进行混合现实。软件架构师必须开放思维,设计出用户真正需要的东西。

案例研究-介绍 World Wild Travel Club

正如我们在本章开头提到的,本书的案例研究将带你走上为一家名为World Wild Travel ClubWWTravelClub)的旅行社创建软件架构的旅程。

WWTravelClub 是一家旅行社,旨在改变人们对他们的度假和世界各地其他旅行做出决定的方式。为此,他们正在开发一个在线服务,其中每次旅行体验的每个细节都将由专门为每个目的地精选的专家俱乐部协助。

这个平台的概念是你可以同时成为游客和目的地专家。你在一个目的地作为专家参与的越多,你得分就越高。这些分数可以在平台上购买的门票上兑换。

客户提出了平台的以下要求。重要的是要知道,一般来说,客户并不会为开发准备好需求。这就是为什么需求收集过程如此重要:

  • 普通用户视图:

  • 主页上的促销套餐

  • 搜索套餐

  • 每个套餐的详情:

  • 购买套餐

  • 购买包含专家俱乐部的套餐:

  • 评论您的经验

  • 询问专家

  • 评估专家

  • 注册为普通用户

  • 目的地专家视图:

  • 与普通用户视图相同

  • 回答询问你目的地专业知识的问题

  • 管理您回答问题得分的积分:

  • 兑换积分以换取门票

  • 管理员视图:

  • 管理套餐

  • 管理普通用户

  • 管理目的地专家

最后,重要的是要注意,WWTravelClub 打算每个套餐拥有超过 100 名目的地专家,并将在全球提供大约 1,000 个不同的套餐。

了解用户需求和系统要求

要总结 WWTravelClub 的用户需求,您可以阅读以下用户故事:

  • US_001: 作为普通用户,我想要在主页上查看促销套餐,这样我就可以轻松找到我的下一个假期

  • US_002: 作为普通用户,我想要搜索主页上找不到的套餐,这样我就可以探索其他旅行机会

  • US_003: 作为普通用户,我想要查看套餐的详情,这样我就可以决定购买哪个套餐

  • US_004: 作为普通用户,我想要注册自己,这样我就可以开始购买套餐

  • US_005: 作为注册用户,我想要处理付款,这样我就可以购买套餐

  • US_006: 作为注册用户,我想要购买包���专家推荐的套餐,这样我就可以拥有独特的旅行体验

  • US_007: 作为注册用户,我想要询问专家,这样我就可以找到我旅行中可以做的最好的事情

  • US_008: 作为注册用户,我想要评论我的经验,这样我就可以从我的旅行中得到反馈

  • US_009: 作为注册用户,我想要评价帮助我的专家,这样我就可以与他人分享他们有多棒

  • US_010: 作为注册用户,我想要注册为目的地专家视图,这样我就可以帮助到来我城市旅行的人

  • US_011: 作为一个专家用户,我想要回答关于我的城市的问题,这样我就可以得分,以便将来兑换

  • US_012: 作为一个专家用户,我想要兑换积分以换取门票,这样我就可以更多地环游世界

  • US_013: 作为管理员用户,我想要管理套餐,这样用户可以有机会进行梦幻般的旅行

  • US_014: 作为管理员用户,我想要管理注册用户,这样 WWTravelClub 可以保证良好的服务质量

  • US_015: 作为管理员用户,我想要管理专家用户,这样我们所有关于目的地的问题都能得到回答

  • US_016: 作为管理员用户,我想要在全球提供超过 1,000 个套餐,这样不同的国家可以体验 WWTravelClub 的服务

  • US_017: 作为 CEO,我想要有超过 1,000 名用户同时访问网站,这样业务可以有效扩展

  • US_018: 作为用户,我想要用我的母语访问 WWTravelClub,这样我就可以轻松理解所提供的套餐

  • US_019: 作为用户,我想要在 Chrome、Firefox 和 Edge 网页浏览器中访问 WWTravelClub,这样我就可以使用我喜欢的网页浏览器

  • US_020: 作为用户,我想要知道我的信用卡信息被安全存储,这样我就可以安全购买套餐

请注意,当您开始编写故事时,可以包括与非功能性需求相关的信息,如安全性、环境、性能和可扩展性。

然而,当您编写用户故事时,可能会忽略一些系统需求,这些需求需要包含在软件规范中。这些需求可能涉及法律方面、硬件和软件先决条件,甚至是正确系统交付的注意事项。它们需要被映射和列出,就像用户故事一样。WWTravelClub 系统需求列在以下清单中。请注意,由于系统尚不存在,因此需求是以未来时态书写的:

  • SR_001: 该系统应使用 Microsoft Azure 组件以提供所需的可伸缩性

  • SR_002: 系统应遵守通用数据保护条例GDPR)的要求

  • SR_003: 该系统应在 Windows、Linux、iOS 和 Android 平台上运行

  • SR_004: 该系统的任何网页应在至少 2 秒内响应,同时具有 1,000 个用户的并发访问

列出用户故事和系统需求的目的是帮助您了解,如果从架构的角度思考,平台的开发可能有多复杂。

总结

在本章中,您学习了软件架构师在软件开发团队中的作用。此外,本章涵盖了软件开发过程模型的基础知识和需求收集过程。您还有机会学习如何创建 Azure 帐户,该帐户将在本书的案例研究中使用,该案例研究在上一节中向您介绍。此外,您甚至学习了功能和非功能需求以及如何使用用户故事来创建它们。这些技术将帮助您交付更好的软件项目。

在下一章中,您将有机会了解功能和非功能需求对软件架构的重要性。

问题

  1. 软件架构师需要具备哪些专业知识?

  2. Azure 如何帮助软件架构师?

  3. 软件架构师如何决定在项目中使用最佳的软件开发过程模型?

  4. 软件架构师如何为需求收集做出贡献?

  5. 软件架构师需要在需求规范中检查哪些类型的需求?

  6. 设计思维和设计冲刺如何帮助软件架构师收集需求?

  7. 用户故事如何帮助软件架构师编写需求?

  8. 开发非常好的性能软件的好技术是什么?

  9. 软件架构师如何检查用户需求是否被正确实现?

进一步阅读

在这里,您可以阅读一些书籍和链接,以获取有关本章的更多信息。

有关 Azure 信息,请查看以下链接:

.NET 5 的信息可以在这里找到:

软件开发过程模型链接:

第二章:非功能性需求

一旦您收集了系统需求,就是时候考虑它们对架构设计的影响了。可伸缩性、可用性、弹性、性能、多线程、互操作性、安全性和其他主题需要进行分析,以便我们能够满足用户需求。我们将这些方面称为非功能性需求。

本章将涵盖以下主题:

  • .NET 5 和 Azure 如何实现可伸缩性、可用性和弹性?

  • 在使用 C#编程时需要考虑的性能问题

  • 软件的可用性,也就是如何设计有效的用户界面

  • .NET 5 和互操作性

  • 通过设计实现安全性

  • 书籍用例-了解.NET Core 项目的主要类型

技术要求

本章提供的示例将需要安装有.NET 5 SDK 的 Visual Studio 2019 社区版。

您可以在github.com/PacktPublishing/Software-Architecture-with-C-9-and-.NET-5找到本章的示例代码。

使用 Azure 和.NET 5 实现可伸缩性、可用性和弹性

对可伸缩性的简短搜索返回了这样的定义,即系统在需求增加时保持良好运行的能力。一旦开发人员读到这一点,他们中的许多人错误地得出结论可伸缩性只意味着添加更多硬件以使应用程序在不停止的情况下继续工作

可伸缩性依赖于涉及硬件解决方案的技术。然而,作为软件架构师,您必须意识到良好的软件将保持可伸缩性在可持续模型中,这意味着良好架构的软件可以节省大量资金。因此,这不仅仅是硬件的问题,也是整体软件设计的问题。这里的重点是系统的运行成本也应该是架构决策的一个因素。

第一章 理解软件架构的重要性中,我们在讨论软件性能时提出了一些克服性能问题的好建议。相同的建议也将帮助您实现可伸缩性。我们在每个过程上花费的资源越少,应用程序就能处理更多用户。

尽管可伸缩性很重要,但云计算应用程序必须设计为能够处理系统故障。每当您确保应用程序从故障中恢复而不向最终用户暴露这种故障时,您就在创建一个弹性应用程序。

您可以在docs.microsoft.com/en-us/azure/architecture/patterns/category/resiliency找到云架构弹性模式。

在云场景中,弹性尤为重要的原因是因为提供给您的基础设施可能需要一小段时间来管理更新、重置,甚至硬件升级。您还更有可能与多个系统一起工作,并且在与它们通信时可能会发生瞬态错误。这就是为什么这种非功能性需求在最近几年开始传播。

当您能够在系统中实现高可用性时,具有可伸缩性和弹性解决方案的可能性变得更加令人兴奋。本书中提出的所有方法都将指导您设计具有良好可用性的解决方案,但在某些情况下,您需要设计特定的替代方案来实现您的目标。

您可以在docs.microsoft.com/en-us/azure/architecture/patterns/category/availability找到云架构可用性模式。

值得知道的是,Azure 和.NET 5 Web 应用程序可以配置以实现这些非功能性需求。让我们在以下小节中进行检查。

在 Azure 中创建可伸缩的 Web 应用程序

在 Azure 中创建一个可扩展的 Web 应用程序非常简单。您必须这样做的原因是能够在不同季节维护不同数量的用户。用户越多,您就需要更多的硬件。让我们向您展示如何在 Azure 中创建一个可扩展的 Web 应用程序。

一旦您登录到 Azure 帐户,您就可以创建新资源(Web 应用程序、数据库、虚拟机等),如下屏幕截图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.1:Microsoft Azure - 创建资源

之后,您可以在热门选项中选择Web 应用程序,或者在搜索市场文本框中输入它。此操作将带您到以下屏幕:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.2:Microsoft Azure - 创建 Web 应用

所需的项目详细信息如下:

  • 订阅:这是将为所有应用程序成本收费的帐户。

  • 资源组:这是您可以定义的资源集合,用于组织策略和权限。您可以指定新的资源组名称,或者将 Web 应用程序添加到在定义其他资源时指定的组中。

此外,实例详细信息如下:

  • 名称:如您所见,Web 应用程序名称是在创建后您的解决方案将采用的 URL。将检查名称以确保其可用。

  • 发布:此参数指示 Web 应用程序是否将直接交付,或者是否将使用 Docker 技术来发布内容。 Docker 将在第五章“将微服务架构应用于企业应用程序”中进行更详细的讨论。如果选择 Docker 容器发布,您将能够配置图像源访问类型图像以及标记信息,以便将其部署到 Web 应用程序。

  • 运行时堆栈:显然,此选项仅在您决定直接交付代码时才可用。在撰写本章时,您可以为.NET Core、ASP.NET、Java 11、Java 8、Node、PHP、Python 和 Ruby 定义堆栈。

  • 操作系统:这是用于托管 Web 应用程序的操作系统的选项。 Windows 和 Linux 都可以用于 ASP.NET Core 项目。

  • 区域:您可以考虑要部署应用程序的位置,考虑到 Azure 在世界各地有许多不同的数据中心。

  • 应用服务计划:这是您定义用于处理 Web 应用程序和服务器区域的硬件计划的地方。此选择定义应用程序的可扩展性、性能和成本。

  • 监控:这是一个用于监控和故障排除 Web 应用程序的有用的 Azure 工具集。在本节中,您将能够启用应用程序洞察。建议您始终为解决方案的不同组件保持相同的区域,因为这将节省从一个数据中心到另一个数据中心的流量交换成本。

创建 Web 应用程序后,可以以两种概念上不同的方式扩展此应用程序:垂直**(向上扩展)和水平(向外扩展)**。如您在以下屏幕截图中所见,这两种方式都可以在 Web 应用程序设置中找到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.3:Web 应用程序的扩展选项

让我们来看看两种扩展类型。

垂直扩展(向上扩展)

扩展意味着更改将托管您的应用程序的硬件规格。在 Azure 中,您有机会从免费共享硬件开始,并在几次点击后转移到独立的机器。以下屏幕截图显示了扩展 Web 应用程序的用户界面:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.4:垂直扩展选项

通过选择提供的选项之一,您可以选择更强大的硬件(具有更多 CPU、存储和 RAM 的机器)。监视您的应用程序及其应用服务计划将指导您决定运行您正在验证的解决方案的最佳基础设施。它还将提供关键见解,例如可能的 CPU、内存和 I/O 瓶颈。

水平扩展(扩展)

扩展意味着将所有请求分配给更多具有相同容量的服务器,而不是使用更强大的机器。所有服务器的负载都会被 Azure 基础架构自动平衡。当整体负载可能在未来发生相当大的变化时,建议使用这种解决方案,因为水平扩展可以自动适应当前负载。下面的屏幕截图显示了由两个简单规则定义的自动扩展策略,该策略由 CPU 使用率触发:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.5:水平扩展示例

值得强调的是,您可以选择具有硬编码实例计数或实现自动缩放规则。

所有可用自动缩放规则的完整描述超出了本书的目的。但是,它们相当容易理解,进一步阅读部分包含了完整文档的链接。

扩展功能仅适用于付费服务计划。

总的来说,水平扩展是一种确保应用程序即使在大量同时访问的情况下也可用的方法。当然,它的使用并不是保持系统可用性的唯一方法,但它肯定会有所帮助。

使用.NET 5 创建可扩展的 Web 应用程序

在所有可用的实现 Web 应用程序的框架中,使用 ASP.NET Core 5 运行可以确保良好的性能,同时具有较低的生产和维护成本。C#作为一种强类型和先进的通用语言,与框架中实现的持续性能改进相结合,使得这个选择在近年来成为企业开发中最佳选择之一。

接下来的步骤将指导您创建基于 ASP.NET Core Runtime 5 的 Web 应用程序。所有步骤都非常简单,但一些细节需要注意。

值得一提的是,.NET 5 为开发提供了在任何平台上进行开发的机会-桌面(WPF,Windows Forms 和 UWP),Web(ASP.NET),云(Azure),移动(Xamarin),游戏(Unity),物联网(ARM32 和 ARM64)和人工智能(ML.NET 和.NET for Apache Spark)。因此,从现在开始的建议是只使用.NET 5。在这种情况下,您可以在 Windows 和更便宜的 Linux 服务器上运行 Web 应用程序。

如今,微软建议使用经典的.NET,以防您需要的功能在.NET Core 中不可用,或者当您在不支持.NET Core 的环境中部署 Web 应用程序时。在其他情况下,您应该优先选择.NET Core 框架,因为它允许您执行以下操作:

  • 在 Windows、Linux、macOS 或 Docker 容器中运行您的 Web 应用程序

  • 设计您的解决方案与微服务

  • 拥有高性能和可伸缩的系统

容器和微服务将在第五章 将微服务架构应用于企业应用程序中进行介绍。在那里,您将更好地了解这些技术的优势。目前,可以说.NET 5 和微服务是为性能和可伸缩性而设计的,这就是为什么您应该在所有新项目中优先选择.NET 5 的原因。

以下步骤将向您展示如何在 Visual Studio 2019 中使用.NET 5 创建 ASP.NET Core Web 应用程序:

  • 当您启动 VS 2019 时,您将能够点击创建新项目

  • 一旦您选择ASP.NET Core Web 应用程序,您将被引导到一个屏幕,在那里您将被要求设置项目名称位置解决方案名称外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.6:创建 ASP.NET Core Web 应用程序

  • 之后,您将能够选择要使用的 .NET 版本。选择ASP.NET Core 5.0以获得最先进和全新的平台。对于此演示,您可以选择Web 应用程序模板。

  • 现在我们已经添加了基本细节,您可以将您的 Web 应用项目连接到您的 Azure 帐户并将其发布。

  • 如果您右键单击您创建的项目,在解决方案资源管理器中,您将有发布选项:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.7:发布 ASP.NET Core Web 应用程序

  • 您将找到不同的目标来发布您的 Web 应用。选择Azure作为目标。

  • 然后,您将能够决定要发布的具体目标。为此演示选择Azure App Service (Windows)

  • 此时可能需要定义您的 Microsoft 帐户凭据。这是因为 Visual Studio 与 Azure 之间有完全集成。这使您有机会在开发环境中查看您在 Azure 门户中创建的所有资源!

图 2.8:Visual Studio 与 Azure 的集成

  • 一旦您决定了您的发布设置,也就是发布配置文件,当您点击发布时,Web 应用将会自动发布。请注意在这里选择 F1 定价层,以便此过程不会产生任何费用:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.9:发布配置文件选项

  • 您目前有两种部署模式。第一种是 Framework-dependent,将需要配置目标框架的 Web 应用。第二种是 self-contained,将不再需要此功能,因为框架的二进制文件将与应用程序一起发布。

  • 值得一提的是,为了以 Framework-dependent 模式发布 ASP.NET 预览版本,您必须在 Azure 门户中的 Web 应用设置面板中添加一个扩展,如下截图所示。但是,在预览版本下,考虑使用自包含模式!

图 2.10:在 Azure Web 应用服务中添加扩展

有关将 ASP.NET Core 5.0 部署到 Azure App Service 的更多信息,请参阅以下链接:docs.microsoft.com/en-us/aspnet/core/host-and-deploy/azure-apps/?view=aspnetcore-5.0&tabs=visual-studio

在这里,我们描述了部署 Web 应用的最简单方法。在第二十章理解 DevOps 原则第二十一章应用 CI 场景的挑战中,我们将向您介绍 Azure DevOps 持续集成/持续交付CI/CD)管道。这个管道是一个进一步的 Azure 工具集,它自动化了将应用程序投入生产所需的所有步骤,即构建、测试、部署到暂存区和部署到生产环境。

在 C# 编程中需要考虑的性能问题

如今,C# 是全球最常用的编程语言之一,因此关于 C# 编程的良好建议对于设计满足最常见非功能性需求的良好架构至关重要。

以下部分提到了一些简单但有效的提示-相关的代码示例可在本书的 GitHub 存储库中找到。

字符串连接

这是一个经典的例子!使用+字符串运算符天真地连接字符串可能会导致严重的性能问题,因为每次连接两个字符串时,它们的内容都会被复制到一个新的字符串中。

因此,如果我们连接,例如,平均长度为 100 的 10 个字符串,第一个操作的成本为 200,第二个操作的成本为200+100=300,第三个操作的成本为300+100=400,依此类推。很容易让你相信总体成本增长像mn²,其中n是字符串的数量,m是它们的平均长度。n²对于小n*(比如,n < 10)来说并不算太大,但当n达到 100-1,000 数量级时,它就变得相当大,当n达到 10,000-100,000 数量级时就变得不可接受。

让我们用一些测试代码来看看这个问题,比较天真的连接和使用StringBuilder类执行相同操作的代码(该代码可在本书的 GitHub 存储库中找到):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.11:连接测试代码结果

如果你创建一个类似var sb =new System.Text.StringBuilder()StringBuilder类,然后用sb.Append(currString)将每个字符串添加到其中,那么字符串不会被复制;相反,它们的指针会排队在一个列表中。它们只在你调用sb.ToString()获取最终结果时被复制到最终字符串中。因此,基于StringBuilder的连接成本简单地增长为mn*。

当然,你可能永远不会找到一个像前面那个连接 100,000 个字符串的函数的软件片段。然而,你需要识别类似这些的代码片段,比如在同时处理多个请求的 Web 服务器中连接 20-100 个字符串可能会导致损害性能的瓶颈。

异常

永远记住,异常比正常代码流慢得多!因此,使用try-catch需要简洁和必要,否则,你将会创建大的性能问题。

以下两个示例比较了使用try-catchInt32.TryParse来检查字符串是否可以转换为整数:

private static string ParseIntWithTryParse()
{
    string result = string.Empty; 
    if (int.TryParse(result, out var value))
        result = value.ToString();
    else
        result = "There is no int value";
    return $"Final result: {result}";
}
private static string ParseIntWithException()
{
    string result = string.Empty;
    try
    {
        result = Convert.ToInt32(result).ToString();
    }
    catch (Exception)
    {
        result = "There is no int value";
    }
    return $"Final result: {result}";
} 

第二个函数看起来并不危险,但比第一个函数慢上千倍:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.12:异常测试代码结果

总之,异常必须用于处理打破正常控制流的异常情况,例如,操作必须因某些意外原因而中止,控制必须返回调用堆栈中的几个级别。

更好的多线程环境-做和不做

如果你想充分利用正在构建的系统提供的所有硬件,你必须使用多线程。这样,当一个线程在等待操作完成时,应用程序可以将 CPU 留给其他线程,而不是浪费 CPU 时间。

另一方面,无论微软如何努力帮助解决这个问题,并行代码都不像吃蛋糕那样简单:它容易出错,难以测试和调试。当你开始考虑使用线程时,作为软件架构师最重要的事情是*你的系统是否需要它们?*非功能性和一些功能性需求会为你解答这个问题。

一旦你确定需要一个多线程系统,你应该决定哪种技术更合适。这里有几个选项,如下:

  • 创建 System.Threading.Thread的实例:这是在 C#中创建线程的经典方式。整个线程生命周期将由你掌控。当你确定自己要做什么时,这是很好的,但你需要担心实现的每一个细节。结果代码很难构思和调试/测试/维护。因此,为了保持开发成本可接受,这种方法应该局限于一些基本的、性能关键的模块。

  • 使用 System.Threading.Tasks.Parallel 类进行编程:自.NET Framework 4.0 以来,您可以使用并行类以更简单的方式启用线程。这很好,因为您不需要担心创建的线程的生命周期,但这将使您对每个线程中发生的事情控制更少。

  • 使用异步编程进行开发:这无疑是开发多线程应用程序的最简单方式,因为编译器承担了大部分工作。根据您调用异步方法的方式,您可能会创建的Task与用于调用它的Thread并行运行,甚至可能会有这个Thread等待而不挂起,直到创建的任务结束。这样,异步代码模仿了经典同步代码的行为,同时保留了一般并行编程的大部分性能优势:

  • 总体行为是确定性的,不取决于每个任务完成所花费的时间,因此不可重现的错误更难发生,生成的代码易于测试/调试/维护。将方法定义为异步任务与否是程序员留下的唯一选择;其他一切都由运行时自动处理。您唯一需要关注的是哪些方法应该具有异步行为。值得一提的是,将方法定义为async并不意味着它将在单独的线程上执行。您可以在docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/上找到有用的信息。

  • 在本书的后面,我们将提供一些异步编程的简单示例。有关异步编程及其相关模式的更多信息,请查看 Microsoft 文档中的基于任务的异步模式(docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap)。

无论您选择哪个选项,作为软件架构师,您都必须注意一些要点和禁忌。具体如下:

  • 使用并发集合(System.Collections.Concurrent):一旦启动多线程应用程序,您就必须使用这些集合。原因是您的程序可能会从不同的线程管理相同的列表、字典等。使用并发集合是开发线程安全程序的最方便选项。

  • 担心静态变量:无法说静态变量在多线程开发中是被禁止的,但您应该注意它们。同样,多个线程处理相同的变量可能会引起很多麻烦。如果您使用[ThreadStatic]属性修饰静态变量,每个线程将看到该变量的不同副本,从而解决了多个线程竞争相同值的问题。然而,ThreadStatic变量不能用于额外的线程通信,因为一个线程写入的值不能被其他线程读取。在异步编程中,AsyncLocal<T>是执行类似操作的选项。

  • 在多线程实现后测试系统性能:线程使您能够充分利用硬件,但在某些情况下,编写不良的线程可能会浪费 CPU 时间,什么也不做!类似的情况可能导致几乎 100%的 CPU 使用率和不可接受的系统减速。在某些情况下,可以通过在一些线程的主循环中添加简单的Thread.Sleep(1)调用来减轻或解决问题,以防止它们浪费太多 CPU 时间,但您需要测试这一点。这种实现的一个用例是在其后台运行许多线程的 Windows 服务。

  • 不要认为多线程很容易:多线程并不像在某些语法实现中看起来那么简单。在编写多线程应用程序时,你应该考虑诸如用户界面同步、线程终止和协调等问题。在许多情况下,由于多线程的糟糕实现,程序会停止正常工作。

  • 不要忘记规划系统应该有多少线程:这对于 32 位程序尤其重要。在任何环境中,你可以拥有多少线程都有限制。在设计系统时,你应该考虑这一点。

  • 不要忘记结束你的线程:如果你没有为每个线程正确的终止程序,你可能会在内存和处理泄漏方面遇到麻烦。

可用性-为什么插入数据需要太长时间

可扩展性、性能提示和多线程是我们可以用来调整机器性能的主要工具。然而,你设计的系统的有效性取决于整个处理流水线的整体性能,其中包括人和机器。

作为软件架构师,你无法提高人类的表现,但你可以通过设计一个有效的用户界面(UI)来提高人机交互的表现,这意味着以下内容:

  • UI 必须易于学习,以减少学习所需的时间和目标用户快速操作之前的时间浪费。如果 UI 更改频繁,并且需要吸引尽可能多的用户的公共网站,这一约束是基本的。

  • UI 不得在数据插入中引起任何类型的减速;数据输入速度必须仅受用户输入能力的限制,而不受系统延迟或可以避免的额外手势的限制。

值得一提的是,市场上有 UX 专家。作为软件架构师,你必须决定他们对项目成功至关重要的时候。以下是在设计易于学习的用户界面时的一些建议:

  • 每个输入屏幕必须清楚地说明其目的。

  • 使用用户的语言,而不是开发者的语言。

  • 避免复杂化。设计 UI 时要考虑一般情况;更复杂的情况可以通过只在需要时出现的额外输入来处理。将复杂的屏幕分割成更多的输入步骤。

  • 使用过去的输入来理解用户意图,并通过消息和自动 UI 更改将用户引导到正确的路径;例如,级联下拉菜单。

  • 错误消息不是系统给用户的坏笔记,而是必须解释如何插入正确输入的消息。

快速的用户界面是通过对以下三个要求的有效解决方案实现的:

  • 输入字段必须按照通常填写的顺序放置,并且应该可以使用 Tab 键或 Enter 键移动到下一个输入。此外,通常保持为空的字段应该放在表单的底部。简而言之,在填写表单时应尽量减少使用鼠标。这样,用户手势的数量就会被最小化。在 Web 应用程序中,一旦确定了输入字段的最佳放置位置,只需使用tabindex属性即可定义用户使用 Tab 键从一个输入字段移动到下一个输入字段的正确方式。

  • 系统对用户输入的反应必须尽可能快。错误消息(或信息消息)必须在用户离开输入字段后立即出现。实现这一点的最简单方法是将大部分帮助和输入验证逻辑移至客户端,以便系统反应不需要通过通信线路和服务器。

  • 有效的选择逻辑。选择现有项目应尽可能简单;例如,在提供的数千种产品中选择一种产品必须能够通过几个手势轻松完成,而无需记住确切的产品名称或其条形码。下一小节分析了我们可以使用的技术,以减少复杂性以实现快速选择。

第十六章Blazor WebAssembly中,我们将讨论这项微软技术如何帮助我们解决使用 C#代码构建基于 Web 的应用程序的挑战。

设计快速选择逻辑

当所有可能的选择都在 1-50 的数量级时,通常的下拉菜单就足够了。例如,这个货币选择下拉菜单:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.13:简单的下拉菜单

当数量级更高但不超过几千时,通常最好选择一个自动完成菜单,显示所有以用户输入字符开头的项目名称:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.14:复杂的下拉菜单

类似的解决方案可以以较低的计算成本实现,因为所有主要数据库都可以高效地选择以给定子字符串开头的字符串。

当名称非常复杂时,当搜索用户输入的字符时,它们应该在每个项目字符串内进行扩展。这种操作无法在通常的数据库中高效执行,需要专门的数据结构。

最后,当我们在由几个单词组成的描述中进行搜索时,需要更复杂的搜索模式。例如,产品描述就是这种情况。如果所选的数据库支持全文搜索,系统可以高效地在所有描述中搜索用户输入的几个单词的出现。

然而,当描述由名称而不是常见单词组成时,用户可能很难记住目标描述中包含的几个确切名称。例如,多国公司名称就是如此。在这些情况下,我们需要找到最适合用户输入字符的算法。用户输入的字符串的子字符串必须在每个描述的不同位置进行搜索。通常情况下,类似的算法无法有效地在基于索引的数据库中实现,而是需要将所有描述加载到内存中,并对用户输入的字符串进行某种排名。

这个类别中最著名的算法可能是Levenshtein算法,大多数拼写检查器使用它来找到一个最适合用户错误输入的单词。该算法最小化了描述和用户输入的字符串之间的 Levenshtein 距离,即将一个字符串转换为另一个字符串所需的最小字符删除和添加次数。

Levenshtein 算法效果很好,但计算成本很高。在这里,我们提供了一个更快的算法,用于在描述中搜索字符出现次数。用户输入的字符不需要在描述中连续出现,但必须按相同顺序出现。有些字符可能会缺失。每个描述都会根据缺失的字符和用户输入的字符出现的距离给予惩罚。更具体地说,该算法对每个描述进行了两个数字的排名:

  • 用户输入的字符在描述中出现的次数:描述中包含的字符越多,排名越高。

  • 每个描述都被赋予一个惩罚,等于描述中用户输入字符之间的总距离。

以下屏幕截图显示了单词Ireland与用户输入的字符串ilad的排名:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.15:Levenshtein 用法示例

出现次数为四(4),而字符出现之间的总距离为三(3)。

一旦所有描述都被评分,它们将根据出现次数进行排序。出现次数相同的描述将根据最低的惩罚进行排序。以下是实现前述算法的自动完成功能:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.16:Levenshtein 算法用户界面体验

完整的类代码以及一个测试控制台项目都可以在本书的 GitHub 存储库中找到。

从大量项目中进行选择

在这里,“巨大”并不是指存储数据所需的空间量,而是指用户在记住每个项目的特性时所遇到的困难。当需要从 10,000-100,000 个项目中选择一个项目时,通过在描述中搜索字符出现的次数来寻找它是没有希望的。在这种情况下,用户必须通过一系列类别来选择正确的项目。

在这种情况下,需要进行多个用户手势才能进行单个选择。换句话说,每个选择都需要与多个输入字段进行交互。一旦确定无法使用单个输入字段进行选择,最简单的选择就是级联下拉菜单,即一系列下拉菜单,其选择列表取决于先前下拉菜单中选择的值。

例如,如果用户需要在世界任何地方选择一个城镇,我们可以使用第一个下拉菜单来选择国家,一旦选择了国家,我们可以使用这个选择来填充第二个下拉菜单,其中包含所选国家中的所有城镇。一个简单的例子如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.17:级联下拉菜单示例

显然,每个下拉菜单在需要时都可以被自动完成所取代,因为它具有大量选项。

如果通过交叉几个不同的层次来做出正确的选择,级联下拉菜单也变得低效,我们需要一个筛选表单,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.18:筛选表单示例

现在,让我们了解与.NET Core 的互操作性。

与.NET Core 的互操作性的奇妙世界

.NET Core 为 Windows 开发人员带来了将其软件交付到各种平台的能力。作为软件架构师,您需要注意这一点。对于 C#爱好者来说,Linux 和 macOS 不再是问题 - 它比这好多了 - 它们是向新客户交付的绝佳机会。因此,我们需要确保性能和多平台支持,这是几个系统中常见的非功能性需求。

在 Windows 中使用.NET Core 设计的控制台应用程序和 Web 应用程序在 Linux 和 macOS 上几乎完全兼容。这意味着您不必重新构建应用程序以在这些平台上运行。此外,非常特定于平台的行为现在也具有多平台支持,例如,从.NET Core 3.0 开始,在 Linux 上就有System.IO.Ports.SerialPort类。

微软提供了脚本来帮助您在 Linux 和 macOS 上安装.NET Core。您可以在docs.microsoft.com/dotnet/core/tools/dotnet-install-script找到它们。一旦安装了 SDK,您只需要像在 Windows 中一样调用dotnet

但是,您必须注意一些在 Linux 和 macOS 系统上不完全兼容的功能。例如,在这些操作系统中不存在 Windows 注册表的等效项,您必须自己开发替代方案。如果需要,加密的 JSON 配置文件可能是一个不错的选择。

另一个重要的一点是 Linux 区分大小写,而 Windows 不区分大小写。请记住这一点,当您处理文件时。另一个重要的事情是 Linux 路径分隔符与 Windows 分隔符不同。您可以使用Path.PathSeparator字段和Path类的所有其他成员来确保您的代码是多平台的。

此外,您还可以通过使用.NET Core 提供的运行时检查来调整您的代码以适应底层操作系统,具体如下:

using System;
using System.Runtime.InteropServices;
namespace CheckOS
{
    class Program
    {
        static void Main()
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                Console.WriteLine("Here you have Windows World!");
            else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
                Console.WriteLine("Here you have Linux World!");
            else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                Console.WriteLine("Here you have macOS World!");
        }
    }
} 

在 Linux 中创建服务

以下脚本可用于在 Linux 中封装命令行.NET Core 应用程序。这项服务的理念是该服务类似于 Windows 服务。考虑到大多数 Linux 安装只能通过命令行运行且无需用户登录,这可能非常有用:

  • 第一步是创建一个将运行命令行应用程序的文件。该应用程序的名称是app.dll,并且安装在appfolder中。该应用程序将每 5000 毫秒进行一次检查。此服务是在 CentOS 7 系统上创建的。使用 Linux 终端,您可以输入以下内容:
cat >sample.service<<EOF
[Unit]
Description=Your Linux Service
After=network.target
[Service]
ExecStart=/usr/bin/dotnet $(pwd)/appfolder/app.dll 5000
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF 
  • 创建文件后,您必须将服务文件复制到系统位置。之后,您必须重新加载system并启用服务,以便在重新启动时重新启动:
sudo cp sample.service /lib/systemd/system
sudosystemctl daemon-reload 
sudosystemctl enable sample 
  • 完成!现在,您可以使用以下命令启动、停止和检查服务。您在命令行应用程序中需要提供的整个输入如下:
# Start the service
sudosystemctl start sample
# View service status
sudosystemctl status sample
# Stop the service
sudosystemctl stop sample 

现在我们已经学习了一些概念,让我们学习如何在我们的用例中实现它们。

通过设计实现安全

正如我们在本书中所看到的,我们用于开发软件的机会和技术是令人难以置信的。如果您在接下来的章节中阅读有关云计算的所有信息,您将会发现机会不断增加,与此同时,维护所有这些计算环境的复杂性也在增加。

作为软件架构师,您必须理解这些机会伴随着许多责任。在过去的几年里,世界发生了很大变化。21 世纪的第二个十年需要大量的技术。应用程序、社交媒体、工业 4.0、大数据和人工智能不再是未来的目标,而主要是您将在日常工作中领导和处理的当前项目。

考虑到这种情况,安全必须有不同的方法。世界已经开始监管管理个人数据的公司。例如,GDPR - 《通用数据保护条例》 - 不仅在欧洲领土上是强制性的,因为它已经改变了软件开发的方式,不仅在欧洲,而且在全球范围内。有许多类似于 GDPR 的倡议必须列入我们的技术和法规范围,考虑到您设计的软件将受到它们的影响。

安全设计必须是您设计新应用程序时关注的一个领域。这个主题很庞大,在这本书中不可能完全涵盖,但作为软件架构师,您必须理解在您的团队中有信息安全领域的专家是确保遵守政策和实践以避免网络攻击并保持服务的机密性、隐私、完整性、真实性和可用性的必要性。

在保护 ASP.NET Core 应用程序方面,值得一提的是该框架具有许多功能来帮助我们。例如,它包括身份验证和授权模式。在 OWASP Cheat Sheet Series 中,您将能够阅读关于许多其他.NET 实践的信息。

开放网络应用安全项目®(OWASP)是一个致力于改善软件安全的非营利基金会。请查看其信息网站owasp.org/

ASP.NET 还提供了帮助我们遵守 GDPR 的功能。基本上,有 API 和模板来指导您实施政策声明和 cookie 使用同意。

实现安全架构的实践清单

以下与安全相关的实践清单当然并未涵盖整个主题。但是,这些实践肯定会帮助您作为软件架构师探索与此主题相关的一些解决方案。

认证

为您的 Web 应用程序定义身份验证方法。现在有许多身份验证选项可供选择,从 ASP.NET Core Identity 到外部提供者身份验证方法,例如 Facebook 或 Google。作为软件架构师,您必须考虑应用程序的目标受众是谁。如果选择这条路,考虑使用 Azure Active Directory 也是值得考虑的起点。

您可能会发现将身份验证与 Azure AD 相关联很有用,这是一个用于管理您所在公司的 Active Directory 的组件。在某些场景中,特别是内部使用,这种替代方案非常好。Azure 目前提供用于B2B - 企业对企业B2C - 企业对消费者的 Active Directory。

根据您正在构建的解决方案的情景,您将需要实施MFA - 多因素身份验证。这种模式的想法是在允许解决方案使用之前要求至少两种身份证明形式。值得一提的是,Azure AD 为您简化了这一点。

不要忘记您必须为您提供的 API 确定身份验证方法。 JSON Web Token 是一个非常好的模式,其使用完全跨平台。

您必须确定您将在 Web 应用程序中使用的授权模型。有四种模型选项:

  1. 简单,您只需在类或方法中使用[Authorize]属性;

  2. 基于角色,您可以为访问您正在开发的Controller声明Roles

  3. 基于声明,您可以定义在身份验证期间必须接收的值,以指示用户是否被授权;

  4. 基于策略,其中有一个旨在定义Controller中的访问权限的策略。

您还可以将控制器或类中的方法定义为对任何用户���全可访问,方法是定义属性[AllowAnonymous]。确保这种实现不会在您设计的系统中造成任何漏洞。

您决定使用的模型将确切地定义每个用户在应用程序中能够做什么。

敏感数据

在设计时,作为软件架构师,您将不得不决定存储的数据的哪一部分是敏感的,并且需要受到保护。通过连接到 Azure,您的 Web 应用程序将能够在诸如 Azure 存储和 Azure Key Vault 之类的组件中存储受保护的数据。 Azure 存储将在第九章“如何在云中选择您的数据存储”中讨论。

值得一提的是,Azure Key Vault 用于保护您的应用可能具有的秘密。当您有这种要求时,请考虑使用这种解决方案。

Web 安全

在没有启用 HTTPS 协议的情况下部署生产解决方案是完全不可接受的。 Azure Web 应用程序和 ASP.NET Core 解决方案有各种可能性,不仅可以使用,而且可以强制使用这种安全协议。

有许多已知的攻击和恶意模式,例如跨站点请求伪造,开放式重定向和跨站点脚本。 ASP.NET Core 保证并提供了解决它们的 API。您需要检测对您的解决方案有用的那些。

通过在查询中使用参数来避免 SQL 注入等良好的编程实践是另一个重要目标。

您可以在docs.microsoft.com/en-us/azure/architecture/patterns/category/security找到云架构安全模式。

最后,值得一提的是,安全性需要使用洋葱方法来处理,这意味着需要实现许多层安全性。您必须有一个确定的策略来保证访问数据的过程,包括使用您正在开发的系统的人员的物理访问。此外,您还必须开发一个灾难恢复解决方案,以防系统遭受攻击。灾难恢复解决方案将取决于您的云解决方案。我们将在第四章决定最佳基于云的解决方案中讨论这一点。

书籍用例 - 了解主要类型的.NET Core 项目

本书用例的开发将基于各种类型的.NET Core Visual Studio 项目。本节描述了它们。让我们在 Visual Studio 的文件菜单中选择新项目

您可以通过在搜索引擎中输入来筛选**.NET Core**项目类型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2.19:在 Visual Studio 中搜索.NET Core 项目类型

在那里,您将找到常见的 C#项目(控制台、类库、Windows Form、WPF),以及基于不同测试框架的各种类型的测试项目:xUnit、NUnit 和 MSTest。在各种测试框架中进行选择只是一种偏好,因为它们都提供了可比较的功能。向解决方案中的每个软件组件添加测试是一种常见做法,可以使软件经常修改而不危及其可靠性。

您还可以在**.NET Standard**下定义您的类库项目,这将在第十三章在 C# 9 中实现代码重用性中讨论。这些类库基于标���,使它们与多个.NET 版本兼容。例如,基于 2.0 标准的库与所有大于或等于 2.0 的.NET Core 版本兼容,并与所有大于 4.6 的.NET Framework 版本兼容。这种兼容性优势是以功能较少为代价的。

除了将项目类型筛选为,我们还有几种项目类型。其中一些将使我们能够定义微服务。基于微服务的架构允许将应用程序拆分为几个独立的微服务。可以创建并分布在多台机器上的同一微服务的多个实例,以微调每个应用程序部分的性能。微服务将在以下章节中描述:

  • 第五章将微服务架构应用于企业应用程序

  • 第六章Azure Service Fabric

  • 第七章Azure Kubernetes Service

最后,测试将在第十八章使用单元测试用例和 TDD 测试您的代码第二十二章功能测试的自动化中详细讨论。最后,我们已经在使用.NET 5 创建可扩展的 Web 应用程序小节中描述了 ASP.NET Core 应用程序。在那里,我们定义了一个 ASP.NET Core 应用程序,但是 Visual Studio 还包含基于 RESTful API 和最重要的单页应用程序框架(如 Angular、React、Vue.js 和基于 WebAssembly 的 Blazor 框架)的项目模板,这将在第十六章Blazor WebAssembly中讨论。其中一些可以在标准的 Visual Studio 安装中找到,而其他一些则需要安装 SPA 包。

总结

描述系统行为的功能要求必须与约束系统性能、可扩展性、可用性、弹性、互操作性、可用性和安全性的非功能性需求一起完成。

性能要求来自响应时间和系统负载要求。作为软件架构师,您应该确保以最低成本获得所需的性能,构建高效的算法,并充分利用多线程的可用硬件资源。

可伸缩性是系统适应增加负载的能力。系统可以通过提供更强大的硬件来进行垂直扩展,也可以通过复制和负载平衡相同的硬件来进行水平扩展,从而增加可用性。总的来说,云和 Azure 可以帮助我们实现动态策略,而无需停止应用程序。

像.NET Core 这样在多个平台上运行的工具可以确保互操作性,也就是您的软件能够在不同的目标机器上以及不同的操作系统(Windows、Linux、macOS、Android 等)上运行。

通过关注输入字段的顺序、项目选择逻辑的有效性以及系统的易学性来确保可用性。

此外,您的解决方案越复杂,它应该具有更好的弹性。弹性的理念不是保证解决方案不会失败,而是保证解决方案在软件的每个部分失败时都有一个定义好的操作。

作为软件架构师,您必须从设计的最开始考虑安全性。遵循确定正确模式的指南,并在您的团队中有一个安全专家,将是实现我们目前所有法规的一个很好的选择。

在下一章中,您将了解 Azure DevOps 工具如何帮助我们收集、定义和记录我们的需求。

问题

  1. 有哪两种概念上的系统扩展方式?

  2. 您能否从 Visual Studio 自动将您的 Web 应用程序部署到 Azure?

  3. 多线程有什么用处?

  4. 异步模式相对于其他多线程技术的主要优势是什么?

  5. 为什么输入字段的顺序如此重要?

  6. .NET Core 的Path类为何对互操作性如此重要?

  7. .NET 标准类库相对于.NET Core 类库的优势是什么?

  8. 列出各种类型的.NET Core Visual Studio 项目。

进一步阅读

以下是一些书籍和链接,您可以考虑阅读以收集更多与本章相关的信息:

第三章:使用 Azure DevOps 记录需求

Azure DevOps 是 Visual Studio Team Services 的演进,它提供了各种新功能,可以帮助开发人员记录和组织他们的软件。本章的目的是介绍 Microsoft 提供的这个工具的概述。

本章将涵盖以下主题:

  • 使用您的 Azure 帐户创建 Azure DevOps 项目

  • 了解 Azure DevOps 提供的功能

  • 使用 Azure DevOps 组织和管理需求

  • 在 Azure DevOps 中提出用例

本章的前两节总结了 Azure DevOps 提供的所有功能,而其余部分专注于文档需求和支持整个开发过程的工具。在其他章节中,将更详细地分析在前两节中介绍的大部分功能。

技术要求

本章要求您创建一个新的免费 Azure 帐户或使用现有的帐户。第一章了解软件架构的重要性部分解释了如何创建一个。Azure DevOps 存储库子部分还需要 Visual Studio 2019 社区版(免费)或更高版本。

介绍 Azure DevOps

Azure DevOps 是 Microsoft 的软件即服务SaaS)平台,使您能够为客户持续提供价值。通过在那里创建一个帐户,您将能够轻松规划项目,安全存储代码,测试代码,将解决方案发布到暂存环境,然后将解决方案发布到实际的生产基础设施。

当然,Azure DevOps 是一个完整的框架,它提供了当前可用的软件开发生态系统。自动化软件生产中涉及的所有步骤确保不断改进和改善现有解决方案,以使其适应市场需求。

您可以在 Azure 门户中开始该过程。如果您不知道如何创建 Azure 门户帐户,请查看第一章了解软件架构的重要性。创建 Azure DevOps 帐户的步骤非常简单:

  1. 选择创建资源,然后选择DevOps Starter外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.1:DevOps 起始页

  1. 一旦开始创建项目的向导,您可以从几种不同的平台中选择如何交付您的系统。这是 Azure DevOps 的最大优势之一,因为您不仅限于 Microsoft 工具和产品,而是可以从市场上所有常见的平台、工具和产品中进行选择:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.2:DevOps 技术选择

  1. 可用的选项将取决于第一步选择的平台。在某些情况下,您可以从几种部署选项中进行选择,如下面的屏幕截图所示,如果您选择.NET 平台:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.3:DevOps 技术选择,更多细节

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.4:DevOps 部署选项

  1. 设置完成后,您将能够根据您提供的信息使用项目门户管理项目。值得一提的是,如果您没有 Azure DevOps 服务,此向导将创建一个。此外,还会自动创建所选的部署资源,例如,如果您选择Windows Web App,将创建一个 Web 应用程序,如果您选择虚拟机,将创建一个虚拟机。Azure DevOps 组织是您可以组织所有 Azure DevOps 项目的地方。整个过程不到 20 分钟:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.5:Web 应用程序项目的 DevOps 详细信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.6:虚拟机项目的 DevOps 详细信息

  1. 之后,您将能够开始规划您的项目。以下屏幕截图显示了 Azure DevOps 项目创建完成后出现的页面。在本书的其余部分,我们将多次回到这个页面,以介绍和描述各种有用的功能,以确保更快速和更有效的部署:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.7:DevOps 项目页面

正如您从前面的屏幕截图中所看到的,创建 Azure DevOps 帐户并开始开发最佳的 DevOps 工具的过程非常简单。值得一提的是,只要您的团队中没有超过五名开发人员,加上任意数量的利益相关者,您就可以免费使用这个出色的工具。

值得一提的是,利益相关者的数量没有限制,因为他们可以使用的功能非常有限。基本上,他们对面板和工作项具有只读权限,并且几乎没有修改它们的可能性。具体来说,他们可以添加新的工作项和现有标签到工作项,并且可以提供反馈。关于构建和发布,他们只能批准发布(在撰写本书时,还有一些其他有限的功能处于预览状态)。

使用 Azure DevOps 组织您的工作

DevOps 将在第二十章中进行详细讨论,理解 DevOps 原则,但您需要将其理解为一种专注于为客户提供价值的哲学。它是人、流程和产品的结合,使用持续集成和持续部署CI/CD)方法来对交付给生产环境的软件应用程序进行持续改进。Azure DevOps 是一个强大的工具,其应用范围涵盖了应用程序的初始开发和随后的 CI/CD 过程中涉及的所有步骤。

Azure DevOps 包含用于收集需求和组织整个开发过程的工具。它们可以通过单击 Azure DevOps 页面上的面板菜单来访问,并将在接下来的两个小节中进行更详细的描述:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.8:面板菜单

Azure DevOps 中的所有其他功能在以下小节中进行了简要回顾。它们将在其他章节中进行详细讨论。具体来说,CI 和构建/测试管道在第十八章中讨论,使用单元测试用例和 TDD 测试您的代码,以及第二十一章应用 CI 场景的挑战,而 DevOps 原则和发布管道在第二十章中讨论,理解 DevOps 原则

Azure DevOps 存储库

存储库菜单项让您访问默认的 Git 存储库,您可以在其中放置项目的代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.9:存储库菜单

单击文件项目,您将进入默认存储库的初始页面。它是空的,并包含有关如何连接到此默认存储库的说明。

您可以通过页面顶部的下拉菜单添加更多的存储库:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.10:添加新存储库

所有创建的存储库都可以通过同一个下拉菜单访问。

如前面的屏幕截图所示,每个存储库的初始页面包含存储库地址和一个按钮,用于生成特定于存储库的凭据,因此您可以使用您喜欢的 Git 工具连接到您的 DevOps 存储库。但是,您也可以从 Visual Studio 内部以非常简单的方式连接:

  1. 启动 Visual Studio,并确保您已登录到与定义 DevOps 项目相同的 Microsoft 帐户(或用于将您添加为团队成员的帐户)。

  2. 选择团队资源管理器选项卡,然后单击连接按钮:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.11:添加新存储库

  1. 单击 Azure DevOps 的**连接…**链接,您将被引导设置与您的 Azure DevOps 项目之一的连接。

一旦连接到您的 DevOps 远程存储库,您可以使用 Visual Studio Git 工具,并且还可以从 Visual Studio 内部与其他 DevOps 功能进行交互。在撰写本书时,交互的类型取决于 Visual Studio 选项中的新 Git 用户体验复选框设置:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.12:新的 Git 用户体验复选框

如果未经检查,您将拥有“经典”的 Visual Studio 体验,其中您可以使用 Team Explorer 访问 Git 和其他 DevOps 功能:

  1. 单击 Team Explorer 的主页按钮。现在,您将看到执行 Git 操作和与其他 Azure DevOps 区域进行交互的命令:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.13:Team Explorer 选项

  1. 如果您被指定为初始化 DevOps 存储库的人,请创建一个起始解决方案,并通过单击更改按钮并按照随后的说明提交您的代码。

  2. 单击同步按钮,将本地存储库与远程 Azure DevOps 存储库同步。

  3. 一旦所有团队成员都使用上述步骤初始化了他们的本地机器存储库和 Azure DevOps 存储库,现在可以打开 Visual Studio。在Team Explorer窗口的底部区域中将显示在本地存储库中创建的解决方案。

  4. 单击窗口以在本地计算机上打开解决方案。然后,与远程存储库同步,以确保您正在修改的代码是最新的。

相反,如果新 Git 用户体验复选框被选中,则Team Explorer窗口只有用于非 Git DevOps 操作的命令,以及用于打开专门用于 Git 操作的新窗口的打开 Git 更改链接:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.14:新 Team Explorer 窗口

一旦进入此窗口,您将被要求克隆或创建一个新的存储库。在两种情况下,您将被提示提供远程 DevOps 存储库的地址。一旦您创建了连接到远程 DevOps 存储库的本地存储库,您可以开始使用新的 Git 窗口,该窗口提供的选项比经典的 Team Explorer 窗口提供的选项更多,总体上提供了更完整的用户体验:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.15:Git 更改窗口

当您有要提交的更改时,您可以在窗口顶部的文本框中插入消息,并通过单击提交所有按钮在本地提交,或者您可以单击此按钮旁边的下拉菜单以访问更多选项:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.16:提交选项

您可以提交和推送,或者提交和同步,但也可以暂存您的更改。Git 更改窗口右上角的三个箭头分别触发获取、拉取和推送。与此同时,窗口顶部的下拉菜单负责分支操作:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.17:分支操作

软件包源

Artifacts菜单处理项目使用或创建的软件包。在那里,您可以为基本上所有类型的软件包定义 feeds,包括 NuGet、Node.js 和 Python。由于商业项目也使用私有软件包,因此需要私有 feeds,因此您需要一个放置它们的地方。此外,构建过程中生成的软件包也放置在这些 feeds 中,因此具有这些软件包作为依赖项的其他模块可以立即使用它们。

一旦进入Artifacts区域,您可以通过单击**+创建 Feed**按钮创建多个 feeds,每个 feed 可以处理多种类型的软件包,如图 3.18所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.18:Feed 创建

如果选择连接到公共来源的软件包选项,默认情况下,feed 会连接到npmjsnuget.orgpypi.org。但是,您可以转到Feed设置页面中的上游来源选项卡,删除/添加软件包来源。通过单击 feed 页面右上角的设置图标可以进入设置页面。以下是新创建的 feed 页面的截图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.19:Feed 页面

每个 feed 的连接到 feed按钮显示一个窗口,解释了如何连接到 feed 的每种软件包类型。特别是对于 NuGet 软件包,您应该将所有项目 feed 添加到您的 Visual Studio 项目/解决方案的nuget.config文件中,以便本地机器也可以使用它们,否则,您的本地构建将失败:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.20:Feed 连接信息

测试计划

测试计划部分允许您定义要使用的测试计划及其设置。测试在第十八章“使用单元测试用例和 TDD 测试代码”和第二十二章“功能测试自动化”中有详细讨论,但在这里,我们想总结一下 Azure DevOps 提供的机会。测试相关的操作和设置可以通过测试计划菜单项访问:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.21:Feed 测试计划菜单

在这里,您可以定义、执行和跟踪由以下内容组成的测试计划:

  • 手动验收测试

  • 自动单元测试

  • 负载测试

自动单元测试必须在 Visual Studio 解决方案中包含的测试项目中定义,并基于诸如 NUnit、xUnit 和 MSTest 之类的框架(Visual Studio 为所有这些都有项目模板)。测试计划让您有机会在 Azure 上执行这些测试,并定义以下内容:

  • 一些配置设置

  • 何时执行它们

  • 如何跟踪它们以及在整个项目文档中报告它们的结果

对于手动测试,您可以在项目文档中为操作员定义完整的指令,涵盖执行它们的环境(例如操作系统)以及报告结果的位置。您还可以定义如何执行负载测试以及如何测量结果。

管道

管道是自动操作计划,指定从代码构建到软件部署到生产环境的所有步骤。它们可以在管道区域中定义,通过管道菜单项访问:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.22:管道菜单

在那里,您可以定义一系列任务的完整管道,以及它们的触发事件,其中包括代码构建、启动测试计划以及测试通过后的操作。

通常,在测试通过后,应用程序会自动部署到一个暂存区,在那里可以进行 Beta 测试。您还可以定义自动部署到生产环境的标准。这些标准包括但不限于以下内容:

  • 应用程序进行 Beta 测试的天数

  • 在 Beta 测试期间发现的错误数量和/或最后一次代码更改删除的错误数量

  • 一个或多个经理/团队成员的手动批准

决策标准将取决于公司希望管理正在开发的产品的方式。作为软件架构师,您必须了解,当涉及将代码移至生产环境时,越安全越好。

在 Azure DevOps 中管理系统需求

Azure DevOps 使您能够使用工作项记录系统需求。工作项存储在项目中,可以分配给某人。它们被分类为各种类型,可能包含所需的开发工作量、状态和它们所属的开发阶段(迭代)的度量。

DevOps 通常与敏捷方法相结合,因此 Azure DevOps 使用迭代,并且整个开发过程组织为一组冲刺。可用的工作项取决于您在创建 Azure DevOps 项目时选择的工作项流程。以下各小节包含在选择敏捷Scrum 工作项流程时出现的最常见工作项类型的描述(默认为敏捷)。

史诗级工作项

想象一下,您正在开发由各种子系统组成的系统。您可能不会在单个迭代中完成整个系统。因此,我们需要一个跨越多个迭代的大伞来包含每个子系统的所有特性。每个史诗级工作项代表这些大伞中的一个,可以包含在各种开发迭代中实现的多个特性。

在史诗级工作项中,您可以定义状态和验收标准,以及开始日期和目标日期。此外,您还可以提供优先级和工作量估计。所有这些详细信息都有助于利益相关者跟踪开发过程。这对于项目的宏观视图非常有用。

特性工作项

您在史诗级工作项中提供的所有信息也可以放在特性工作项中。因此,这两种类型的工作项之间的区别不是与它们包含的信息类型有关,而是与它们的角色和您的团队将达到的目标有关。史诗可能跨越多个迭代,并且在特性之上具有层次结构,也就是说,每个史诗级工作项与多个子特性相关联,而每个特性工作项通常在几个迭代中实现,并且是单个史诗级工作项的一部分。

值得一提的是,所有工作项都有团队讨论的部分。在那里,您可以通过输入@字符(就像在许多论坛/社交媒体应用程序中一样)找到讨论区域的团队成员。在每个工作项内,您可以链接和附加各种信息。您还可以在特定部分检查当前工作项的历史记录。

特性工作项是记录用户需求的起点。例如,您可以编写一个名为访问控制的特性工作项,以定义实现系统访问控制所需的完整功能。

产品积压项/用户故事工作项

这些工作项中的哪些是可用的取决于所选的工作项流程。它们之间存在细微差异,但它们的目的基本相同。它们包含了与它们连接的特性工作项描述的功能的详细要求。更具体地说,每个产品积压/用户故事工作项都指定了作为其父特性工作项描述的行为的一部分的单个功能的要求。例如,在用于系统访问控制的特性工作项中,用户的维护和登录界面应该是两个不同的用户故事/产品积压项。这些要求将指导其他子工作项的创建:

  • 任务:这些是描述需要完成的工作的重要工作项,以满足父产品积压项/用户故事工作项中规定的要求。任务工作项可以包含有助于团队容量管理和整体安排的时间估计。

  • 测试用例:这些项目描述了如何测试由需求描述的功能。

您将为每个产品积压项/用户故事工作项创建的任务和测试用例的数量将根据您使用的开发和测试场景而变化。

用例 - 在 Azure DevOps 中呈现用例

本节通过 WWTravelClub 的实际示例澄清了前一节中概念。考虑到第一章中描述的场景,理解软件架构的重要性,我们决定定义三个史诗级工作项,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.23:用户案例史诗

创建这些工作项非常简单:

  1. 在每个工作项内部,我们链接不同类型的工作项,就像您在图 3.24中看到的那样。

  2. 了解工作项之间的连接在软件开发过程中非常重要。因此,作为软件架构师,您必须向团队提供这些知识,而且更重要的是,您必须激励他们建立这些连接!

图 3.24:定义链接

  1. 一旦您创建了一个特性工作项,您将能够将其连接到几个详细说明其规格的产品积压工作项。以下截图显示了产品积压工作项的详细信息!

图 3.25:产品积压工作项

  1. 之后,可以为每个产品积压工作项创建任务和测试用例工作项。Azure DevOps 提供的用户界面非常有效,因为它使您能够跟踪功能链和它们之间的关系!

图 3.26:看板视图

  1. 一旦您完成了产品积压和任务工作项的输入,您将能够与团队一起规划项目冲刺。计划视图使您能够将产品积压工作项拖放到每个计划的冲刺中!

图 3.27:积压视图

通过在右侧点击特定的冲刺,您将只看到分配给该冲刺的工作项。每个冲刺页面与积压页面非常相似,但包含更多选项卡:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3.28:用户案例史诗

左侧的冲刺菜单也非常有用,它使每个用户能够立即跳转到他们参与的所有项目的当前冲刺。

这就是这些工作项是如何创建的。一旦您了解了这个机制,您就能够创建和规划任何软件项目。值得一提的是,工具本身不会解决与团队管理相关的问题。然而,该工具是激励团队更新项目状态的一个很好的方式,这样您就可以保持对项目进展的清晰视角。

总结

本章介绍了如何为软件开发项目创建 Azure DevOps 帐户,以及如何开始使用 Azure DevOps 管理您的项目。它还简要回顾了所有 Azure DevOps 功能,并解释了如何通过 Azure DevOps 主菜单访问它们。本章更详细地描述了如何管理系统需求,以及如何使用各种工作项规划和组织可以提供史诗解决方案和许多特性的冲刺。

下一章将讨论软件架构的不同模型。我们还将了解在开发解决方案基础架构时,如何从 Azure 等复杂云平台提供的选项中选择基本提示和标准。

问题

  1. Azure DevOps 仅适用于.NET 项目吗?

  2. Azure DevOps 中有哪些测试计划可用?

  3. DevOps 项目可以使用私有 NuGet 包吗?

  4. 我们为什么使用工作项?

  5. 史诗和特性工作项之间有什么区别?

  6. 任务和产品积压项/用户故事工作项之间存在什么样的关系?

进一步阅读

以下是一些您可能考虑阅读的书籍和链接,以获取有关本章的更多信息:

第四章:选择最佳的基于云的解决方案

在设计应用程序使其基于云时,你必须了解不同的架构设计,从最简单到最复杂。本章讨论了不同的软件架构模型,并教会你如何利用云所提供的机会来解决问题。本章还将讨论我们在开发基础设施时可以考虑的不同类型的云服务,理想的场景是什么,以及我们可以在哪些地方使用它们。

本章将涵盖以下主题:

  • 基础设施即服务解决方案

  • 平台即服务解决方案

  • 软件即服务解决方案

  • 无服务器解决方案

  • 如何使用混合解决方案以及它们为何如此有用

值得一提的是,在这些选项之间的选择取决于项目场景的不同方面。这也将在本章中讨论。

技术要求

在本章的实际内容中,你必须创建或使用 Azure 账户。我们在第一章理解软件架构的重要性创建 Azure 账户部分中解释了账户创建过程。

不同的软件部署模型

云解决方案可以使用不同的模型进行部署。你决定如何部署你的应用程序取决于你所在团队的类型。在有基础设施工程师的公司,你可能会发现更多的人使用基础设施即服务IaaS)。另一方面,在 IT 不是核心业务的公司,你会发现一堆软件即服务SaaS)系统。对于开发人员来说,决定使用平台即服务PaaS)选项或者无服务器选项是很常见的,因为在这种情况下他们不需要交付基础设施。

作为软件架构师,你必须应对这种环境,并确保你在解决方案的初始开发期间以及在维护期间都在优化成本和工作因素。此外,作为架构师,你必须了解你系统的需求,并努力将这些需求与一流的外围解决方案连接起来,以加快交付速度,并使解决方案尽可能接近客户的规格。

IaaS 和 Azure 的机会

基础设施即服务是许多不同云服务提供商提供的云服务的第一代。它的定义在许多地方都很容易找到,但我们可以总结为“通过互联网提供的计算基础设施”。就像我们在本地数据中心中有服务的虚拟化一样,IaaS 也会为你提供云中的虚拟化组件,如服务器、存储和防火墙。

在 Azure 中,提供了几种基于 IaaS 模型的服务。其中大部分是收费的,在测试时需要注意这一点。值得一提的是,本书并不打算详细描述 Azure 提供的所有 IaaS 服务。然而,作为软件架构师,你只需要了解到你会找到以下这些服务:

  • 虚拟机:Windows Server、Linux、Oracle、数据科学和机器学习

  • 网络:虚拟网络、负载均衡器和 DNS 区域

  • 存储:文件、表、数据库和 Redis

要在 Azure 中创建任何服务,你必须找到最适合你需求的服务,然后创建一个资源。下面的截图显示了正在配置 Windows Server 虚拟机。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.1:在 Azure 中创建虚拟机

按照 Azure 提供的向导设置你的虚拟机,你将能够使用远程桌面协议RDP)连接到它。下一张截图展示了你部署虚拟机的一些硬件选项。考虑到我们只需点击选择按钮就可以获得不同的容量,这是一个有趣的想法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.2:Azure 中可用的虚拟机大小

如果你将本地交付硬件的速度与云交付的速度进行比较,你会意识到在上市时间方面,没有比云更好的了。例如,截图底部呈现的D64s_v3机器,具有 64 个 CPU,256GB 的 RAM 和 512GB 的临时存储,这是你在本地数据中心可能找不到的。此外,在某些用例中,这台机器可能只在一个月中的某些小时内使用,因此在本地场景中无法证明其购买是合理的。这就是云计算如此令人惊叹的原因!

IaaS 中的安全责任

安全责任是关于 IaaS 平台的另一个重要事项。许多人认为一旦你决定转向云端,所有安全问题都由提供商解决了。然而,这是不正确的,正如你在下面的截图中所看到的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.3:云计算中的安全管理

IaaS 将迫使你从操作系统到应用程序都要关注安全。在某些情况下,这是不可避免的,但你必须明白这将增加你的系统成本。

如果你只想将已经存在的本地结构转移到云端,IaaS 可能是一个不错的选择。这使得可伸缩性成为可能,因为 Azure 提供给你的工具以及所有其他服务。然而,如果你计划从头开始开发一个应用程序,你也应该考虑 Azure 上其他可用的选项。

让我们在下一节看看其中一个最快的系统,也就是 PaaS。

PaaS-开发者的无限机会

如果你正在学习或已经学习了软件架构,你可能完全理解下一句的意思:当涉及软件开发时,世界要求高速!如果你同意这一点,你会喜欢 PaaS。

正如你在前面的截图中所看到的,PaaS 使你只需要担心与你的业务更密切相关的安全方面:你的数据和应用程序。对于开发人员来说,这意味着不必实施一堆使你的解决方案安全运行的配置。

安全处理并不是 PaaS 的唯一优势。作为软件架构师,你可以将这些服务作为提供更丰富解决方案的机会。上市时间肯定可以证明许多基于 PaaS 运行的应用程序的成本。

现在在 Azure 中有很多作为 PaaS 交付的服务,再次强调,本书的目的不是列举所有这些服务。然而,有些确实需要提到。列表不断增长,建议是:尽可能多地使用和测试这些服务!确保你会以此为考虑来提供更好设计的解决方案。

另一方面,值得一提的是,使用 PaaS 解决方案,你将无法完全控制操作系统。事实上,在许多情况下,你甚至无法连接到它。大多数情况下这是好事,但在某些调试情况下,你可能会错过这个功能。好消息是,PaaS 组件每天都在不断发展,微软最关注的问题之一就是使它们广泛可见。

以下部分介绍了微软为.NET Web 应用程序提供的最常见的 PaaS 组件,例如 Azure Web 应用程序和 Azure SQL Server。我们还描述了 Azure 认知服务,这是一个非常强大的 PaaS 平台,展示了 PaaS 世界中开发的美妙之处。我们将在本书的其余部分深入探讨其中一些。

Web 应用程序

Web 应用程序是您可以用来部署 Web 应用程序的 PaaS 选项。您可以部署不同类型的应用程序,如.NET、.NET Core、Java、PHP、Node.js 和 Python。这在第一章理解软件架构的重要性中有所介绍。

好处在于创建 Web 应用程序不需要任何结构和/或 IIS Web 服务器设置。在某些情况下,如果您使用 Linux 来托管您的.NET 应用程序,您根本不需要 IIS。

此外,Web 应用程序还有一个计划选项,您无需支付使用费。当然,也有一些限制,比如只能运行 32 位应用程序,无法实现可伸缩性,但这对于原型设计来说可能是一个很好的场景。

SQL 数据库

想象一下,如果您拥有完整的 SQL 服务器的强大功能,而无需为部署此数据库而支付大型服务器的费用,您可以多快部署解决方案。这适用于 SQL 数据库。使用它们,您可以使用 Microsoft SQL Server 执行您最需要的功能-存储和数据处理。在这种情况下,Azure 负责备份数据库。

SQL 数据库甚至可以自行管理性能。这被称为自动调整。同样,使用 PaaS 组件,您将能够专注于对您的业务至关重要的事情:非常快速的上市时间。

创建 SQL 数据库的步骤非常简单,就像我们之前为其他组件所见的那样。但是,有两件事情需要注意:服务器本身的创建以及如何收费。

当您创建资源时,您可以搜索SQL 数据库,您将找到此向导来帮助您:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.4:在 Azure 中创建 SQL 数据库

SQL 数据库依赖于 SQL 服务器来托管它。因此,正如您所看到的,您必须创建(至少对于第一个数据库)一个database.windows.net服务器,您的数据库将托管在那里。该服务器将提供您访问 SQL 服务器数据库所需的所有参数,如 Visual Studio、SQL Server 管理工作室和 Azure 数据工作室等当前工具。值得一提的是,您有许多关于安全性的功能,如透明数据加密和 IP 防火墙。

一旦您决定数据库服务器的名称,您将能够选择系统将收费的定价层。特别是在 SQL 数据库中,有几种不同的定价选项,如您在下面的截图中所见。您应该仔细研究每一个,因为根据您的情况,通过优化定价层,您可能会节省一些费用:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.5:配置 Azure SQL 数据库定价层

有关 SQL 配置的更多信息,您可以使用此链接:azure.microsoft.com/en-us/services/sql-database/

一旦您完成配置,您将能够以与在本地安装 SQL 服务器时相同的方式连接到此服务器数据库。您需要注意的唯一细节是 Azure SQL 服务器防火墙的配置,但这很容易设置,并且很好地展示了 PaaS 服务的安全性。

Azure 认知服务

人工智能AI)是软件架构中最经常讨论的话题之一。我们离一个真正伟大的世界只有一步之遥,那里人工智能将无处不在。为了实现这一目标,作为软件架构师,您不能一直把人工智能视为您需要一直从头开始重新发明的软件。

Azure 认知服务可以帮助您解决这个问题。在这组 API 中,您将找到各种开发视觉、知识、语音、搜索和语言解决方案的方法。其中一些需要进行训练才能实现,但这些服务也提供了相应的 API。

PaaS 的优点从这个场景中可以看出。在本地环境或 IaaS 环境中,您需要执行大量任务来准备应用程序。在 PaaS 中,您无需担心这个。您完全专注于作为软件架构师真正关心的问题:解决业务问题的解决方案。

在 Azure 帐户中设置 Azure 认知服务也非常简单。首先,您需要像添加其他 Azure 组件一样添加认知服务,如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.6:在 Azure 中创建认知服务 API

一旦完成这一步,您就可以使用服务器提供的 API。您将在创建的服务中找到两个重要的功能:端点和访问密钥。它们将在您的代码中用于访问 API。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.7:创建的认知服务端点

以下代码示例展示了如何使用认知服务来翻译句子。这个翻译服务的主要概念是,您可以根据设置服务的密钥和区域,发布您想要翻译的句子。以下代码使您能够向服务 API 发送请求:

private static async Task<string> PostAPI(string api, string key, string region, string textToTranslate)
{
   using var client = new HttpClient();
   using var request = new HttpRequestMessage(HttpMethod.Post, api);
   request.Headers.Add("Ocp-Apim-Subscription-Key", key);
   request.Headers.Add("Ocp-Apim-Subscription-Region", region);
   client.Timeout = TimeSpan.FromSeconds(5);
   var body = new[] { new { Text = textToTranslate } };
   var requestBody = JsonConvert.SerializeObject(body);
   request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json");
   var response = await client.SendAsync(request);
      response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStringAsync();
} 

值得一提的是,上述代码将允许您将任何文本翻译为任何语言,前提是您在参数中定义了它。以下是调用前面方法的主程序:

static async Task Main()
{
   var host = "https://api.cognitive.microsofttranslator.com";
   var route = "/translate?api-version=3.0&to=es";
   var subscriptionKey = "[YOUR KEY HERE]";
   var region = "[YOUR REGION HERE]";

   var translatedSentence = await PostAPI(host + route,
   subscriptionKey,region, "Hello World!");

   Console.WriteLine(translatedSentence);

} 

有关更多信息,请访问docs.microsoft.com/en-us/azure/cognitive-services/translator/reference/v3-0-languages

这是一个完美的例子,展示了您可以多么轻松快速地使用此类服务来构建项目。此外,这种开发方法非常好,因为您使用的是已经经过其他解决方案测试和使用的代码片段。

SaaS - 只需登录并开始使用!

SaaS 可能是使用基于云的服务最简单的方式。云服务提供商为其最终用户提供了许多解决公司常见问题的好选择。

Office 365 是这种类型服务的一个很好的例子。这些平台的关键点在于您无需担心应用程序的维护。这在您的团队完全专注于开发应用程序的核心业务的场景中特别方便。例如,如果您的解决方案需要提供良好的报告,也许您可以使用 Power BI 进行设计(Power BI 包含在 Office 365 中)。

另一个很好的 SaaS 平台例子是 Azure DevOps。作为软件架构师,在 Azure DevOps 之前,您需要安装和配置 Team Foundation Server(TFS)(甚至是更早的工具,如 Microsoft Visual SourceSafe),以便团队使用共享存储库和应用程序生命周期管理工具。

我们过去花了很多时间,要么是为 TFS 安装准备服务器,要么是升级和持续维护已安装的 TFS。由于 SaaS Azure DevOps 的简单性,这不再需要。

理解无服务器的含义

无服务器解决方案是一种不关注代码运行位置的解决方案。即使在“无服务器”解决方案中,仍然存在服务器。问题在于,您不知道或不关心代码在哪个服务器上执行。

您现在可能会认为无服务器只是另一种选择——当然,这是真的,因为这种架构并没有提供完整的解决方案。但这里的关键是,在无服务器解决方案中,您拥有一个非常快速、简单和灵活的应用程序生命周期,因为几乎所有无服务器代码都是无状态的,并且与系统的其余部分松散耦合。一些作者将此称为函数即服务FaaS)。

当然,服务器总是运行在某个地方。这里的关键是您不需要担心这一点,甚至扩展性。这将使您完全专注于您的应用业务逻辑。再次强调,世界需要快速开发和良好的客户体验。您越专注于客户需求,就越好!

第十章“使用 Azure 函数”中,您将探索微软在 Azure 中提供的最佳无服务器实现之一——Azure 函数。在那里,我们将重点介绍如何开发无服务器解决方案以及它们的优缺点。

为什么在许多情况下混合应用如此有用?

混合解决方案是指其部分不共享统一的架构选择的解决方案;每个部分都做出不同的架构选择。在云中,混合一词主要指混合云子系统与本地子系统的解决方案。然而,它也可以指混合网络子系统与特定设备子系统,如移动设备或任何运行代码的其他设备。

由于 Azure 可以提供的服务数量以及可以实现的设计架构数量,混合应用可能是本章主要讨论的主要问题的最佳答案,即如何在项目中利用云所提供的机会。如今,许多当前项目正在从本地解决方案转移到云架构,并且根据您将要交付这些项目的地方,您仍然会发现许多关于转移到云的错误先入之见。其中大部分与成本、安全性和服务可用性有关。

您需要了解这些先入之见中有一些真理,但人们的想法并非如此。当然,作为软件架构师,您不能忽视它们。特别是在开发关键系统时,您必须决定是否一切都可以在云上运行,还是最好将系统的一部分交付到边缘。

边缘计算范式是一种用于在更靠近所需位置的机器或设备上部署系统部分的方法。这有助于减少响应时间和带宽消耗。

移动解决方案可以被视为混合应用的经典示例,因为它们将基于 Web 的架构与基于设备的架构混合在一起,以提供更好的用户体验。有许多情况可以用响应式网站替换移动应用程序。然而,当涉及界面质量和性能时,也许响应式网站无法给最终用户真正需要的东西。

在下一节中,我们将讨论书中用例的实际示例。

书中用例——哪种云解决方案最好?

如果您回到第一章“理解软件架构的重要性”,您将找到一个系统要求,描述了我们的 WWTravelClub 示例应用程序应该运行的系统环境。

SR_003:系统应该在 Windows、Linux、iOS 和 Android 平台上运行。

乍一看,任何开发人员都会回答:Web 应用。然而,iOS 和 Android 平台也需要您作为软件架构师的关注。在这种情况下,就像在几种情况下一样,用户体验是项目成功的关键。决策不仅需要由开发速度驱动,而且还需要由提供出色用户体验所获得的好处驱动。

在这个项目中,软件架构师必须做出的另一个决定与移动应用程序的技术相关,如果他们决定开发一个的话。同样,这将是在混合和本地应用程序之间做出选择,因为在这种情况下,可以使用诸如 Xamarin 之类的跨平台解决方案。因此,对于移动应用程序,您也可以选择继续使用 C#编写代码。

以下屏幕截图代表了 WWTravelClub 架构的第一个选择。依赖 Azure 组件的决定与成本和维护考虑相关。这些项目中的每一项将在本书的后续部分中讨论,在第八章在 C#中与数据交互-Entity Framework Core第九章如何在云中选择您的数据存储,以及第十章使用 Azure Functions,以及选择的原因。现在,知道 WWTravelClub 是一个混合应用程序,在移动设备上运行 Xamarin 应用程序,并在服务器端运行 ASP.NET Core Web 应用程序就足够了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4.8:WWTravelClub 架构

正如您在图片中所看到的,WWTravelClub 架构主要是由 Azure 提供的 PaaS 和无服务器组件设计的。所有的开发将在 Azure DevOps SaaS Microsoft 平台上进行。

在我们设想的 WWTravelClub 场景中,赞助商已经指出 WWTravelClub 团队中没有人专门从事基础设施。因此,软件架构使用 PaaS 服务。考虑到这种情况和所需的开发速度,这些组件肯定会表现良好。

当我们在本书讨论的章节和技术中飞速前进时,这种架构将会发生变化和演变,而不会受到任何早期选择的限制。这是 Azure 和现代架构设计提供的绝佳机会。随着解决方案的演变,您可以轻松更改组件和结构。

总结

在本章中,您学会了如何利用云中提供的服务以及您可以选择的各种选项来解决问题。

本章介绍了以云为基础结构提供相同应用程序的不同方式。我们还注意到微软是如何迅速为其客户提供所有这些选项的,因为您可以在实际应用程序中体验所有这些选项,并选择最适合您需求的选项,因为没有适用于所有情况的灵丹妙药。作为软件架构师,您需要分析您的环境和团队,然后决定在解决方案中实施最佳的云架构。

下一章专门讲述了如何构建由称为微服务的小型可扩展软件模块组成的灵活架构。

问题

  1. 为什么应该在解决方案中使用 IaaS?

  2. 为什么应该在解决方案中使用 PaaS?

  3. 为什么应该在解决方案中使用 SaaS?

  4. 为什么应该在解决方案中使用无服务器?

  5. 使用 Azure SQL Server 数据库的优势是什么?

  6. 如何在应用程序中使用 Azure 加速 AI?

  7. 混合架构如何帮助您设计更好的解决方案?

进一步阅读

您可以查看这些网页链接,以决定在本章中涵盖的哪些主题您应该深入学习:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值