第一篇 · 认识世界 / 第 3 章

软件是怎么跑起来的

为什么一个网页背后要有前端、后端和数据库三拨人? 这一章把一次点击拆开给你看:谁在接客、谁在干活、谁在记账。

预计阅读
25 分钟
前置
第 2 章 · 计算机与网络
关键词
前端、后端、数据库、API、部署、Git

读完这一章,你能

  • 用餐厅三格和五层表,指出午饭登记当前缺的是哪一层;
  • 对照 8 步图,说出一次提交在浏览器、接口(API)、后端和数据库之间怎么走;
  • 判断一个接口密钥(API Key)该放前端还是服务端,并说明理由。

午饭登记 · 当前状态:一个 HTML 文件,只能在本机打开

本章地图
  • 必读:三格与五层——知道 AI 说的每句话属于哪一层。
  • 必读:一次点击的 8 步——出问题时能说出卡在哪一站。
  • 必读:数据库、接口(API)与 JSON、密钥——决定数据能不能留下、Key 会不会泄露。
  • 可选以后再看:运行方案对比、Git 分支,等你要上线或多人协作时再回来。

文件和路径、程序怎么运行、终端怎么用、报错怎么读,完整内容见 第 2 章 · 计算机与网络。 本章不重复这些基础,只讲它们组合起来之后的样子。

午饭登记:一个软件由什么组成

先看最常见的一种说法:一个软件分三块——前端(front-end,用户看得见、点得着的部分)、 后端(back-end,在服务器上处理请求和规则的部分)、 数据库(database,专门长期存放和查询数据的地方)。

你在网上听到的“前端、后端、数据库三拨人”,说的就是这三块。用一家餐厅来对应,一眼就能懂:

你 前端 后端 数据库 点一下 提要求 存取 ↓ 换成餐厅来理解 ↓ 客人 菜单与点餐台 你能看见的部分 厨房 你看不见的部分 仓库 食材存放处 前端 = 你看得见、点得着的部分;后端 = 你看不见、但真正干活的部分 数据库 = 东西存在哪儿,关掉再打开还在的那部分
你平时说“我要一个网页”,其实要的是这三样东西的合体。 AI 问“你要做前端还是后端”,现在你知道它在问什么了。

记住,这只是第一层地图。它足够解释日常对话,但真实系统还会多出两样东西: 前后端之间的“接口”(程序之间约定好的问与答方式),以及程序跑在哪台机器上的“运行层”。下一节补上。

午饭登记走到哪了

现在它只是一个 HTML 文件:页面能打开,填完的数据只留在这台电脑上。 本章要回答一个问题:怎样让它从“本机能开”变成“别人也能用、数据还不会丢”?

停一下

如果你把这个 HTML 文件发给同事,他打开后能看到你填的记录吗? 为什么?先自己想,再往下看。

三格 → 五层 + 横切

三格图回答“谁在干活”,但定位问题时还差两格:接口层(前后端之间怎么问、怎么答的约定) 和运行层(程序跑在哪台机器上,别人从哪个地址访问)。

再加上一类贯穿所有层的“横切关注点”,就是下面这张精简地图。这里不列技术方案,只列每一层管什么。

层它管什么在午饭登记里对应什么
界面层(前端,也叫接入层) 把数据变成画面,把点击变成请求 填写姓名和菜名的页面,提交后显示今天的列表
接口层(API) 规定前端怎么问、后端怎么答 GET /api/lunch-orders?date=today 这类约定
逻辑层(后端) 判断规则、处理数据、保管密钥(Key 这类凭证) 判断今天还能不能填、同一个人重复提交怎么处理
数据层 把数据存下来、按条件找出来 lunch_orders 表和里面的每一行登记
运行层 程序跑在哪台机器上,别人从哪个地址访问 页面和后端部署到哪里,同事通过什么链接打开
横切关注点 不属于任何一层,但每一层都要用 密钥、登录、日志、Git、成本

每层可替换的技术方案、选型对比、四套组合套餐和升级时机,完整内容见 进阶:架构与选型。 这一章只保留一个用途:出问题时,先判断它大概在哪一层。

一次点击的 8 步

