# Módulos

Módulos são onde nossas funções vivem. Elas não podem estar por ai sem um lugar para ficar, pois poderiam se perder e nunca mais ser utilizadas. Elixir obriga todas as funções estarem em módulos.

Para definir um modulo, utilizamos a palavra chave [`defmodule`](https://elixir-lang.org/getting-started/modules-and-functions.html) seguido do nome e da abertura de seu contexto usando `do`. No exemplo criado na seção `Meu "Hello, world"` podemos vê-lo no arquivo `hello_world.ex`

<pre class="language-elixir" data-title="lib/hello_world.ex" data-line-numbers><code class="lang-elixir"><strong>defmodule HelloWorld do # aqui está o nome do nosso módulo
</strong>  def hello do
    :world
  end
end
</code></pre>

Isso serve para quando chamarmos nossas funções. Ao invés de somente `hello`, temos `HelloWorld.hello` e facilmente sabemos quem ela é.

No arquivo de teste podemos ver como o código é executado utilizando a chamada do modulo e depois a função.

<pre class="language-elixir" data-title="test/hello_world_test.exs" data-line-numbers><code class="lang-elixir">defmodule HelloWorldTest do
  use ExUnit.Case
  doctest HelloWorld

  test "greets the world" do
<strong>    assert HelloWorld.hello() == :new_world # Chamada do modulo e função
</strong>  end
end
</code></pre>

Podemos definir diversas funções dentro de um modulo (mas não façam isso, precisamos de organização certo?). Alguns bons exemplos de módulos e funções:

* `Authentication.login(user, password)`
* `Authentication.logout(user)`
* `Article.save(content)`
* `Article.delete(id)`
* `Article.update(article, new_content)`

Percebem como as funções são organizadas dentro de módulos? Isso facilita a leitura e organização do código e deixa as coisas mais intuitivas.

Temos por regra:

* Todo módulo deve começar com letra maiúscula, no estilo [CamelCase](https://pt.wikipedia.org/wiki/CamelCase);
* O modulo deve conter apenas o que é necessário para sua execução;

Nome de módulos podem ter mais de uma nível de profundidade, exemplo `Project.Authentication.Meta.Token` e geralmente seguem a estrutura de pastas.&#x20;

```
lib/authenticatin/meta/token.ex
```

### Atributos de módulo

Podemos definir atributos no módulo. São um tipo de variáveis que vivem apenas dentro do módulo e nunca veem a luz do dia. Útil para utilização interna. Para declarar ela, utilizamos o arroba(@) seguido do nome do atributo e logo após o valor (sem sinal de igual). Exemplo `@attribute_name 10`

Vamos alterar nosso programa para concatenar o atributo de módulo em nossa resposta. Primeiro nosso teste:

<pre class="language-elixir" data-title="test/hello_world_test.exs" data-line-numbers><code class="lang-elixir">defmodule HelloWorldTest do
  use ExUnit.Case
  doctest HelloWorld

  test "greets the world" do
<strong>    assert HelloWorld.hello() == "Hello, new world"
</strong>  end
end
</code></pre>

Rode o programa e voce terá o relatório de erro

```shell
mix test
1) test greets the world (HelloWorldTest)
     test/hello_world_test.exs:5
     Assertion with == failed
     code:  assert HelloWorld.hello() == "Hello, new world"
     left:  :world
     right: "Hello, new world"
     stacktrace:
       test/hello_world_test.exs:6: (test)
```

Precisamos alterar nosso programa para atender a nova resposta e para isso, utilizaremos atributos de módulo, apenas para exemplificar

<pre class="language-elixir" data-title="lib/hello_world.ex" data-line-numbers><code class="lang-elixir">defmodule HelloWorld do
<strong>  @message "Hello, new world" # definição do atributo de módulo
</strong>  
  def hello do
<strong>    @message # Utilização do atributo de módulo
</strong>  end
end

</code></pre>

Basta rodar novamente o teste e tudo estará funcionando.

```shell
mix test
Compiling 1 file (.ex)
.
Finished in 0.01 seconds (0.00s async, 0.01s sync)
1 test, 0 failures
```

#### Para se manter atento

* Atributo de módulo não pode ser acessado do lado de fora do módulo.
* Suporta apenas tipos primitivos, então não poderá executar uma função para obter uma resposta diretamente nele.

### Conclusão

Módulos são formas de agregar funções a fim de deixa-las próximas por contexto, facilitando a utilização e criação da mesma.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://aprenda.cafecomelixir.com.br/basico/modulos.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
