Cómo usar Application

En la máquina BEAM una aplicación consiste en un supervisor y una configuración. El código fuente del paquete compone la aplicación, y la configuración permite parametrizar el comportamiento de la aplicación.

En Elixir, el concepto de aplicación tiene un matiz especial que difiere un poco de lo que podríamos imaginar si venimos de otros lenguajes o entornos. En la máquina virtual BEAM, una aplicación no es simplemente un programa monolítico, sino que se define como un conjunto de módulos junto con una configuración específica que determina cómo esos módulos deben comportarse. Esto nos permite modularizar y parametrizar el comportamiento de nuestro código de forma flexible.

Por ejemplo, podríamos tener varios módulos que implementen un servidor web. En lugar de codificar directamente el puerto en el que escucha el servidor, podemos definir esa configuración externamente, de modo que la misma aplicación pueda ejecutarse con diferentes parámetros sin necesidad de modificar el código fuente. Este enfoque es muy común en librerías como Phoenix o Ecto, donde la configuración externa es clave para adaptar su funcionamiento a distintos entornos.

La BEAM está diseñada para correr múltiples aplicaciones simultáneamente. Esto significa que cuando ejecutamos un proyecto real, no solo estamos lanzando nuestra propia aplicación, sino también otras aplicaciones que forman parte del ecosistema, como Logger para el registro de eventos, Ecto para la gestión de bases de datos o sistemas de PubSub. Cada una de estas aplicaciones es un conjunto de módulos con su propia configuración y árbol de supervisión, y todas conviven dentro de la misma máquina virtual.

Para ver esto en acción, podemos usar herramientas como Observer, que nos muestran las aplicaciones que se están ejecutando y sus árboles de supervisión. Por ejemplo, al iniciar iex, veremos aplicaciones como Logger o incluso ExUnit, que es el framework de pruebas unitarias, funcionando en segundo plano como aplicaciones independientes.

Cuando queremos crear nuestra propia aplicación en Elixir, Mix nos ofrece varias opciones. El comando mix new crea un proyecto básico, pero si queremos que nuestro proyecto sea una aplicación con un árbol de supervisión, debemos usar la opción --sup. Esto genera un archivo application.ex dentro de nuestro proyecto, que define el módulo principal de la aplicación y su función start.

En el archivo mix.exs, al usar --sup, se añade una línea en la configuración que indica cuál es el módulo principal de la aplicación mediante la clave mod. Este módulo debe usar Application y definir la función start/2, que es el punto de entrada cuando la aplicación se inicia. En esta función es donde configuramos el árbol de supervisión que gestionará los procesos de nuestra aplicación.

Por ejemplo, si definimos la función start simplemente para imprimir un mensaje, como:

defmodule Prueba1.Application do
  use Application

  def start(_type, _args) do
    IO.puts("hola mundo")
  end
end

y ejecutamos mix run, veremos que la aplicación intenta arrancar y ejecuta ese código. Sin embargo, esto genera un error porque la función start debe devolver una tupla con la forma {:ok, pid}, donde pid es el identificador del proceso supervisor que se ha iniciado. Esto es parte de la especificación OTP que debemos cumplir para que la BEAM gestione correctamente nuestra aplicación.

Por lo tanto, la implementación correcta de start debe iniciar un supervisor y devolver su referencia, algo así:

defmodule Prueba1.Application do
  use Application

  def start(_type, _args) do
    children = [
      # Aquí irían los GenServers u otros procesos supervisados
    ]

    opts = [strategy: :one_for_one, name: Prueba1.Supervisor]
    Supervisor.start_link(children, opts)
  end
end

De esta forma, cuando ejecutemos mix run, la BEAM sabrá cómo iniciar y supervisar los procesos de nuestra aplicación.

Además, en el archivo mix.exs podemos pasar argumentos al módulo principal de la aplicación a través de la clave mod. Por ejemplo, si definimos:

def application do
  [
    extra_applications: [:logger],
    mod: {Prueba1.Application, :hola}
  ]
end

el segundo parámetro :hola llegará como argumento a la función start/2, lo que nos permite personalizar el comportamiento de inicio según sea necesario.

En definitiva, para crear una aplicación en Elixir con todas las garantías, debemos definir un módulo que use Application, implementar la función start/2 que devuelva un árbol de supervisión y declararlo en mix.exs con la clave mod. Usar mix new --sup es la forma más sencilla de empezar con esta estructura, pero si olvidamos esta opción, siempre podemos añadirla manualmente.

En próximos pasos, podemos avanzar creando aplicaciones que lancen GenServers reales y gestionen procesos supervisados, aprovechando toda la potencia que nos ofrece OTP y la BEAM para construir sistemas robustos y concurrentes.

Lista de reproducción
  1. 1
    Cómo crear procesos
    11 minutos
  2. 2
    Cómo pasar mensajes entre procesos
    13 minutos
  3. 3
    Diccionario de un proceso y mantener un estado
    15 minutos
  4. 4
    Cómo enlazar procesos para detectar fallos
    13 minutos
  5. 5
    Cómo monitorizar procesos
    10 minutos
  6. 6
    ¿Qué es un GenServer?
    15 minutos
  7. 7
    Cómo enviar mensajes con un GenServer
    19 minutos
  8. 8
    Control de errores y gestión de un GenServer
    19 minutos
  9. 9
    Cómo renombrar procesos
    11 minutos
  10. 10
    Cómo crear un Supervisor Tree
    17 minutos
  11. 11
    Estrategias para trabajar con Supervisor
    18 minutos
  12. 12
    Estrategias para crear un Supervisor
    11 minutos
  13. 13
    Resumen sobre procesos OTP
    12 minutos
  14. 14
    Cómo usar Application
    12 minutos
  15. 15
    Ejemplo de Application con hijos
    14 minutos