12 Factor 方法论合并知识图谱 / 分组目录 / 12 Factor App 体系 / 依赖

依赖

App 体系基础方法原则GA · 12 Factor App 体系

What · 是什么

显式声明并隔离依赖,绝不依赖系统级隐式包
多数编程语言提供打包系统分发支持库,如 Perl 的 CPAN、Ruby 的 Rubygems;经打包系统安装的库可装到系统全局(site packages)或限定到应用目录(vendoring/bundling)。
十二要素应用绝不依赖系统级包的隐式存在:通过依赖声明清单完整且精确地声明全部依赖及其版本约束,这使构建在任何环境都能可复现、结果确定。
执行时使用依赖隔离工具,确保没有隐式依赖从周围系统泄漏进应用运行环境,是十二要素保证开发与生产一致的关键手段。
完整显式的依赖规格对生产与开发环境统一应用,保证两处依赖完全一致、行为可复现,环境搭建因此只需少量前置条件即可一步到位。
Ruby 的 Bundler 提供 Gemfile 清单格式作依赖声明,bundle exec 作隔离;声明与隔离两步骤常是两个独立工具。
Python 中 Pip 负责声明、Virtualenv 负责隔离;C 用 Autoconf 声明、用静态链接提供隔离能力。
无论何种工具链,依赖声明与隔离必须同时使用,只用一个不足以满足十二要素的要求,从根本上杜绝隐式依赖在不同机器上的行为差异。

Why · 为什么

原理 · Principle

显式声明简化新开发者上手:检出代码后只需语言运行时与依赖管理器两个前置条件,即可搭建全部运行所需环境。

通过确定性构建命令即可搭好一切,如 bundle install、lein deps,减少环境搭建的试错成本与手工步骤。

系统工具的隐式存在无法保证:ImageMagick、curl 等可能在某些运行系统缺失,或版本与应用不兼容导致运行失败。

隔离机制杜绝隐式依赖从系统泄漏,保证运行环境纯净可复现,避免开发环境过得了而生产环境崩溃,这使构建在任何环境都能可复现、结果确定。

How · 怎么做

用依赖清单(Gemfile、requirements.txt 等)完整精确声明全部依赖及版本约束,不遗漏任何传递依赖。
用隔离工具运行应用:bundle exec、virtualenv、静态链接等,阻止系统包泄漏进应用环境。
开发与生产统一使用同一套显式依赖规格,杜绝两处依赖漂移,这使构建在任何环境都能可复现、结果确定,是十二要素保证开发与生产一致的关键手段。
新开发者前置条件收敛为语言运行时 + 依赖管理器两个,一条构建命令即可跑通,环境搭建因此只需少量前置条件即可一步到位。
确定性构建命令:Ruby/Bundler 用 bundle install,Clojure/Leiningen 用 lein deps。
若应用需要 shell out 到系统工具(如 ImageMagick),应把该工具 vendored 进应用而非依赖系统安装。

案例 · Cases

代表性案例
Bundler:Ruby 依赖声明(Gemfile)与隔离(bundle exec)的一体化工具,业界典范实现。
Pip:Python 依赖声明工具;Virtualenv:Python 依赖隔离工具,两者配套使用。
Autoconf:C 依赖声明;静态链接可提供 C 依赖隔离,弥补声明之外的空缺,这使构建在任何环境都能可复现、结果确定。
Leiningen:Clojure 依赖工具,lein deps 为确定性构建命令,一条命令解决依赖。
CPAN:Perl 打包系统;Rubygems:Ruby 打包系统,是打包分发的经典基础设施,是十二要素保证开发与生产一致的关键手段。

反模式 · Anti-patterns

相关边

实践资源 · 源码引用

路径说明
08-source/app-content-en/dependencies.mdII. Dependencies 原文:声明/隔离两步骤、Gemfile/bundle exec、build command、系统工具 vendoring
08-source/app-content-en/admin-processes.md依赖隔离一致性在 admin 进程的应用(bundle exec rake db:migrate 等)
08-source/app-deploy/Gemfile12factor 站点自身 Gemfile 示例:sinatra/thin/maruku/i18n 等依赖声明
08-source/app-deploy/Readme.md实例:bundle install 作本地运行前置步骤