README.md

DelegateBehaviour
=================

Elixir macros to define modules that delegate to concrete implementations of behaviours.
Useful to select specific implementation of behaviour in a pluggable way, like dependency injection.

- [Hex package information](https://hex.pm/packages/delegate_behaviour)

[![Hex.pm](http://img.shields.io/hexpm/v/delegate_behaviour.svg)](https://hex.pm/packages/delegate_behaviour)
[![Hex.pm](http://img.shields.io/hexpm/dt/delegate_behaviour.svg)](https://hex.pm/packages/delegate_behaviour)
[![Build Status](https://travis-ci.org/skirino/delegate_behaviour.svg)](https://travis-ci.org/skirino/delegate_behaviour)
[![Coverage Status](https://coveralls.io/repos/skirino/delegate_behaviour/badge.png?branch=master)](https://coveralls.io/r/skirino/delegate_behaviour?branch=master)
[![Github Issues](http://githubbadges.herokuapp.com/skirino/delegate_behaviour/issues.svg)](https://github.com/skirino/delegate_behaviour/issues)
[![Pending Pull-Requests](http://githubbadges.herokuapp.com/skirino/delegate_behaviour/pulls.svg)](https://github.com/skirino/delegate_behaviour/pulls)

## Installation

- Add `:delegate_behaviour` as a mix dependency.
- `$ mix deps.get`

## Usage example

Suppose you have a behaviour and two modules that implement the behaviour.

```ex
iex> defmodule B do
...>   use Behaviour
...>   @callback f(integer) :: integer
...> end
iex> defmodule Impl1 do
...>   @behaviour B
...>   def f(i), do: i + 1
...> end
iex> defmodule Impl2 do
...>   @behaviour B
...>   def f(i), do: i + 2
...> end
```

Now you can easily define a module that implements the behaviour `B`
by delegating all behaviour functions to the module `Impl1` or `Impl2`.
There are two variants of delegations:

- Choosing target implementation at compile-time

    ```ex
    iex> defmodule C do
    ...>   require DelegateBehaviour
    ...>   DelegateBehaviour.compile_time(B) do
    ...>     # Put code block to choose the target module;
    ...>     # do whatever you like to determine which module you delegate to,
    ...>     # e.g. environment variable, application config, config file, etc.
    ...>     # The code block is evaluated at compile time.
    ...>     case System.get_env("SOME_ENV_VAR") do
    ...>       "Impl1" -> Impl1
    ...>       _       -> Impl2
    ...>     end
    ...>   end
    ...> end
    iex> C.f(0)
    2
    ```

- Choosing target implementation at runtime

    ```ex
    iex> defmodule R do
    ...>   require DelegateBehaviour
    ...>   DelegateBehaviour.runtime(B) do
    ...>     # Put code block to choose the target module;
    ...>     # do whatever you like to determine which module you delegate to,
    ...>     # e.g. environment variable, application config, config file, etc.
    ...>     # The code block is evaluated at each invocation of the behaviour functions.
    ...>     case System.get_env("SOME_ENV_VAR") do
    ...>       "Impl1" -> Impl1
    ...>       _       -> Impl2
    ...>     end
    ...>   end
    ...> end
    iex> R.f(0)
    2
    ```

All behaviour interface functions are generated as delegations, together with their type specifications.