想象你搬进了一间全新的厨房。柜子空空荡荡,你随手把酱油瓶、洗洁精、面粉袋和一袋土豆全塞进同一格。头两天只有你自己做饭,倒还好;周末来了五个朋友要一起做年夜饭,厨房立刻变成灾难现场:酱油找不到,菜刀和砧板在角落里,盐罐被压在面粉袋下面,有人还差点把洗洁精当油倒进锅里。你缺的不是厨艺,而是一套收纳系统。AI 项目也是这样。写一个 demo 时,代码随手堆在某个 notebook 里确实能跑;可一旦要多人协作、长期维护、上线部署,项目结构就成了决定成败的“厨房收纳”。目录分层是橱柜分区,模块解耦是每件厨具固定归位,配置管理是菜谱与食材分离,依赖与虚拟环境是小灶台与采购清单,测试和文档是试菜记录与使用说明,工程模板是样板厨房,版本协作是公用厨房的规矩,作品集优化则是把厨房开放成明厨亮灶。这篇文章会带你把这套系统一一搭建起来。
对 AI 从业者来说,结构组织能力决定了作品能否从“能跑”走向“能用、可维护、可协作”。它是代码评审、技术选型和晋升答辩中绕不开的隐形加分项。
目录
可视化演示
本节配有交互动效(进入视口后自动加载,约 3KB)。
项目目录结构设计 ——高内聚低耦合 src/: 核心源代码 tests/: 镜像src结构 config/: 配置与代码分离 原则:高内聚+低耦合+配置分离+测试镜像
目录分层设计:给厨房分好储物柜
一个合格的厨房,绝不会把洗洁精和酱油放在同一层。锅碗瓢盆、五谷杂粮、调料干货都应该有各自的储物柜,这样做饭时闭着眼睛都能摸到要用的东西。AI 项目也一样,如果所有 Python 文件都堆在项目根目录,就像把食材全部倒在大理石台面上,看起来方便,实际一动手就乱套。目录分层要做的,就是给项目建起一个个贴着标签的“橱柜”。
在 Python 生态里,目录分层的第一层结构通常包括:src/ 放产品代码,tests/ 放测试,config/ 放配置,docs/ 放文档。这里有个容易混淆的概念:包(package)就是带有 __init__.py 文件的目录,相当于一个贴着标签的收纳抽屉;而模块(module)是单个 .py 文件,相当于抽屉里的一件厨具。把包和模块按功能放进对应的大分类中,新成员看到 src/ 就知道业务代码在哪,看到 tests/ 就知道测试在哪,不需要翻遍整个仓库。
目录分层不是越深越好。太浅,所有文件堆在一起;太深,每找一个文件都要穿过七八层抽屉。平均目录深度是一个实用的观测指标:
步骤 1:统计文件总数:先数清项目里有多少个需要纳入统计的文件,这就是 $N$ 的含义。
步骤 2:记录每个文件层级:根目录下的第 1 层目录记为 1,之后每嵌套一层加 1,得到每个文件的目录深度 $d_i$。
步骤 3:汇总并取平均:把所有 $d_i$ 相加,再除以文件总数,得到平均目录深度。
一个成功的收纳系统,是让新来的人也能在 5 秒内找到盐罐。目录分层做到了这一点,项目就具备了被团队接手的第一前提。
模块解耦原则:每件厨具各就各位
厨房里的电器和工具有各自的“地盘”:电饭锅不能泡在水池里,菜刀不能塞进调料瓶,烤箱插头也不能和灶台抢同一个插座。如果锅铲坏了,你不需要把整个橱柜拆掉才能更换它。这种“互不拖累”的设计思想,在项目里叫作模块解耦。解耦不是让模块之间老死不相往来,而是让它们的依赖关系清楚、可控、容易替换。
模块解耦的第一原则是单一职责:一个模块只负责一类事情,比如 data_loader 只负责加载数据,model_trainer 只负责训练模型。第二原则是依赖方向:上层模块可以依赖下层模块,但下层模块不应该反向依赖上层模块。第三原则是接口抽象:模块之间通过定义清晰的函数签名或类接口通信,而不是直接操作对方内部变量。第四原则是避免循环导入:A 导入 B、B 又导入 A,就像两把椅子互相撑着却谁都不落地,一旦项目变大必然崩塌。
模块之间的耦合程度,可以用一个简单的指标来观察。假设项目共有 $N$ 个模块,$E$ 是它们之间实际存在的 import 依赖边数,那么耦合度:
步骤 1:确认模块总数:先统计当前项目里参与计算的模块数量,记为 $N$。
步骤 2:统计实际依赖边:数一数代码中模块与模块之间 import 关系的总数,记为 $E$。
步骤 3:计算最大可能依赖边:如果任意两个模块都互相依赖,最多会出现 $\frac{N(N-1)}{2}$ 条边。
步骤 4:计算耦合度:用实际依赖边数除以最大可能边数,得到耦合度 $C$。
好的解耦就像一套模块化厨具:坏了一把锅铲,只换锅铲;想升级烤箱,不用砸掉整个厨房。模块之间各自独立,团队才能并行开发而不互相踩脚。
配置管理策略:菜谱与食材分开
厨师做菜时,不会把“放三克盐”直接刻在盐罐上,因为不同客人、不同菜品需要的咸淡不同。菜谱负责描述做法,调料罐负责提供食材,两者分开,才能灵活调整。项目中的配置管理也是这个道理:代码是“灶台和厨具”,配置是“今天这桌菜怎么做的具体参数”。如果把参数写死在代码里,换一个环境就要改代码,就像为了调整咸淡把整个盐罐重新铸造一遍。
配置管理的核心是分层与覆盖。通常可以分成四层:第一层是代码里的默认值,相当于菜谱的“基础做法”;第二层是配置文件,比如 config.yaml,相当于“宴客版做法”;第三层是环境变量,相当于“今天的特殊要求”;第四层是命令行参数,相当于“客人现场点的加辣”。每一层都能覆盖上一层,最终生效的配置就是它们叠加后的结果。
用公式表达最终生效配置:
步骤 1:确定基础配置:把项目中最通用的默认值写入代码,记为 $C_{\mathrm{base}}$。
步骤 2:确定环境增量:根据开发、测试、生产等环境读取不同的环境变量,得到 $\Delta C_{\mathrm{env}}$。
步骤 3:叠加得到最终配置:把基础配置和环境增量相加,得到最终生效配置。
还要特别记住:数据库密码、API 密钥这类“敏感调料”绝不能写进菜谱里。它们应该放进 .env 文件或密钥管理服务,并且被 .gitignore 挡在 Git 仓库之外。这样,换环境只是换一张菜谱,而不是重造一间厨房。
依赖与虚拟环境:采购清单要短而稳
做饭前要有采购清单:买什么食材、哪个品牌、多少克,都写清楚。如果没有清单,今天多买一瓶酱油,明天买错一包盐,冰箱里堆满过期调料。项目里的依赖管理就是这张采购清单。依赖(dependency)是项目运行时需要的第三方库,它们不是“货架上随便拿的”,而是需要记录版本和用途的“固定食材”。
虚拟环境则是给每个项目单独准备的一个“小灶台”。不同项目可能依赖不同版本的 Python 包,如果共用系统环境,就像所有菜都挤在一口锅里:昨天做的实验需要 numpy==1.21,今天的新项目需要 numpy==2.0,互相打架。虚拟环境让每个项目拥有独立的安装空间,互不污染。
合理的依赖应该分组管理。运行依赖是菜品本身需要的食材,开发依赖是厨师使用的工具,构建依赖是包装上桌用的材料。把它们分开,总依赖集合可以表示为:
步骤 1:整理运行依赖:把项目运行时真正 import 到的库放进运行依赖集合,记为 $D_{\mathrm{runtime}}$。
步骤 2:整理开发依赖:把 pytest、black 等只在开发和测试时使用的工具放入开发依赖集合。
步骤 3:整理构建依赖:把打包、发布时需要的工具放入构建依赖集合,记为 $D_{\mathrm{build}}$。
步骤 4:合并总集合:三个集合的并集就是整个项目的依赖范围。
为了让采购清单“可复现”,还应该锁住版本:用 requirements.txt 记录顶层的直接依赖,用 lock 文件记录每一层传递依赖的精确版本。这样任何人任何时候走进这间厨房,买到的都是同一批食材,做出来的菜才可能一样。
测试与文档布局:试菜记录和菜谱放一起
厨师研发新菜时,每调整一次调料就要试吃一次,并记录下“哪一步咸了、哪一步火大了”。这些试菜记录和最终菜谱放在一起,下一次才能稳定复现。项目里的测试就是试菜记录,文档就是菜谱。没有测试,代码改动就像蒙着眼睛调味;没有文档,别人拿到项目就像面对一份没有步骤的食材清单。
测试目录布局的推荐做法是:在顶层建立 tests/ 目录,并让它的内部结构镜像 src/ 或包目录。比如 src/model.py 对应 tests/test_model.py,src/utils.py 对应 tests/test_utils.py。这样,看到测试目录的层级,就能反推源码目录的组织。文档则建议分层放置:根目录的 README.md 是“餐厅招牌”,给出项目一句话介绍和快速启动方式;docs/ 下放详细的使用指南、API 参考和架构说明。
测试是否到位,覆盖率是一个常用指标。覆盖率计算的是被测代码中有多少比例的代码行被执行过:
步骤 1:统计被测代码总行数:确定被测模块的代码总行数,记为 $L_{\mathrm{total}}$。
步骤 2:统计覆盖代码行数:运行测试后,统计被执行过的代码行数,记为 $L_{\mathrm{covered}}$。
步骤 3:计算覆盖率百分比:覆盖行数除以总行数再乘以 100%,得到覆盖率。
需要注意,覆盖率不是越高越好,而是要把力气花在关键路径上。就像试菜不需要把每粒盐都称一遍,但要确保糖、盐、火候这些核心变量都被验证过。测试与文档布局清晰,项目才敢交给别人持续改动。
工程模板实践:用样板厨房快速开张
新开一家餐厅,最省力的方式不是从零砌灶台,而是参考一个成熟的样板厨房:水槽在哪、灶台在哪、储物柜怎么分,都已经验证好用。工程模板就是这个“样板厨房”。它把目录分层、模块解耦、配置管理、测试文档布局这些经验固化下来,让新项目从一开始就站在正确的起点上。
在 Python 生态中,最常用的脚手架工具之一是 Cookiecutter。它允许你定义一个项目模板,包含 src/、tests/、config/、docs/ 等目录,以及 pyproject.toml、.gitignore、README.md 等基础文件。运行一条命令,就能生成一个结构和规范都符合团队预期的项目骨架。这些模板通常还会预置包管理配置,让依赖管理和构建发布在项目第一天就绪。
使用模板节省的初始化成本可以这样看:
步骤 1:估算手搭成本:统计从零创建目录、配置文件、CI 脚本等花掉的时间,记为 $T_{\mathrm{manual}}$。
步骤 2:估算模板成本:统计运行脚手架生成同一套骨架的时间,记为 $T_{\mathrm{scaffold}}$。
步骤 3:计算节省时间:两者相减得到模板节省的时间。
真正的好模板不是“越多越好”,而是“生成即用”。团队一旦选定一个模板,就应该把它作为新项目默认起点,避免每个成员各搭一套不同的厨房。
版本协作规范:公用厨房靠规矩
多人共用一个厨房时,总不能每个人想怎么摆就怎么摆。有人用完酱油不放回原位,有人把湿抹布搭在电饭锅上,下次做饭的人只能到处找东西。Git 团队协作也是同样道理。Git 本身只是记录文件变化的工具,真正的秩序来自协作规范:目录怎么改、分支怎么合、代码怎么审,都要有共同约定。
最容易产生合并冲突的地方,就是多人同时修改同一批文件。如果项目结构把模块拆分得足够独立,每个人只需要改自己负责的模块,冲突自然减少。反过来,如果所有人都集中在 main.py 里改代码,就像六个人挤在一个灶台上炒菜,不撞锅才怪。除了模块拆分,还应该约定小步提交、清晰 commit message、合并前做代码评审,以及用 .gitignore 排除生成文件和敏感信息。
冲突概率与协作结构的关系可以近似表示为:
步骤 1:统计同时改动文件数:记录一个迭代周期内被多个分支同时修改的文件数,记为 $n_{\mathrm{touch}}$。
步骤 2:统计并行分支数:记录同时存在的开发分支数量,记为 $n_{\mathrm{branch}}$。
步骤 3:统计模块总数:项目被拆分为多少个可独立开发的模块,记为 $M_{\mathrm{module}}$。
步骤 4:分析比例关系:分子越大越容易冲突,分母越大越不容易冲突。
公用厨房的规矩,本质上是对公共空间的尊重。好结构让每个人都有自己的操作台,规范让公共区域保持整洁,两者合在一起,团队才能长期高速运转。
作品集项目优化:把厨房开成明厨亮灶
个人作品集里的 AI 项目,就像要把自家厨房开放给客人参观。如果后厨堆满了没洗的盘子、过期的食材、乱放的刀具,客人第一眼就会失去信任。哪怕你的菜做得再好,也挡不住“厨房太乱”的减分。作品集项目优化的目标,是让一个完全不了解项目的人,也能快速看懂你的“厨房”为什么值得参观。
面向展示的项目,通常需要在结构上做三件事。第一,写一份展示型 README:用五分钟能读完的篇幅说明项目解决什么问题、数据从哪来、怎么运行、目录怎么组织、有哪些亮点。第二,补齐运行环境说明:给出 Python 版本、依赖安装命令、需要设置的配置项,最好提供一键复现的脚本。第三,管理好数据和模型:大文件不进 Git,用数据版本管理工具或网盘链接管理,并在文档里写明文件放置规则。
为了让“展示力”可量化,可以给作品集项目打分:
步骤 1:评价 README:为项目 README 的完整度和可读性打分,记为 $R$。
步骤 2:评价 Demo 可运行度:为 demo 能不能一键跑通、效果是否直观打分,记为 $D$。
步骤 3:评价结构与文档:为目录清晰程度和文档完整程度打分,得到 $S$ 与 $T$。
步骤 4:加权求和:按 0.4、0.3、0.2、0.1 的权重相加,得到最终展示分数。
作品集项目不需要把每一道菜的烹饪过程都摆给客人看,而是要呈现一个干净、有序、能马上试吃的明厨亮灶。好的结构,本身就是你作为 AI 工程师专业度最直接的证明。
AI 应用场景
场景一:新项目冷启动
阶段:项目初始化
解决的问题:传统方式从零手写项目目录,src、tests、config 散落各处,每个成员都有自己的一套习惯,项目刚启动就埋下混乱的隐患。AI 方式是用工程模板生成标准骨架,让团队从第一天就在同一套目录规范下工作。
具体案例:某公司的机器学习团队启动用户流失预测项目时,使用 Cookiecutter 生成 src/、tests/、config/、docs/ 骨架,并预置 pyproject.toml 和 .gitignore。成员不再花时间讨论目录结构,直接进入数据处理和模型实验。
场景二:多算法团队协作平台
阶段:模块化开发与持续集成
解决的问题:多个算法工程师并行开发特征、模型、服务模块时,如果模块没有解耦,一次 merge 可能产生十几个冲突文件。AI 方式通过模块独立、接口抽象和配置分层,把每个人的改动限制在自己的“操作台”里。
具体案例:推荐系统团队把 feature、model、serving 拆成独立包,包之间用数据类接口通信,训练脚本只依赖配置文件和接口。两周内三个工程师并行完成了实验,合并时几乎没有发生代码冲突。
场景三:AI 作品集求职展示
阶段:项目展示与评估
解决的问题:面试官收到一个结构混乱的 Github 仓库时,连依赖都装不起来,更别提评估模型能力。AI 方式是用展示型 README、可复现环境和清晰目录降低项目的理解成本。
具体案例:一位求职者提交图像分类项目,根目录 README 写清任务、数据集来源、运行命令和目录结构,src/、tests/、config/ 分层清晰。面试官 clone 后按 README 操作,5 分钟跑通了 demo。
Python 演示
import osimport sysfrom pathlib import Path EXPECTED = {"src", "tests", "config", "docs", "README.md"} class ProjectAuditor: def __init__(self, root: Path): self.root = Path(root) self.seen_dirs = set() self.top_items = set() self.file_count = 0 def scan(self): for dirpath, dirnames, filenames in os.walk(self.root): rel = Path(dirpath).relative_to(self.root) parts = rel.parts if parts and parts[0] in {"__pycache__", ".git", ".venv"}: dirnames[:] = [] continue if str(rel) == ".": for f in filenames: self.top_items.add(f) else: self.seen_dirs.add(str(rel)) self.file_count += len(filenames) return self def missing(self): found = set() for path in self.seen_dirs: first = path.split(os.sep)[0] found.add(first) found.update(self.top_items) return sorted(EXPECTED - found) def report(self): missing = self.missing() if missing: print("[CHECK] 缺少推荐目录/文件: " + ", ".join(missing)) else: print("[PASS] 目录结构符合推荐模板") first_dirs = sorted({d.split(os.sep)[0] for d in self.seen_dirs if d != "."}) print("文件总数: %d" % self.file_count) print("顶层目录: " + ", ".join(first_dirs)) if __name__ == "__main__": target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".") ProjectAuditor(target).scan().report()
EXPECTED = {"src", "tests", "config", "docs", "README.md"}规定标准厨房的“抽屉清单”,审计时按这份清单找东西。for dirpath, dirnames, filenames in os.walk(self.root):从根目录开始一层层遍历所有文件夹,相当于逐个打开橱柜。rel = Path(dirpath).relative_to(self.root)把绝对路径转换为相对根目录的路径,方便判断属于哪个顶层分区。if parts and parts[0] in {"__pycache__", ".git", ".venv"}:跳过缓存、版本库和虚拟环境这些不需要检查的“杂物间”。self.file_count += len(filenames)统计每个目录里的文件个数,用于感知项目规模。first = path.split(os.sep)[0]取出每个路径的第一层名字,汇总成顶层结构集合。missing = sorted(EXPECTED - found)拿推荐清单和实际顶层结构做差集,找出缺失项。ProjectAuditor(target).scan().report()对目标目录执行“厨房巡检”,并输出审计结果。
常见误区
误区以为把项目拆成十几个顶层目录就是结构清晰,结果每次找文件都要一层层点开,最后自己也忘了文件放在哪。
正解结构清晰的核心是职责单一、层级适中。普通 AI 项目顶层有 4 到 6 个核心目录就足够,比如 src、tests、config、docs。就像厨房分区太多,反而会让做饭的人找不到剪刀;每个目录都有明确用途,且深度控制在三层以内,才是真正可维护的结构。
为何常见:网上教程经常展示大型项目的复杂树形图,容易让人误以为目录越多越专业,忽略了目录数量应该匹配项目规模。
误区把所有配置都集中到一个 `config.py` 文件里,不区分开发、测试、生产环境,甚至把数据库密码也明文写在代码里。
正解config.py 只能承载默认值,环境差异应该用环境变量或配置文件覆盖,敏感信息要走密钥管理。这相当于菜谱写“适量盐”,具体咸淡到做菜那天再调;如果把密码写死在代码里,就等于把盐罐和菜谱焊在了一起,换一口锅就要重写菜谱。
为何常见:简单项目这样做确实能跑,一旦项目需要部署到多个环境,问题才会爆发,于是坏习惯被一路带进团队。
误区在虚拟环境里执行 `pip freeze > requirements.txt`,把所有包一股脑导出,就以为完成了依赖锁定。
正解pip freeze 会导出当前环境里所有已安装包,包括大量与项目无关的传递依赖,而且没有区分运行依赖和开发依赖。更合理的做法是用 pyproject.toml 记录直接依赖,再用 pip-tools、Poetry 或 uv 生成 lock 文件锁住精确版本。这就像把整个冰箱搬去当采购单,而不是按菜谱列出一张清晰可复用的清单。
为何常见:pip freeze 一条命令太方便,加上小项目里也能跑,导致很多人忽视了依赖分组的价值。
误区为了让 import 更方便,把 `test_model.py` 和 `model.py` 放进同一个目录,认为这样测试与代码“形影不离”更合理。
正解当项目规模变大后,测试混入业务目录会让包变得臃肿,也会让依赖方向变得模糊。推荐在顶层建立 tests/ 目录,并让它的结构镜像源码目录。只要配置好 pytest 的 rootdir 和 pyproject.toml,import 并不会成为障碍。试菜记录和菜谱分开放,找起来才有规律,而不是把每一道菜的试吃笔记都夹在菜谱里。
为何常见:小项目里把测试放旁边确实能快速跑通,时间久了就形成路径依赖,换到大项目时仍然沿用。
误区以为 README 越详细越好,把安装教程、算法原理、实验结果、团队信息全部堆进一个文件,最后竟然有上万字。
正解README 应该像电梯演说:用最短时间讲清楚项目解决什么问题、怎么快速跑起来、目录结构长什么样、有什么资质和许可证。详细内容放 docs/ 分文档管理。餐厅菜单不会把每道菜的烹饪过程写上去,只会写菜名和卖点;README 太长反而没人愿意读。
为何常见:作者想通过 README 展示工作量,却忽视了阅读者的真实需求是快速上手,而不是读一篇论文。
面试题
Q1. 一个 AI 项目要把模型代码、测试、配置分开,通常推荐的顶层目录划分是?
- A.src 放代码,tests 放测试,config 放配置← 正确答案
- B.model 和 test 和 cfg 全都放根目录
- C.所有代码放入 tools 目录,测试不放
- D.仅用一个 main.py 就足够
答案:A。推荐做法是让顶层目录各司其职,src/ 放业务代码、tests/ 放测试、config/ 放配置。B、C、D 都缺少明确分区,就像把厨房所有东西堆在一个台面上,短期能跑,长期必乱。
Q2. 模块解耦的首要原则是?
- A.模块之间依赖越多越稳定
- B.每个模块只负责一个职责← 正确答案
- C.所有模块共享同一份配置
- D.模块命名尽量越短越好
答案:B。单一职责是解耦的起点,一个模块只需做好一类事情。依赖过多会提高耦合度;共享配置不解决职责问题;命名短不等于边界清晰。解耦是为了让每个“厨具”独立可替换。
Q3. 配置管理中“敏感信息隔离”的最佳做法是?
- A.在 config.py 中写默认密码
- B.使用环境变量或密钥管理服务← 正确答案
- C.把密钥提交到 Git 仓库
- D.在 README 中公开连接串
答案:B。数据库密码、API 密钥属于敏感信息,应该通过环境变量或专用密钥管理服务注入,并在 .gitignore 中忽略。把它们写进代码或仓库,就像把厨房钥匙贴在餐厅门口,安全性会立刻崩盘。
Q4. 使用虚拟环境的主要目的是?
- A.提升 Python 解释器运行速度
- B.让项目依赖相互隔离、版本可控← 正确答案
- C.替代 Git 做版本管理
- D.自动生成项目全部文档
答案:B。虚拟环境为每个项目提供独立的第三方库安装空间,避免不同项目依赖同一个包的冲突版本。它不提升解释器速度,也不能替代 Git,更不会自动生成文档,而是负责隔离“食材”和“厨具”。
Q5. 测试覆盖率公式 R = L_covered / L_total × 100% 中的 L_total 是指?
- A.测试文件的总行数
- B.被测代码的总行数← 正确答案
- C.项目配置的总行数
- D.Git 提交的总行数
答案:B。覆盖率衡量的是被测代码被执行的比例,所以分母是被测代码的总行数,分子是测试运行中覆盖到的代码行数。如果把测试文件行数当分母,就无法体现代码验证的完整程度。
Q6. 关于项目工程模板(如 Cookiecutter)的作用,下列说法正确的是?
- A.减少新项目初始化时间← 正确答案
- B.统一团队目录与配置规范← 正确答案
- C.保证模型精度一定提升
- D.自带测试与文档骨架← 正确答案
答案:ABD。模板能生成标准目录、配置、测试和文档骨架,从而减少初始化时间并统一团队规范。但它只决定项目结构,不会影响模型训练效果,因此 C 是错误的。
Q7. 某项目有 4 个模块,任取两个模块都至少存在一条依赖边,按耦合度公式 C = E / (N(N-1)/2) 计算,C 的值是?
- A.总依赖边数除以最大可能边数,结果为 1← 正确答案
- B.总依赖边数除以最大可能边数,结果为 2/3
- C.总依赖边数除以最大可能边数,结果为 1/2
- D.总依赖边数除以最大可能边数,结果为 1/6
答案:A。N=4 时,两两组合的最大可能边数是 4×3/2=6。题目说明任取两个模块都至少有一条依赖边,所以实际依赖边数 E=6,C=6/6=1。这表示模块之间已经完全纠缠,属于高耦合的警示状态。
Q8. 从 Git 协作角度,降低合并冲突最有效的结构手段是?
- A.让所有人修改同一个入口脚本
- B.按功能拆分独立模块,减少相交改动← 正确答案
- C.提交次数越少越不容易冲突
- D.只在主分支直接推送代码
答案:B。冲突来自多人同时修改同一批文件。按功能拆分模块后,每个人只改自己的区域,相交改动自然减少。A 会放大冲突;C 无法解决并行修改同一文件的问题;D 没有分支保护,会把风险直接带上主分支。
Q9. 作品集 AI 项目想让人快速看懂,应该包含?
- A.展示型 README 与环境说明← 正确答案
- B.可运行的 Demo 与数据说明← 正确答案
- C.数据与模型的管理方式← 正确答案
- D.完整在线的部署运维手册
答案:ABC。作品集重点是让读者快速理解项目并复现 demo,因此 README、运行环境、数据和模型管理方式都很关键。部署运维手册对作品集来说不是必需项,过度追求反而偏离了展示重点。
Q10. 在依赖管理中,下列做法能提高环境可复现性的是?
- A.锁住直接依赖的精确版本← 正确答案
- B.把运行、开发、构建依赖分组← 正确答案
- C.每次安装前覆盖 requirements 文件
- D.使用 lock 文件并校验哈希← 正确答案
答案:ABD。精确版本、依赖分组、lock 文件和哈希校验都能让不同时间、不同机器上安装出同一套环境。C 的做法是用 pip freeze 覆盖 requirements,会引入无关包且不稳定,反而降低可复现性。