现在把一次“提交午饭”放大。用户在页面上点一下,0.2 秒内会按 浏览器 → 接口 → 业务 → 数据库 → 响应 → 渲染 的顺序走完 8 步。 下面这张泳道图(按“谁在做”分行的流程图)分成四行,按时间从左往右读。

请求往下走,响应往回走 浏览器 接口层 后端业务 数据库 ① 点击提交 ② 发出 POST 请求 ③ 校验参数 ④ 套用业务规则 ⑤ 读写登记表 ⑥ 返回结果 ⑦ 组装 JSON 响应 ⑧ 重新渲染列表 深色 = 请求路径;强调色 = 响应路径
一次提交要穿过浏览器、接口、后端业务和数据库,再带着结果原路返回。 任何一步断了,用户看到的都是“没反应”“一直转圈”或一句报错。

第 1–5 步把请求送进数据库,第 6–8 步把结果送回页面。 你不需要记住每一步的代码,只需要能在出问题时说出:卡在哪一站。

完整的 16 步表只在进阶页

这里只保留能用来定位问题的 8 步。每一步的细节、出错症状和排障顺序,完整内容见 进阶:架构与选型 · 一次请求的 16 步。

停一下

如果数据库那一步失败了,前端应该显示什么? 是继续显示“提交成功”,还是明确告诉用户“没存上,请重试”?为什么?

数据层:Excel 撑不住之后

最早做午饭登记,一个 Excel 就够了:一列姓名,一列菜名。一个人用、几十行数据,它完全够用。

但只要有三个人同时填,Excel 就开始出问题:后保存的人会覆盖先保存的人。 数据层要解决的,就是这类“多人、长期、不能丢”的问题。

场景Excel数据库
两个人同时改后保存的覆盖前面的各自提交,由数据库按规则排队
找“今天谁点了牛肉面”手动筛选,容易漏行一条查询,靠索引(类似目录)快速定位
写到一半断电文件可能损坏事务保证要么全成、要么全不成
谁能看哪一列整个文件一起给可以按账号分配权限
涨到十万行打开和筛选明显变慢仍然可以按条件查

这不是说 Excel 不好。它是很好的个人工具,只是不适合当多人同时使用的后台仓库。

七个必须认识的词

表(table)
同一类数据的清单。午饭登记就是 lunch_orders 表。
行(row)
表里的一条记录。一次登记就是一行。
列(column)
一条记录里的一个属性,比如 name、dish。
主键(primary key)
每一行唯一的编号,表里的 id。它永远不会重复。
索引(index)
像书的目录,让“按日期找”不用从头翻到尾。
事务(transaction)
一组操作要么全部成功、要么全部撤销,不能只做一半。
备份(backup)
定期另存一份。机器坏了、误删了,还能把数据找回来。

午饭登记的最小表

lunch_orders(
  id,          -- 主键:每一行唯一
  name,        -- 姓名
  dish,        -- 想吃的菜
  created_at   -- 登记时间
)

一条登记就是一行。id 是主键,保证每一行都有唯一编号; created_at 记录登记时间,按日期汇总时要用它。

idnamedishcreated_at
12小王牛肉面2026-10-19T12:03:00
13小李番茄鸡蛋饭2026-10-19T12:05:00
为什么不能只用 Excel

一个人用、数据量小、丢了也不心疼,Excel 完全够。 一旦要多人同时写、要长期保留、还要按日期查,就该换成数据库。 判断标准不是“哪个高级”,而是出错的代价你扛不扛得住。

停一下

两个人几乎同时提交午饭登记时,数据库为什么要用“事务”来保证一组写入? 如果一条登记只写进了登记表,却没写进按日期汇总的统计表,会留下什么问题?

接口与 JSON:程序之间怎么说话

前端不能直接把手伸进数据库。它必须通过接口 (API,Application Programming Interface,程序之间约定好的问与答方式)向后端提要求。

接口就是一份合同:用什么方法、访问哪个地址、带什么数据、返回什么格式。 合同定下来,前端换成手机 App,后端换一种语言,两边仍然能对接。

方法地址用途带什么
GET/api/lunch-orders?date=today读取今天的登记地址里的日期条件
POST/api/lunch-orders新增一条登记请求体(随请求一起发送的数据)里的姓名和菜名
DELETE/api/lunch-orders/{id}删掉填错的那条地址里的编号

