文档章节

elixir官方教程Mix与OTP(六) 依赖和伞形项目

ljzn
 ljzn
发布于 2016/08/11 10:55
字数 2615
阅读 80
收藏 0
点赞 1
评论 1

#依赖和雨伞项目

  1. 外部依赖
  2. 内部依赖
  3. 雨伞项目
  4. 伞内依赖
  5. 总结

本章,我们将讨论如何在Mix中管理依赖.

我们的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生态系统都是它的齿轮,所以我们能够把我们的项目分解成多个更小的项目,而不是组建一个巨大的,整个的应用.

在创建应用之前,我们必须讨论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依赖:

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.getmix 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依赖和雨伞项目的内容.我们决定构建一个雨伞项目,是因为我们认为kvkv_server是只在本项目中有用的内部依赖.

未来,我们将写一些应用,你会注意到它们可以被提取到一个简洁的单元中,然后被不同的项目使用.这时,就应该使用Git或Hex依赖了.

这里有一些问题,当处理依赖时你可以问自己.开始:这个应用在此项目之外还有意义吗?

- 如果没有,使用带伞孩子的雨伞项目 - 如果有,该项目是否可以分享到你的公司/组织之外? - 如果不行,使用私有git仓库. - 如果可以,将你的代码push到git仓库并经常使用Hex发布.

我们的雨伞项目已经构建并运行了,现在让我们开始编写服务器.

© 著作权归作者所有

共有 人打赏支持
ljzn
粉丝 29
博文 69
码字总数 96245
作品 0
南平
程序员
加载中

评论(1)

ifsc01
ifsc01
Umbrella 可以不翻译
elixir官方教程Mix与OTP(一) Mix入门

Mix入门 我们的第一个项目 编辑项目 执行测试 环境 探索 在本教程中,我们将学习如何构建一个完整的Elixir应用,包括监督树,配置,测试等等. 这个应用的功能是分布式键值仓库.我们将把键值对安排...

ljzn ⋅ 2016/08/07 ⋅ 2

elixir官方入门教程 学习资料

下一步该去哪 构建你的第一个Elixir项目 元编程 社区与其它资源 Erlang基础 想要学习更多?继续阅读! 构建你的第一个Elixir项目 为了开始你的第一个项目,Elixir装载了一个叫做Mix的构建工具....

ljzn ⋅ 2016/08/06 ⋅ 0

elixir官方入门教程 介绍

介绍 安装 交互模式 运行脚本 提出疑问 欢迎! 在本教程中我们将教给你Elixir的基础,语法,如何定义模块,如何操作常用数据结构的特性等等.本章将确保Elixir安装好了,并且你能够成功运行Elixir的...

ljzn ⋅ 2016/08/06 ⋅ 0

elixir官方教程Mix与OTP(四) 主管与应用

主管与应用 我们的第一个主管 理解应用 开启应用 应用回调 项目还是应用? 简单的一对一主管 监督树 观察者 测试中的共用状态 现在,我们的应用有个一个能监控几十个桶,不是几百个,的注册表.尽...

ljzn ⋅ 2016/08/10 ⋅ 0

(译)循序渐进学习Elixir

——Chris Bell Learning Elixir at Made by Many 在今年奥兰多的Elixir大会上演讲之后,就经常有人问我:你们团队是如何学习Elixir和OTP的? 和学习其他语言一样,学习Elixir也需要付出时间...

ljzn ⋅ 2016/09/29 ⋅ 0

Phoenix官方教程 (一) 构建和运行

首个教程的目的在于尽可能快地让一个Phoenix应用构建好并运行起来. 在我们开始前,请花一分钟阅读Installation Guide.安装好了所有必要的依赖,我们才能让应用流畅地构建和运行. 所以,我们需要...

ljzn ⋅ 2016/08/15 ⋅ 0

Elixir v1.2.0-rc.1 发布,函数式编程语言

Elixir v1.2.0-rc.1 发布,Elixir v1.2 依赖于 Erlang 18 的大量特性,至少要求 Erlang 18+ 版本。 此版本更新内容如下: 改进 [Mix] Raise readable error message when parsertools is not...

oschina ⋅ 2015/12/31 ⋅ 2

