LoginSignup
15
1

More than 1 year has passed since last update.

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の真上に関数ドキュメントが書かれています。

ご参考までに

15
1
0

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
  3. You can use dark theme
What you can do with signing up
15
1