如何摆脱教程地狱并发布真实代码

发布: (2026年3月8日 GMT+8 16:05)
12 分钟阅读
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的正文内容,我将为您翻译成简体中文,同时保留原始的格式、Markdown 语法以及代码块和 URL 不变。)

Source:

打破教程地狱的循环

你已经完成了教程。Todo 应用可以运行了。你觉得已经准备好了。

于是你打开一个空白编辑器想要构建真正的东西,却一无所获。

教程会同时给你问题答案。真实项目只会给你问题。

下面是5 个具体步骤——每一步都有真实示例——帮助你从“卡住”走向可运行的原创项目。

步骤 1:挑选一个你真正需要的问题

每个教程都以“我们来构建一个 …”开头,给你预先挑好的问题。这是第一个陷阱:你从未练习软件开发中最难的部分——决定要构建什么

从你真的需要的东西开始。 它不必惊人,只要对你有用即可。

不佳的选择

  • “我要构建一个社交媒体克隆” – 规模太大,缺乏个人关联。
  • “我要做一个区块链应用” – 你根本不需要。
  • “我要搭建一个电商网站” – Shopify 已经存在。

好的选择

  • 一个根据日期重命名已下载文件的脚本。
  • 一个追踪今年读过哪些书的 API。
  • 一个检查你最喜欢的网站是否宕机的 CLI 工具。

规则: 如果你真的会使用它,你就真的会完成它。

步骤 2:在写代码前先写 README

大多数初学者会跳过这一步。他们直接进入代码,卡在架构决策上,最终放弃。

  1. 创建一个名为 README.md 的文件。
  2. 回答以下三个问题:
# Book Tracker API

它的作用是什么?

一个简单的 REST API,允许我添加、列出和删除今年阅读的书籍。

适用于谁?

我——我想要一种快速查看阅读进度的方法,而不必打开电子表格。

我怎么知道它能正常工作?

  • GET /books 返回我的书籍的 JSON 数组。
  • POST /books 添加一本新书并返回创建的记录。
  • DELETE /books/:id 删除一本书并返回 204 状态码。

拥有这个“契约”可以在一开始就指导你的设计,让你保持专注。

### 第 3 步:勾勒最小可行产品(MVP)

不要尝试实现你能想到的所有功能。列出满足 README 所需的绝对最小需求。

| 功能                         | 必须拥有? |
|-----------------------------|------------|
| 添加一本书(标题、作者、日期) | ✅ |
| 列出所有书籍                | ✅ |
| 按 ID 删除一本书             | ✅ |
| 将数据持久化到文件           | ✅ |
| 身份验证                     | ❌ |
| Web UI                      | ❌ |

现在你拥有了一个清晰、可拆分的范围。

### 第 4 步:选择最小可行的技术栈  

挑选你已经足够熟悉、能够高效使用的工具,同时还能完成 MVP。

- **语言:** Node.js(JavaScript)—— 你在教程中已经使用过。  
- **框架:** Express —— 路由简洁,无需额外样板代码。  
- **数据存储:** 通过 `fs` 操作的 JSON 文件 —— 不需要数据库配置。  
- **测试:** Jest —— 为每个端点编写简单的单元测试。

如果需要学习新库,只选一个文档完善、易于上手的组件。

### 第 5 步:实现、测试、迭代  

1. **实现** 端点,一次一个,按照 MVP 表中的顺序。  
2. **编写测试** 为每个端点 *在* 编码之前(测试驱动开发)。  
3. **运行测试** —— 它应当失败。  
4. **编写代码** 使测试通过。  
5. 如有必要,**重构**,然后继续下一个端点。

因为你已经有了明确的 README、MVP 列表和轻量的技术栈,你将保持进度,完成一个可用的项目,而不是仅仅复制教程。

## 完成时…

你将拥有一个 **working Book Tracker API**,它是真正能用的,来源于你关心的问题,具备清晰的规范、最小的范围,以及你能管理的技术栈。这个过程可以复用于任何未来的想法,将“教程地狱”转变为 **real‑world development confidence**。

## 它的功能是什么?

- 记录我读过的书籍。  
- 存储标题、作者、完成日期以及 1‑5 评分。  
- 支持按作者或评分进行查询。

## 如何使用?

| 方法   | 端点                     | 描述                     |
|----------|------------------------------|---------------------------------|
| `POST`   | `/books`                     | 添加一本新书                  |
| `GET`    | `/books`                     | 列出所有书籍                  |
| `GET`    | `/books?author=Knuth`        | 按作者筛选书籍                |
| `DELETE` | `/books/{id}`                | 根据 ID 删除书籍               |

## 什么技术?  

**Python + FastAPI + SQLite**

### 步骤 3 – 首先构建最小可工作版本  

