README.md

![PhoenixUp](https://raw.githubusercontent.com/henriquefernandez/use_case/master/priv/static/small_logo.png)

# UseCase

![](https://img.shields.io/hexpm/v/use_case?style=social) ![](https://img.shields.io/hexpm/l/use_case?style=social)

A way to increase *Elixir* projects readability and maintenance. Heavily inspired by *Clean Architecture*. We can join it with [clean mixer](https://github.com/miros/clean_mixer) for a very nice *Clean Architecture* code experience.

## Table of contents

  - [Installation](#installation)
  - [About](#about)
  - [Creating Interactors](#creating-interactors)
    - [Defining inputs](#defining-inputs)
    - [Defining errors](#defining-errors)
    - [Default fields](#default-fields)
    - [Composing with pipes](#composing-with-pipes)
    - [Sending Options](#sending-options)
  - [Mix Tasks](#mix-tasks)
  - [Contribute](#contribute)


## Installation

The package can be installed by adding `use_case` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:use_case, "~> 0.2.1"}
  ]
end
```

## About

Lets see some of the benefits from using the library (or only the idea behind use cases interactors). Imagine a library system where we have the context "books". On normal *Phoenix* systems, the design may look like the example below:

```
▾ library/                 
  ▾ books/                 
         author.ex      
         book.ex        
       application.ex    
       books.ex           
       repo.ex           
```

There we have some problems:

- It is not yet clear what our application intend to do.
- Contexts files (books.ex) can get extremely fat with a lot of business logic.

Now, thinking in use case interactors we can imagine *Phoenix* contexts as a *Facade* for your use cases, and do that:

```
▾ library/                 
  ▾ books/                 
         author.ex      
         book.ex        
         create_author.ex        
         create_book.ex        
         sell_book.ex        
       application.ex    
       books.ex           
       repo.ex           
```

Our context will look like the example above:

```Elixir
defmodule Library.Books do                         
  @moduledoc """                                   
  The Books context.                               
  """                                              
  import UseCase, only: [call: 1]                                   
  import __MODULE__.{CreateAuthor, SellBook, CreateBook}

  @doc """                                       
  Creates a authors.                             
                                                 
      iex> create_authors(name)       
      {:ok, %Library.Books.CreateAuthor.Output{ ... }}
                                                 
      iex> create_authors(bad_name)   
      {:error, %Library.Books.CreateAuthor.Error{message: "Bad name given"}}
                                                 
  """                                            
  def create_author(name),                
    do: call(%CreateAuthor{name: name})          

  # ...
  def create_book(name, author),                
    do: call(%CreateBook{name: name, author: author})          

  # ...
  def sell_book(book_id),                
    do: call(%SellBook{book_id: book_id})          
```

Let's say that now `CreateBook`, `CreateAuthor` and `SellBook` are gateways for our business rules. *Controllers*, *views* and even *Phoenix* know almost nothing about our business, they know that we can "create books" and "sell books", and for that we need the params "name", "author" or "book_id", but nothing about what goes inside. Goals: 

- Its clear what our application intend to do. It screams.
- Contexts files are only facades, an api for our use cases interactors to the external world. They dont know Repos or Schemas.
- When we call an use case interactor, we will get a specific output or an specific error from that use case (and we have a specific input too), making the system code more assertive in relation to what it is doing.

And this is just the tip of the iceberg, to full enjoy this library, i recommend you to read the *Clean Architecture* book.

## Creating interactors

The most basic interactor can be created using the `UseCase.Interactor` module, defining an `output` for it and creating a `call/2` function:

```elixir
defmodule SayHello do
  use UseCase.Interactor,
    output: [:message]

  def call(%{name: name}, _opts), do: ok(message: "Hello #{name}!")
  def call(%{name: nil}, _opts), do: error("name is obrigatory")
end
```

Now our `SayHello` module has the `ok` and `error` macros and a struct for `Output` like `%SayHello.Output{message: "something"}`.

The `ok` and `error` macro can be used to define when our interactor success or fail.

After define, we can call it in many ways:

```elixir
iex> UseCase.call(SayHello, %{name: "Henrique"}) 
iex> {:ok, SayHello.Output{message: "Hello Henrique!", _state: nil}}

iex> SayHello.call(%{name: "Henrique"})
iex> {:ok, SayHello.Output{message: "Hello Henrique!", _state: nil}}

iex> UseCase.call(SayHello, %{name: nil}) 
iex> {:error, SayHello.Error{message: "name is obrigatory!"}}

iex> UseCase.call!(SayHello, %{name: "Henrique"}) 
iex> SayHello.Output{message: "Hello Henrique!", _state: nil}

iex> UseCase.call!(SayHello, %{name: nil}) 
iex> **** SayHello.Error name is obrigatory!
```

### Defining inputs

Sometimes we want to guarantee the inputs our interactors will receive, we can do it defining this way:  

```elixir
defmodule SayHello do
  use UseCase.Interactor,
    output: [:message],
    input: [:name] # Add this

  def call(%SayHello{name: name}, _opts), do: ok(message: "Hello #{name}!")
  def call(%SayHello{name: nil}, _opts), do: error("name is obrigatory")
end
```

Now, with `UseCase` module we can call it using the input directly:

```elixir
iex> UseCase.call %SayHello{name: "Henrique"} 
iex> {:ok, SayHello.Output{message: "Hello Henrique!", _state: nil}}

iex> UseCase.call! %SayHello{name: "Henrique"} 
iex> SayHello.Output{message: "Hello Henrique!", _state: nil}
```

### Defining errors

If we want to send extra informations in errors, we can do it as `input` and `output`.

```elixir
defmodule SayHello do
  use UseCase.Interactor,
    output: [:message],
    input: [:name],
    error: [:code] # Add this

  def call(%SayHello{name: name}, _opts), do: ok(message: "Hello #{name}!")
  def call(%SayHello{name: nil}, _opts), do: error("name is obrigatory", code: 500) # And use it
end
```

```elixir
iex> UseCase.call(SayHello, %{name: nil}) 
iex> {:error, SayHello.Error{message: "name is obrigatory!", code: 500}}
```

### Default fields

When not defined, input, output and error defaults to:

```
input: [:_state],
output: [],
error: [:message]
```

Fields `:_state` in `input` and `:message` in `error` are always appended. The `:_state` field is very useful for pipe operations.

### Composing with pipes

Lets define an `LogOperation` interactor:

```elixir
defmodule LogOperation do
  use UseCase.Interactor

  def call(%{message: message}, _opts) do
    # .. log message
    ok()
  end
end
```

We can compose with our `SayHello` simple as that:

```elixir
iex> %SayHello{name: "Henrique"} |> UseCase.pipe [SayHello, LogOperation]
iex> {:ok, LogOperation.Output{_state: nil}}

iex> UseCase.pipe [%SayHello{name: "Henrique"}, LogOperation] 
iex> {:ok, LogOperation.Output{_state: nil}}

iex> UseCase.pipe [%SayHello{name: nil}, LogOperation] 
iex> {:error, SayHello.Error{message: "name is obrigatory!", code: 500}}

iex> %SayHello{name: "Henrique"} |> UseCase.pipe! [SayHello, LogOperation]
iex> LogOperation.Output{_state: nil}

iex> UseCase.pipe! [%SayHello{name: "Henrique"}, LogOperation] 
iex> LogOperation.Output{_state: nil}

iex> UseCase.pipe! [%SayHello{name: nil}, LogOperation] 
iex> **** SayHello.Error name is obrigatory!
```

All we need is match outputs and inputs and use one of pipe `UseCase` functions.

### Sending options

All `UseCase` functions last argument is the options keyword list that is sent to interactors:

```Elixir
import UseCase

call(%SayHello{name: "henrique"}, my_option: true)
%SayHello{name: "Henrique"} |> pipe([SayHello, LogOperation], my_option: true)
pipe([%SayHello{name: "Henrique"}, LogOperation], my_option: true)
```

## Mix Tasks

`mix use_case.gen.interactor`

`mix use_case.gen.phx_resource`

`mix use_case.gen.phx_resource_html`

`mix use_case.gen.phx_resource_json`

`mix use_case.gen.phx_resource_temple`

## Contribute

*UseCase* is not only for me, but for the *Elixir* community.

I'm totally open to new ideas. Fork, open issues and feel free to contribute with no bureaucracy. We only need to keep some patterns to maintain an organization:

#### branchs

*your_branch_name* or *your-branch-name* 

#### commits

*[your_branch_name] Your commit* or *[your-branch-name] Your commit*