组织科学程序员的源代码:让我们开始对话
Source: Dev.to
请提供您希望翻译的具体文本内容,我将为您翻译成简体中文并保留原有的格式、Markdown 语法以及代码块和 URL。谢谢!
为什么重要
组织不善不仅仅带来不便——它会导致真正的问题:
- 数据丢失
- 分析无法复现
- 花费数小时寻找文件
一个组织良好的仓库可以加速科学进程,促进协作,并使您的研究可复现。当团队中的每个人都能预测文件应该放在哪里时,协作就会变得直观,而不是令人沮丧。
起点(非刚性规定)
科学代码库的关键组织原则是 按文件类型和用途结构化。下面是一个建议的目录布局:
project-name/
├── data/
│ ├── raw/
│ └── processed/
├── src/
│ ├── data_processing/
│ ├── analysis/
│ └── visualization/
├── notebooks/
├── scripts/
├── results/
│ ├── figures/
│ └── output/
├── docs/
├── tests/
├── environment/
├── README.md
├── LICENSE
└── .gitignore
注意: 这只是一个供讨论的起点,而非刚性规定。
下面我们逐一拆解每个组件,并为社区提出一些问题。
data/ – 神圣之地
子目录
data/raw/– 原始、未修改的数据文件。将其视为不可变(甚至可以把文件设为只读)。data/processed/– 已清洗、转换或分析后的数据版本。
为何要分离?
它保证了可重复性:任何人都应该能够在原始数据上运行你的处理代码,重新生成处理后的数据。
小贴士
- 对于大型数据集,只在版本控制中存放元数据或下载脚本。
- 使用外部服务(OSF、Zenodo、机构存储库)来存放实际的数据文件。
社区提问:
你会以不同方式组织数据吗?你如何处理中间处理阶段?是否会使用 data/interim/ 目录?
src/ – 项目核心分析代码
这里存放 可复用、生产级质量的代码——项目的“科学核心”。
指南
- 按逻辑模块或包进行组织。
- 编写清晰的 docstring 和文档。
- 使代码可测试,并(理想情况下)编写测试。
- 确保可以在交互环境或脚本中导入使用。
社区提问:
你如何组织多语言项目?是为每种语言单独建目录,还是使用混合的 src/?
notebooks/ – 探索与原型
交互式环境(Jupyter、R Markdown、Pluto.jl、MATLAB Live Scripts、Mathematica notebooks)非常适合探索,但它们也可能导致代码缺乏模块化并积累冗余。
最佳实践
- 将 notebook 用于 探索、可视化和原型开发。
- 每个 notebook 聚焦于特定问题或分析。
- 使用数字前缀明确命名,以便排序,例如
01-data-exploration.ipynb02-initial-modeling.Rmd03-sensitivity-analysis.jl
- 当代码成熟后,迁移到
src/并 导入 函数,而不是复制代码。 - 当 notebook 变得臃肿时,将可复用部分提取为
src/中的模块。
社区提问:
有的研究者把所有工作都放在 notebook/脚本里;有的则全部迁移到模块。你的理念是什么?是否会随项目阶段而变化?
scripts/ – 自动化与批处理
脚本用于 自动化、可重复的工作流。它们应当:
- 无需交互即可运行。
- 接受命令行参数或配置文件。
- 能在集群或流水线中执行。
- 编排从头到尾的完整分析。
典型使用场景
- 数据下载与预处理流水线。
- 使用不同参数运行模型。
- 为论文生成所有图表。
- 对多个数据集进行批量处理。
一个 控制脚本(例如 run_all.sh、Makefile、Snakefile)能够按顺序执行整个分析工作流,对可重复性极为重要。
社区提问:
你使用工作流管理工具吗(Make、Snakemake、Nextflow、Drake、Luigi)?你如何组织流水线定义?
results/ – 分析输出
将生成的输出 放在版本控制之外(加入 .gitignore):
results/
├── figures/ # 绘图、可视化
├── output/ # 表格、统计数据、处理结果
└── models/ # 训练好的模型、拟合参数
为何要与 data/ 分离?
结果是由代码生成的,应该是可重复的。如果你丢失了这些输出,只要代码和原始数据仍在,就可以重新生成。
them,您可以重新生成它们。但原始数据无法重新生成。
Community question:
您是否对任何结果进行版本控制?对于需要数天/数周才能生成的结果,您如何处理?
docs/ – 文档
包括:
- 项目文档。
- 分析笔记或实验室笔记条目。
- 手稿草稿。
- 补充材料。
- API 文档(如果是自动生成的)。
Community question:
您把手稿放在哪里?在仓库中、单独的仓库、Overleaf、Google Docs …?
tests/ – 测试代码
是的,即使是科研代码也应该有测试!至少应包括:
- 核心函数的单元测试。
- 端到端工作流的集成测试(如果可行)。
- 用于防止意外结果变化的回归测试。
environment/ – 可复现的环境
存放环境规范:
environment.yml(conda)或requirements.txt(pip)。- Dockerfile、
environment.yaml(用于 Binder)或renv.lock(用于 R)。
这些文件使任何人都能重新创建用于分析的精确软件栈。
最终思考
上述结构是一个 起点。请随意根据你的学科、团队规模和项目复杂度进行调整。目标是创建一个仓库,使其:
- 是 直观 易于导航的。
- 支持 可重复性。
- 实现 协作 无摩擦。
加入讨论
- 你是如何组织你的科学代码库的?
- 什么方法有效?什么方法无效?
- 我还有哪些遗漏?
你的经验和建议将帮助社区达成最佳实践。 🚀
集成与验证测试
- 工作流的集成测试
- 验证测试,用于检查已知结果
测试有助于确保正确性,并在修改代码时捕获错误。
社区提问:
你对科学代码的测试哲学是什么?
- 你会测试 所有内容 吗?
- 只测试 关键函数 吗?
- 还是根本不测试?
README – 项目的前门
Your README should contain at least the following sections:
- 项目概述与目标
- 安装说明
- 快速入门指南
- 项目结构说明
- 如何复现关键结果
- 依赖项与要求
- 引用信息
- 联系信息
环境规范文件
| 语言 | 常见文件 |
|---|---|
| Python | environment.yml (conda) requirements.txt (pip) pyproject.toml (现代打包) |
| R | renv.lock (renv) DESCRIPTION (R 包) install.R (安装脚本) |
| Julia | Project.toml & Manifest.toml |
| MATLAB | README 中的依赖列表或单独文档 |
| 多语言 | Dockerfile (容器化环境) 为每种语言单独的 env 文件 设置整个环境的 Shell 脚本 |
社区提问:
你如何处理跨多语言的依赖?
- 容器?
- 虚拟机?
- 详细文档?
许可
如果你的项目是开源的,请包含许可证。科学代码常用的选择有:
- MIT
- BSD
- GPL
忽略生成的文件
通过添加特定语言的 .gitignore 条目来防止杂乱(参见集合 at )。
适用于 所有 项目的最小集合:
data/raw/*
results/*
.DS_Store # macOS
建议的目录结构
小型 / 探索性项目
project/
├── data/
├── analysis/
├── results/
├── environment/
└── README.md
适用于课堂项目或快速原型,在这些情况下你不期望有大幅扩展。
大型、多年/多篇论文项目
project/
├── data/
│ ├── study1/
│ ├── study2/
│ └── shared/
├── src/
│ ├── preprocessing/
│ ├── analysis_core/
│ └── utils/
├── analyses/
│ ├── paper1/
│ ├── paper2/
│ └── exploratory/
├── docs/
└── manuscripts/
├── paper1/
└── paper2/
关键思路: 按 输出(论文、报告)组织分析,同时将共享代码放在中心的 src/ 目录中。
给社区的提问:
你是如何组织多年、多篇论文的项目的?
- 使用一个仓库还是多个?
- 共享代码如何处理?
自包含性 vs. 复制
目标: 为了复现分析所需的一切都应位于项目目录内部。
优点: 确保审稿人和未来合作者能够重复实验。
缺点: 可能在不同项目之间重复存放大型数据集。
同事应能够:
git clone该仓库- 设置环境(conda、Docker 等)
- 运行分析脚本
- 复现结果
给社区的提问:
你如何在自包含性和在项目之间共享代码/数据之间取得平衡?
什么应该放在仓库里?
| 类别 | 推荐包含内容 |
|---|---|
| 代码 | 脚本、交互式笔记本、源文件 |
| 文档 | README、设计文档、API 文档 |
| 环境规范 | environment.yml、requirements.txt、Dockerfile 等 |
| 小数据 | 足够小可以存放在仓库中的文件 |
以上结构是一个 起点,而非最终答案。
核心通用原则
- 分离关注点 – 将数据、代码和结果保存在不同的目录中。
- 保留原始数据 – 永不修改原始文件。
- 模块化代码 – 提取可重用的功能。
- 记录一切 – 未来的你会感谢现在的你。
- 版本控制 – 跟踪更改并实现协作。
- 实现可复现性 – 任何人都应能够复现你的工作。
实施方式会根据以下因素而有所不同:
- 编程语言
- 领域惯例
- 团队偏好
- 项目规模与复杂性
- 计算环境(笔记本、HPC、云)
轮到你了
- 哪些做得好? 你是如何组织科学代码的?使用什么目录结构?
- 哪些做得不好? 你尝试过哪些失败的做法?还有哪些痛点?
- 缺少了什么? 我是否遗漏了科学代码组织的关键方面?
- 语言特定的技巧? 分享在你的语言中特别有效的技巧。
期待讨论!
组织科学代码:技巧、资源与社区讨论
为什么要组织代码?
- 可重复性 – 使您和他人更容易复现结果。
- 协作 – 清晰的结构在多人共同开发同一项目时减少摩擦。
- 可维护性 – 良好组织的代码库更易于扩展、调试和重构。
“目标不是完美,而是进步。”
今天就开始更好地组织代码,并在学习适合您和团队的方式时不断迭代。
常见问题
- 我应该使用什么语言?
- 该领域的特定约定是什么?
- 我所在学科的规范是什么?
在评论中分享您的经验。让我们共同构建一个关于实际有效做法的社区知识库。
有用资源
| # | Resource | What It Offers |
|---|---|---|
| 1 | “Good Enough Practices in Scientific Computing” – Wilson et al. | 对科学计算最佳实践的全面指南。 |
| 2 | Software Carpentry | 关于版本控制、测试和项目组织的工作坊。 |
| 3 | “Ten Simple Rules for Taking Advantage of Git and GitHub” – PLOS Computational Biology | 有效使用 Git/GitHub 的实用规则。 |
| 4 | Cookie‑Cutter Data Science | 标准化的项目结构模板。 |
| 5 | The Turing Way | 可重复、伦理且协作式数据科学的手册。 |
您是如何组织科学代码的?
- 分享您的文件夹结构、命名约定或任何有用的脚本。
- 在下方评论中发布技巧、提问或建议其他资源!
参考文献
- Wilson G, Bryan J, Cranston K, Kitzes J, Nederbragt L, Teal TK (2017). Good enough practices in scientific computing. PLOS Computational Biology 13(6): e1005510. https://doi.org/10.1371/journal.pcbi.1005510.
- Software Carpentry. Lessons. https://software-carpentry.org/lessons/.
- Perez‑Riverol Y, Gatto L, Wang R, Sachsenberg T, Uszkoreit J, Leprevost FdV, et al. (2016). Ten Simple Rules for Taking Advantage of Git and GitHub. PLOS Computational Biology 12(7): e1004947. https://doi.org/10.1371/journal.pcbi.1004947.
- DrivenData. Cookiecutter Data Science. https://cookiecutter-data-science.drivendata.org/.
- The Turing Way Community. (2022). The Turing Way: A handbook for reproducible, ethical and collaborative research. Zenodo. https://doi.org/10.5281/zenodo.3233853.