Open2

Elixir callback, behaviour, 共通処理化の習作

tatotato

同じような処理をするモジュールがある

  • 基本的な処理は1つ
  • たまに違う処理にしたい
  • たまに基本的な処理も使って違う処理にしたい

で考えてみたコード例
// 注意:著者はElixir業務経験なしです。

defmodule Worker do
  @callback run :: :ok

  def run do
    IO.puts "base function"
    :ok
  end

  def commons(args \\ []) do
    excepts = Keyword.get(args, :except, [])

    quote do
      if not Enum.member?(unquote(excepts), :run) do
        defdelegate run, to: Worker
      end
    end
  end

  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end

  defmacro __using__({which, args}) when is_atom(which) do
    apply(__MODULE__, which, [args])
  end
end

defmodule AWorker do
  @behaviour Worker
  use Worker, :commons
end

defmodule BWorker do
  @behaviour Worker
  use Worker, {:commons, except: [:run]}

  @impl true
  def run do
    IO.puts "My Runner"
    :ok
  end
end

defmodule CWorker do
  @behaviour Worker
  use Worker, {:commons, except: [:run]}

  @impl true
  def run do
    Worker.run()
    IO.puts "My Runner with base function"
    :ok
  end
end

AWorker.run()
BWorker.run()
CWorker.run()
tatotato

たまに基本的な処理も使って追加したい

これは欲張りすぎで機能分割(runを細かく)して、run自体は使わない方が真っ当かもしれない