18

Por qué Elixir es un diamante en bruto

839Puntos

hace 2 años

En la últimas dos décadas hemos podido observar un repunte en el uso de los lenguajes de programación funcional, quizá la predicción de dicho auge la podamos ver claramente en el famoso artículo escrito por Herb Sutter, un prominente experto en C++, en el año 2005, The Free Lunch Is Over, A Fundamental Turn Toward Concurrency in Software. En dicho artículo, Herb Sutter, indicaba algo que ya sabemos hoy, la velocidad de reloj del procesador estaba llegando a sus límites físicos. Las mayores consecuencias de esto eran dos:

CPU
  • La manufactura de procesadores se iba a enfocar en mejor soporte para multi-threading y multi-cores.
  • A los desarrolladores de software se nos había acabado el almuerzo gratis, esto quiere decir que anteriormente la mayoría de las aplicaciones, incluso sin modificación alguna, se hacían el doble de rápidas al cabo de un par de años, solo debías actualizar tu hardware, las ganancias venían principalmente de tu CPU y luego de la memoria y discos duros. Pero en aquel entonces, año 2005, la situación obligaba a un cambio de paradigma, teníamos que ajustar o re-diseñar nuestros programas para soportar un mundo concurrente y aprovechar los recursos.

Sin embargo, la programación concurrente es compleja si tienes que hacerla desde cero. Por eso en dicho artículo también se menciona que aquellos lenguajes de programación que ya implementan soporte a la programación concurrente, obtendrán una nueva vida. La expectativa será un incremento en la demanda por lenguajes y sistemas que optimicen estas nuevas áreas.

Como veremos más adelante en este artículo, la programación funcional, la inmutabilidad, el pase de mensajes entre procesos, y otros conceptos más, facilitan ese cambio de paradigma que Herb Sutter mencionaba en su famoso artículo.

Elixir, en particular, será el lenguaje funcional del cual hablaremos en detalle en este artículo.

Acerca de Elixir

  • Es un lenguaje dinámico y funcional, diseñado para construir aplicaciones escalables y mantenibles.
  • Funciona encima de la máquina virtual de Erlang, la cual es conocida por ejecutar sistemas de baja latencia, distribuidos y tolerantes a fallos.
  • Es un lenguaje de propósito general, se ha utilizado con éxito en el desarrollo web, software embebido, ingestión de datos y procesamiento multimedia, así como una amplia gama de industrias.

El sitio oficial de Elixir, expone algunos casos de éxito por si quieres saber más acerca de cómo compañías a lo largo de diferentes industrias están usando el poder de Elixir y su ecosistema para crear y hacer crecer sus negocios.

Llegados a este punto, ya vas observando que al hablar de Elixir, también tenemos que hablar de Erlang, así que mejor hagamos una pausa para hablar sobre Erlang y su ecosistema.

Erlang y su ecosistema

https://raw.githubusercontent.com/milmazz/elixir_fundamentals/main/blog/erlang-ecosystem.png

En la actualidad existe todo un ecosistema que aprovecha la máquina virtual de Erlang o BEAM (Bogdan/Björn’s Erlang Abstract Machine). Tenemos a Erlang y Elixir por un lado. Hasta lenguajes como LFE que permite la sintaxis de Lisp, o Erlog que permite ejecutar Prolog, Lua, Gleam, entre otros.

Erlang es un lenguaje originalmente desarrollado dentro de Ericsson Computer Science Laboratory alrededor del año 1986, que posteriormente fue liberado open-source en 1998. Ericsson impuso algunos requisitos que vienen a cubrir gran parte de las necesidades en sistemas distribuidos hoy día. Los requisitos fueron:

  • Manejar un gran número de actividades concurrentes.
  • Acciones a realizar en un momento determinado o dentro de cierto tiempo. A esto también se le conoce como sistemas soft-real time.
  • Sistemas distribuidos en varios ordenadores.
  • Interacción con hardware.
  • Sistemas de software muy grandes.
  • Funcionalidad compleja, como la interacción entre componentes.
  • Funcionamiento continuo durante varios años.
  • Mantenimiento de software (reconfiguración, etc.) sin detener el sistema. También conocido en algunos entornos como hot swapping code.
  • Requisitos estrictos de calidad y confiabilidad.
  • Tolerancia a fallas. Esto incluye tanto fallas de hardware como errores de software.

