跳到主要内容

项目组织:别让代码变成一锅粥

为什么要讲项目结构?

你刚学编程的时候,所有代码都写在一个文件里,感觉挺好的。但当代码量超过 500 行,你会发现:

  • 找一个函数要翻半天——"那个处理用户登录的函数在哪来着?"
  • 改一个地方,另一个地方莫名其妙坏了——因为全局变量太多
  • 同事问你代码结构,你说"都在 main.py 里"——然后他沉默了

好的项目结构就像整理衣柜:T 恤放一个抽屉,裤子放一个抽屉,袜子放一个抽屉。找东西的时候,一秒定位。

Python 项目结构

一个典型的 Python 项目长这样

加载代码编辑器中……

对比一下,会发现两边长得几乎一样!好的项目结构是跨语言的——models/services/utils/tests/ 这些概念到处都适用。

关键差异

PythonJavaScript
源代码目录和项目同名的文件夹src/ 文件夹
包标志需要 __init__.py不需要任何标志文件
测试文件命名test_xxx.pyxxx.test.jsxxx.spec.js
配置文件pyproject.tomlpackage.json

__init__.py:Python 的"门牌号"

Python 有一个 JS 没有的概念——__init__.py。它告诉 Python:"这个文件夹是一个(package),不只是一个普通文件夹。"

加载代码编辑器中……
PythonJavaScript
文件夹入口__init__.pyindex.js
必须存在?传统上必须(标记为包)不必须(但很常用)
作用初始化包 + 控制导出集中导出(桶文件)
自动识别import models__init__.pyimport "./models"index.js

绝对导入 vs 相对导入

项目大了之后,文件之间互相引用的路径会变得很复杂。两种语言的策略不同:

加载代码编辑器中……
PythonJavaScript
推荐方式绝对导入相对导入(或路径别名)
../ 深度很少超过两级可能很深 ../../../
路径别名不需要(绝对导入天然好用)需要配置(@/ 别名)
导入顺序标准库 > 第三方 > 本地第三方 > 本地

JS 的相对路径有时会变成 "../../../../utils/helper.js" 这种噩梦。所以很多项目会配置路径别名(@/ 指向 src/),让导入看起来更干净。

常见的文件夹约定

不管什么语言,好的项目结构都遵循一些通用模式:

文件夹放什么例子
models/数据结构定义User、Product、Order
services/业务逻辑发邮件、支付、认证
utils/helpers/通用工具函数格式化日期、校验邮箱
routes/api/API 路由/users、/posts
config/配置数据库连接、密钥
tests/测试文件单元测试、集成测试
types/类型定义(TS)接口、类型别名
constants/常量状态码、错误消息

一个设计原则:按功能分,不按类型分

加载代码编辑器中……

小项目(几十个文件)用"按类型分"完全没问题。但当项目变大(几百个文件),"按功能分"会让你的生活轻松很多。

入口文件的作用

每个项目都有一个"起点"——入口文件:

加载代码编辑器中……
PythonJavaScript
入口文件main.py / app.pyindex.js / app.js
运行方式python main.pynode index.js / npm start
防止被误执行if __name__ == "__main__":没有内置机制(靠约定)
指定入口pyproject.toml 的 scriptspackage.json 的 main/scripts
问问 AI

问 AI:"什么是 monorepo?它和传统的多仓库(multi-repo)方式有什么区别?什么时候应该用 monorepo?"

Monorepo 是近年来很火的项目组织方式——把多个相关项目放在一个仓库里。Google、Meta、微软都在用。了解一下这个趋势,对你理解大型项目的结构很有帮助。

🏋️AI 练习

假设你要做一个"校园二手交易平台",功能包括:

  • 用户注册/登录
  • 发布商品
  • 搜索商品
  • 私信聊天
  • 订单管理

请分别设计 Python 和 Node.js 版本的项目目录结构。要求:

  1. 使用"按功能分"的组织方式
  2. 包含 models、services、routes
  3. 包含 config 和 utils
  4. 包含 tests 目录

可以让 AI 帮你生成目录树,然后和 AI 讨论:"这个结构有什么可以改进的地方?"

小结

概念PythonJavaScript
包标志文件__init__.pyindex.js(约定)
源代码目录同名包目录src/
推荐导入方式绝对导入相对导入 + 路径别名
入口文件main.py + if __name__index.js + package.json
测试命名test_xxx.pyxxx.test.js

一句话:好的项目结构就像一个整齐的衣柜——每样东西都有自己的位置,找的时候不用翻箱倒柜。 不管用 Python 还是 JS,models/services/utils/ 这些经典分类都是通用的。项目小的时候别过度设计,项目大了再逐步重构——这就是工程师的智慧。