地址里的 {id} 是占位符。要删第 12 条,就把它换成 /api/lunch-orders/12。

JSON 是人话版数据

JSON(JavaScript Object Notation,一种用键值对表示数据的文本格式) 不是代码,只是一段有固定格式的文本。花括号表示一个对象,方括号表示一组对象。

冒号左边是字段名,右边是值。"name": "小王" 读作:姓名是小王。

[
  {
    "id": 12,
    "name": "小王",
    "dish": "牛肉面",
    "created_at": "2026-10-19T12:03:00"
  },
  {
    "id": 13,
    "name": "小李",
    "dish": "番茄鸡蛋饭",
    "created_at": "2026-10-19T12:05:00"
  }
]

这段响应的意思是:今天有两条登记。第一条编号 12,姓名小王,菜是牛肉面, 登记时间是 2026 年 10 月 19 日 12 点 03 分。

一个请求,一个响应

读取今天登记的请求,只有一行:

GET /api/lunch-orders?date=today

200 OK
[ { "id": 12, "name": "小王", "dish": "牛肉面", "created_at": "2026-10-19T12:03:00" } ]

新增一条时,方法从 GET 换成 POST,数据放进请求体。 请求体上面那行 Content-Type: application/json,是在告诉后端“这段数据按 JSON 解析”。

POST /api/lunch-orders
Content-Type: application/json

{ "name": "小王", "dish": "牛肉面" }

成功时后端通常返回 201 和新记录的 id; 参数不对返回 4xx;服务器自己出错返回 5xx。 你不需要背状态码(服务器返回的三位数字结果),只要知道: 4 开头多半该改请求,5 开头多半该找服务端。

去实验页看三种视图

实验:午饭登记 提供页面、表格、JSON 三种视图。 切到 JSON 视图,你能看到后端实际返回的内容长什么样。 实验页的数据存在你自己的浏览器里,但请求和响应的形状与真实接口一致。

停一下

如果 POST 的请求体漏了 dish,应该由哪一层拒绝? 为什么不能让它先写进数据库再说?

运行层:从本机到别人能打开

先把两个词分开:运行(run)是在你自己的电脑上把程序启动一次; 部署(deploy)是把它放到一台一直开着的机器上,让别人通过地址访问。

本机能打开,不等于别人能打开。这是新手最常混淆的一件事。

方式一句话适合什么
本地直接打开 双击 HTML 或在本机启动,只有这台电脑能访问 自己做实验、验证想法
静态托管 把 HTML、CSS、JS 文件上传,平台给你地址和 HTTPS 纯前端页面、作品展示
云服务器 租一台一直开着的电脑,自己装环境、启动后端 需要后端和数据库的团队工具
托管应用平台(云) 把代码交给平台,平台负责运行和证书,不用自己管机器 想少管机器、快速上线

域名(domain)是别人记住的地址名;HTTPS 是地址栏里的小锁, 表示传输过程被加密。纯静态页面通常可以免费托管,后端和数据库一般按月计费——具体价格以官方为准。

IP、DNS、HTTP 这些词的定义在 第 2 章 · 计算机与网络。 各运行方案的对比和选择,完整内容见 进阶:架构与选型。

一句话判断

把链接发给一个不在你身边的人,他能打开并看到数据,才叫“部署好了”。 如果只有你能打开,那只是“在本机运行”。

密钥与环境变量

API Key(接口密钥)是一段密码,让你的程序有资格调用别人的服务, 比如地图、短信、AI 模型。它通常按用量计费,泄露了别人可以花你的钱。

前端代码会被完整送到用户的浏览器里。任何人打开“查看网页源代码”或网络面板,都能看到里面写了什么。 所以前端永远不能放 API Key——那等于把钥匙贴在店门口。

环境变量(environment variable)是程序启动时,操作系统递给它的一小袋配置。 代码里只写变量名,真正的值放在运行环境里,不写进代码。

代码里:读取变量 LUNCH_API_KEY
.env 里:LUNCH_API_KEY=真实的值
.gitignore 里:.env

