#依赖和雨伞项目git
本章,咱们将讨论如何在Mix中管理依赖.github
咱们的kv
应用已经完成,因此是时候实现可以处理咱们在第一章中定义的请求的服务器了:服务器
CREATE shopping OK PUT shopping milk 1 OK PUT shopping eggs 3 OK GET shopping milk 1 OK DELETE shopping eggs OK
然而,咱们将构建一个最为另外一个应用的TCP服务器,它是kv
应用的一个客户端.而不是添加更多代码到kv
应用中.由于对于应用来讲,整个运行时和Elixir生态系统都是它的齿轮,因此咱们可以把咱们的项目分解成多个更小的项目,而不是组建一个巨大的,整个的应用.app
在建立应用以前,咱们必须讨论Mix是如何处理依赖的.在实际中,有两种咱们常见的依赖:内部和外部依赖.Mix支持这两种机制.分布式
#外部依赖函数
外部依赖就是你的业务范围以外的东西.例如,若是你须要一个HTTP API给你的分布式KV应用,你可使用Plug项目做为一个外部依赖.工具
安装外部依赖很简单.一般,咱们使用Hex包管理工具,它能列出在咱们的mix.exs
文件中全部deps函数以内的依赖.学习
def deps do [{:plug, "~> 1.0"}] end
这个依赖的定义是指Plug 1.x.x系列的最新版本已经被Hex添加了.这是由版本号以前的~>
代表的.想知道更多关于制定版本要求的信息,请查阅Version模块的文档.测试
通常,稳定的版本会被加入Hex.若是你想要依赖于一个仍在开发阶段的外部依赖,Mix也可以管理git依赖:ui
def deps do [{:plug, git: "git://github.com/elixir-lang/plug.git"}] end
你会发现当你添加了一个依赖到你的项目,Mix生成了一个mix.lock
文件,它保证了构建的可重复性.锁文件必须被导入到你的版本控制系统中,来保证每一个人使用该项目时,依赖的版本与你相同.
Mix提供了许多命令来处理依赖,能够再mix help
中看到:
$ mix help mix deps # 列出依赖,和它们的状态 mix deps.clean # 删除给定的依赖的文件 mix deps.compile # 编译依赖 mix deps.get # 获取全部最新版本的依赖 mix deps.unlock # 解锁给定的依赖 mix deps.update # 更新给定的依赖
最经常使用的命令是mix deps.get
与mix deps.update
.获取依赖以后,它会自动编译.你能够经过mix help deps
或查看Mix.Task.Deps模块的文档,来获取更多关于deps的信息.
#内部依赖
内部依赖是特定于你的项目的.它们一般在你的项目/公司/机构以外就没有意义.多数时候,出于技术,经济仍是业务上的缘由,你想要保持它们的私用性.
若是你有一个内部依赖,Mix支持两种操做方法:git仓库或雨伞计划.
例如,若是你添加kv
项目到一个git仓库,你只须要在你的deps代码中按顺序列出它们就能使用:
def deps do [{:kv, git: "https://github.com/YOUR_ACCOUNT/kv.git"}] end
若是仓库是私有的,你可能须要指定一个私有URLgit@github.com:YOUR_ACCOUNT/kv.git
.任什么时候候,Mix都会获取到它,只要你有合适的凭证.
在Elixir中不是特别推荐使用git依赖.记住运行时和Elixir生态系统已经提供了应用的概念.因此,咱们但愿你能常常地将你的代码打碎成多个应用,它们可以在本地组合,即便是在单个项目中.
然而,若是将每一个应用做为独立的项目添加到git仓库,你的项目会变得很难维护,由于你会花费大量时间来管理这些git仓库,而不是写你的代码.
出于该缘由,Mix支持了"雨伞计划".雨伞计划容许你建立一个包含着许多应用的项目,它们所有都放在一个单个的源代码仓库里.这就是下一部分咱们将探索的方法.
让咱们建立一个新的Mix项目.项目名称是kv_umbrella
,这个新项目中既有已存在的kv
应用,也有新的kv_server
应用.它的目录结构会是这样:
+ kv_umbrella + apps + kv + kv_server
有趣的地方是Mix为这样的项目提供了许多便捷性,例如可以用一句命令来编译和测试apps
中全部的应用.然而,即便它们在apps
中是排列在一块儿的,它们之间仍然是解耦的,因此你能够随意独立地构建,测试和部署每一个应用.
让咱们开始吧!
#雨伞计划
让咱们使用mix new
开始新项目.这个新项目名为kv_umbrella
,建立时咱们还须要传递一个--umbrella
选项.不要在已存在的kv
项目中建立这个新项目!
$ mix new kv_umbrella --umbrella * creating .gitignore * creating README.md * creating mix.exs * creating apps * creating config * creating config/config.exs
从打印出的信息中,咱们看到不多的文件被生成.生成的mix.exs
文件也不一样.让咱们来看看(注释已删除):
defmodule KvUmbrella.Mixfile do use Mix.Project def project do [apps_path: "apps", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end defp deps do [] end end
使得该项目于以前的项目不一样的缘由就是apps_path
:项目定义中的"apps"
条目.这意味着该项目会像一个雨伞同样运做.这样的项目没有源文件或测试,尽管他们能够由本身的依赖(不与孩子们共用).咱们将在apps目录中建立新应用.
让咱们进入apps目录,并开始构建kv_server
.这一次,咱们将传送--sup
旗帜,它会让Mix保证为咱们自动生成一个监督树,而不是像以前那样手动构建:
$ cd kv_umbrella/apps $ mix new kv_server --module KVServer --sup
生成的文件与咱们一开始为kv
所生成的类似,只有一些不一样.让咱们打开mix.exs
:
defmodule KVServer.Mixfile do use Mix.Project def project do [app: :kv_server, version: "0.1.0", build_path: "../../_build", config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock", elixir: "~> 1.3", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, deps: deps] end def application do [applications: [:logger], mod: {KVServer, []}] end defp deps do [] end end
首先,由于咱们是在kv_umbrella/apps
中生成的这个项目,Mix自动检测到了雨伞结构并添加了四行代码到项目定义中:
build_path: "../../_build", config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock",
这些选项意味着全部依赖将被签出至kv_umbrella/deps
,而且它们会分享相同的构建,配置和锁文件.这保证了整个雨伞结构中依赖只会被获取并编译一次,而不是每一个应用都要.
第二个改变是mix.exs
中的application
函数:
def application do [applications: [:logger], mod: {KVServer, []}] end
由于咱们传送了--sup
旗帜,Mix自动添加了mod: {KVServer, []}
,将KVServer
指定为了咱们的应用回调模块.KVServer
将会启动咱们的应用监督树.
事实上,让咱们打开lib/kv_server.ex
:
defmodule KVServer do use Application def start(_type, _args) do import Supervisor.Spec, warn: false children = [ # worker(KVServer.Worker, [arg1, arg2, arg3]) ] opts = [strategy: :one_for_one, name: KVServer.Supervisor] Supervisor.start_link(children, opts) end end
注意它定义了应用回调函数,start/2
,并使用了Supervisor
模块,而不是定义一个名为KVServer.Supervisor
的主管,内联地定义一个主管很方便!你能够经过阅读Supervisor模块文档来获取更多关于这种主管的信息.
咱们已经能够试试咱们的第一个雨伞孩子.咱们能在apps/kv_server
目录中运行测试,可是并不有趣.让咱们转到雨伞项目的根文件并运行mix test
:
$ mix test
运行成功!
因为咱们但愿kv_server
最后能使用咱们在kv
中定义的功能,因此咱们须要将kv
做为一个依赖添加到咱们的应用中.
#伞内依赖
Mix提供了一个简单的机制来使一个伞孩子可以依赖于另外一个.打开apps/kv_server/mix.exs
并修改deps/0
函数:
defp deps do [{:kv, in_umbrella: true}] end
上述代码使得kv
能够做为一个:kv_server
中的依赖.咱们能够导入kv
中定义的而模块,但不会自动启动:kv
应用.因此,咱们也须要在application/0
中列出:kv
:
def application do [applications: [:logger, :kv], mod: {KVServer, []}] end
如今Mix将会保证:kv
应用在:kv_server
启动以前启动.
最后,复制咱们已经构建了的kv
应用到咱们的雨伞项目中的apps
目录里.最终的目录结构是和咱们以前提到的同样:
+ kv_umbrella + apps + kv + kv_server
如今咱们只须要修改apps/kv/mix.exs
来包含咱们以前在apps/kv_server/mix.exs
中看到的雨伞条目.打开apps/kv/mix.exs
并添加到project
函数:
build_path: "../../_build", config_path: "../../config/config.exs", deps_path: "../../deps", lockfile: "../../mix.lock",
如今你能够在雨伞的根目录运行mix test
来对两个项目进行测试了.欧耶!
记住,雨伞项目是一个帮助你组织和管理应用的便捷方法.apps
目录中的应用仍然是互相解耦的.它们之间的依赖必须被明确列出.它们能够被共同开发,可是若是须要的话,能够独立地被编译,测试和部署.
#总结
本章咱们学习了更多关于Mix依赖和雨伞项目的内容.咱们决定构建一个雨伞项目,是由于咱们认为kv
和kv_server
是只在本项目中有用的内部依赖.
将来,咱们将写一些应用,你会注意到它们能够被提取到一个简洁的单元中,而后被不一样的项目使用.这时,就应该使用Git或Hex依赖了.
这里有一些问题,当处理依赖时你能够问本身.开始:这个应用在此项目以外还有意义吗?
- 若是没有,使用带伞孩子的雨伞项目 - 若是有,该项目是否能够分享到你的公司/组织以外? - 若是不行,使用私有git仓库. - 若是能够,将你的代码push到git仓库并常用Hex发布.
咱们的雨伞项目已经构建并运行了,如今让咱们开始编写服务器.