65.9K
CodeProject 正在变化。 阅读更多。
Home

Excelsior!在没有安全网的情况下构建应用程序 - 第 0 部分

starIconstarIconstarIconstarIconstarIcon

5.00/5 (9投票s)

2021年5月12日

CPOL

12分钟阅读

viewsIcon

8318

介绍一个系列文章,我们将构建一个应用程序,展示编写整个应用程序的思考过程。

引言

我记得,作为一个年轻的开发者,我曾经对那些似乎不费吹灰之力就能坐下来编码的人感到敬畏。系统似乎毫不费力地从他们的指尖流淌出来,制作精巧,优雅而精致。感觉就像我正在见证米开朗基罗在西斯廷教堂里,或者莫扎特坐在一张新鲜的五线谱前。当然,随着经验的增长,我现在知道我所看到的是开发者在做开发者所做的事情。有些人做得很好,真正理解开发的技巧,而另一些人则生产出不那么优雅、写得不好的作品。多年来,我有幸向一些出色的开发者学习,但我一次又一次地回到同一个基本问题,那就是……

如果我能听到其他开发者在编写应用程序时的思考过程,我现在作为开发者会好多少?

在本系列文章中,我将带您了解我在开发应用程序时的思考过程。文章附带的代码将以“原生态”的方式开发,这样您就可以看到我是如何将一个东西从初始需求阶段带到我乐于让其他人使用的状态。这意味着这些文章将展示我犯的每一个错误以及我在充实想法时采取的捷径。我不会声称我是一个伟大的开发者,但我足够胜任和经验丰富,这应该能帮助这个领域的新手更早地克服他们的敬畏,并获得自信。

目标受众

这些文章面向希望了解构建应用程序时思维过程的初级开发者。它们也适用于那些只想在某人犯下我在这系列文章中无疑会犯下的巨大错误时一笑了之的高级开发者。

注意事项

现在,我心里还没有任何代码。我还没有做出决定。我只有一组初始需求,很快就会在这篇介绍性文章中描述。作为一个独立开发,这不会遵循敏捷或瀑布开发等方法;我将要进行的开发更可能与敏捷对齐,但我不需要遵循这些方法。

通常,当我写文章时,我倾向于使用第三人称,以使内容更具包容性。但在本系列中我不会这样做,因为重点是让您“听到”我的思考过程。

我必须警告您,这些文章的文字会比代码多得多。我将解释我为什么做出某些决定,而且可能会有很多重构,这意味着我必须解释我为什么这样做。显然,我并非一张白纸,这意味着会有很多假设的知识;我以前做过的一些事情,我会本能地去使用,我为此道歉,但这种情况将会发生。当我这样做时,我会尝试通过解释或链接到其他解释得很好的来源来解决这个问题。有时我可能会遗漏这一点,所以如果您遇到这种情况,请给我留言,我会尝试解决。

现在,我脑中只有我的高层要求以及我最初将用于开发的语言。让我们把这些记录下来,开始这个过程。

我们将要构建什么

我构建了很多 RESTful API。这意味着我花了很多时间测试它们。我大量使用 Postman 和 Swagger,但它们有其局限性。如果您没用过 Swagger,它常与 REST API 一起使用,作为一种通过可视化界面测试它们的方式(好的,Swagger 的功能远不止于此,但为了我们即将构建的内容,我们只关注它的这一方面)。同样,Postman 是一款第三方工具,允许我们从编辑器向 API 编写请求,并接收响应。要使用 Swagger,代码必须嵌入到 API 中。如果没有嵌入,就无法使用。虽然我喜欢 Postman,但我发现随着时间的推移,它会变慢,并且界面会冻结。因此,基于此,我有了以下需求和约束:

  • 我想要一个应用程序,允许我向 API 发送请求。
  • 最初,我希望发送的请求是 GETPUTPOSTDELETEPATCH 请求。
  • 请求可以有请求头
  • 请求可以有请求体和/或参数
  • 应用程序将接收来自 API 的响应
  • 响应将被解码
  • 我将用 C# 语言开发请求/响应代码
  • 我将至少使用 .NET 5 进行开发

虽然我使用 Visual Studio 和 JetBrains Rider 进行 C# 开发,但这都可以通过 Visual Studio Code 等编辑器完成,所以我将展示一些 dotnet 命令以及开发过程。在接下来的章节中,我们将看到 dotnet 命令如何被不想使用 Rider 或 Visual Studio 等 IDE 的人使用,以及如何添加文件来帮助那些想使用 IDE 的人。

本系列

本系列包含以下文章

入门

这可能听起来很傻,但我在这里要做的第一个决定之一就是如何命名这个应用程序?我的代码解决方案名称需要与应用程序的最终名称匹配吗?在我脑海深处,我有一个想法,希望名称基于“Excelsior”这个词,仅仅是因为我喜欢已故的伟大人物斯坦·李,而这是他采用的座右铭。我打算给这个词加一点“时髦”感,所以我要把它改成 xlcr(发音为 EX EL CEE AR)。这个项目将在 Github 上发布,所以我需要检查它在那里是否已被使用。

哇,这真糟糕。有人已经在 GitHub 上占用了 xlcr,所以我需要回去重新考虑产品名称。我的下一个想法是,我偶尔会给项目起一个“异想天开”的名字“Goldlight”;是的,这是对旧版 Silverlight 产品的玩味,并且与很久以前添加了一些帮助 Silverlight 开发的功能有关,这些 Silverlight 辅助工具被称为 Goldlight。多年来,我一直重温这个名字,所以我要将它们合并(我确信斯坦·李会赞成这种“合并”!),创建 Goldlight.Xlcr。

快速的谷歌搜索显示这个名字没有被使用,所以是时候用这个名字创建一个 dotnet 解决方案了。我将从为解决方案创建一个文件夹开始。

