Rules for Writing Software Tutorials
軟體教學撰寫規範
Most software tutorials are tragically flawed.
大多數軟體教學都存在著令人遺憾的缺陷。
Tutorials often forget to mention some key detail, preventing readers from replicating the author’s process. Other times, the author brings in hidden assumptions that don’t match their readers’ expectations.
教學文章常常忽略一些關鍵細節,導致讀者無法複製作者的步驟。有時,作者也會引入一些隱藏的假設,而這些假設與讀者的預期並不相符。
The good news is that it’s easier than you think to write an exceptional software tutorial. You can stand out in a sea of mediocre guides by following a few simple rules.
好消息是,撰寫一篇出色的軟體教學比您想像的更容易。只要遵循一些簡單的規則,就能讓您的文章在眾多平庸的指南中脫穎而出。
Rules🔗 規則 🔗
- Write for beginners 從入門者角度出發
- Promise a clear outcome in the title
在標題中明確指出成果 - Explain the goal in the introduction
在引言中闡明目標 - Show the end result
展示最終成果 - Make code snippets copy/pasteable
確保程式碼片段可直接複製貼上 - Use long versions of command-line flags
使用命令列標誌的完整版本 - Separate user-defined values from reusable logic
將使用者自定義的值與可重複使用的邏輯分離 - Spare the reader from mindless tasks
省去讀者繁瑣的操作 - Keep your code in a working state
保持程式碼的可執行狀態 - Teach one thing 一次只教一件事
- Don’t try to look pretty
不要過於追求程式碼的表面美觀 - Minimize dependencies 最小化依賴關係
- Specify filenames clearly
檔案名稱需清楚明確 - Use consistent, descriptive headings
使用一致且具描述性的標題 - Demonstrate that your solution works
展示你的解決方案確實有效 - Link to a complete example
提供完整範例的連結
Write for beginners🔗 以初學者為對象撰寫 🔗
The most common mistake tutorials make is explaining beginner-level concepts using expert-level terminology.
教學中最常見的錯誤是用專家級的術語來解釋初學者級的概念。
Most people who seek out tutorials are beginners. They may not be beginners to programming, but they’re beginners to the domain they’re trying to learn about.
大多數尋找教學的人都是初學者。他們也許不是程式設計的初學者,但他們是正在學習的領域的初學者。
不良示範:引用初學者無法理解的概念
In this tutorial, I’ll show you how to create your first “Hello world” SPA using React.
在本教學中,我將示範如何使用 React 建立你的第一個「Hello world」SPA。
Open the included hello.jsx
file and change the greeting from "Hello world"
to "Hello universe"
.
打開包含的 hello.jsx
檔案,並將問候語從 "Hello world"
更改為 "Hello universe"
。
The browser should hot reload with the new text. Because of React’s efficient JSX transpilation, the change feels instant.
瀏覽器應透過熱重載來顯示新文字。由於 React 高效的 JSX 轉譯,變更幾乎是即時的。
The browser doesn’t even have to soft reload the page because React’s reconciliation engine compares the virtual DOM to the rendered DOM and updates only the DOM elements that require changes.
瀏覽器甚至不需要刷新頁面,因為 React 的協調引擎會比較虛擬 DOM 和渲染後的 DOM,並只更新需要變更的 DOM 元素。
The above example would confuse and alienate beginners.
上述範例會讓初學者感到困惑和難以理解。
A developer who’s new to the React web framework won’t understand terms like “JSX transpilation” or “reconciliation engine.” They probably also won’t understand “SPA,” “soft reload,” or “virtual DOM” unless they’ve worked with other JavaScript frameworks.
剛接觸 React 網頁框架的開發者不會理解像是「JSX 轉譯」或「協調引擎」這樣的術語。除非他們使用過其他的 JavaScript 框架,否則他們可能也不懂「SPA」、「刷新」或「虛擬 DOM」。
When you’re writing a tutorial, remember that you’re explaining things to a non-expert. Avoid jargon, abbreviations, or terms that would be meaningless to a newcomer.
在撰寫教學時,請記住您是在向非專業人士解釋。避免使用術語、縮寫或對新手來說毫無意義的詞彙。
Here’s an introduction to a React tutorial that uses language most readers will understand, even if they have no background in programming:
以下是一個 React 教學的引言,它使用大多數讀者都能理解的語言,即使他們沒有程式設計背景:
優良範例:使用初學者能理解的詞彙
In this tutorial, I’ll show you how to create a simple webpage using modern web development tools.
在本教學中,我將示範如何使用現代網頁開發工具建立一個簡單的網頁。
To generate the website, I’m using React, a free and popular tool for building websites.
為了產生網站,我使用了 React,這是一個免費且熱門的網站建構工具。
React is a great tool for creating your first website, but it’s also full-featured and powerful enough to build sophisticated apps that serve millions of users.
React 不僅是建立第一個網站的絕佳工具,它也功能齊全且強大,足以建構服務數百萬用戶的複雜應用程式。
Writing for beginners doesn’t mean alienating everyone with more experience. A knowledgeable reader can scan your tutorial and skip the information they already know, but a beginner can’t read a guide for experts.
為初學者寫作並不意味著要疏遠所有經驗豐富的人。經驗豐富的讀者可以瀏覽您的教程並跳過他們已經知道的資訊,但初學者無法閱讀專家指南。
Promise a clear outcome in the title🔗
在標題中承諾清晰的結果 🔗
If a prospective reader is Googling a problem, would the title of your article lead them to the solution? If they see your tutorial on social media or in a newsletter, will your title convince them it’s worth clicking?
如果潛在讀者正在 Google 上搜尋問題,您的文章標題會引導他們找到解決方案嗎?如果他們在社群媒體或電子報中看到您的教程,您的標題會說服他們點擊嗎?
Consider the following weak titles:
考慮以下幾個較弱的標題:
- A Complete Guide to Becoming a Python CSV Ninja
成為 Python CSV 高手的完整指南 - How to Build Your Own Twitter
如何建構自己的 Twitter - Key Mime Pi: A Cool Gadget You Can Make
關鍵 Mime Pi:您可以製作的酷炫小工具 - How to Combine Django with Front-End JavaScript
如何將 Django 與前端 JavaScript 結合
The above examples are poor titles because they’re vague. From the title alone, you’d be hard-pressed to say what the tutorial will teach you.
以上範例都是不好的標題,因為它們含糊不清。單從標題來看,您很難說出本教程會教您什麼。
A tutorial’s title should explain succinctly what the reader can expect to achieve by following your guide.
教程的標題應該簡潔地說明讀者按照您的指南可以預期達到的目標。
Here are clearer rewrites of the previous titles:
以下是先前標題更清晰的改寫:
優良範例:使用承諾清晰成果的標題
- How to Read a CSV File in Python
如何使用 Python 讀取 CSV 檔案 - Build a Real-Time Twitter Clone in 15 Minutes with Phoenix LiveView
使用 Phoenix LiveView 在 15 分鐘內建構一個實時 Twitter 複製網站 - Key Mime Pi: Turn Your Raspberry Pi into a Remote Keyboard
關鍵 Mime Pi:將您的 Raspberry Pi 變成遠端鍵盤 - Organizing Your Front-End Codebase in a Django Project
在 Django 專案中組織您的前端程式碼庫
These titles give you a clear sense of what you’d learn by reading the tutorial. The titles are clear and specific in what the tutorial delivers.
這些標題讓您清楚地了解閱讀教學後將會學到什麼。這些標題清楚明確地說明了教學內容。
Explain the goal in the introduction🔗
在引言中解釋目標 🔗
If the reader clicks your tutorial, you’re off to a great start. Someone is interested in what you have to say. But you still have to convince them to continue reading.
如果讀者點擊了您的教學,這是一個好的開始。有人對您要說的話感興趣。但您仍然必須說服他們繼續閱讀。
As the reader begins a tutorial, they’re trying to answer two critical questions as quickly as possible:
當讀者開始閱讀教學時,他們會試圖盡快回答兩個關鍵問題:
- Should I care about this technology?
我需要關注這項技術嗎? - If I care, is this the right tutorial for me?
如果我需要,這份教學適合我嗎?
The first few sentences of your article should answer those questions.
你的文章開頭幾句就應該回答這些問題。
For example, if you were writing a tutorial about how to use Docker containers, this would be a terrible introduction:
舉例來說,如果你正在撰寫一篇關於如何使用 Docker 容器的教學,以下的開場白就很糟糕:
An Introduction to Docker Containers🔗
Docker 容器簡介 🔗
Docker is an extremely powerful and versatile technology. It allows you to run your app in a container, which means that it’s separate from everything else on the system.
Docker 是一個極其強大且用途廣泛的技術。它允許你在容器中運行你的應用程式,這意味著它與系統上的其他所有東西都是隔離的。
In this tutorial, I’ll show you how to use Docker to run containers on your internal infrastructure as well as in the cloud.
在本教學中,我將向你展示如何在內部基礎架構以及雲端中使用 Docker 運行程式容器。
Based on the above introduction, what problem does Docker solve? Who should use it?
根據上述簡介,Docker 解決了什麼問題?誰應該使用它?
The introduction fails to answer those questions and instead hand-waves with vague terms that ignore anything the reader cares about.
這段引言未能回答這些問題,反而用讀者毫不關心的模糊詞彙敷衍了事。
Here’s a rewrite that explains how Docker solves pain points the reader might have:
以下的改寫版本解釋了 Docker 如何解決讀者可能遇到的痛點:
優點:說明具體成果和效益
How to Use Docker for Reliable App Deployments🔗
如何使用 Docker 進行可靠的應用程式部署 🔗
Do you have a production server that you’re terrified to touch because nobody knows how to rebuild it if it goes offline? Have you ever torn your hair out trying to figure out why your staging environment behaves differently than your production environment?
您是否擁有一台不敢輕易碰觸的生產伺服器,因為一旦它離線,就沒人知道如何重建?您是否曾為了弄清楚為什麼您的測試環境與生產環境的行為不同而抓狂?
Docker is a tool for packaging your app so that it has a consistent, reproducible environment wherever it runs. What’s more, it allows you to define your app’s environment and dependencies in source code, so you know exactly what’s there, even if your app has survived years of tweaks by different teams.
Docker 是一個用於打包應用程式的工具,讓應用程式無論在哪裡運行,都能擁有一致且可重現的環境。更重要的是,它允許您在原始碼中定義應用程式的環境和依賴項,讓您確切地知道有哪些內容,即使您的應用程式已經歷經不同團隊多年的調整。
In this tutorial, I’ll show you how to use Docker to package a simple web app and help you avoid common Docker gotchas.
在本教學中,我將向您展示如何使用 Docker 打包一個簡單的網路應用程式,並幫助您避免常見的 Docker 陷阱。
The above introduction explains the problems Docker solves and what the tutorial will deliver.
以上引言說明了 Docker 解決的問題以及本教學將提供的內容。
The introduction doesn’t say, “This tutorial is for people who are brand new to Docker,” but it doesn’t need to. It introduces Docker as a new concept, which tells the reader that the guide is for newcomers.
雖然引言中沒有明確指出「本教學適用於 Docker 新手」,但這並非必要。它將 Docker 作為一個新概念引入,這就足以讓讀者理解本指南是面向新手的。
Show the end result🔗
展示最終成果 🔗
As soon as possible, show a working demo or screenshot of what the reader will create by the end of your tutorial.
盡快展示一個讀者在完成教學後將會建立的功能演示或螢幕截圖。
The end result doesn’t have to be anything visually stunning. Here’s an example of how I showed the terminal UI the user would see at the end of my tutorial:
最終成果不一定要在視覺上令人驚豔。以下是一個例子,展示了我在教學結束時如何向使用者展示終端機介面:
Showing the final product reduces ambiguity about your goal. It helps the reader understand if it’s the right guide for them.
展示最終成品能減少目標的模糊性,並幫助讀者判斷這份指南是否適合他們。
Make code snippets copy/pasteable🔗
確保程式碼片段可複製貼上 🔗
As the reader follows your tutorial, they’ll want to copy/paste your code snippets into their editor or terminal.
讀者在跟著教學步驟進行時,會希望將程式碼片段複製貼上到他們的編輯器或終端機中。
An astonishing number of tutorials unwittingly break copy/paste functionality, making it difficult for the reader to follow along with their examples.
令人驚訝的是,許多教學文章在不經意間破壞了複製貼上的功能,使讀者難以跟著範例操作。
Make shell commands copyable🔗
確保 Shell 指令可複製 🔗
One of the most common mistakes authors make in code snippets is including the shell prompt character.
作者在程式碼片段中最常犯的錯誤之一,就是包含了 shell 提示字元。
A shell snippet with leading $
characters will break when the user tries to paste it into their terminal.
開頭包含 $
字元的 shell 程式碼片段,在使用者試圖貼到終端機時會失效。
$ sudo apt update # <<< Don't do this!
$ sudo apt install vim # <<< Users can't copy/paste this sequence without
$ vim hello.txt # << picking up the $ character and breaking the command.
Even Google gets this wrong. In some places, their documentation helpfully offers a “Copy code sample” button.
就連 Google 也會犯這個錯誤。在某些地方,他們的說明文件貼心地提供了一個「複製程式碼範例」的按鈕。
If you click the copy button, it copies the $
terminal prompt character, so you can’t paste the code:
如果您點擊複製按鈕,它會複製 $
終端機提示字元,導致您無法貼上程式碼:
michael@ubuntu: $ gcloud services enable pubsub.googleapis.com
$ gcloud services disable pubsub.googleapis.com
bash: $: command not found
bash: $: command not found
michael@ubuntu:
There’s a different version of this copy/paste error that’s more subtle:
這種複製/貼上錯誤還有一個更不易察覺的版本:
不佳:呈現需要使用者輸入的連續指令
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.9
If I try to paste the above snippet, here’s what I see in the terminal:
如果我嘗試貼上以上程式碼片段,我會在終端機中看到以下內容:
0 upgraded, 89 newly installed, 0 to remove and 2 not upgraded.
Need to get 36.1 MB of archives.
After this operation, 150 MB of additional disk space will be used.
Do you want to continue? [Y/n] Abort.
$
What happened? 發生了什麼事?
When the apt install software-properties-common
command executes, it prompts the user for input. The user can’t answer the prompt because apt
just continues reading from the clipboard paste.
當 apt install software-properties-common
指令執行時,它會提示使用者輸入。使用者無法回應提示,因為 apt
會繼續從剪貼簿貼上的內容讀取。
Most command-line tools offer flags or environment variables to avoid forcing the user to respond interactively. Use non-interactive flags to make command snippets easy for the user to paste into their terminal.
大多數命令列工具都提供旗標或環境變數,以避免強制使用者互動式回應。使用非互動式旗標,讓使用者可以輕鬆地將程式碼片段貼到終端機中。
良好:使用可避免互動式使用者輸入的命令列旗標
sudo apt update
sudo apt install --yes software-properties-common
sudo add-apt-repository --yes ppa:deadsnakes/ppa
sudo apt install --yes python3.9
Join shell commands with &&
🔗
使用 &&
🔗 連接 shell 指令
Take another look at the Python installation example I showed above, as it has a second problem:
讓我們再看一下上面顯示的 Python 安裝範例,它還有第二個問題:
差:忽略失敗的指令
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt install python3.9
If one of the commands fails, the user might not notice. For example, if the first command was sudo apt cache ppa:dummy:non-existent
, that command would fail, but the shell would happily execute the next command as if everything was fine.
如果其中一個指令失敗,使用者可能不會注意到。例如,如果第一個指令是 sudo apt cache ppa:dummy:non-existent
,該指令會失敗,但 shell 會很樂意地執行下一個指令,就好像一切正常一樣。
In most Linux shells, you can join commands with &&
and continue lines with a backslash. That tells the shell to stop when any command fails.
在大多數 Linux shell 中,您可以使用 &&
連接指令,並使用反斜線繼續輸入指令。這會告知 shell 在任何指令失敗時停止執行。
Here’s the user-friendly way to include a series of copy-pasteable commands:
以下是如何以使用者友善的方式提供一系列可複製貼上的指令:
&&
優:使用
&&
將指令串連在一起sudo apt update && \
sudo apt install --yes software-properties-common && \
sudo add-apt-repository --yes ppa:deadsnakes/ppa && \
sudo apt install --yes python3.9
The user can copy/paste the entire sequence without having to tinker with it in an intermediate step. If any of the commands fail, the sequence stops immediately.
使用者可以複製/貼上整個序列,而無需在中間步驟進行修改。如果有任何指令失敗,序列會立即停止。
Only show the shell prompt to demonstrate output🔗
僅顯示 shell 提示符號以演示輸出 🔗
Occasionally, showing the shell prompt character benefits the reader.
顯示 shell 提示字元有時對讀者有益。
If you show a command and its expected output, the shell prompt character helps the reader distinguish between what they type and what the command returns.
如果您顯示指令及其預期輸出,shell 提示字元可幫助讀者區分他們輸入的內容和指令返回的內容。
For example, a tutorial about the jq
utility might present results like this:
例如,關於 jq
工具的教學可能會呈現如下結果:
良好範例:使用 shell 提示字元區分指令及其輸出結果。
The jq
utility allows you to restructure JSON data elegantly:
jq
工具可讓您輕鬆地調整 JSON 資料的結構:
$ curl \
--silent \
--show-error \
https://status.supabase.com/api/v2/summary.json | \
jq '.components[] | {name, status}'
{
"name": "Analytics",
"status": "operational"
}
{
"name": "API Gateway",
"status": "operational"
}
...
Exclude line numbers from copyable text🔗
從可複製的文字中排除行號 🔗
It’s fine to include line numbers alongside your code snippets, but make sure they don’t break copy/paste. For example, if the user tries to copy the count_tables
function from the following snippet, they’d have to remove line numbers from their pasted text.
程式碼片段旁加上行號是可以的,但請確保它們不會干擾複製/貼上的操作。例如,如果使用者嘗試從以下程式碼片段複製 count_tables
函式,他們必須從貼上的文字中移除行號。
不良範例:在可複製的文字中包含行號
123 def count_tables(form):
124 if not form:
125 return None
Use long versions of command-line flags🔗
使用命令列旗標的完整版本 🔗
Command-line utilities often have two versions of the same flag: a short version and a long version.
命令列工具通常有兩種版本的旗標:簡短版本和完整版本。
-r / --recursive : Run recursively
^ ^
| |
| long flag
|
short flag
Always use long flags in tutorials. They’re more descriptive, so they make your code easier to read, especially for beginners.
在教學中,請務必使用完整旗標。它們更具描述性,因此程式碼更易於閱讀,尤其對於初學者而言。
不良範例:使用簡短、難懂的命令列旗標版本
Run the following command to find all the pages with <span>
elements:
執行以下指令以找出所有包含 <span>
元素的頁面:
grep -i -o -m 2 -r '<span.*</span>' ./
Even if the reader is familiar with the grep
tool, they probably haven’t memorized all of its flags.
即使讀者熟悉 grep
工具,他們可能也並未記住所有標誌。
Use long flags to make your examples clear to both experienced and inexperienced readers.
使用長標誌,使您的示例對經驗豐富和經驗不足的讀者都清晰易懂。
優良做法:使用詳盡、描述性的命令列標誌版本
Run the following command to find all the pages with <span>
elements:
執行以下命令以查找所有包含 <span>
元素的頁面:
grep \
--ignore-case \
--only-matching \
--max-count=2 \
--recursive \
'<span.*</span>' \
./
Separate user-defined values from reusable logic🔗
將使用者自訂的值與可重複使用的邏輯分開🔗
Often, a code example contains elements that are inherent to the solution and elements that each reader can customize for themselves. Make it clear to the reader which is which.
通常,程式碼範例包含解決方案固有的元素和每個讀者可以自行設定的元素。要向讀者清楚說明哪些是哪些。
The distinction between a user-defined value and the rest of the code might seem obvious to you, but it’s unclear to someone new to the technology.
使用者自訂值和程式碼其餘部分之間的區別對您來說可能顯而易見,但對於剛接觸這項技術的人來說卻並非如此。
Use environment variables in command-line examples🔗
在命令列範例中使用環境變數🔗
A logging service that I use lists the following example code for retrieving my logs on the command line:
我使用的日誌服務列出了以下用於在命令列上擷取我的日誌的程式碼範例:
不良做法:將使用者自訂的變數寫死在程式碼中
LOGS_ROUTE="$(
curl \
--silent \
--header "X-Example-Token: YOUR-API-TOKEN" \
http://api.example.com/routes \
| grep "^logs " \
| awk '{print $2}'
)" && \
curl \
--silent \
--header "X-Example-Token: YOUR-API-TOKEN" \
"http://api.example.com${LOGS_ROUTE}" \
| awk \
-F'T' \
'$1 >= "YYYY-MM-DD" && $1 <= "YYYY-MM-DD" {print $0}'
Given that example, which values am I supposed to replace?
鑑於這個例子,我應該替換哪些值?
Clearly, YOUR-API-TOKEN
is a placeholder that I need to replace, but what about YYYY-MM-DD
? Am I supposed to replace it with real dates like 2024-11-23
? Or is it specifying a date schema, meaning that YYYY-MM-DD
is the literal value I’m supposed to keep?
顯然, YOUR-API-TOKEN
是一個我需要替換的佔位符,但是 YYYY-MM-DD
呢?我應該用真實的日期(例如 2024-11-23
)來替換它嗎?或者它是指定一個日期模式,意味著 YYYY-MM-DD
是我應該保留的字面值?
There are several other numbers and strings in the example. Do I need to replace any of those?
範例中還有其他幾個數字和字串。我需要替換任何一個嗎?
Instead of forcing the reader to search through your example and guess which values to change, create a clean separation. Start with the editable values, then give them the snippet they can copy/paste verbatim.
與其強迫讀者在您的範例中搜尋並猜測要更改哪些值,不如乾脆俐落地分開。先列出可編輯的值,然後再提供他們可以直接複製/貼上的程式碼片段。
Here’s my rewrite of the example above:
以下是我對上面範例的改寫:
優點:使用環境變數設定使用者自定義值
API_TOKEN='YOUR-API-KEY' # Replace with your API key.
START_DATE='YYYY-MM-DD' # Replace with desired start date.
END_DATE='YYYY-MM-DD' # Replace with desired end date.
LOGS_ROUTE="$(
curl \
--silent \
--header "X-Example-Token: $API_TOKEN" \
http://api.example.com/routes \
| grep "^logs " \
| awk '{print $2}' \
)" && \
curl \
--silent \
--header "X-Example-Token: $API_TOKEN" \
"http://api.example.com${LOGS_ROUTE}" \
| awk \
-F'T' \
-v start="$START_DATE" \
-v end="$END_DATE" \
'$1 >= start && $1 <= end {print $0}'
The new version distinguishes between values the reader must replace and code that must remain in place.
新版本區分了讀者必須替換的值和必須保留的程式碼。
Using environment variables clarifies the intent of the user-defined values and means the user only has to enter each unique value once.
使用環境變數可以闡明使用者自定義值的意圖,並且意味著使用者只需輸入每個唯一值一次。
Use named constants in source code🔗
在原始程式碼中使用命名常數 🔗
Suppose that you were writing a tutorial that demonstrated how to crop an image so that it displays well in social sharing cards on Bluesky, Twitter, and Facebook:
假設您正在撰寫一個教學,示範如何裁剪圖片,使其在 Bluesky、Twitter 和 Facebook 等社群平台的分享卡片上顯示良好:
Here’s how you might show code for cropping an image to fit social media cards:
以下是如何編寫程式碼來裁剪圖片以適應社群媒體卡片的範例:
差:讓讀者猜測哪些數字可以更改
func CropForSocialSharing(img image.Image) image.Image {
targetWidth := 800
targetHeight := int(float64(targetWidth) / 1.91)
bounds := img.Bounds()
x := (bounds.Max.X - targetWidth) / 2
y := (bounds.Max.Y - targetHeight) / 2
rgba := image.NewRGBA(
image.Rect(x, y, x+targetWidth, y+targetHeight))
draw.Draw(
rgba, rgba.Bounds(), img, image.Point{x, y}, draw.Src)
return rgba
}
The example shows four numbers:
範例顯示了四個數字:
800
1.91
2
2
(again)2
(再次)
Which numbers are the reader free to change?
讀者可以自由更改哪些數字?
In source code examples, make it obvious which values are inherently part of the solution and which are arbitrary.
在原始碼範例中,應明確指出哪些值是方案中固有的,哪些是可任意調整的。
Consider this rewrite that makes the intent of the numbers clearer:
請參考以下重寫後的程式碼,它更清晰地表達了這些數字的意圖:
優:明確標示不可更改的值
// Use a 1.91:1 aspect ratio, which is the dominant ratio
// on popular social networking platforms.
const socialCardRatio = 1.91
func CropForSocialSharing(img image.Image) image.Image {
// I prefer social cards with an 800px width, but you can
// make this larger or smaller.
targetWidth := 800
// Choose a height that fits the target aspect ratio.
targetHeight := int(float64(targetWidth) / socialCardRatio)
bounds := img.Bounds()
// Keep the center of the new image as close as possible to
// the center of the original image.
x := (bounds.Max.X - targetWidth) / 2
y := (bounds.Max.Y - targetHeight) / 2
rgba := image.NewRGBA(
image.Rect(0, 0, targetWidth, targetHeight))
draw.Draw(
rgba, rgba.Bounds(), img, image.Point{x, y}, draw.Src)
return rgba
}
In this example, the code puts the value of 1.91
in a named constant and has an accompanying comment explaining the number. That communicates to the reader that they shouldn’t change the value, as it will cause the function to create images with poor proportions for social sharing cards.
在此範例中,程式碼將 1.91
的值放入一個具名常數,並附帶註釋說明該數字的意義。這讓讀者明白不應更改此值,因為它會導致函式產生的圖片比例不適合社群分享卡片。
On the other hand, the value of 800
is more flexible, and the comment makes it obvious to the reader that they’re free to choose a different number.
另一方面, 800
的值更具彈性,而註釋清楚地表明讀者可以自由選擇不同的數字。
Spare the reader from mindless tasks🔗
別讓讀者費心做瑣事 🔗
The reader will appreciate your tutorial if you show that you respect their time.
如果你能尊重讀者的時間,他們會更感激你的教學。
Don’t force the reader to perform tedious interactive steps when a command-line snippet would achieve the same thing.
如果一行命令就能完成同樣的事情,就不要強迫讀者執行繁瑣的互動步驟。
不佳:強迫讀者執行不必要的繁瑣步驟
Do the following tedious steps:
執行以下繁瑣的步驟:
- Run
sudo nano /etc/hostname
執行sudo nano /etc/hostname
- Erase the hostname 清除主機名稱
- Type in
awesomecopter
輸入awesomecopter
- Hit Ctrl+o to save the contents
按下 Ctrl+o 儲存內容 - Hit Ctrl+x to exit the editor
按下 Ctrl+x 即可退出編輯器。
The above steps make your tutorial boring and error-prone. Who wants to waste mental cycles manually editing a text file?
以上步驟會讓你的教學枯燥乏味且容易出錯。誰想浪費腦力去手動編輯文字檔呢?
Instead, show the reader a command-line snippet that achieves what they need:
反之,應該向讀者展示一個能達成他們需求的命令列程式碼片段:
優點:將不具資訊性或趣味性的步驟寫成腳本。
Paste the following simple command:
貼上以下簡單的指令:
echo 'awesomecopter' | sudo tee /etc/hostname
Keep your code in a working state🔗
保持程式碼的可運作狀態 🔗
Some authors design their tutorials the way you’d give instructions for an origami structure. It’s a mysterious sequence of twists and folds until you get to the end, and then: wow, it’s a beautiful swan!
有些作者設計教學的方式,就像是在指導摺紙一樣。那是一連串神秘的扭轉和摺疊,直到最後:哇,是一隻美麗的天鵝!
A grand finale might be fun for origami, but it’s stressful for the reader.
這種華麗的結尾或許適用於摺紙,但對讀者來說卻是一種壓力。
Give the reader confidence that they’re following along correctly by keeping your example code in a working state.
藉由保持範例程式碼的可運作狀態,讓讀者確信他們正在正確地跟隨步驟。
缺點:參考讀者尚未看到的程式碼。
Here’s some example code, but don’t even think about compiling it. It’s missing the parseOption
function LOL!
這裡有一些範例程式碼,但千萬別想編譯它。它少了 parseOption
函式,哈哈!
// example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 256
int main() {
char line[MAX_LINE_LENGTH];
char key[MAX_LINE_LENGTH];
char value[MAX_LINE_LENGTH];
while (fgets(line, sizeof(line), stdin)) {
// Don't do this!
parseOption(line, key, value); // <<< Not yet defined
printf("Key: '%s', Value: '%s'\n", key, value);
}
return 0;
}
If the reader tries to compile the above example, they get an error:
如果讀者嘗試編譯上面的例子,他們會得到一個錯誤:
$ gcc example.c -o example
example.c: In function ‘main’:
example.c:14:7: warning: implicit declaration of function ‘parseOption’
[-Wimplicit-function-declaration]
14 | parseOption(line, key, value); // <<< Not yet defined
| ^~~~~~~~~~~
/usr/bin/ld: /tmp/ccmLGENX.o: in function `main':
example.c:(.text+0x2e): undefined reference to `parseOption'
collect2: error: ld returned 1 exit status
As early as possible, show the reader an example they can play with. Build on that foundation while keeping the code in a working state.
盡早向讀者展示一個他們可以操作的範例。在這個基礎上逐步建構,同時保持程式碼的可運作狀態。
優點:展示一個使用者可以建構的例子,而不會跳過任何步驟。
// example.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE_LENGTH 256
void parseOption(char *line, char *key, char *value) {
// Fake the parsing part for now.
strncpy(key, "not implemented", MAX_LINE_LENGTH - 1);
strncpy(value, "not implemented", MAX_LINE_LENGTH - 1);
}
int main() {
char line[MAX_LINE_LENGTH];
char key[MAX_LINE_LENGTH];
char value[MAX_LINE_LENGTH];
while (fgets(line, sizeof(line), stdin)) {
parseOption(line, key, value);
printf("Key: '%s', Value: '%s'\n", key, value);
}
return 0;
}
Now, I test the program to see that it runs:
現在,我測試程式以確認它可以運行:
$ gcc example.c -o example && \
printf 'volume:25\npitch:37' | \
./example
Key: 'not implemented', Value: 'not implemented'
Key: 'not implemented', Value: 'not implemented'
The code fakes parsing options for now, but the dummy code confirms that everything else is working.
程式碼目前模擬解析選項,但這個虛擬程式碼確認了其他一切正常運作。
Keeping your code in a working state gives the reader confidence that they’re following along correctly. It frees them from the worry that they’ll waste time later retracing their steps to find some minor error.
保持程式碼可運作,能讓讀者確信他們正在正確地學習。這讓他們免於擔心之後需要回溯步驟來查找一些小錯誤而浪費時間。
Teach one thing🔗 教授單一知識點 🔗
A good tutorial should explain one thing and explain it well.
一個好的教學應該只解釋一件事,並且把它解釋清楚。
A common mistake is to claim a tutorial is about a particular topic, and then bury the lesson in a hodgepodge of unrelated technologies.
一個常見的錯誤是,聲稱一個教學是關於某個特定主題,然後卻將課程淹沒在一堆不相關的技術的大雜燴中。
不佳:同時教授數個不相關的概念
In this tutorial, I’ll show you how to add client-side search to your Hugo blog so that readers can do instant, full-text search of all your blog posts, even on spotty mobile connections.
在本教學中,我將向您展示如何在 Hugo 部落格中新增用戶端搜尋功能,讓讀者即使在行動網路不穩定的情況下,也能立即對所有部落格文章進行全文搜尋。
But that’s not all! 但這還不是全部!
While I’m showing full-text search, I’ll simultaneously demonstrate how you can use browser local storage to store your user’s search history and then use an expensive AI service to infer whether the user prefers your website’s dark mode or light mode UI theme.
我在展示全文搜尋的同時,還會示範如何使用瀏覽器的本地儲存來儲存使用者的搜尋紀錄,然後使用昂貴的 AI 服務來推斷使用者偏好網站的深色模式還是淺色模式 UI 主題。
In the example above, the tutorial starts by promising something many readers want: full-text search of a blog.
在上面的例子中,該教學一開始承諾提供許多讀者想要的功能:部落格的全文搜尋。
Immediately after promising full-text search, the tutorial layers in a grab bag of unrelated ideas. Now, anyone interested in full-text search has to untangle the search concepts from everything else.
在承諾提供全文搜尋之後,該教學立刻塞進了一堆不相關的概念。現在,任何對全文搜尋感興趣的人都必須從其他所有內容中理出搜尋的概念。
People come to a tutorial because they want to learn one new thing. Let them learn that one thing in isolation.
人們閱讀教學是因為他們想學習一件新事物。讓他們專心學習那一件事。
優良:將教學重點放在單一新概念上
In this tutorial, I’ll show you how to add client-side search to your Hugo blog so that readers can do instant, full-text search of all your blog posts, even on spotty mobile connections.
在本教學中,我將向您展示如何在 Hugo 部落格中新增用戶端搜尋功能,讓讀者即使在行動網路不穩定的情況下,也能立即對所有部落格文章進行全文搜尋。
That’s the only thing I’ll demonstrate in this tutorial.
這也是我在本教學中唯一會示範的內容。
If you have to stack technologies, wait until the end🔗
如果必須堆疊技術,請等到最後 🔗
Sometimes, a tutorial has to combine technologies.
有時,教學課程必須結合多種技術。
For example, the PHP web programming language doesn’t have a production-grade web server built-in. To demonstrate how to deploy a PHP app to the web, you’d have to choose a server like Apache, nginx, or Microsoft IIS. No matter which server technology you choose, you alienate readers who prefer a different web server.
例如,PHP 網頁程式語言沒有內建生產級的網路伺服器。為了示範如何將 PHP 應用程式部署到網路,您必須選擇 Apache、nginx 或 Microsoft IIS 等伺服器。無論您選擇哪種伺服器技術,您都會疏遠偏好不同網路伺服器的讀者。
If you have to combine concepts, defer it to the end. If you’re teaching PHP, take the tutorial as far as you can go using PHP’s development server. If you show how to deploy the PHP app in production using nginx, push those steps to the end so everyone who prefers a different web server can follow everything in your tutorial until the web server portion.
如果必須結合多個概念,請將其延後到最後。如果您正在教授 PHP,請盡可能使用 PHP 的開發伺服器來完成教學。如果您展示如何使用 nginx 在生產環境中部署 PHP 應用程式,請將這些步驟推遲到最後,以便所有偏好不同網路伺服器的讀者都能跟上您教學中的所有內容,直到網路伺服器部分。
Don’t try to look pretty🔗
不要試圖讓它看起來很漂亮 🔗
Here’s an excerpt from an article I read recently. Can you guess what type of tutorial it was?
以下是我最近閱讀的一篇文章的摘錄。你能猜到它是哪種類型的教學嗎?
<div class="flex flex-row mb-4 overflow-hidden bg-white">
<div class="flex flex-col w-full p-6 text-light-gray-500">
<div class="flex justify-between mb-3">
<span class="uppercase">{{ title }}</span>
</div>
<slot></slot>
</div>
</div>
If you guessed that I was reading a tutorial about a CSS framework, you’d be wrong.
如果您猜測我正在閱讀有關 CSS 框架的教學,那您就錯了。
The above snippet was from a tutorial about using the <slot>
element in the Vue web framework. So, why was half the code just CSS classes? The author added them to make their example look pretty.
以上程式碼片段摘錄自一篇關於在 Vue 網頁框架中使用 <slot>
元素的教學。那麼,為什麼一半的程式碼只是 CSS 類別呢?作者添加它們是為了讓他們的範例看起來更漂亮。
Here’s the same snippet as above, reduced to the code necessary to convey the concept:
以下是與上面相同的程式碼片段,簡化為傳達概念所需的程式碼:
優良作法:保持示範 UI 簡單且與樣式無關
<div class="card">
<p class="card-title">{{ title }}</p>
<slot></slot>
</div>
The simplified code doesn’t generate a beautiful browser-friendly card, but who cares? It sets a clear foundation to explain the <slot>
element without distracting you with unrelated technology.
簡化的程式碼並不會產生賞心悅目的網頁卡片,但那又何妨?它的重點在於為講解 <slot>
元素奠定清晰的基礎,而不會讓您分心於無關的技術。
Readers don’t care if your toy application looks beautiful. They want a tutorial that makes new concepts obvious.
讀者並不關心您的示範應用程式是否美觀。他們想要的是能讓新概念一目瞭然的教學。
Minimize dependencies🔗 最小化 dependencies 🔗
Every tutorial has dependencies. At the very least, the reader needs an operating system, but they likely also need a particular compiler, library, or framework to follow your examples.
每個教學都有 dependencies。至少,讀者需要一個作業系統,但他們可能還需要特定的編譯器、函式庫或框架才能跟著您的範例操作。
Every dependency pushes work onto the reader. They need to figure out how to install and configure it on their system, which reduces their chances of completing your tutorial.
每個 dependency 都會增加讀者的負擔。他們需要弄清楚如何在他們的系統上安裝和設定它,這降低了他們完成教學的機率。
Make your tutorial easy on the reader by minimizing the number of dependencies it requires.
盡量減少教學所需的 dependencies 數量,讓讀者更容易上手。
不佳示範:用難以安裝的 dependencies 讓讀者措手不及
We’re at step 12 of this tutorial, so it’s time to install a bunch of annoying packages I didn’t mention earlier:
我們已經來到教學的第 12 步,現在該安裝一些我之前沒提到的惱人套件了:
- ffmpeg, compiled with the libpita extension (precompiled binaries are not available)
ffmpeg,需使用 libpita 副檔名編譯(沒有預先編譯好的二進位檔) - A special fork of Node.js that my friend Slippery Pete published in 2010 (you’ll need Ubuntu 6.06 to compile it)
我的朋友 Slippery Pete 在 2010 年發布的一個 Node.js 特殊分支版本(您需要 Ubuntu 6.06 才能編譯它) - Perl 4
The most common and frivolous dependencies I see are date parsing libraries. Have you seen instructions like this?
我見過最常見也最輕率的依賴關係就是日期解析函式庫。你看過這樣的指示嗎?
不佳:引入第三方依賴來解決微不足道的小問題
The CSV file contains dates in YYYY-MM-DD
format. To parse it, install this 400 MB library designed to parse any date string in any format, language, and locale.
這個 CSV 檔案包含 YYYY-MM-DD
格式的日期。要解析它,請安裝這個 400 MB 的函式庫,它設計用於解析任何格式、語言和地區設定的日期字串。
You never need a whole third-party library to parse a simple date string in example code. At worst, you can parse it yourself with five lines of code.
在程式碼範例中,您永遠不需要一個完整的第三方函式庫來解析簡單的日期字串。最糟的情況下,您也可以自己用五行程式碼就能解析。
Beyond making your guide harder to follow, each dependency also decreases your tutorial’s lifespan. In a month, the external library might push an update that breaks your code. Or the publisher could unpublish the library, and now your tutorial is useless.
除了讓您的指南更難理解之外,每個依賴項也會縮短您教學的壽命。一個月後,外部函式庫可能會推送更新,從而破壞您的程式碼。或者發佈者可能會取消發佈該函式庫,那麼您的教學就變得毫無用處了。
You can’t always eliminate dependencies, so use them strategically. If your tutorial resizes an image, go ahead and use a third-party image library instead of reimplementing JPEG decoding from scratch. But if you can save yourself a dependency with less than 20 lines of code, it’s almost always better to keep your tutorial lean.
您不可能永遠擺脫所有依賴項,因此請策略性地使用它們。如果您的教學需要調整圖片大小,那就放心地使用第三方圖片庫,而不是從頭重新實現 JPEG 解碼。但如果您可以用少於 20 行的程式碼省去一個依賴項,那麼保持教學精簡幾乎總是更好的選擇。
Pin your dependencies to specific versions🔗
將您的依賴項版本鎖定 🔗
Be explicit about which versions of tools and libraries you use in your tutorial. Libraries publish updates that break backward compatibility, so make sure the reader knows which version you confirmed as working.
請明確說明您在教學中使用的工具和程式庫版本。程式庫發布的更新可能會破壞向下相容性,因此請確保讀者知道您確認可行的版本。
不佳:使用定義不清的依賴項
Install a stable version of Node.js.
安裝穩定版本的 Node.js。
良好:明確宣告您的依賴項版本
Install Node.js 22.x. I tested this on Node.js v22.12.0 (LTS).
安裝 Node.js 22.x 版本。我是在 Node.js v22.12.0 (LTS) 版本上測試的。
Specify filenames clearly🔗
清楚地指定檔案名稱 🔗
My biggest pet peeve in a tutorial is when it casually instructs me to “add this line to your configuration file.”
我在教學中最討厭的事情就是它漫不經心地指示我「將此行添加到您的設定檔中」。
Which configuration file? Where?
哪個設定檔?在哪裡?
不佳:針對如何編輯檔案給予模糊的指示
To enable tree-shaking, add this setting to your config file:
要啟用程式碼精簡(Tree-shaking),請將此設定添加到您的設定檔中:
optimization: {
usedExports: true,
minimize: true
}
If the reader needs to edit a file, give them the full path to the file, and show them exactly which line to edit.
如果讀者需要編輯檔案,請提供檔案的完整路徑,並準確顯示要編輯哪一行。
There are plenty of ways to communicate the filename: in a code comment, in a heading, or even in the preceding paragraph. Anything works as long as it unambiguously shows the user where to make the change.
傳達檔案名稱有很多種方法:在程式碼註釋中、標題中,甚至在前面的段落中。只要能明確地向使用者顯示在哪裡進行更改,任何方法都行。
優良:具體說明要編輯哪個檔案以及在哪裡放置變更
To enable tree-shaking, add the following optimization
setting to your Webpack configuration file under module.exports
:
要啟用程式碼精簡(Tree-shaking),請將以下 optimization
設定新增至 module.exports
下的 Webpack 設定檔:
// frontend/webpack.config.js
module.exports = {
mode: "production",
entry: "./index.js",
output: {
filename: "bundle.js",
},
// Enable tree-shaking to remove unused code.
optimization: {
usedExports: true,
minimize: true,
},
};
Use consistent, descriptive headings🔗
使用一致且具描述性的標題 🔗
Most readers skim a tutorial before they decide to read it in detail. Skimming helps the reader assess whether the tutorial will deliver what they need and how difficult it will be to follow.
大多數讀者在決定細讀教程之前,都會先瀏覽一遍。瀏覽能幫助讀者評估教程是否能滿足他們的需求,以及理解教程的難度。
If you omit headings, your tutorial will intimidate the reader with a giant wall of text.
如果您省略標題,您的教程會以一大片文字嚇跑讀者。
Instead, use headings to structure your tutorial. A 25-step tutorial feels friendlier if you structure it as a five-step tutorial in which each step has four to six substeps.
反之,使用標題來組織您的教程。一個 25 步驟的教程,如果您將其組織成一個五步驟的教程,而每個步驟又包含四到六個子步驟,則會感覺更為親切易懂。
Write clear headings🔗 撰寫清晰的標題 🔗
It’s not enough to stick a few headings between long stretches of text.
只在長篇幅的文字之間插入幾個標題是不夠的。
Think about the wording of the headings so that they communicate as much as possible without sacrificing brevity.
仔細斟酌標題的措辭,使其在簡潔的同時,盡可能傳達更多信息。
Which of these tutorials would you rather read?
您更願意閱讀以下哪個教程?
- Go 開始
- Installation 安裝
- Hello, world! 你好,世界!
- Deployment 部署
Or this? 還是這個?
- Why Choose Go? 為何選擇 Go 語言?
- Install Go 1.23 安裝 Go 1.23
- Create a Basic “Hello, World” Go App
建立一個基礎的「Hello, World」Go 應用程式 - Deploy Your App to the Web
將您的應用程式部署到網路
The second example communicates more information to the reader and helps them decide if this is the right tutorial for them.
第二個例子向讀者傳達了更多資訊,並幫助他們判斷這份教學是否適合他們。
Make your headings consistent🔗
保持標題一致性 🔗
Before you publish your tutorial, review your headings for consistency.
發佈教學前,請檢查標題的一致性。
不佳範例:使用不一致的標題
- How I Installed Go 1.23
Go 1.23 安裝指南 - Step 2: Your First App
第二步:您的第一個應用程式 - How I package Go apps
Go 應用程式打包方法 - Part D: How you’ll deploy your App
第四部分:應用程式部署方式
When reviewing your headings, check for consistency in the following:
審閱標題時,請檢查以下幾項是否一致:
- Casing 大小寫
- Do your headings use title casing or sentence casing?
標題使用的是標題式大小寫還是句子式大小寫?
- Do your headings use title casing or sentence casing?
- Point of view 觀點
- Are the steps presented as “I did X,” “You do X,” or neutral?
步驟的呈現方式是「我做了 X」、「您要做 X」還是中性敘述?
- Are the steps presented as “I did X,” “You do X,” or neutral?
- Verb tense 動詞時態
- Are you using present tense, past tense, or future tense?
你使用的是現在式、過去式還是未來式?
- Are you using present tense, past tense, or future tense?
Create a logical structure with your headings🔗
使用標題建立邏輯結構 🔗
Ensure that your headings reflect a logical structure in your tutorial.
確保你的標題反映教程的邏輯結構。
I often see tutorials where the headings create a nonsensical structure.
我經常看到一些教程,標題的結構很不合理。
不佳:使用不合邏輯的標題結構
- Why Go? 為什麼選擇 Go 語言?
- The history of nginx nginx 的發展歷程
- Configuring nginx for local access
設定 nginx 以供本地端存取
- Creating your First Go app
建立你的第一個 Go 應用程式- Why Go is better than Perl
Go 語言為何優於 Perl?
- Why Go is better than Perl
- Serve a basic page 提供一個基礎頁面
In the example above, the heading “Why Go?” has a subheading of “The history of nginx,” even though nginx’s history isn’t a logical subtopic of Go.
在上面的例子中,「為何選擇 Go?」這個標題下有一個子標題「nginx 的歷史」,即使 nginx 的歷史並不是 Go 的邏輯子主題。
Demonstrate that your solution works🔗
展示你的解決方案有效 🔗
If your tutorial teaches the reader how to install a tool or integrate multiple components, show how to use the result.
如果你的教學教導讀者如何安裝工具或整合多個組件,請展示如何使用成果。
不佳:只展示安裝過程,沒有其他內容。
Finally, run this command to enable the nginx service:
最後,執行以下指令以啟用 nginx 服務:
sudo systemctl enable nginx
Congratulations! You’re done!
恭喜!你完成了!
I assume that you know how to do everything from here, so I offer no further guidance.
我假設您知道接下來該怎麼做,因此我不再提供進一步的指導。
If you explain how to install something, use the result to show the reader how it works.
如果你說明如何安裝某個東西,請使用安裝結果向讀者展示它是如何運作的。
Your example can be as simple as printing out the version string. Just show how to use the tool for something so that the reader knows whether or not the tutorial worked.
你的例子可以簡單到只印出版本字串。只要展示如何使用該工具做一些事情,讓讀者知道教學是否成功即可。
詳細說明讀者如何與該工具互動。
Finally, run this command to enable the nginx service:
最後,執行以下指令以啟用 nginx 服務:
sudo systemctl enable nginx
Next, visit this URL in your browser:
接著,在您的瀏覽器中造訪此網址:
If everything worked, you should see the default nginx success page.
如果一切順利,您應該會看到 nginx 預設的成功頁面。
In the following sections, I’ll show you how to replace nginx’s default webpage and configure nginx’s settings for your needs.
在以下章節中,我將會向您展示如何替換 nginx 的預設網頁,並根據您的需求配置 nginx 的設定。
Link to a complete example🔗
完整範例連結 🔗
Even if you’re diligent about keeping the reader oriented throughout the tutorial, it still helps to show how everything fits together.
即使您在整個教學過程中都盡力引導讀者,展示所有環節如何契合仍然有所助益。
Link the reader to a code repository that contains all the code you demonstrated in your tutorial.
提供讀者一個程式碼儲存庫的連結,其中包含您在教學中示範的所有程式碼。
Ideally, the repository should run against a continuous integration system such as CircleCI or GitHub Actions to demonstrate that your example builds in a fresh environment.
理想情況下,該儲存庫應該能與持續整合系統(例如 CircleCI 或 GitHub Actions)搭配運作,以驗證您的範例可以在全新的環境中建置。
Bonus: Show the complete code at each stage🔗
加碼放送:每一步驟的完整程式碼🔗
I like to split my repository into git branches so that the reader can see the complete state of the project at every step of the tutorial, not just the final result.
我喜歡將儲存庫拆分成不同的 Git 分支,如此讀者便能看到教程中每個步驟的完整專案狀態,而不僅僅是最終結果。
For example, in my tutorial, “Using Nix to Fuzz Test a PDF Parser,” I show the reader the earliest buildable version of the repository in its own branch:
例如,在我的教程「使用 Nix 模糊測試 PDF 解析器」中,我在一個獨立的分支中展示了最早的可建置版本:
At the end of the tutorial, I link to the final result:
在教程的結尾,我附上了最終結果的連結:
If your tutorial involves files that are too large to show for each change, link to branches to show how the pieces of your tutorial fit together.
如果您的教程包含一些檔案過大而無法顯示每次變更,請連結到各個分支以展示教程各部分是如何組合在一起的。
Read the full book 閱讀完整書籍
This is an excerpt from my upcoming book,
Refactoring English: Effective Writing for Software Developers.
這是我即將出版的著作《重構英文:軟體開發人員的有效寫作》的節錄。
Sign up below to receive updates and free sample chapters as I write the
book.
請在下方註冊以接收更新資訊和免費的樣本章節。
Revisions🔗 修訂版本🔗
I’m writing this book iteratively based on reader feedback. I’ve listed significant changes below.
我正根據讀者的回饋逐步編寫這本書。以下列出了重要的變更。
- 2025-01-02: Published original version
2025 年 1 月 2 日:發佈原始版本 - 2025-01-02: Changed the heading, “Boil it down to the essentials” to, “Teach one thing”
2025 年 1 月 2 日:將標題「去蕪存菁」改為「專注一事」 - 2025-01-03: Removed section, “Let computers evaluate conditional logic”
2025 年 1 月 3 日:移除「讓電腦評估條件邏輯」章節
Illustration by Loraine Yow.
Loraine Yow 绘圖