elixir官方教程Mix與OTP(六) 依賴和傘形項目

#依賴和雨傘項目git

  1. 外部依賴
  2. 內部依賴
  3. 雨傘項目
  4. 傘內依賴
  5. 總結

本章,咱們將討論如何在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.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發佈.

咱們的雨傘項目已經構建並運行了,如今讓咱們開始編寫服務器.

相關文章
相關標籤/搜索