mkdir goldlight.xlcr

测试困境

在这一点上,我需要做出一些决定。我是否会编写单元测试来配合我的代码?我是否会遵循测试驱动开发(TDD)?我不得不将这些问题口头化可能听起来很傻,但无论有意无意,它们都会影响我们编写代码的方式。我们肯定会编写单元测试,在我看来这是毋庸置疑的,但第二个问题需要更多思考。

如果您以前没有接触过测试驱动开发(TDD),它的理念很简单——在没有为代码编写测试之前,您不会编写任何代码。这似乎是一个反直觉的想法,但实际上它非常简单。您编写一个会失败的测试。您编写最少的代码来使该测试通过。您围绕该代码编写另一个测试,进一步完善它,并使其失败。您完善代码以使其通过,依此类推。这里的想法是,您将测试视为开发过程中的有机组成部分,因此您自然会开始考虑什么可能会破坏您的代码。TDD 做得好的美妙之处在于,当您重构代码时,它可以帮助您轻松得多。换句话说,如果您更改代码以使用改进的算法,那么您的测试应该为您提供安全网,确保您所做的任何更改仍然有效而没有意外的副作用。

当我为是否在此开发中遵循 TDD 而纠结时,我不得不权衡以下事实:遵循这种方法可能会模糊我试图通过文章传授的内容。这些文章可能会变成我编写失败的测试条件、修复测试、编写更多失败的测试等等的乏味重复。我意识到这对于阅读文章的您来说可能会很困难。与此同时,我已经从事 TDD 很久了,它是我工作方式中自然的一部分,所以我倾向于本能地遵循它。我必须权衡的是,TDD 的实践可能会模糊我试图传达的思维过程,因为我最终会专注于代码的小部分,并展示如何为其编写测试,而没有明确这些小组件如何融入更大的图景。

最终,我认为最好的折衷方案是让我开始使用 TDD 来开发本系列。如果我发现文章的叙述由于这种对测试的关注而变得难以理解,那么我将放弃这种方法。至少,到那时,您将已经看到了足够的实践,可以理解我为什么这样工作,并且您可以选择是否将其作为您日常开发风格的一部分。

添加项目

既然我决定了至少目前遵循 TDD,我将添加一个项目来存放我的测试。因此,在解决方案文件夹内,我将添加一个用于测试的子文件夹,以及另一个存放实际源代码的文件夹。

chdir goldlight.xlcr
mkdir tests 
mkdir src

但我首先要写什么?我将通过我的第一组测试和代码来满足哪些需求?我将在我的项目中如何布局?

系统的核心是处理请求和响应,所以我将从考虑发送 GET 请求到端点的代码开始。这是最简单的 API 请求之一,因此是一个很好的起点。由于请求是系统的核心,我将把包含此功能的项目命名为 goldlight.xlcr.core。每当我测试一个项目时,我喜欢将测试项目命名为相同,并在末尾加上 .tests。这有助于我一目了然地看到哪些测试与哪些代码相关联,因此我们的测试将位于 goldlight.xlcr.core.tests 中。我将在 src 文件夹中添加一个 goldlight.xlcr.core 文件夹,并在 tests 文件夹中添加一个 goldlight.xlcr.core.tests 文件夹。

现在,在 goldlight.xlcr.core 文件夹中,我将添加一个类库来存放核心逻辑。添加它就像运行以下命令一样简单:

dotnet new classlib --name goldlight.xlcr.core --output src/goldlight.xlcr.core

当我添加类库和单元测试时,我使用的是小写名称,因为我考虑到基于 Linux 的环境中的命名约定。由于我们针对的是 .NET Core,我有一个想法,我也可以在非 Windows 环境中部署应用程序。正如我们将在本文后面看到的那样,这个决定确实对代码中生成的命名空间有影响。我将演示如何在以后将命名空间恢复为更常见的 Pascal 命名约定。

我还想创建一个单元测试项目。开箱即用的 dotnet 命令支持许多测试框架。我喜欢使用 xUnit 来运行测试,所以我会将其用于项目。测试框架的选择是任意的个人偏好。有些人喜欢使用 nUnit,另一些人喜欢使用 Visual Studio 测试。对我来说,xUnit 的语法很吸引我,因为它非常符合我对测试的看法。

dotnet new xunit --name goldlight.xlcr.core.tests --output tests/goldlight.xlcr.core.tests

我不会将测试代码交付给任何人,所以我需要确保单元测试项目引用类库。为此,我必须运行以下命令:

chdir tests\goldlight.xlcr.core.tests
dotnet add reference ..\..\src\goldlight.xlcr.core\goldlight.xlcr.core.csproj

最后,我想添加一个 Visual Studio 解决方案文件并添加这些项目,这样如果我想的话,就可以在 Visual Studio 或 Rider 中打开代码。

chdir ..\..
dotnet new sln --name goldlight.xlcr
dotnet sln add src/goldlight.xlcr.core/goldlight.xlcr.core.csproj
dotnet sln add tests/goldlight.xlcr.core.tests/goldlight.xlcr.core.tests.csproj

你可能还记得我说过我想把这个项目上传到 Git。我将让 dotnet 为我添加一个合适的 .gitignore 文件,这样我就不会尝试上传 binobj 文件。

dotnet new gitignore

最后,我将恢复所有已添加的 NuGet 包,并构建解决方案。

dotnet restore
dotnet build

我现在已经完成了命令行操作,接下来我将开始使用 Rider 或 Visual Studio。

后续步骤

现在我已经创建了项目和解决方案,我已经准备好开始编写应用程序本身了。在下一部分,我将开始编写代码的过程。

历史

  • 2021年5月12日:初始版本
© . All rights reserved.