发布于: 2026-1-31最后更新: 2026-1-31字数 3776阅读时长 10 分钟

ℹ️
作为一个在公司里独自负责所有 IT 开发工作的人,我所有的开发方式都是自己摸索出来的——没有团队、没有 Code Review、没有人告诉我"你这样做不对"。时间久了,总会有一种不确定感:"我的做法到底对不对?正规的软件公司是怎么做的?" 这篇文章整理了我与Claude作为资深开发员人设的对话,涵盖了正规软件开发流程的核心实践,以及如何在单人开发的环境下落地这些实践。内容包括开发流程概览、Docker 开发环境搭建、测试入门、代码复用策略,以及从开发到生产的完整部署流程。 如果和真实情况不符合,欢迎交流。
 

一、正规软件开发流程概览

1.1 从需求到交付的完整链条

正规公司的开发流程一般是这样的:
一个人开发的时候,很多步骤会被压缩甚至跳过,这很正常。但有几个环节跳过了代价特别大,下面逐一展开。

1.2 写下来再动手

很多人(包括正规公司的新人)拿到需求就开始写代码。但好的团队会先写一个简短的技术设计文档,哪怕只是半页纸,回答三个问题:
  1. 要解决什么问题?
  1. 大概怎么做?
  1. 有什么风险或取舍?
单人开发的时候,这个习惯更重要,因为没有人帮你把关方向。可以在 Notion 里建一个简单模板,每个新功能或项目动手前先填一下。事后回头看,这也是你的技术决策记录。

1.3 正规流程的本质是制造反馈

单人开发最缺的不是技术能力,而是反馈循环。正规公司流程的本质就是在各个层面制造反馈:
  • Code Review 是代码层面的反馈
  • 测试 是功能层面的反馈
  • 监控 是生产环境的反馈
一个人的时候要刻意给自己制造这些反馈机制。后续章节会介绍具体的做法。

二、版本控制:不只是用 Git,而是怎么用

2.1 分支策略

正规团队会有分支策略。最基本的原则是:main 分支永远是可部署的,开发在 feature 分支上做,做完通过 PR(Pull Request)合并。
即使只有一个人,养成"不在 main 上直接改代码"的习惯,好处是你随时可以回滚,也逼自己把改动拆成有意义的小块。
保持简单就好:main 是稳定版,开发在 feature/xxx 分支上做,做完合并回 main。不需要搞 Git Flow 那一套复杂的东西。

2.2 使用 Gitea 作为内部代码托管

如果公司没有 GitHub 账号,Gitea 是一个非常好的选择。它支持和 GitHub 几乎一样的工作流:
  • Pull Request 流程:虽然只有你一个人,但创建 PR 让你有一个地方集中看这次改动的全貌,写一句话描述为什么改。日后排查问题的时候这个历史非常有价值。
  • Gitea Actions:从 1.19 版本开始支持,语法和 GitHub Actions 几乎一样,可以用来跑自动化测试或自动部署,不需要额外装 Jenkins 之类的重型工具。

2.3 Code Review 的替代方案

没有同事帮你看代码,可以做几件事来弥补:
  • 隔天自审:写完代码隔一天再自己 review 一遍,用新鲜的眼光看。
  • 工具辅助:善用 linter 和 formatter 来保持代码一致性。
  • AI 辅助 Review:把代码片段拿给 AI 帮忙审查,这不是偷懒,这是聪明的做法。

三、Docker 开发环境:让开发和生产保持一致

3.1 为什么要在 Docker 内开发

核心原因就一个:开发环境和生产环境一致
你本机装的 Python 版本、Node 版本、数据库版本,和 Docker 容器里的可能不一样。本机能跑不代表容器里能跑。在 Docker 内开发就是把这个差异直接消除,避免经典的"本机跑得好好的,Docker 里就出问题"。

3.2 用 docker compose 定义开发环境

以一个 FastAPI + PostgreSQL 项目为例:
volumes: - .:/app 是关键中的关键。 它把你本地的代码文件夹"挂"进容器里,所以你在本机用 VS Code 改代码,容器里立刻就能看到变化。配合 FastAPI 的 --reload,改完代码自动重载,体验和本机开发几乎一样。
对应的开发用 Dockerfile:

3.3 日常开发命令

3.4 开发环境 vs 生产环境

可以维护两套配置:
开发环境
生产环境
Compose 文件
docker-compose.dev.yml
docker-compose.prod.yml
Dockerfile
Dockerfile.dev
Dockerfile
代码挂载
volumes: .:/app(实时同步)
无挂载(代码构建进镜像)
热重载
--reload 开启
关闭
数据库端口
对外暴露(方便调试)
不对外暴露
镜像体积
不在意
多阶段构建,尽量小

四、测试入门:从"不知道怎么测"到自然而然

4.1 测试的真正目的

写完一个函数,手动试一下,确认没问题——这不叫测试,这叫调试
测试的真正价值是保护未来的你。三个月后你改了一行代码,测试自动告诉你"你这次改动把另一个地方搞坏了"。没有测试的话,你可能部署上去了才发现,甚至用户先发现。
Bug 最喜欢藏在"这么简单不可能出错"的地方。

4.2 不需要追求完美覆盖率

很多教程一上来就讲 TDD、100% 覆盖率,这会把人吓跑。实际原则是先保护最值钱的逻辑
值得测试的(按优先级):
  1. 计算逻辑:任何涉及数字运算的函数,特别是有条件分支的(如果薪水大于多少用这个比率,否则用那个比率)。
  1. 数据转换:把一种格式转成另一种格式的函数,输入输出都很明确,特别好写测试。
  1. 边界情况:薪水为 0 怎么办?金额有小数点精度问题怎么办?日期跨月怎么办?
