教程的问题
2022 年 3 月 8 日,作者 Burke Holland,@burkeholland
写一篇优秀的教程并不容易。我深有体会——我写过很多教程,但并非每个都取得了巨大成功。
事实证明,制作一个优秀的教程不是关于你写了什么,而是关于开发者是否无需阅读每个字就能成功。在本文中,我们将探讨开发容器如何减少用户可能遇到的错误,以及 Laravel PHP 项目如何在他们自己的教程中优雅地实现这一点,并取得了巨大成效。
没人阅读
我们自己关于如何在 Visual Studio Code 中使用开发容器的教程,长期以来完成率都很低——大约只有 4 - 6%。
为了找出人们放弃的地方,我们进行了用户研究,并观察人们如何尝试完成我们的教程。这……太痛苦了。
人们无法完成教程的原因立刻变得清晰:没有人阅读它。人们跳过说明,直接进入操作步骤。不可避免地,他们会因为犯了如果阅读说明本可以避免的错误而卡住。
宾夕法尼亚州立大学教授John M. Carroll在他的开创性著作《纽伦堡漏斗——为实用计算机技能设计极简指令》中谈到了这一点。他写道:“[学习者]忙于学习,以至于无法充分利用指令。这就是理解的悖论。”
我对此感同身受,你可能也一样。当我学习教程时,我的眼睛会扫描代码块,因为我试图通过实践来学习。我真的忙于学习,没时间看说明。
人们不会阅读你的教程。或者至少不会像你希望的那样多。你所能做的最好的事情就是尽可能多地消除读者在学习过程中可能出错的地方。一种方法是使用预配置的容器环境,完全移除所有环境设置步骤。
容器化开发环境
任何教程的很大一部分通常都专门用于列出一长串先决条件和环境设置。我清楚地记得,在学习 Ruby on Rails 时,大部分时间都花在了试图在 Windows 上正确安装 Ruby 上——纳闷“gem”到底是什么,以及为什么它们总是莫名其妙地缺失。
容器化开发环境的理念是你在 Docker 容器内部进行开发。这使得拥有一个完全可移植、完全配置的开发环境成为可能,你可以随意启动或关闭它。然后你可以将这个环境以配置文件的形式提供给他人。
但是,你如何在容器内进行开发呢?容器又没有用户界面,可以让你直接启动 VS Code。
VS Code 的 开发容器 扩展正是做这件事的。它包含了将 Docker 容器配置为开发环境的机制,以及允许你从 VS Code 连接到该环境的功能。它通过在容器内安装一个小型服务器组件来实现这一点,你的本地 VS Code 与该组件通信。然后你就可以像在本地开发一样进行开发,但 VS Code 连接的是容器环境而不是你的本地环境。
为了创建容器化开发环境,通常你需要了解一些 Docker 知识。很多人确实了解,但很多人不了解(你可能看不到我,但我举起了手),所以这个扩展试图尽可能地抽象容器设置过程。我设置了一个新的 Python 容器。一个向导会引导你选择基础镜像和 Python 版本。然后它会给你机会通过一个选择列表向镜像添加额外的软件。在这种情况下,我添加了 Azure CLI、Dotnet CLI 和 PowerShell……
这个过程会向此项目添加一个包含必要 `Dockerfile` 的 `.devcontainer` 文件夹。它还会添加一个 `devcontainer.json` 文件,这是定义开发容器各方面(例如应该安装哪些扩展、容器构建后应该运行哪些设置命令等)的标准。由于你对环境及其设置拥有完全控制权,因此你可以几乎自动化所有事情——包括依赖项安装、库版本等。
通过这种方式,你可以字面上地交给某人一个完整、即用的环境,无需额外的设置步骤或因 Ruby gems 而引发的存在危机。
一些人已经在使用基于开发容器的方法,帮助他们的用户快速启动和运行那些原本非常复杂的环境。一个很好的例子是 PHP 的 Laravel 框架。
Laravel 解决方案
Laravel 是一个开源的 PHP MVC 框架。它非常全面,因为它还包括对象关系映射器 (ORM)、直接数据库访问、打包系统等。Laravel 可以做很多事情。为了体验它,你在开始时至少需要一个数据库。通常,这会要求用户不仅安装 PHP,还需要安装数据库——通常是 MySQL。当用户只是想尝试你的框架时,这是一个相当大的要求。
Laravel 通过容器化开发环境和名为 Sail 的工具解决了这个问题。要从零开始使用 Laravel、MySQL 服务器和 Redis 缓存,你只需运行一个命令……
curl -s "https://laravel.build/example-app?with=mysql,redis" | bash
这会创建一个包含 `docker-compose` 文件的新项目。该文件设置了三个容器——一个应用程序容器、一个 MySQL 容器和一个 Redis 容器。你无需了解任何关于容器或这三个服务的信息。Sail 会为你抽象所有这些。然后你执行 Sail 命令来启动环境……
./vendor/bin/sail up
示例应用程序只是运行。无需安装 PHP。无需安装 Laravel。无需依赖项解析步骤。只有即时成功。
我指定了我们的项目有一个 MySQL 服务器和 Redis 缓存,所以当项目启动时,我们实际上会得到三个容器。我们可以通过 VS Code 的 Docker 扩展来查看。
这些容器相互联网,因此我们可以从应用程序容器调用 MySQL 或 Redis 缓存容器。
如果您将交互式终端连接到 `sail-8.1/app 容器`,您将在 `/var/www/html` 文件夹中看到您的项目。Docker 将项目从您的机器“挂载”到容器中,因此您在开发时所做的任何更改都会在刷新时反映到应用程序中。
添加开发容器
也已添加对开发容器扩展的支持。要将正确的开发容器配置添加到此项目,您可以搭建相同的项目并添加 `&devcontainer` 标志。
curl -s "https://laravel.build/example-app?with=mysql,redis&devcontainer" | bash
请注意,如果您想向现有 Sail/Laravel 项目添加 devcontainer,可以通过运行 `php artisan sail:install --devcontainer` 来完成。
这将创建相同的项目配置,但会包含一个 `.devcontainer` 文件夹。VS Code 会自动检测该文件夹并提示您在容器中重新打开项目,从而跳过所需的 `sail up` 步骤。
VS Code 连接到容器,因此您是在容器环境中进行开发,而不是在本地环境中。您可以通过 VS Code 左下角的远程指示器来识别这一点……
在容器内而不是容器外进行开发具有一些显著的优势。
开发上下文与应用上下文镜像
连接到容器时,您进行开发的上下文与应用程序运行的上下文相同。因此,您的终端将成为容器的终端……
开发容器扩展还为您提供了更完整的视图,例如哪些端口被转发——以防您忘记应用程序正在运行的位置。
Laravel 应用程序会自动启动,并且应用程序日志会通过管道传输到容器日志。由于您可能希望了解应用程序中发生的情况,开发容器扩展在 VS Code 中提供了一个新视图,您可以在其中查看所有正在运行的容器,并连接到流式容器日志。
自动化开发环境设置
最佳的开发者体验将包括编辑器的自定义设置。这包括编辑器本身的设置,以及需要添加到开箱即用体验中的任何扩展或其他支持。
对于 VS Code 和 Laravel,扩展在 `devcontainer.json` 中被建议,但被注释掉,因此它们不会自动安装。这允许用户从一组已识别的扩展中进行选择,而不必费力寻找配置编辑器的正确方法。
...
"extensions": [
// "mikestead.dotenv",
// "amiralizadeh9480.laravel-extra-intellisense",
// "ryannaddy.laravel-artisan",
// "onecentlin.laravel5-snippets",
// "onecentlin.laravel-blade"
],
少读多做
人们不爱阅读。这应该没问题。Laravel 的教程不一定比其他的短,但重要的是,如果你跳到代码并直接运行命令,它就能工作。开发容器使这成为可能。现在,如果我们能弄清楚如何为我们自己的使用 Docker 容器作为 Visual Studio Code 的开发环境教程制作一个开发容器就好了……
编程愉快!
Burke Holland (@burkeholland)