教程的问题
2022 年 3 月 8 日,作者:Burke Holland,@burkeholland
撰写一篇出色的教程并非易事。我深有体会——我写过很多教程,但并非每一篇都取得了巨大的成功。
事实证明,制作一篇出色的教程的关键不在于你写了什么,而在于开发者是否能在不阅读每个字的情况下取得成功。在本文中,我们将探讨开发容器如何减少用户可能遇到的错误,以及 Laravel PHP 项目 如何在其教程中优雅地实现这一点并取得了显著效果。
没人会阅读
我们关于 如何在 Visual Studio Code 中使用开发容器 的教程一直以来完成率都很低——大约只有 4% 到 6%。

为了弄清楚人们在哪里放弃了,我们进行了用户研究,并观察了人们尝试完成我们教程的过程。那过程……令人痛苦。
人们无法完成教程的原因立即变得清晰起来:没人会阅读它。人们跳过了说明,直接进入操作步骤。不可避免地,他们会因为犯了一个错误而卡住,如果他们阅读了说明,就不会犯这个错误。
宾夕法尼亚州立大学教授 John M. Carroll 在他的重要著作《纽伦堡漏斗——为实用计算机技能设计极简主义教学法》(The Nurnberg Funnel - Designing Minimalist Instruction for Practical Computer Skill)中讨论了这个问题。他写道:“[学习者]太忙于学习,以至于无法充分利用指导。这是意义构建的悖论。”
我对此深有体会,你可能也是。当我浏览教程时,我的眼睛在寻找代码块,因为我正试图通过实践来学习。我真的太忙于学习而无暇阅读说明。
人们不会阅读你的教程。或者至少不会像你希望的那样多。你能做的最好的事情就是尽可能多地移除读者在学习过程中可能犯错的地方。其中一种方法是使用预配置的容器环境,完全移除任何环境设置步骤。
容器化开发环境
任何教程中很大一部分通常都致力于一长串的先决条件和环境设置。我清楚地记得尝试学习 Ruby on Rails 时,大部分时间都在努力在 Windows 上正确安装 Ruby,想知道“gem”到底是什么,为什么它们总是缺失。
容器化开发环境背后的理念是你在 Docker 容器内部进行开发。这使得拥有一个完全可移植、完全配置的开发环境成为可能,你可以随意启动或关闭它。然后,你可以将这个环境作为一组配置文件提供给其他人。
但是如何在容器内部进行开发呢?容器又没有一个你可以直接启动 VS Code 的 UI。
VS Code 的 开发容器 扩展正是这样做的。它既包含将 Docker 容器配置为开发环境的机制,又允许你从 VS Code 连接到该环境。它是通过在容器内部安装一个小型的服务器组件来实现的,你的本地 VS Code 与之通信。然后你就像在本地一样进行开发,但 VS Code 连接的是容器环境而不是你的本地环境。

为了创建容器化开发环境,你通常需要对 Docker 有所了解。很多人确实了解,但很多人不了解(你看不到我,但我的手正举着),所以这个扩展试图尽可能多地抽象容器设置过程。我设置了一个新的 Python 容器。一个向导会引导你选择基础镜像和 Python 版本。然后它让你有机会通过一个选择列表向镜像添加额外的软件。在这种情况下,我添加了 Azure CLI、Dotnet CLI 和 PowerShell……

这个过程会向该项目添加一个 .devcontainer 文件夹,其中包含必要的 Dockerfile。它还会添加一个 devcontainer.json 文件,这是定义开发容器各个方面的标准,例如应该安装哪些扩展,在容器构建后应该运行哪些设置命令等等。由于你对环境及其设置拥有完全控制权,你可以自动化几乎所有事情——包括依赖项安装、库版本等。
通过这种方式,你可以字面上地交给某人一个完整的、即用型的环境,无需额外的设置步骤,也不会因为 Ruby gems 而引发生存危机。
一些人已经在使用基于开发容器的方法,让他们的用户快速启动和运行原本非常复杂的环境。Laravel PHP 框架就是一个很好的例子。
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 container,你会在 /var/www/html 文件夹中看到你的项目。Docker 将你的机器上的项目“挂载”到容器中,因此你在开发时所做的任何更改都会在刷新应用程序时反映出来。

添加开发容器
对 开发容器 扩展的支持也已添加。要将适当的开发容器配置添加到此项目,你可以搭建相同的项目并添加 &devcontainer 标志。
curl -s "https://laravel.build/example-app?with=mysql,redis&devcontainer" | bash
请注意,如果你想向现有的 Sail/Laravel 项目添加开发容器,可以通过运行
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)