# `DoubleDown.BehaviourFacade`
[🔗](https://github.com/mccraigmccraig/double_down/blob/main/lib/double_down/behaviour_facade.ex#L1)

Generates a dispatch facade for a vanilla Elixir `@behaviour` module.

Use this when you want DoubleDown's dispatch machinery for a behaviour
you don't control — a third-party library behaviour, an existing
`@behaviour` in your codebase, or any module that defines `@callback`
declarations without using `defcallback`.

For behaviours you *do* control, prefer `DoubleDown.ContractFacade` with
`defcallback` — it gives you richer features (pre_dispatch transforms,
`@doc` tag sync, combined contract + facade in one module).

## Usage

    defmodule MyApp.Todos do
      use DoubleDown.BehaviourFacade,
        behaviour: MyApp.Todos.Behaviour,
        otp_app: :my_app
    end

The behaviour module must be compiled **in a prior compilation
unit** — its `.beam` file must be on disk before the facade
compiles. In a Mix project, this means the behaviour and facade
must be in separate `elixirc_paths` directories (e.g. behaviour
in `lib/` or an earlier test support directory, facade in a
later one). Combined contract + facade in a single module is
not supported — use `DoubleDown.ContractFacade` for that.

## Options

  * `:behaviour` (required) — the vanilla behaviour module to generate
    a facade for. Must define `@callback` declarations.
  * `:otp_app` (required) — the OTP application name for config-based
    dispatch. Implementations are resolved from
    `Application.get_env(otp_app, behaviour)[:impl]`.
  * `:test_dispatch?` — same as `DoubleDown.ContractFacade`. Defaults to
    `Mix.env() != :prod`.
  * `:static_dispatch?` — same as `DoubleDown.ContractFacade`. Defaults to
    `Mix.env() == :prod`.

## Param names

Where `@callback` declarations use annotated types like
`id :: String.t()`, the annotation name is used as the facade
function's parameter name. For bare types like `String.t()`,
parameter names are synthesized as `arg1`, `arg2`, etc.

## Configuration

    # config/config.exs
    config :my_app, MyApp.Todos.Behaviour, impl: MyApp.Todos.Impl

## Testing

    setup do
      DoubleDown.Testing.set_fn_handler(MyApp.Todos.Behaviour, fn
        :get_item, [id] -> {:ok, %{id: id}}
        :list_items, [] -> []
      end)
      :ok
    end

## Limitations vs `DoubleDown.ContractFacade`

  * No `pre_dispatch` transforms
  * No `@doc` tag sync from contract to facade
  * No combined contract + facade in one module
  * Param names are synthesized for bare (unannotated) types
  * No compile-time spec mismatch warnings

## See also

  * `DoubleDown.ContractFacade` — dispatch facades for `defcallback` contracts
    (richer features, recommended for new code).
  * `DoubleDown.DynamicFacade` — Mimic-style bytecode interception for any module.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