Erlang llegó a cubrir todos los requisitos impuestos por Ericsson, lo cual ofrece la posibilidad de desarrollar sistemas distribuidos bastante robustos. Y ha sido probado en multiples sistemas en producción por décadas.

En la máquina Virtual de Erlang todo el código se ejecuta en pequeños procesos concurrentes.

  • Cada uno de esos procesos contiene su propio estado, dicho estado no es compartido en lo absoluto con otros procesos.
  • Dichos procesos hablan unos con otros procesos por medio de pase de mensajes.
  • El intercambio de mensajes entre procesos es gestionado por la máquina virtual de Erlang, de manera transparente.
  • Erlang, ofrece un ambiente perfecto para el desarrollo de software distribuido.

Si no has programado en Erlang, seguramente has sido usuario indirecto o directo. Te comparto algunas estadísticas ofrecidas en la charla How Cisco is using Erlang for intent-based networking:

  • Cisco despliega 2 millones de dispositivos por año con Erlang en ellos.
  • 90% de todo el tráfico de Internet atraviesa nodos controlados por Erlang.
  • Los 8 mayores proveedores de servicios y proveedores de equipos de redes usan Erlang para controlar sus sistemas.

Sin embargo, en la opinión del creador de Elixir, José Valim, a pesar de las ventajas claras que ofrece Erlang, hace más de una década, sintió que habían partes que echaba de menos de otros lenguajes. Algunas de esas partes él solía usarlas en su día a día, como la meta-programación, extensibilidad del software brindando polimorfismo por medio de Protocols, y algunas herramientas que incrementan la productividad de los desarrolladores; algunas otras las descubrió al leer el libro Seven Languages in Seven Weeks. Así que decidió explorar la posibilidad de desarrollar un nuevo lenguaje encima de la máquina virtual de Erlang. Dicho lenguaje fue Elixir. En esencia, puedes ver a Elixir como otro lenguaje de programación funcional que expone todo lo que la máquina virtual de Erlang viene proveyendo por décadas de una manera diferente y a otros desarrolladores que no lo habrían experimentado de otra manera.

¿Cómo se ve Elixir?

defmodule Grapheme do@moduledoc"""
  Basic operations over Unicode graphemes

  A grapheme is a minimally distinctive unit of writing
  in the context of a particular writing system.
  """@doc"Returns a map with the grapheme frequencies"
  def frequencies(string) do
    string
    |> String.graphemes()
    |> Enum.frequencies()
  endend
iex> Grapheme.frequencies("Elixir")
%{"E" => 1, "i" => 2, "l" => 1, "r" => 1, "x" => 1}

Funcionalidades de la plataforma

Escalabilidad

Todo el código en Elixir se ejecuta dentro de hilos de ejecución livianos, llamados procesos, que están aislados unos de otros e intercambian información vía mensajes.

current_process = self()

# Spawn an Elixir process (not an operating system one!)
spawn_link(fn ->
  send(current_process, {:msg, "hello world"})
end)

# Block until the message is received
receive do
  {:msg, contents} -> IO.puts(contents)
end

Dada la naturaleza liviana de estos procesos, no es extraño tener cientos de miles de procesos ejecutándose simultáneamente en la misma máquina. El aislamiento entre procesos permite que la recolección de elementos no utilizados o basura (garbage collected) sea independiente, lo que reduce las pausas en todo el sistema y utiliza los recursos de la máquina de la manera más eficiente posible (escalabilidad vertical)

Los procesos también pueden comunicarse con otros procesos que se ejecutan en diferentes máquinas en la misma red. Esto proporciona la base para la distribución, lo que permite a los desarrolladores coordinar el trabajo en varios nodos (escalabilidad horizontal).

Tolerancia a fallos

La verdad inevitable sobre el software que se ejecuta en producción es que las cosas saldrán mal. Más aún cuando tenemos en cuenta la red, los sistemas de archivos y otros recursos de terceros.

Para hacer frente a las fallas, Elixir proporciona supervisores que describen cómo reiniciar partes de su sistema cuando las cosas salen mal, volviendo a un estado inicial conocido que se garantiza que funcionará.

children = [
  TCP.Pool,
  {TCP.Acceptor, port: 4040}
]