不需要测试的:
  • 简单的 CRUD 接口(从数据库拿数据、存数据)
  • 纯粹的 UI 展示
  • 配置文件

4.3 第一个测试长什么样

假设有一个 Python 函数算 EPF:
测试就是这样:
运行测试:
终端会告诉你几个通过、几个失败。就这么简单,没有什么框架要学、没有什么复杂配置。

4.4 上手方法:三个测试用例法则

下次开发一个新功能的时候,不用改变整个流程,就做一件事:写完核心计算函数后,顺手写三个测试用例:
  1. 一个正常情况
  1. 一个边界情况
  1. 一个异常情况
三个就够了。等你习惯了,自然会想写更多,因为写测试的过程本身就帮你理清了逻辑。

4.5 和 Docker 开发环境结合

在容器内跑测试,确保测试环境和开发环境一致:
再进一步,可以在 Gitea Actions 里配置推代码时自动跑测试,这样就有了一个基本的 CI 流程。

五、代码复用:共用库的正确时机

5.1 三次法则(Rule of Three)

没有人能提前预知哪些代码会重复。正规公司也不会一开始就知道什么该抽成共用库。实际的做法是:
  • 第一次写:正常写在项目里。
  • 第二次发现:"这个我好像写过",先复制粘贴过来,心里记一下。
  • 第三次再遇到:好,这东西确实是通用的,该抽出来了。
不要在第一次就过度设计,也不要到了第三次还在复制粘贴。

5.2 记录重复的灵感

在 Notion 里开一个页面叫"可以抽成共用的东西",每次复制粘贴旧代码的时候,花十秒钟记一行:
  • "数据库连接配置——第二次重复了"
  • "Excel 导出的格式化函数——第三次了,该抽了"
积累到一定程度再统一处理。

5.3 Python 共用库的最简结构

写一个 Python 库没有想象中那么复杂。最简单的版本就是一个文件夹加一个配置文件:
pyproject.toml 的内容:
推到 Gitea 上,其他项目要用就:
然后在代码里:
不需要发布到 PyPI,不需要复杂的构建流程。本质上就是一个放在 Git 上的文件夹,pip 知道怎么从 Git 安装它。

5.4 正确的心态

不是"把以前的测试拿出来用",而是把以前的代码和测试一起打包成库,新项目直接引用这个库。测试留在库里保护那段逻辑,新项目只需要测自己新写的业务代码。

六、从开发到生产:部署流程

6.1 推送到生产服务器的是镜像,不是开发环境

本机的 docker-compose.dev.yml 永远留在本机,生产服务器上用的是另一套配置。

6.2 方式一:在服务器上直接构建(推荐起步)

适合小规模项目,不需要额外工具。
生产环境的 compose 文件:
密码不要写死在文件里,用 .env 文件(不要提交到 Git):

6.3 方式二:使用镜像仓库

等项目多了,每台服务器都 git pullbuild 会慢。可以用镜像仓库,Gitea 自带 Container Registry 功能:
这样服务器上不需要有源代码,只有镜像和 compose 文件。

6.4 方式三:Gitea Actions 全自动化(最终形态)

推代码到 Gitea,自动构建镜像、跑测试、部署到服务器:
推到 main 分支就自动部署,完全不用 SSH 上去手动操作。

6.5 部署方式的升级路径

从方式一开始,零额外成本,今天就能用。等觉得每次 SSH 上去手动操作很烦了,再升级到方式二或三。

七、多项目共享数据库资源

7.1 核心原则

数据库单独一个 compose,应用各自一个 compose。
原因很实际——你更新 Web 应用的时候不想把数据库也重启了,数据库应该是稳稳运行着的基础设施。

7.2 使用 Docker 外部网络串联

先创建一个共享网络:

数据库(独立运行)

Web 应用(连上同一个网络)

后台任务(也连上同一个网络)

DATABASE_URL 里的主机名 postgres 就是数据库 compose 里的 service 名称。同一个 Docker 网络里,容器之间用 service 名称互相访问,Docker 会自动做 DNS 解析。

7.3 一个实例,多个数据库

推荐在同一个 PostgreSQL 实例里创建多个数据库,各个应用数据隔离但共享资源。
初始化脚本:
在数据库的 compose 里挂载:
PostgreSQL 会在第一次启动时自动执行这个脚本。

7.4 启动顺序

7.5 推荐的服务器目录结构

每个项目独立部署、独立更新、独立重启,但都能访问共享的数据库。重新部署 web-app 的时候,worker 和数据库完全不受影响。

八、落地优先级

不要试图一口气全改。推荐的升级顺序:
  1. 先把 Docker 开发环境搭起来——直接改善每天的工作体验。
  1. 开始对新功能写简单的测试——三个测试用例起步,养成习惯。
  1. 规范 Git 工作流——feature 分支 + PR,哪怕只有自己 review。
  1. 搭建部署流程——从最简单的方式一开始。
  1. 抽取共用库——等自然而然发现"这段代码我又在写第三遍了"再动手。
每一步都建立在前一步的基础上,循序渐进。

Loading...
SSH 密钥免密登录完整教程

🗒️SSH 密钥免密登录完整教程


Deco X50 Mesh的设置

🌐Deco X50 Mesh的设置

Mesh路由器Deco X50解决楼上WiFi不稳定问题