.env 是本地保存这些值的小文件。它永远不能提交到 Git, 所以要把它写进 .gitignore,让 Git 主动忽略。

位置可以放绝不能放
前端代码 页面文案、样式、公开的接口地址 API Key、数据库密码、私钥
后端环境变量 API Key、数据库地址、第三方密钥 提交到 Git 的明文 .env
看到这句话就要警惕

如果 AI 说“把 Key 直接写在前端代码里,方便测试”,先停下来。 测试也不行:一旦上传到公开仓库或部署上线,它就等于公开了。 密钥、配置和成本的完整讨论见 进阶:架构与选型 · 横切关注点。

Git:给你的项目装一台时光机

Git 是一个版本控制工具,说白了就是给项目存档。

没有它的时候,人们这样管理文件:

我的项目/
  app.py
  app.py.bak
  app.py.bak2
  app.py.备份-别删
  app.py.最终版
  app.py.最终版真的

这些文件最后没人知道哪个能用。Git 把这些“另存为”收进一个地方, 只保留每次改动前后的差异。

提交(commit)
一次存档。你给 Git 一句话备注,比如“加上登录功能”。
回滚(rollback)
读档。任何一次提交都能退回去,代码变回那时的样子。
分支(branch)
一条平行的实验线。满意了合回主线,不满意就丢掉,主线不受影响。
仓库(repository)
装着所有存档和分支的那个文件夹。

具体命令不用背,AI 可以替你执行。你只需要在让它大改之前说一句: “先提交,再改。” 终端怎么用见 第 2 章 · 计算机与网络。

对 vibe coding 来说,Git 是安全网

你不敢让 AI 大刀阔斧地改,是因为怕改坏了回不来。 有了存档点,你就敢了。 每次确认“现在是对的”,就先存个档,然后再让 AI 改。 改砸了?一句话退回上一个存档,损失为零。

这也是为什么第 6 章会把“存档”放进标准流程里——它不是程序员的形式主义, 而是你敢于大胆尝试的底气。

三句话带走

  1. 一个软件至少有三格:前端是点餐台,后端是厨房,数据库是仓库;真实系统还要加上接口层和运行层。
  2. 一次点击要穿过浏览器、接口、后端和数据库,再带着响应回来;出问题时先定位在哪一层。
  3. 数据要落进数据库才算真的留下;密钥只能放服务端环境变量;Git 是你敢让 AI 大改的存档点。

自测:三个问题

午饭登记换一台设备后看不到之前填的记录,最可能缺哪一层?

缺后端和数据库。页面本身只能显示,数据只留在当前浏览器里; 写入数据库之后,换一台设备、换一个浏览器才能重新读出来。

GET /api/lunch-orders?date=today 和 POST /api/lunch-orders 有什么区别?

GET 用来读取,条件放在地址里,不修改数据; POST 用来新增,姓名和菜名放在请求体里,会写入一条新记录。

AI 说“把 API Key 写在前端代码里,方便测试”,你能答应吗?

不能。前端代码会完整送到用户浏览器,任何人都能看到。 Key 应该放在服务端的环境变量里,`.env` 文件还要写进 `.gitignore`。

动手 10 分钟

打开 实验:午饭登记,做三件事:

  1. 提交一条登记,记下你填的姓名和菜名。
  2. 切到 JSON 视图,找到这条记录,指出 id、name、dish、created_at 四个字段。
  3. 换一个浏览器或换一台设备打开实验页,看看还能不能看到你刚填的那条。用本章的话解释为什么。

如果你看到 X,大概率是 Y

  • 换一台设备就看不到 → 没有后端和数据库,数据只留在当前浏览器里。
  • 提示保存成功,重启后却没了 → 数据没真正落库,或者只写进了内存。
  • 浏览器里能看到 API Key → 密钥放错了位置,应该移到服务端环境变量。
  • 本机能打开,别人打不开 → 只是运行了,还没有部署。
  • 改坏了回不去 → 动手前没有提交,先让 AI 帮你建立一个存档点。
下一章

你已经知道软件由哪些层组成。下一章换一个问题: AI 本身是怎么工作的——它为什么会一本正经地胡说, 又为什么会在对话变长之后“变笨”。