參加你附近的 ,瞭解 VS Code 中的 AI 輔助開發。

教程的問題

2022年3月8日,作者:Burke Holland, @burkeholland

編寫一篇出色的教程並非易事。我深有體會——因為我寫過很多,但並非每一篇都大獲成功。

事實證明,寫出好教程的關鍵不在於你寫了什麼,而在於開發者是否無需閱讀每個字就能成功上手。在本文中,我們將探討開發容器如何減少使用者可能遇到的錯誤,以及 Laravel PHP 專案 如何在其教程中優雅地實現這一點,並取得了巨大成功。

沒人會閱讀

我們自己關於如何在 Visual Studio Code 中使用開發容器的教程,完成率一直很低——大約在 4% 到 6% 之間。

dev containers learn module screenshot

為了找出人們在哪個環節放棄,我們進行了使用者研究,觀察人們嘗試完成我們教程的過程。那場面……相當痛苦。

人們無法完成教程的原因顯而易見:根本沒人閱讀。大家直接跳過說明,直奔操作步驟。結果不可避免地,他們會因為犯下某個錯誤而卡住,而如果他們讀了說明,這個錯誤本可以避免。

賓夕法尼亞州立大學教授 John M. Carroll 在他的開創性著作《The Nurnberg Funnel - Designing Minimalist Instruction for Practical Computer Skill》中談到了這一點。他寫道:“[學習者] 忙於學習,以至於無暇充分利用說明。這就是‘意義建構的悖論’。”

對此我感同身受,你可能也一樣。當我在看一篇教程時,我的眼睛會掃描程式碼塊,因為我想透過實踐來學習。我真的太忙於學習,以至於沒時間閱讀說明。

人們不會閱讀你的教程。至少不會像你希望的那樣仔細閱讀。你能做的最好的事情,就是儘可能地消除學習過程中可能出錯的地方。其中一種方法是使用預配置的容器環境,完全移除任何環境設定步驟。

容器化開發環境

任何教程的很大一部分通常都專門用於羅列一長串的先決條件和環境設定。我清楚地記得,當初我嘗試學習 Ruby on Rails 時,大部分時間都花在如何在 Windows 上正確安裝 Ruby 上——搞不清楚“gem”到底是什麼,以及為什麼它們好像全都缺失了。

容器化開發環境的理念是,你在一個 Docker 容器內部進行開發。這使得擁有一個完全可移植、配置齊全的開發環境成為可能,你可以隨時啟動或銷燬它。然後,你可以將這個環境以一組配置檔案的形式交給別人。

但是,你如何在一個容器內部進行開發呢?容器又不像有使用者介面,可以讓你直接啟動 VS Code。

VS Code 的 Dev Containers 擴充套件正是為此而生。它既包含了將 Docker 容器配置為開發環境的機制,也允許你從 VS Code 連線到該環境。它透過在容器內安裝一個小型伺服器元件來實現這一點,你本地的 VS Code 會與該元件通訊。然後,你就像在本地開發一樣,只不過 VS Code 連線的是容器環境,而不是你的本地環境。

The Dev Containers extension screenshot from extension gallery

為了建立一個容器化的開發環境,你通常需要對 Docker 有所瞭解。很多人確實瞭解,但也有很多人瞭解(你看不到我,但我舉手了),所以該擴充套件試圖儘可能地將容器設定過程抽象化。我設定了一個新的 Python 容器。一個嚮導會引導你選擇基礎映象和 Python 版本。然後,它讓你有機會透過一個選擇列表向映象中新增額外的軟體。在這個例子中,我添加了 Azure CLI、Dotnet CLI 和 PowerShell……

Adding a dev container configuration to a Python project

這個過程會在專案中新增一個 .devcontainer 資料夾,其中包含必要的 Dockerfile。它還會新增一個 devcontainer.json 檔案,這是一個定義開發容器各方面特性的標準檔案,比如應該安裝哪些擴充套件、容器構建後應該執行哪些設定命令等。由於你可以完全控制環境及其設定,你幾乎可以自動化所有事情——包括依賴安裝、庫版本等。

透過這種方式,你完全可以把一個完整、即用型的環境交給別人,而不需要任何額外的設定步驟,也不會讓他們因為 Ruby gem 而陷入存在危機。

一些人已經在使用基於開發容器的方法,來幫助他們的使用者快速上手那些原本非常複雜的環境。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,也無需解決依賴問題。立刻就能成功。

An example Laravel application running in the browser on localhost

我指定了我們的專案有一個 MySQL 伺服器和一個 Redis 快取,所以當專案啟動時,我們實際上得到了三個容器。我們可以使用 VS Code 的 Docker 擴充套件來看到這一點。

The Docker extension in VS Code

這些容器透過網路連線在一起,這樣我們就可以從應用容器中呼叫 MySQL 或 Redis 快取容器。

如果你將一個互動式終端連線到 sail-8.1/app 容器,你會在 /var/www/html 資料夾中看到你的專案。Docker 將專案從你的機器“掛載”到容器中,所以你在開發過程中所做的任何更改,重新整理後都會反映在應用程式中。

The file structure of the Laravel project in a container

新增 Dev Containers

現在也已經添加了對 Dev Containers 擴充套件的支援。要將適當的開發容器配置新增到這個專案中,你可以搭建相同的專案並新增 &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 步驟。

A notification in VS Code saying "Reopen in container"

VS Code 會附加到容器上,所以你是在容器環境內部進行開發,而不是在你的本地環境。你會知道這一點,因為 VS Code 左下角的遠端指示器會告訴你……

The remote indicator in VS Code showing connection to a container

在容器內開發相比於在容器外,有一些明顯的優勢。

開發上下文與應用上下文一致

當連線到容器時,你進行開發的上下文與應用程式執行的上下文是相同的。所以你的終端就變成了容器的終端……

The VS Code terminal connected to the running container instance

Dev Containers 擴充套件還為你提供了一個更全面的檢視,讓你瞭解正在發生什麼,比如哪些埠被轉發了——以防你忘記應用程式在哪裡執行。

The port forwarding view in VS Code showing port 80 forwarded

Laravel 應用程式會自動啟動,應用程式日誌會透過管道傳輸到容器日誌。由於你可能想看到應用程式中發生了什麼,Dev Containers 擴充套件在 VS Code 中提供了一個新的檢視,在那裡你可以看到所有正在執行的容器,並連線以流式傳輸容器日誌。

The Laravel application container logs in 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)