diff --git a/README.md b/README.md index a1241e3..e3eac15 100644 --- a/README.md +++ b/README.md @@ -73,18 +73,19 @@ ## 模块 2: Application Development -> 理解软件是怎么运作的。基于 Chicago Booth BUSN 36110 课程核心思想,用螺旋式学习法(Spiral Learning)从零构建对 Web 应用的完整心智模型。 +> 理解软件是怎么运作的。基于 Chicago Booth BUSN 36110 课程核心思想,用螺旋式学习法构建对 Web 应用的完整心智模型。 > -> → [**模块首页**](modules/app-dev-fundamentals/README.md)(课程思想、7 个目标、螺旋式学习法) - -| 阶段 | 内容 | -|------|------| -| Web 基础 | HTTP、API、HTML / CSS | -| 编程逻辑 | 控制流、面向对象 | -| 动态应用 | 路由、表单、数据处理 | -| 数据层 | 关系型数据库、数据关联 | -| 安全与认证 | Cookie、认证、权限 | -| 综合实践 | "First of Many" 最终项目 | +> → [**模块首页**](modules/app-dev-fundamentals/README.md)(课程思想、教学理念、与 Agentic Coding 的关系) + +| 章节 | 主题 | 一句话简介 | +|------|------|-----------| +| [01](modules/app-dev-fundamentals/01-how-the-web-works/README.md) | 互联网是怎么工作的 | HTTP 请求与响应,URL 的工作原理 | +| [02](modules/app-dev-fundamentals/02-data-modeling/README.md) | 数据建模 | 最高杠杆的技能——名词变成表 | +| [03](modules/app-dev-fundamentals/03-request-lifecycle/README.md) | 请求的生命周期 | RCAV: URL 如何变成你看到的页面 | +| [04](modules/app-dev-fundamentals/04-databases-and-crud/README.md) | 数据库与 CRUD | 增删改查——所有应用的骨架 | +| [05](modules/app-dev-fundamentals/05-apis/README.md) | API | "一切都是 HTTP 请求" | +| [06](modules/app-dev-fundamentals/06-auth-and-security/README.md) | 认证与安全 | 谁是你,你能做什么 | +| [方法论](modules/app-dev-fundamentals/methodology/README.md) | 教学理念 | 螺旋学习、砍范围、AI 是乘数 | --- diff --git a/modules/app-dev-fundamentals/01-how-the-web-works/README.md b/modules/app-dev-fundamentals/01-how-the-web-works/README.md new file mode 100644 index 0000000..46bc679 --- /dev/null +++ b/modules/app-dev-fundamentals/01-how-the-web-works/README.md @@ -0,0 +1,136 @@ +> [← 模块首页](../README.md) · [下一章: 数据建模 →](../02-data-modeling/README.md) + +# 01: 互联网是怎么工作的(HTTP 请求与响应) + +> 一句话:你在浏览器输入一个网址,按下回车,发生了什么? + +## 为什么 Coding Agent 用户需要懂这个 + +当你让 Claude Code 或 Cursor"加一个页面"时,你其实在要求它做一件非常具体的事:创建一个 URL,让服务器在收到这个 URL 的请求时返回一段 HTML 响应。 + +如果你不理解"页面 = URL = 请求 + 响应"这个等式,你就没法准确描述你想要什么。你可能会说"加一个关于我们的页面",但你真正需要说的是"加一个 `/about` 路由,返回公司介绍页面"。 + +后一种说法,AI 能更准确地执行。 + +## 核心心智模型 + +### 餐厅点餐类比 + +整个互联网的运作逻辑,和去餐厅吃饭差不多: + +| 餐厅 | 互联网 | +|------|--------| +| 你(顾客) | 浏览器(Browser) | +| 你想吃的菜名 | 网址 / URL | +| 你的点菜单 | 请求(Request) | +| 厨房 | 服务器(Server) | +| 端上来的菜 | 响应(Response) | + +流程是这样的: + +1. 你(浏览器)走进餐厅,告诉服务员你要什么(输入 URL) +2. 服务员把你的点菜单递给厨房(发送 HTTP 请求) +3. 厨房做菜(服务器处理请求、查数据库、生成页面) +4. 菜端上来(服务器返回 HTTP 响应) +5. 你看到菜了(浏览器渲染页面) + +每一次你在网上点击一个链接、提交一个表单、刷新一个页面,都是在重复这个过程。没有例外。 + +### HTTP 方法:你在对服务器说什么 + +不是所有请求都一样。最常用的两种: + +- **GET** — "给我看一下这个东西"。你打开一个页面、查看一篇文章,都是 GET 请求。就像在餐厅看菜单,你只是在看,没有改变任何东西。 +- **POST** — "我要提交一些信息"。你注册一个账号、提交一个表单、发布一条评论,都是 POST 请求。就像正式点菜——你在告诉厨房"请做这道菜"。 + +还有 PUT/PATCH(修改)和 DELETE(删除),但 GET 和 POST 是最基础的两个。理解了这两个,其他的都是变体。 + +### URL 的结构 + +一个 URL 不是一串随机字符,它有明确的结构: + +``` +https://www.example.com/users/123?tab=posts +│ │ │ │ +协议 域名 路径 查询参数 +``` + +- **协议**(Protocol):`https://` — 通信规则,https 表示加密的 +- **域名**(Domain):`www.example.com` — 服务器的地址,就像餐厅的名字和位置 +- **路径**(Path):`/users/123` — 你想要的具体资源,就像菜单上的菜名 +- **查询参数**(Query String):`?tab=posts` — 额外的要求,就像"少辣"、"多加醋" + +当你让 AI"加一个用户详情页面"时,你其实在定义一个新的路径(比如 `/users/:id`),这个路径在收到 GET 请求时返回对应用户的信息。 + +### "动态"意味着什么 + +这是一个关键概念:**同一个 URL 模式,可以返回不同的内容**。 + +`/users/1` 和 `/users/2` 的 URL 结构一样,但返回的是不同用户的信息。这就是"动态"的意思——页面不是提前写好的文件,而是服务器根据请求中的参数,实时从数据库里查出数据,拼装成页面返回给你。 + +这和静态网页(一个 HTML 文件对应一个页面)完全不同。理解这一点,你才能理解为什么现代应用都需要数据库。 + +### 状态码:服务器在告诉你发生了什么 + +每个响应都会带一个三位数的状态码,告诉浏览器"结果怎么样": + +| 状态码 | 含义 | 餐厅类比 | +|--------|------|----------| +| **200** | 成功(OK) | 菜上了,一切正常 | +| **301/302** | 重定向(Redirect) | "这道菜改名了,帮你换一个" | +| **404** | 找不到(Not Found) | "菜单上没有这道菜" | +| **403** | 没有权限(Forbidden) | "这是 VIP 专属,你不能点" | +| **500** | 服务器内部错误(Internal Server Error) | "厨房着火了" | + +当你的应用报错时,第一步就是看状态码。404 说明 URL 路径写错了或者路由没配置;500 说明服务器端的代码有 bug。这是最基本的排错信息。 + +## 常见误区 + +### 误区 1:"网页是一个文件" + +很多人以为每个网页都对应服务器上的一个 HTML 文件。在静态网站时代确实如此,但现代 Web 应用完全不同——每个页面都是服务器收到请求后**动态生成**的响应。同一个 URL,登录用户和未登录用户看到的内容可能完全不同。 + +### 误区 2:"前端和后端是两个独立的东西" + +前端和后端不是两个独立的世界,它们通过 HTTP 请求紧密连接。前端(浏览器)发送请求,后端(服务器)处理请求并返回响应。理解它们之间的这条"管道"比分别理解两端更重要。 + +## 这个概念在 Agentic Coding 中的应用 + +理解 HTTP 请求-响应模型后,你在 Agentic Coding 模块中会更顺畅: + +- **Week 2(全栈开发)**:你会用 AI 构建一个完整的 Web 应用。每一个页面、每一个表单提交,都是一次 HTTP 请求-响应。理解这个模型后,你能更准确地描述你要的功能。 +- **Week 3(MCP 服务器)**:MCP 协议本质上也是基于请求-响应模式的通信。理解了 HTTP,你对 MCP 的理解会快很多。 +- **调试**:当应用报错时,你的第一反应应该是"这是哪一步出了问题?是请求没发出去?是服务器处理出错?还是响应格式不对?" + +## 动手试一试 + +不需要安装任何东西,点开就能练: + +### 练习 1:看一个真实的 HTTP 请求 +1. 打开浏览器,按 `F12`(或右键 → 检查)打开开发者工具 +2. 切换到 **Network**(网络)标签 +3. 在地址栏输入任意网址(比如 `https://httpbin.org/get`)并回车 +4. 观察 Network 面板里出现的请求:请求方法(GET)、状态码(200)、响应内容(JSON) +5. 这就是一个完整的 HTTP 请求-响应过程 + +### 练习 2:发送不同类型的请求 +打开 [httpbin.org](https://httpbin.org/) — 这是一个专门用来测试 HTTP 请求的免费服务: +- 点击 `/get` → 看 GET 请求返回什么 +- 点击 `/status/404` → 体验一个 404 状态码 +- 点击 `/status/500` → 体验一个服务器错误 + +### 练习 3:理解 URL 结构 +观察这个 URL,尝试拆解它的组成部分: +``` +https://www.google.com/search?q=coding+agent&hl=zh +``` +- 协议是什么?域名是什么?路径是什么?查询参数有哪些? +- 试着修改 `q=` 后面的内容,看搜索结果怎么变化 + +## 下一步 + +→ [02: 数据建模 — 最高杠杆的技能](../02-data-modeling/README.md) + +--- + +[← 模块首页](../README.md) · [下一章: 数据建模 →](../02-data-modeling/README.md) diff --git a/modules/app-dev-fundamentals/02-data-modeling/README.md b/modules/app-dev-fundamentals/02-data-modeling/README.md new file mode 100644 index 0000000..3bea5c2 --- /dev/null +++ b/modules/app-dev-fundamentals/02-data-modeling/README.md @@ -0,0 +1,203 @@ +> [← 模块首页](../README.md) · [← 上一章: 互联网是怎么工作的](../01-how-the-web-works/README.md) · [下一章: 请求的生命周期 →](../03-request-lifecycle/README.md) + +# 02: 数据建模 — 最高杠杆的技能 + +> 一句话:在写任何代码之前,先想清楚你要存什么数据、数据之间是什么关系。 + +## 为什么这是最重要的一课 + +> "If we can get this part right, the rest of the code practically writes itself." +> +> (如果我们能把数据建模做对,剩下的代码几乎是自动写出来的。) + +这句话在传统开发中就已经是真理。在 Coding Agent 时代,它的分量增加了十倍。 + +为什么?因为 AI 特别擅长根据数据结构来生成代码。你给 AI 一个清晰的数据模型——有哪些表、每张表有哪些字段、表之间是什么关系——AI 就能自动生成增删改查的接口、表单页面、数据校验逻辑。但如果你的数据模型是错的,AI 生成的一切都会建立在一个有裂缝的地基上。 + +**一个正确的数据模型,是你能给 Coding Agent 的最高杠杆输入。** + +## 核心心智模型 + +### "名词变成表"方法 + +数据建模听起来很抽象,但方法非常简单: + +1. **列出你的应用里的核心名词** — 用户、文章、评论、订单、商品、标签…… +2. **每个名词 = 一张数据表** — User 表、Article 表、Comment 表…… +3. **每张表的列 = 这个名词的属性** — User 表有 name、email、password;Article 表有 title、body、published_at + +就这样。数据建模的第一步不是画 ER 图、不是写 SQL,而是用日常语言列出你的应用里有哪些"东西"。 + +**试一试**:想想你日常用的任何一个应用——微信、淘宝、抖音。列出它的核心名词。你会发现,虽然界面天差地别,但底层的数据结构都是"名词 + 属性 + 关系"。 + +### "纸质表格测试" + +这是检验数据模型是否正确的最朴素方法: + +1. 在纸上画出你的每张表,像 Excel 那样,列头是字段名 +2. 填上几行示例数据(真实的、具体的数据,不是"xxx") +3. 用手指模拟查询:"我想查张三发布的所有文章"——你能从这些表里找到吗? +4. 再试:"我想看某篇文章的所有评论"——找得到吗? +5. 如果找不到,说明你缺了某个字段或某个关系 + +如果你手动能查到想要的数据,说明数据模型是对的。如果查不到,问题一定出在表的设计上——要么缺了某张表,要么缺了某个关联字段。 + +这个测试看起来很"低技术",但它比任何建模工具都有效。因为它迫使你用真实数据去验证,而不是在抽象概念里打转。 + +### 关系类型 + +数据之间的关系只有三种。记住这三种,你就能建模 95% 的应用: + +#### 一对多(One-to-Many) + +一个用户有多篇文章,但每篇文章只属于一个用户。 + +怎么实现?在"多"的那一方加一个外键(Foreign Key)。文章表里加一个 `user_id` 列,指向用户表的 `id`。 + +``` +用户表 (Users) 文章表 (Articles) +┌────┬──────┐ ┌────┬──────────┬─────────┐ +│ id │ name │ │ id │ title │ user_id │ +├────┼──────┤ ├────┼──────────┼─────────┤ +│ 1 │ 张三 │ │ 1 │ 第一篇 │ 1 │ +│ 2 │ 李四 │ │ 2 │ 第二篇 │ 1 │ +└────┴──────┘ │ 3 │ 第三篇 │ 2 │ + └────┴──────────┴─────────┘ +``` + +张三(id=1)有两篇文章,李四(id=2)有一篇。通过 `user_id` 就能查到。 + +#### 多对多(Many-to-Many) + +一个学生选多门课,一门课有多个学生。 + +这时候不能简单地在一方加外键。你需要一张**中间表**(Join Table),专门记录"谁选了哪门课": + +``` +学生表 选课表 (Enrollments) 课程表 +┌────┬──────┐ ┌────┬────────────┬───────────┐ ┌────┬────────┐ +│ id │ name │ │ id │ student_id │ course_id │ │ id │ name │ +├────┼──────┤ ├────┼────────────┼───────────┤ ├────┼────────┤ +│ 1 │ 张三 │ │ 1 │ 1 │ 1 │ │ 1 │ 数学 │ +│ 2 │ 李四 │ │ 2 │ 1 │ 2 │ │ 2 │ 英语 │ +└────┴──────┘ │ 3 │ 2 │ 1 │ └────┴────────┘ + └────┴────────────┴───────────┘ +``` + +张三选了数学和英语,李四选了数学。中间表就是那个"粘合剂"。 + +#### 一对一(One-to-One) + +一个用户有一份个人档案。相对少见,但偶尔会用到。处理方式和一对多类似——在其中一方加外键,**但必须加上唯一性约束**(Unique Constraint),确保每个用户只能有一份档案。没有唯一性约束的话,它实际上就变成了一对多。 + +### 判断关系的黄金问题 + +面对任意两个名词,问自己两个问题: + +> "一个 X 能有多个 Y 吗?一个 Y 能有多个 X 吗?" + +| X → 多个 Y? | Y → 多个 X? | 关系类型 | +|:---:|:---:|:---:| +| 否 | 否 | 一对一 | +| 是 | 否 | 一对多(X 是"一",Y 是"多") | +| 否 | 是 | 一对多(Y 是"一",X 是"多") | +| 是 | 是 | 多对多 | + +每次遇到新的名词关系,用这两个问题一测,答案立刻出来。 + +## 常见误区 + +### 误区 1:"先写代码再想数据结构" + +这是最常见的错误。很多人上来就让 AI 写页面、写功能,结果做到一半发现数据存不对,只好推翻重来。**数据结构决定一切**。先用 5 分钟想清楚名词、属性、关系,后面能省几个小时的返工。 + +### 误区 2:"表越多越好"或"越少越好" + +表的数量不是目标,**每个独立的名词一张表**才是原则。不要把不同的东西硬塞进一张表(比如把"用户"和"订单"放在一起),也不要把一个东西拆成多张表(比如把用户的基本信息和联系方式分成两张表,除非有特殊理由)。 + +### 误区 3:"AI 会帮我设计数据模型" + +AI 可以建议数据模型,但只有你才理解你的业务领域。"一个老师能教多门课吗?"这种问题取决于你的业务规则,不取决于技术。如果你在教培机构,一个老师可能只教一门课;如果你在大学,一个老师通常教多门课。AI 不知道你的具体情况,你知道。 + +## 练习:用你自己的项目试一试 + +试着为一个**读书笔记应用**做数据建模: + +**第一步:列出名词** +- 用户(User) +- 书(Book) +- 笔记(Note) +- 标签(Tag) + +**第二步:列出属性** +- User:name、email、password +- Book:title、author、isbn +- Note:content、page_number、created_at +- Tag:name + +**第三步:用黄金问题判断关系** +- 一个用户能有多本书吗?是。一本书能属于多个用户吗?是。→ **多对多**(需要中间表,比如 UserBook) +- 一本书能有多条笔记吗?是。一条笔记能属于多本书吗?否。→ **一对多**(Note 加 book_id) +- 一条笔记能有多个标签吗?是。一个标签能属于多条笔记吗?是。→ **多对多**(需要中间表 NoteTag) +- 一个用户能有多条笔记吗?是。一条笔记能属于多个用户吗?否。→ **一对多**(Note 加 user_id) + +**第四步:纸质表格测试** + +在纸上画出这些表,填上几行数据,试试能不能查到"张三在《思考,快与慢》这本书上写的所有笔记"。如果能查到,数据模型就是对的。 + +## 动手试一试 + +### 在线 SQL 练习:亲手建表查询 +打开 [SQLiteOnline](https://sqliteonline.com/) — 浏览器里直接写 SQL,不需要安装任何东西: + +1. **建一张用户表**(复制粘贴到左侧编辑器,点 Run): +```sql +CREATE TABLE users ( + id INTEGER PRIMARY KEY, + name TEXT, + email TEXT +); +INSERT INTO users VALUES (1, '张三', 'zhang@example.com'); +INSERT INTO users VALUES (2, '李四', 'li@example.com'); +SELECT * FROM users; +``` + +2. **建一张文章表,体验外键关联**: +```sql +CREATE TABLE articles ( + id INTEGER PRIMARY KEY, + title TEXT, + user_id INTEGER +); +INSERT INTO articles VALUES (1, '第一篇文章', 1); +INSERT INTO articles VALUES (2, '第二篇文章', 1); +INSERT INTO articles VALUES (3, '第三篇文章', 2); +SELECT * FROM articles WHERE user_id = 1; +``` +最后一行查询的意思是:"查找张三(id=1)的所有文章"。运行看看结果。 + +3. **试试连表查询**: +```sql +SELECT users.name, articles.title +FROM articles +JOIN users ON articles.user_id = users.id; +``` +这就是把两张表"连"起来,同时看到作者名字和文章标题。 + +> 这些 SQL 你不需要背。重要的是亲手跑一遍,体会"表"和"关系"在真实数据库中是怎么工作的。 + +## 这个概念在 Agentic Coding 中的应用 + +数据建模是你与 Coding Agent 协作的起点。实际操作建议: + +1. **先描述数据模型,再描述功能** — 给 AI 的 prompt 中,第一段就应该是数据模型:"这个应用有四张表:User、Book、Note、Tag,关系如下……"。然后再说功能需求。这是最高效的沟通方式。 +2. **把数据模型写进 CLAUDE.md** — 如果你用 Claude Code,在项目的 CLAUDE.md 文件中明确写出数据模型。这样 AI 在整个开发过程中都有一致的参照。(参见 [Agentic Coding Week 4](../../agentic-coding/week4/README.md)) +3. **数据模型变了,所有代码都要跟着变** — 如果你中途发现某个关系类型判断错了(比如把一对多误判为一对一),要立刻修正。越早修正代价越小。 + +## 下一步 + +→ [03: 请求的生命周期(RCAV 模式)](../03-request-lifecycle/README.md) + +--- + +[← 上一章: 互联网是怎么工作的](../01-how-the-web-works/README.md) · [下一章: 请求的生命周期 →](../03-request-lifecycle/README.md) diff --git a/modules/app-dev-fundamentals/03-request-lifecycle/README.md b/modules/app-dev-fundamentals/03-request-lifecycle/README.md new file mode 100644 index 0000000..6435ed6 --- /dev/null +++ b/modules/app-dev-fundamentals/03-request-lifecycle/README.md @@ -0,0 +1,153 @@ +> [← 模块首页](../README.md) · [← 上一章: 数据建模](../02-data-modeling/README.md) · [下一章: 数据库与 CRUD →](../04-databases-and-crud/README.md) + +# 03: 请求的生命周期(RCAV 模式) + +> 一句话:一个 URL 如何变成你看到的页面?四步:Route → Controller → Action → View。 + +## 为什么 Coding Agent 用户需要懂这个 + +当你对 AI 说"加一个显示用户资料的页面"时,AI 实际上需要创建至少四样东西:一条路由规则、一个控制器、一个处理逻辑、一个页面模板。 + +如果你理解 RCAV 模式,你就能: + +- **检查 AI 是不是四步都做了** — 有时候 AI 会漏掉某一步,比如定义了路由但忘了写视图 +- **精准定位出错的位置** — 页面白屏?可能是路由没匹配上。页面出来了但数据为空?可能是 Action 里没查数据库。会看 RCAV 四步,就能快速缩小排查范围 +- **用结构化语言下指令** — "在 `/dashboard` 路由的 `index` action 里查询当前用户的所有项目,传给 view 渲染"比"做一个仪表板"精确十倍 + +## 核心心智模型 + +### 一个类比:餐厅的完整点餐流程 + +在 [01 章](../01-how-the-web-works/README.md)我们讲了请求-响应的基本模型。现在我们展开来看请求到达服务器之后,内部具体发生了什么: + +| 步骤 | 餐厅 | Web 应用 | +|------|------|----------| +| 1. 点菜 | 你说"我要宫保鸡丁" | 浏览器请求 `/dishes/kung-pao-chicken` | +| 2. 服务员查菜单 | 确认菜单上有这道菜,找到对应的厨师 | **Route**:URL 匹配路由规则,找到控制器 | +| 3. 对应的厨师 | 中餐厨师负责 | **Controller**:DishesController 处理 | +| 4. 具体做法 | 厨师按菜谱操作:切鸡肉、炒花生… | **Action**:`show` 方法查数据库、准备数据 | +| 5. 装盘上桌 | 把做好的菜装在盘子里端上来 | **View**:把数据渲染成 HTML 页面返回 | + +### RCAV 四步详解 + +#### 第一步:Route(路由) + +路由是 URL 和代码之间的"路标"。它定义了一条规则:当收到某个 URL 的请求时,交给哪个 Controller 的哪个 Action 去处理。 + +``` +GET /users/123 → UsersController#show +GET /articles → ArticlesController#index +POST /articles → ArticlesController#create +``` + +注意:同一个 URL(`/articles`)在不同的 HTTP 方法(GET vs POST)下可以指向不同的 Action。GET `/articles` 是"查看文章列表",POST `/articles` 是"创建新文章"。 + +#### 第二步:Controller(控制器) + +Controller 是一个"部门",负责处理一类相关的请求。UsersController 处理所有和用户相关的请求,ArticlesController 处理所有和文章相关的请求。 + +一个 Controller 通常对应你数据模型里的一个名词(还记得 [02 章](../02-data-modeling/README.md) 的"名词变成表"吗?)。有 User 表,就通常有 UsersController。 + +#### 第三步:Action(动作) + +Action 是 Controller 里的一个具体方法,是真正"干活"的地方。它做两件事: +1. 和数据库交互(查数据、存数据、改数据、删数据) +2. 把结果准备好,交给 View 去渲染 + +#### 第四步:View(视图) + +View 是最终用户看到的东西。它拿到 Action 准备好的数据,渲染成 HTML(或者 JSON)返回给浏览器。 + +View 本身不做任何逻辑判断、不做数据库查询——它只负责"展示"。这是一个重要的职责分离原则。 + +### 标准的 7 个 Action + +几乎所有 Web 框架都遵循同一套约定:对每个资源(名词),有 7 个标准的 Action: + +| Action | HTTP 方法 | URL 示例 | 做什么 | +|--------|-----------|----------|--------| +| **index** | GET | `/articles` | 显示列表 | +| **show** | GET | `/articles/123` | 显示一条的详情 | +| **new** | GET | `/articles/new` | 显示"新建"表单 | +| **create** | POST | `/articles` | 保存新建的数据 | +| **edit** | GET | `/articles/123/edit` | 显示"编辑"表单 | +| **update** | PATCH/PUT | `/articles/123` | 保存修改的数据 | +| **destroy** | DELETE | `/articles/123` | 删除数据 | + +这 7 个 Action 覆盖了大多数 Web 应用 **90% 以上的操作**。当你理解了这 7 个 Action,你就理解了几乎所有"增删改查"页面的工作方式。 + +更重要的是:当你让 AI"为文章加上编辑功能"时,AI 知道它需要加 `edit` action(显示表单)和 `update` action(保存修改)——两步,不是一步。如果你也知道这一点,你就能检查 AI 是否做完整了。 + +### RCAV 的完整图解 + +``` +浏览器请求 GET /articles/123 + │ + ▼ + ┌──────────┐ + │ Route │ 匹配规则:GET /articles/:id → ArticlesController#show + └────┬─────┘ + │ + ▼ + ┌──────────────────┐ + │ Controller │ ArticlesController + │ └─ Action: show │ article = 从数据库查 id=123 的文章 + └────┬─────────────┘ + │ + ▼ + ┌──────────┐ + │ View │ 把 article 的标题、内容渲染成 HTML + └────┬─────┘ + │ + ▼ + 浏览器收到 HTML,显示页面 +``` + +## 常见误区 + +### 误区 1:"每个页面都是独立的" + +不是。每个页面都经过 RCAV 四步。看似独立的页面背后,共享着相同的模式。理解了一个页面的 RCAV,你就理解了所有页面的 RCAV。 + +### 误区 2:"URL 就是文件路径" + +在早期的静态网站中,`/about.html` 确实对应服务器上的一个文件。但在现代 Web 应用中,URL 是一条**路由规则**,它映射到代码逻辑,不映射到文件。`/users/123` 不是服务器上的某个文件夹,而是一个匹配规则,触发 UsersController 的 show action。 + +### 误区 3:"前端框架改变了一切" + +React、Vue 这些前端框架看起来打破了 RCAV 模式,但本质没变。它们只是把"View 渲染"从服务器搬到了浏览器端。请求-路由-数据处理-展示这四步依然存在,只是执行的位置变了。理解了 RCAV,你对前端框架的理解也会更快。 + +## 这个概念在 Agentic Coding 中的应用 + +RCAV 是和 AI 协作开发时最实用的"共同语言"之一: + +- **描述需求时用 RCAV 的语言**:"添加一个 `GET /dashboard` 路由,在 `DashboardController` 的 `index` action 里查询当前用户的所有项目,用 `dashboard/index` 视图渲染成卡片列表。" 这比"做一个仪表板页面"有效十倍。 +- **Review AI 生成的代码时按 RCAV 检查**:路由定义了吗?Controller 存在吗?Action 里查了数据库吗?View 模板写了吗?四步都到位了,功能就不会缺失。 +- **调试时按 RCAV 定位**:404 错误?大概率是 Route 的问题。500 错误?看 Action 里的代码。页面出来了但数据不对?看 Action 查询逻辑或 View 渲染逻辑。 + +## 动手试一试 + +### 练习 1:在真实网站中追踪 RCAV +1. 打开任意一个 Web 应用(比如 GitHub) +2. 点击不同的页面,观察 URL 的变化: + - `github.com/AlexAnys` → 这是哪个 Controller 的哪个 Action?(Users#show) + - `github.com/AlexAnys/agent-first-dev` → (Repositories#show) + - `github.com/AlexAnys/agent-first-dev/issues` → (Issues#index) + - `github.com/AlexAnys/agent-first-dev/issues/new` → (Issues#new) +3. 你会发现所有页面都符合 RCAV 模式——URL 决定了走哪条路由 + +### 练习 2:用 JSON Placeholder 体验 7 个标准 Action +打开 [JSONPlaceholder](https://jsonplaceholder.typicode.com/) — 一个免费的模拟 API: +- **index**(列表):在浏览器打开 `https://jsonplaceholder.typicode.com/posts` → 看到所有文章 +- **show**(详情):打开 `https://jsonplaceholder.typicode.com/posts/1` → 看到第 1 篇文章 +- **嵌套资源**:打开 `https://jsonplaceholder.typicode.com/posts/1/comments` → 看到第 1 篇文章的所有评论 + +注意 URL 的模式:`/资源名` = 列表,`/资源名/id` = 详情。这就是 RCAV 中的 Route 规则。 + +## 下一步 + +→ [04: 数据库与 CRUD](../04-databases-and-crud/README.md) + +--- + +[← 上一章: 数据建模](../02-data-modeling/README.md) · [下一章: 数据库与 CRUD →](../04-databases-and-crud/README.md) diff --git a/modules/app-dev-fundamentals/04-databases-and-crud/README.md b/modules/app-dev-fundamentals/04-databases-and-crud/README.md new file mode 100644 index 0000000..081f70f --- /dev/null +++ b/modules/app-dev-fundamentals/04-databases-and-crud/README.md @@ -0,0 +1,103 @@ +> [← 模块首页](../README.md) · [← 03: 请求的生命周期](../03-request-lifecycle/README.md) · [05: API →](../05-apis/README.md) + +# 04: 数据库与 CRUD — 数据的四种基本操作 + +> 一句话:所有应用本质上都在做四件事——创建(Create)、读取(Read)、更新(Update)、删除(Delete)。 + +## 为什么 Coding Agent 用户需要懂这个 + +When you ask AI to "add a feature to save user preferences", you're asking it to implement Create and Update operations. Understanding CRUD helps you describe features precisely and verify AI's implementation. + +## 核心心智模型 + +### CRUD = 所有应用的骨架 + +- **Create**: 用户注册、发帖、下单 +- **Read**: 查看个人资料、浏览商品列表、搜索 +- **Update**: 修改密码、编辑文章、更新订单状态 +- **Delete**: 注销账户、删除评论 + +Every feature you can think of maps to one of these four operations. + +### 数据库 = 电子表格 + +最简单的类比:数据库就是一个Excel。 + +- 数据库 = 整个 Excel 文件 +- 表(Table)= 一个 Sheet +- 行(Row)= 一条记录 +- 列(Column)= 一个字段 +- 每行有唯一 ID(主键) + +### 查询 = 提问 + +"给我所有状态为'待发货'的订单" = 一个查询(Query) + +"这个月注册了多少用户?" = 一个聚合查询 + +查询就是向数据库提问,数据库返回符合条件的行。 + +### 外键:表与表之间的桥梁 + +文章表里有一个 user_id 列 → 这就是外键 + +它的意思是:"这篇文章属于 ID 为 X 的用户" + +外键把 02 数据建模中设计的关系变成了数据库中的现实 + +## 常见误区 + +1. "数据库很复杂" — 心智模型就是电子表格,操作就是 CRUD +2. "删除就是真删除" — 很多应用用"软删除"(加一个 deleted 标记),数据还在 +3. "AI 会自动处理数据关系" — AI 需要你告诉它表之间怎么关联(外键) + +## 这个概念在 Agentic Coding 中的应用 + +当你描述需求时,用 CRUD 语言:"用户可以 Create 新的笔记,Read 自己的笔记列表,Update 笔记内容,Delete 不需要的笔记"。这比"做一个笔记功能"精确得多。 + +Link to Agentic Coding Week 2 (全栈开发中会实际操作数据库) + +## 动手试一试 + +### 练习:用在线数据库体验 CRUD +打开 [SQLiteOnline](https://sqliteonline.com/),复制粘贴以下 SQL 逐步运行: + +**Create(创建)**: +```sql +CREATE TABLE notes ( + id INTEGER PRIMARY KEY, + title TEXT, + content TEXT, + created_at TEXT DEFAULT CURRENT_TIMESTAMP +); +INSERT INTO notes (title, content) VALUES ('学习笔记', '今天学了 CRUD'); +INSERT INTO notes (title, content) VALUES ('读书笔记', '看了《思考,快与慢》'); +``` + +**Read(读取)**: +```sql +-- 查看所有笔记 +SELECT * FROM notes; +-- 只看标题 +SELECT title FROM notes; +-- 查找包含"学习"的笔记 +SELECT * FROM notes WHERE title LIKE '%学习%'; +``` + +**Update(更新)**: +```sql +UPDATE notes SET content = '今天学了 CRUD,感觉很有收获' WHERE id = 1; +SELECT * FROM notes; +``` + +**Delete(删除)**: +```sql +DELETE FROM notes WHERE id = 2; +SELECT * FROM notes; +``` + +> 跑完这四步,你就亲手体验了所有应用的骨架操作。任何"保存"按钮背后是 Create,任何"列表页"背后是 Read,任何"编辑"按钮背后是 Update,任何"删除"按钮背后是 Delete。 + +## 下一步 + +→ 05: API — 一切都是 HTTP 请求 diff --git a/modules/app-dev-fundamentals/05-apis/README.md b/modules/app-dev-fundamentals/05-apis/README.md new file mode 100644 index 0000000..a875407 --- /dev/null +++ b/modules/app-dev-fundamentals/05-apis/README.md @@ -0,0 +1,95 @@ +> [← 模块首页](../README.md) · [← 04: 数据库与 CRUD](../04-databases-and-crud/README.md) · [06: 认证与安全 →](../06-auth-and-security/README.md) + +# 05: API — "一切都是 HTTP 请求" + +> 一句话:你的应用要查天气、发短信、调用 AI?都是发一个 HTTP 请求,拿回一段数据。 + +## 为什么 Coding Agent 用户需要懂这个 + +AI coding agents themselves are APIs. When you use Claude Code, it sends HTTP requests to Claude's API. When you ask AI to "integrate weather data", it needs to make API calls. Understanding this pattern demystifies both AI and external services. + +## 核心心智模型 + +### API = 程序之间的对话方式 + +- 你的应用想知道明天的天气 → 发一个请求给天气 API +- 天气 API 返回一段 JSON 数据 → 你的应用解析并展示 + +和浏览器访问网页一模一样(01 已学),只是: +- 浏览器请求 → 返回 HTML(给人看) +- 程序请求 API → 返回 JSON(给程序读) + +### JSON:机器的通用语言 + +```json +{ + "city": "上海", + "temperature": 22, + "condition": "晴" +} +``` + +JSON 就是一种结构化的文本格式。所有 API 都用它。 +理解 JSON 不需要编程经验——它就是"键:值"对。 + +### API 的核心要素 + +1. **端点(Endpoint)**: URL 地址,比如 `api.weather.com/forecast` +2. **方法(Method)**: GET(查询)或 POST(提交数据) +3. **认证(Auth)**: API Key 或 Token,证明你有权限 +4. **请求体(Body)**: 你发送的数据(POST 时需要) +5. **响应(Response)**: 返回的 JSON 数据 + +### "AI 调用"被去神秘化 + +调用 ChatGPT/Claude API 和调用天气 API 在技术上完全一样: + +1. 发一个 POST 请求到 API 端点 +2. 带上 API Key +3. 请求体里放你的 prompt +4. 拿回 JSON 格式的回复 + +## 常见误区 + +1. "API 很高级" — 它就是 01 学过的 HTTP 请求,只是返回 JSON 而非 HTML +2. "每个 API 都不一样" — 核心模式完全相同:endpoint + method + auth + body → response +3. "AI 代理会自己处理 API" — AI 需要知道 endpoint 和认证方式,这是你要告诉它的 + +## 这个概念在 Agentic Coding 中的应用 + +Link to Week 3 (MCP 本质上就是标准化的 API 协议) and Week 5 (多代理工作流中代理之间的通信也是 API) + +## 动手试一试 + +### 练习 1:在浏览器里调用 API +直接在浏览器地址栏输入以下 URL,你就在调用 API 了: + +- **查天气数据**:`https://wttr.in/Shanghai?format=j1` → 返回上海天气的 JSON +- **查 GitHub 用户**:`https://api.github.com/users/AlexAnys` → 返回 GitHub 用户信息 +- **查随机名言**:`https://dummyjson.com/quotes/random` → 返回一条随机名言 + +观察返回的 JSON 数据,找到你感兴趣的字段。这就是"调用 API"——没什么魔法,就是访问一个 URL,拿回一段结构化数据。 + +### 练习 2:用 Hoppscotch 发送 POST 请求 +打开 [Hoppscotch](https://hoppscotch.io/) — 一个免费的 API 测试工具(不需要注册): + +1. 把方法改为 **POST** +2. URL 填入 `https://jsonplaceholder.typicode.com/posts` +3. 点击 **Body** → 选 **application/json**,填入: +```json +{ + "title": "我的第一个 API 请求", + "body": "这是通过 POST 发送的数据", + "userId": 1 +} +``` +4. 点 **Send** → 看返回结果 + +你刚刚完成了一个 POST 请求——和"提交表单"、"调用 AI API"在技术上完全一样。 + +### 练习 3:理解 AI API 调用 +以上练习的核心启示:当你的应用"调用 ChatGPT"时,技术上发生的事情和练习 2 一模一样——发一个 POST 请求,body 里放 prompt,拿回 JSON 格式的回复。 + +## 下一步 + +→ 06: 认证与安全 diff --git a/modules/app-dev-fundamentals/06-auth-and-security/README.md b/modules/app-dev-fundamentals/06-auth-and-security/README.md new file mode 100644 index 0000000..b736885 --- /dev/null +++ b/modules/app-dev-fundamentals/06-auth-and-security/README.md @@ -0,0 +1,82 @@ +> [← 模块首页](../README.md) · [← 05: API](../05-apis/README.md) · [方法论 →](../methodology/README.md) + +# 06: 认证与安全 — 谁是你,你能做什么 + +> 一句话:认证(Authentication)= 证明你是谁;授权(Authorization)= 你被允许做什么。 + +## 为什么 Coding Agent 用户需要懂这个 + +Every real application has users. "Add user login" is one of the most common requests to AI, but if you don't understand the concepts, you can't evaluate if AI's implementation is secure. Security mistakes are the most costly mistakes in software. + +## 核心心智模型 + +### 认证 vs 授权 + +**认证(Authentication)**: 你是谁? +- 用户名 + 密码 → 登录 +- 类比:进大楼时出示工牌 + +**授权(Authorization)**: 你能做什么? +- 普通用户只能看自己的数据,管理员能看所有数据 +- 类比:你的工牌能刷开哪些门 + +### Session 和 Cookie:记住你是谁 + +1. 你登录(提交用户名密码) +2. 服务器验证成功,生成一个 Session ID +3. 把 Session ID 通过 Cookie 存到你的浏览器里 +4. 之后每次请求,浏览器自动带上这个 Cookie +5. 服务器通过 Cookie 认出你,不需要再次登录 + +Cookie 就是浏览器里的一个小文本文件,仅此而已。 + +### 常见的认证方式 + +- 用户名 + 密码(最传统) +- OAuth("用 Google 账号登录") +- API Key(程序之间的认证,05 已提到) + +### 安全的基本原则 + +- 永远不要明文存储密码(用哈希) +- HTTPS = 加密传输(HTTP + 锁) +- 最小权限原则:只给用户需要的权限 +- 永远不要信任用户输入(SQL 注入、XSS) + +## 常见误区 + +1. "安全可以后面再加" — 安全必须从第一天就考虑 +2. "用了框架就自动安全" — 框架帮你处理了很多,但你需要正确使用它 +3. "AI 生成的代码是安全的" — 不一定,这是你必须亲自检查的部分 + +## 这个概念在 Agentic Coding 中的应用 + +Link to Week 6 (安全扫描 — 用 AI 检查 AI 生成代码的安全性) — this is exactly why Week 6 exists + +## 动手试一试 + +### 练习 1:查看你浏览器里的 Cookie +1. 打开任意你已登录的网站(比如 GitHub) +2. 按 `F12` 打开开发者工具 +3. 切换到 **Application**(应用)标签(Chrome)或 **Storage**(存储)标签(Firefox) +4. 在左侧找到 **Cookies** → 点击当前网站域名 +5. 你会看到一堆键值对——这就是 Cookie,服务器用它来"记住你是谁" + +尝试删除所有 Cookie,然后刷新页面——你会发现自己被"登出"了。这就是 Session 的工作原理:Cookie 没了,服务器就不认识你了。 + +### 练习 2:体验 HTTPS 的作用 +1. 打开浏览器,访问 `http://httpbin.org/get`(注意是 **http** 不是 https) +2. 再访问 `https://httpbin.org/get` +3. 注意浏览器地址栏的变化——https 会显示一个锁的图标 +4. 区别在于:http 的数据是"明文传输"(像明信片),https 是"加密传输"(像密封信件) + +### 练习 3:理解权限控制 +打开 GitHub,试试以下操作: +- 访问你自己的仓库设置页 → 能打开(你有权限) +- 访问别人的仓库设置页 → 404 或无法访问(你没权限) + +这就是 Authorization(授权)在起作用:同一个功能,不同的用户看到不同的结果。 + +## 下一步 + +→ 方法论:这门课是怎么教的 diff --git a/modules/app-dev-fundamentals/README.md b/modules/app-dev-fundamentals/README.md index 4d30152..1cd0000 100644 --- a/modules/app-dev-fundamentals/README.md +++ b/modules/app-dev-fundamentals/README.md @@ -12,6 +12,42 @@ 这门课不是培养程序员。它要解决的是一个商业问题:**当你身边的一切都在被软件吃掉时,你至少要理解软件的运作逻辑。** +## 为什么 Coding Agent 用户需要这个模块 + +有人会问:既然 AI 能帮你写代码,为什么还要理解这些概念? + +答案是:**AI 是一个乘数,它放大的是你已有的技能。** 如果你对软件运作一无所知,乘数再大,零乘以任何数还是零。 + +具体来说,你需要心智模型来做三件事: + +1. **准确描述你想要的东西** — 当你让 AI"加一个页面",你需要知道"页面"在技术上意味着什么(一个 URL、一个路由、一个请求-响应的过程)。否则你说的和 AI 理解的可能完全不同。 +2. **评估 AI 生成的结果** — AI 给你生成了一堆代码和文件,你需要有能力判断:数据模型对不对?路由逻辑合理吗?安全措施到位了吗?没有心智模型,你只能看着代码跑起来就觉得"应该没问题"。 +3. **在出错时定位问题** — 所有应用都会出错。当 AI 的代码跑不通,你需要理解错误信息在说什么,问题可能出在哪一层(是路由?是数据库?还是认证?),才能给 AI 有效的指令去修复。 + +这个模块就是给你这套心智模型。不是教你写代码,而是教你**理解代码在做什么**。 + +## 教学理念 + +本模块的教学方法来自 BUSN 36110 的核心设计哲学,每一条都在 Coding Agent 时代变得更加重要: + +### 螺旋式学习(Spiral Learning) + +> "我们不会对每个主题逐一做深度讲解,然后一直学下去却永远不去构建真实的东西。我们会从一个简单产品开始——一个静态网页——只学让这个想法落地所需的知识。然后构建一个稍复杂的产品,加深对已学内容的理解,同时引入新的知识。" + +不是线性地从 A 学到 Z。而是每一圈都在构建真实产品,每一圈都只学当下需要的知识。学完第一遍觉得半懂不懂?没关系,你会在下一圈回来,带着实践经验重新理解。 + +### 先构建,后解释(Build First) + +先动手把东西做出来,在做的过程中遇到问题,然后再去理解背后的原理。这比先花三周学理论再开始写第一行代码高效十倍。在 Coding Agent 时代更是如此——让 AI 先帮你搭出一个能跑的东西,然后逐步理解它是怎么运作的。 + +### 即时学习(Just-in-Time Learning) + +只在你需要的时候学你需要的东西。不要提前囤积知识。遇到数据库问题了?那就去学数据库。遇到认证报错了?那就去学认证。这正是本模块的组织方式——每个概念页都是独立可查阅的参考。 + +### AI 是乘数(AI as Multiplier) + +AI 能帮你写代码,但不能替你思考。你对软件运作的理解越深,AI 的产出质量就越高。一个理解数据建模的人给 AI 的指令,和一个不理解的人给的指令,产出的代码质量可以差十倍。 + ## 课程的 7 个目标 原课程为 MBA 学生设定了 7 个目标,每一个都直接指向"非技术背景的人为什么需要理解开发": @@ -24,32 +60,17 @@ 6. **能做出概念验证** — 不是完美产品,而是能跑的 Proof of Concept 7. **获得一个全新的创造性出口** — 编程可以很有趣 -## 螺旋式学习:这门课的方法论 - -> "我们不会对每个主题逐一做深度讲解,然后一直学下去却永远不去构建真实的东西。我们会从一个简单产品开始——一个静态网页——只学让这个想法落地所需的知识。然后构建一个稍复杂的产品,加深对已学内容的理解,同时引入新的知识。" - -这就是**螺旋式学习**(Spiral Learning): - -``` -第一圈:静态网页 → 学 HTML、CSS、部署 -第二圈:动态应用 → 加上路由、表单、数据处理 -第三圈:完整应用 → 加上数据库、用户认证、API -最终项目:"First of Many" → 你自己的想法,从零到上线 -``` - -每一圈都在构建真实产品,每一圈都只学当下需要的知识。这正是我们整个知识库倡导的 **Just-in-Time Learning**——不是先学完再做,而是在做的过程中学。 - ## 课程内容 -| 阶段 | 周次 | 你会理解 | +| 章节 | 主题 | 你会理解 | |------|------|----------| -| **Web 基础** | Week 1 | HTTP 请求的运作机制、API 是什么、HTML 与 CSS | -| **编程逻辑** | Week 2 | 控制流、面向对象、代码如何组织 | -| **动态应用** | Week 3-4 | 服务端如何处理请求、路由、表单、数据传输 | -| **框架思维** | Week 5 | 从轻量工具到完整框架的演进、线框图、数据建模 | -| **数据层** | Week 6 | 关系型数据库、数据关联、数据完整性 | -| **安全与认证** | Week 7 | Cookie、用户认证、权限控制 | -| **综合实践** | Week 8-10 | 自选主题 + "First of Many" 最终项目 | +| [01](01-how-the-web-works/README.md) | 互联网是怎么工作的 | HTTP 请求与响应、URL 结构、状态码 | +| [02](02-data-modeling/README.md) | 数据建模 | 名词变成表、关系类型、最高杠杆的技能 | +| [03](03-request-lifecycle/README.md) | 请求的生命周期 | RCAV 模式、路由、控制器、视图 | +| [04](04-databases-and-crud/README.md) | 数据库与 CRUD | 关系型数据库、增删改查、数据完整性 | +| [05](05-apis/README.md) | API | 接口设计、JSON、第三方集成 | +| [06](06-auth-and-security/README.md) | 认证与安全 | Cookie、用户认证、权限控制 | +| [方法论](methodology/README.md) | 调试与开发方法论 | READ THE ERROR MESSAGE、螺旋式学习 | > **关于编程语言**:原课程使用 Ruby / Rails 作为教学语言。在 Coding Agent 时代,具体语言已不再是门槛——重要的是理解上面这些**通用模式**。无论你用什么语言和框架,HTTP、数据库、认证的逻辑是相同的。 @@ -73,6 +94,4 @@ --- -> 本模块正在建设中。内容将基于 BUSN 36110 的核心思想重构,适配 AI 辅助开发的自学场景。 - [← 返回首页](../../README.md) · [Agentic Coding 模块 →](../agentic-coding/README.md) diff --git a/modules/app-dev-fundamentals/methodology/README.md b/modules/app-dev-fundamentals/methodology/README.md new file mode 100644 index 0000000..eec7483 --- /dev/null +++ b/modules/app-dev-fundamentals/methodology/README.md @@ -0,0 +1,94 @@ +> [← 模块首页](../README.md) · [← 06: 认证与安全](../06-auth-and-security/README.md) + +# 方法论:这门课是怎么教的 + +> 这些教学原则来自 Chicago Booth 的 Application Development 课程,但它们不只是教学方法——它们是自学者与 AI 协作开发的最佳实践。 + +## 1. 螺旋式学习(Spiral Learning) + +传统方式:先学完 HTML → 再学完 CSS → 再学完 JavaScript → 再学数据库 → 终于可以做项目了。 + +螺旋方式: +- 第一圈:做一个静态网页 → 只学 HTML 和部署 +- 第二圈:做一个动态应用 → 加上路由和表单 +- 第三圈:做一个完整应用 → 加上数据库和认证 + +每一圈都在构建真实产品。每一圈都只学当下需要的知识。这就是 **Just-in-Time Learning**。 + +**对 AI 协作的启示**:不要让 AI 一次性生成整个应用。分层构建:先让 AI 搭骨架,跑起来,再一层层加功能。每加一层,你对系统的理解也加深一层。 + +## 2. 先做,后解释(Build First) + +> "我们不会先深入讲解每个主题,再动手。我们会先做出一个能跑的东西,然后回头理解它。" + +这个原则对 AI 协作尤其重要。很多人在使用 AI 之前,想先"学够了"再开始。但正确的顺序是: + +1. 让 AI 帮你做一个能跑的版本 +2. 看它做了什么 +3. 理解每一步 +4. 在理解的基础上迭代 + +"光读不做"是最低效的学习方式。 + +## 3. 残忍地砍范围(Ruthless Scope Elimination) + +课程教授在每个项目中都强调:**先做 Proof of Concept,不做 MVP。** + +- Proof of Concept = 核心功能能跑就行 +- MVP = 最小可用产品(已经比 PoC 复杂了) + +自学者最常犯的错误是一开始就想做太多。AI 可以无限快地生成功能,但每个功能都增加系统复杂度。 + +**实践原则**: +- 写下你想要的所有功能 +- 砍掉一半 +- 再砍掉一半 +- 剩下的就是你该先做的 + +## 4. 读错误信息(Read The Error Message) + +> "READ THE ERROR MESSAGE! It usually tells you exactly what is going wrong." + +这是整门课最被强调的一句话。错误信息不是噩耗——它是免费的调试指南。 + +当 AI 生成的代码报错时: +1. **先读错误信息**,不要直接把错误丢给 AI +2. 尝试理解错误在说什么 +3. 带着你的理解再和 AI 沟通 + +这样你每次调试都在学习,而不是把 AI 当黑盒反复试错。 + +## 5. AI 是乘数,不是替代品 + +> "AI is a multiplier on how much skill you have." + +如果你的技能值是 0,0 × 任何乘数 = 0。这就是为什么你需要先理解本模块的 6 个核心概念。 + +课程的做法是:**先让学生手动写过一遍,再引入代码生成器。** 理解了生成器在做什么,你才敢改它生成的代码。 + +同样的原则适用于 AI 编码代理: +- 先理解 RCAV 模式 → 才能审查 AI 生成的路由和控制器 +- 先理解数据建模 → 才能判断 AI 设计的数据库是否合理 +- 先理解 CRUD → 才能描述你要的功能 + +## 6. 用你自己的问题驱动学习 + +> "Notice problems, don't think them up." — Paul Graham + +最好的学习动力是解决你自己关心的问题。不要为了学技术而学技术——找到一个你真正想解决的问题,然后为了解决它去学必要的知识。 + +课程把最终项目叫做 **"First of Many"**。这不是终点考试,而是你开始创造的起点。 + +--- + +## 这些原则的优先级 + +如果你只记住三条: + +1. **先做出来** — 让 AI 帮你搭一个能跑的版本,然后理解它 +2. **砍范围** — 你想做的功能砍掉 75%,先做最核心的 +3. **读错误信息** — 错误是学习机会,不是失败 + +--- + +[← 模块首页](../README.md)