Start with an in‑memory API (no DB, auth, or deployment).

```python
# main.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()
books: list[dict] = []
next_id: int = 1

class BookCreate(BaseModel):
    title: str
    author: str
    rating: int

@app.post("/books")
def add_book(book: BookCreate):
    global next_id
    entry = {"id": next_id, **book.model_dump()}
    books.append(entry)
    next_id += 1
    return entry

@app.get("/books")
def list_books(author: str | None = None):
    if author:
        return [b for b in books if b["author"].lower() == author.lower()]
    return books

@app.delete("/books/{book_id}")
def delete_book(book_id: int):
    for i, b in enumerate(books):
        if b["id"] == book_id:
            return books.pop(i)
    raise HTTPException(status_code=404, detail="Book not found")

Run it:

pip install fastapi uvicorn
uvicorn main:app --reload

访问 http://localhost:8000/docs 查看交互式文档。

步骤 4 – 一次添加一个功能

目标
1内存 API(如上)。提交。
2添加一个测试。
3用 SQLite 替换列表(仅存储层)。
4使用 Pydantic 添加输入验证。

示例测试(test_main.py):

from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_add_and_list_books():
    resp = client.post("/books", json={"title":"TAOCP Vol 1","author":"Knuth","rating":5})
    assert resp.status_code == 200
    data = resp.json()
    assert data["title"] == "TAOCP Vol 1"
    assert data["id"] == 1

    resp = client.get("/books")
    assert resp.status_code == 200
    assert len(resp.json()) >= 1

运行测试:

pip install pytest httpx
pytest test_main.py -v

验证示例:

from pydantic import BaseModel, Field

class BookCreate(BaseModel):
    title: str = Field(min_length=1, max_length=200)
    author: str = Field(min_length=1, max_length=100)
    rating: int = Field(ge=1, le=5)

无效的负载现在会自动返回 422 错误。

步骤 5 – 将其放到大家能看到的地方

  1. 创建一个 GitHub 仓库。
  2. 推送代码。
  3. 编写包含以下内容的 README:
    • 项目描述。
    • 本地运行说明(pip installuvicorn)。
    • 测试命令(pytest)。
    • 未来路线图(第 3‑4 周)。

简洁、结构良好的 README 能展示可运行的代码和前瞻性的规划——这是初级开发者作品集的关键。

未来改进

  • 用 SQLite 替换内存存储
  • 添加基于 JWT 的用户认证
  • 部署到 Railway 或 Render
  • 为大型书籍列表添加分页

这些并非模糊的愿望。每一行都是具体且可实现的功能。这就是“我时间不够”和“我确切知道接下来要做什么”之间的区别。

这些步骤背后的模式

注意我们没有做的事情:

  • 我们没有先观看12小时的课程。
  • 我们没有从“前10名作品项目”列表中挑选项目。
  • 我们没有在写下第一行业务逻辑之前就设置 Docker、CI/CD 或云数据库。
  • 我们没有在开始之前尝试学习所有东西。

我们挑选了一个真实的问题,编写了规格说明,构建了最小可行版本,逐步添加功能,并让它可见。这才是专业软件的构建方式。教程教语法;项目教判断力。

仍然陷入教程地狱的信号

  • 你可以跟着教程走,但无法从零开始构建。 关闭教程,打开一个空文件。如果你在不查资料的情况下写不出前 10 行代码,你需要更多的实践,而不是更多的教程。
  • 你的 GitHub 没有任何原创项目。 Fork 的仓库和教程克隆不算数。一个丑陋但能正常运行、由你自己设计的项目,价值远超十个打磨得很好的教程副本。
  • 你不断开始新课程,却不完成项目。 下一门课程并不能解决这个问题。解决办法是交付(发布)一些东西,即使它很小。
  • 你害怕展示自己的代码。 推送它吧。它不会完美。没有人的第一个项目是完美的。你敬佩的开发者们也曾在早期交付过尴尬的代码。

逃离之后会怎样

一旦你从零开始完成一个项目,第二个项目就会更容易。第三个会更快。到了第五个时,你不再思考语法,而是开始考虑设计。

这就是教程追随者和真正构建者之间的真实技能差距。构建者会思考代码为何这样组织。教程只展示代码的什么样子。

你的第一个项目会很凌乱。会有 bug。命名会不一致。错误处理会不完整。但仍然发布它。

雇主雇佣的不是最整洁的程序员,而是那些交付了真实作品、从混乱中学习并在下次交付更好作品的人。

今天就开始。 选一个问题。写 README。构建最小可行版本。添加一个功能。提交它。

关注 @klement_gunndu 获取更多编程和职业内容。我们正在公开构建。

0 浏览
Back to Blog

相关文章

阅读更多 »