search
LoginSignup
1
Help us understand the problem. What are the problem?

posted at

updated at

Organization

Elixir defdelegateで委譲

Elixirプログラムの構成を考える時にたまに便利なdefdelegate/2という関数があります。

Defines a function that delegates to another module.

Functions defined with defdelegate/2 are public and can be invoked from outside the module they're defined in, as if they were defined using def/2. Therefore, defdelegate/2 is about extending the current module's public API. If what you want is to invoke a function defined in another module without using its full module name, then use alias/2 to shorten the module name or use import/2 to be able to invoke the function without the module name altogether. 

  • 他のモジュールに委譲する関数を定義
  • defdelegate/2で定義された関数はpublicであり、def/2で定義された場合と同様に、定義されたモジュールの外から呼び出すことが可能

論よりRun。

サンプルElixirプロジェクトを生成

$ mix new myapp

$ cd myapp

$ ls
README.md lib       mix.exs   test

lib/myapp.exの中身はこんなコードになっています。

defmodule Myapp do
  @moduledoc """
  Documentation for `Myapp`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> Myapp.hello()
      :world

  """
  def hello do
    :world
  end
end

IEx内でサンプルElixirプロジェクトを起動し、Myapp.hello/1を実行してみます。

$ iex -S mix

iex> Myapp.hello()
:world

defdelegate/2を用いて委譲

lib/myapp.exの中身を変更します。

  • Myapp.Toukonモジュールを作り、hello/0を定義
  • defdelegate/2を用いてMyapp.hello/0Myapp.Toukon.hello/0委譲
defmodule Myapp do
  @moduledoc """
  Documentation for `Myapp`.
  """

  defdelegate hello, to: Myapp.Toukon
end

defmodule Myapp.Toukon do
  @doc """
  闘魂あいさつ
  """
  def hello, do: "元気ですかーーーーッ!"
end

IEx.Helpers.recompile/1で再コンパイルし、Myapp.hello/1をもう一度実行してみます。

iex> recompile
Compiling 1 file (.ex)
:ok
iex> Myapp.hello()
"元気ですかーーーーッ!"

Myappモジュールの使用者から見ると、Myapp.hello/0は普通の関数ですが、実際の処理はMyapp.Toukonモジュールへ移譲されています。

関数ドキュメントは委譲されない

あるElixirパッケージの開発をしている最中に気づきました。関数ドキュメントはできればコードの近くに置いておきたいものですが、defdelegate/2で別の関数から移譲された場合は関数ドキュメントがdelegate_to: Myapp.Toukon.hello/0のようになります。自分のコードであればたいして問題にならないのですが、Elixirパッケージの開発ではpublic関数のドキュメントを読みやすくすることが重要です。

CleanShot 2022-11-22 at 20.04.19@2x.png

対策としては、単純にdefdelegate/2の真上に関数ドキュメントを書くしかなさそうです。

@doc """
闘魂あいさつ

## Examples

    iex> Myapp.hello()
    "元気ですかーーーーッ!"

"""
defdelegate hello, to: Myapp.Toukon

Elixirの実装にも何箇所か出てきます。

意外なことに、Webアプリ開発フレームワークのPhoenixでは1箇所だけしか使用されていないようです。

やっぱりdefdelegate/2の真上に関数ドキュメントが書かれています。

ご参考までに

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1
Help us understand the problem. What are the problem?