elixir官方教程Mix与OTP(九) 分布式任务与配置

分布式任务与配置 我们的第一个分布式代码 同步/等待 分布式任务 路由层 测试过滤器与标签 应用环境与配置 总结 本章,我们将回到应用并添加一个路由层,它能让我们根据桶名来在节点之间分布请...

ljzn ⋅ 2016/08/12 ⋅ 0

elixir官方入门教程 进程

进程 和 链接 任务 状态 在Elixir中,所有代码都运行在进程内。进程相互独立,并发地运行,通过传送信息来交流。进程不是Elixir中唯一的并发基础,但它意味着能够构建分布式的,可容错的程序...

ljzn ⋅ 2016/08/04 ⋅ 0

elixir官方教程Mix与OTP(二) 代理

代理 状态问题 代理 ExUnit回调 其它代理动作 代理中的客户端/服务器 本章我们将创建一个名为的模块.这个模块的作用是以一种可以被其它进程读取和修改的方式存储我们的键值对. 如果你跳过了入...

ljzn ⋅ 2016/08/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

用ZBLOG2.3博客写读书笔记网站能创造今日头条的辉煌吗?

最近两年,著名的自媒体网站今日头条可以说是火得一塌糊涂,虽然从目前来看也遇到了一点瓶颈,毕竟发展到了一定的规模,继续增长就更加难了,但如今的今日头条规模和流量已经非常大了。 我们...

原创小博客 ⋅ 今天 ⋅ 0

MyBatis四大核心概念

本文讲解 MyBatis 四大核心概念(SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper)。 MyBatis 作为互联网数据库映射工具界的“上古神器”,训有四大“神兽”,谓之:Sql...

waylau ⋅ 今天 ⋅ 0

以太坊java开发包web3j简介

web3j(org.web3j)是Java版本的以太坊JSON RPC接口协议封装实现,如果需要将你的Java应用或安卓应用接入以太坊,或者希望用java开发一个钱包应用,那么用web3j就对了。 web3j的功能相当完整...

汇智网教程 ⋅ 今天 ⋅ 0

2个线程交替打印100以内的数字

重点提示: 线程的本质上只是一个壳子,真正的逻辑其实在“竞态条件”中。 举个例子,比如本题中的打印,那么在竞态条件中,我只需要一个方法即可; 假如我的需求是2个线程,一个+1,一个-1,...

Germmy ⋅ 今天 ⋅ 0

Springboot2 之 Spring Data Redis 实现消息队列——发布/订阅模式

一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式,这里利用redis消息“发布/订阅”来简单实现订阅者模式。 实现之前先过过 redis 发布订阅的一些基础概念和操...

Simonton ⋅ 今天 ⋅ 0

error:Could not find gradle

一.更新Android Studio后打开Project,报如下错误: Error: Could not find com.android.tools.build:gradle:2.2.1. Searched in the following locations: file:/D:/software/android/andro......

Yao--靠自己 ⋅ 昨天 ⋅ 0

Spring boot 项目打包及引入本地jar包

Spring Boot 项目打包以及引入本地Jar包 [TOC] 上篇文章提到 Maven 项目添加本地jar包的三种方式 ,本篇文章记录下在实际项目中的应用。 spring boot 打包方式 我们知道,传统应用可以将程序...

Os_yxguang ⋅ 昨天 ⋅ 0

常见数据结构(二)-树(二叉树,红黑树,B树)

本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自coursera上普林斯顿的课程《Algorithms, Part I》中的Slides 相关命题的证明可参考《算法(第...

浮躁的码农 ⋅ 昨天 ⋅ 0

android -------- 混淆打包报错 (warning - InnerClass ...)

最近做Android混淆打包遇到一些问题,Android Sdutio 3.1 版本打包的 错误如下: Android studio warning - InnerClass annotations are missing corresponding EnclosingMember annotation......

切切歆语 ⋅ 昨天 ⋅ 0

eclipse酷炫大法之设置主题、皮肤

eclipse酷炫大法 目前两款不错的eclipse 1.系统设置 Window->Preferences->General->Appearance 2.Eclipse Marketplace下载【推荐】 Help->Eclipse Marketplace->搜索‘theme’进行安装 比如......

anlve ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部