Supervisor.start_link(children, strategy: :one_for_one)

La combinación de tolerancia a fallas y programación basada en eventos a través del pase de mensajes hace que Elixir sea una excelente opción para la programación reactiva y arquitecturas robustas.

Funcionalidades del lenguaje

Programación funcional

La programación funcional promueve un estilo de código que ayuda a los desarrolladores escribir código que es breve, conciso, y mantenible. Por ejemplo, la coincidencia de patrones permite a los desarrolladores descomponer fácilmente las estructuras de datos y acceder a su contenido.

%User{name: name, age: age} = User.get("John Doe")
name#=> "John Doe"

Cuando mezclamos guardas, la coincidencia de patrones nos permite especificar de manera elegante las condiciones específicas en las que un bloque de código se ejecutará.

defdrive(%User{age: age})when age >= 16do# Code that drives a carend

drive(User.get("John Doe"))
#=> Fails if the user is under 16

Elixir depende en gran medida en estas funcionalidades para garantizar que el software funcione en las condiciones esperadas. Y cuando eso no pasa, no te preocupes, los supervisores, mencionados en la sección previa, cuidaran nuestras espaldas.

Extensibilidad y DSLs (Domain-Specific Languages)

Elixir ha sido diseñado para ser extensible, dejando que los desarrolladores naturalmente extiendan el lenguaje a dominios particulares con el propósito de incrementar su productividad.

Un ejemplo claro de esto es el framework de pruebas unitarias incluido en Elixir, llamado ExUnit.

defmoduleMathTestdouse ExUnit.Case, async:true

  test "can add two numbers"do
    assert 1 + 1 == 2endend

La opción async: true permite que los tests corran concurrentemente, usando tantos CPU cores como sea posible. Mientras que assert puede hacer introspección del código, proveyendo reportes en caso de fallas. Estas funcionalidades fueron construidas usando macros, haciendo posible agregar nuevos constructos tal como si fueran parte del lenguaje.

Herramientas

Mix

Elixir viene con un gran conjunto de herramientas para facilitar el desarrollo. Mix es una herramienta que te permite crear proyectos, administrar tareas, ejecutar pruebas y más.

$ mix new my_app
$ cd my_app
$ mix test
.

Finished in 0.04 seconds (0.04s on load, 0.00s on tests)
1 test, 0 failures

Mix también puede administrar dependencias y se integra con el administrador de paquetes Hex, el cual te permite realizar resolución de dependencias, obtener paquetes remotos y alojar documentación para todo el ecosistema de Erlang.

Desarrollo interactivo

Herramientas como IEx (la consola interactiva de Elixir) te ofrecen una manera de explorar todas las ventajas del lenguaje. Permite auto-completado, ayudantes para depuración del código, acceso a la documentación con un formato amigable, entre otros.

$ iex
Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex> h String.trim           # Prints the documentation forfunction
iex> i "Hello, World"        # Prints information about the given datatype
iex> break! String.trim/1    # Sets a breakpoint in the String.trim/1function
iex> recompile               # Recompiles the currentprojecton the fly

Compatibilidad con Erlang

Como ya hemos mencionado previamente, Elixir se ejecuta sobre la máquina virtual de Erlang, lo cual permite a los desarrolladores acceder al ecosistema de Erlang. Desde Elixir puedes invocar funciones de Erlang sin ningún costo en tiempo de ejecución.

iex> :crypto.hash(:md5, "Using crypto from Erlang OTP")
<<192, 223, 75, 115, ...>>


Si deseas dominar este lenguaje de programación, sigue estos maravillosos cursos de Elixir:

Milton
Milton
Escribe tu comentario
+ 2
Ordenar por:
5
15485Puntos

Este post es una joya 💎 Elixir es una bestialidad de lenguaje, bien por Platzi.

2
4938Puntos

Tengo una gigantesca duda, Exactamente en que casos se puede aplicar elixir y ejemplos? Disculpen es que soy nuevo y no entendí absolutamente nada, pero talvez con ejemplos pueda aclarar las dudas.

2
16885Puntos

Elixir es una maravilla!!! ☺️

1
10985Puntos

Que interesante lenguaje y el artículo esta muy completo. Creo que tomare el curso de introducción para checarlo más a detalle.