Ecto y Elixir

Ecto no es un ORM

Mon, 20 Jan 2020

iver.mx

Uno de los principales cambios de paradigma en los desarrolladores que empiezan a utilizar Elixir es el uso de Ecto como si fuera un ORM.

Justo este tema se trata en la publicación de plataformatec (realizada por José Valim) llamada The Little Ecto Cookbook.

A continuación haré un extracto en español de la publicación de ”What is new in Ecto 2.0“.

Los proyectos que utilizan Ecto pueden terminar con God Schemas (Esquemas Dios) que hacen de todo en el sistema. Comúnmente conocidos como Modelos de Dios, Modelos gordos. Dichos esquemas pueden contener cientos de campos, que a menudo reflejan malas decisiones tomadas en la capa de datos. En lugar de proporcionar un solo esquema con campos que abarcan múltiples preocupaciones, es mejor dividir el esquema en múltiples contextos.

“Elixir no es un lenguaje Orientado a Objetos, por lo tanto Ecto no puede ser un ORM (Object-Relational Mapper).”

O es para Objetos

Los objetos combinan estado y comportamiento juntos. En el mismo objeto de user, puede tener datos como user.name y el comportamiento, como confirmar una cuenta de uso particular a través de user.confirm().

Mientras que algunos lenguajes imponen diferentes sintaxis entre los datos de acceso (user.name sin paréntesis) y el comportamiento (user.confirm() con paréntesis), otros idiomas siguen el Principio de Acceso Uniforme (Uniform Access Principle) en el que un objeto no debe hacer una distinción entre las dos sintaxis. Eiffel y Ruby son idiomas que siguen tal principio.

En Elixir, trabajamos con diferentes estructuras de datos como tuplas, listas, mapas y otros. El comportamiento no se puede adjuntar a las estructuras de datos. El comportamiento siempre se agrega a los módulos a través de funciones.

Elixir falla la prueba de “acoplamiento de estado y comportamiento”.

Cuando es necesario trabajar con datos estructurados, Elixir proporciona estructuras (structs). Las estructuras definen un conjunto de campos. Una estructura será referenciada por el nombre del módulo donde se define:

defmodule User do
  defstruct [:name, :email]
end

user = %User{name:"John Doe", email:"john@example.com"}

Una vez que se crea una estructura de usuario, podemos acceder a su correo electrónico a través de user.email. Sin embargo, las estructuras son solo datos. Es imposible invocar user.confirm() en una estructura en particular de una manera que ejecute el código relacionado con la confirmación por correo electrónico.

Aunque no podemos adjuntar el comportamiento a las estructuras, es posible agregar funciones al mismo módulo que define la estructura:

defmodule User do
  defstruct [:name, :email]
  
  def confirm(user) do
  	# Confirm the user email
  end
end

Incluso con la definición anterior, es imposible en Elixir confirmar un usuario dado llamando a user.confirm(). En su lugar, se requiere el prefijo de usuario y la estructura de usuario se debe dar explícitamente como argumento, como en User.confirm(user). Al final del día, no hay acoplamiento estructural entre la estructura de user y las funciones en el módulo User. Por lo tanto, Elixir no tiene métodos, tiene funciones.

Sin tener objetos, Ecto ciertamente no puede ser un ORM. Sin embargo, si dejamos ir la letra “O” por un segundo, ¿puede Ecto seguir siendo un mapeador relacional?

Loading...
Iván Jaimes

Iván Jaimes Padre, esposo y desarrollador de software. Programa en go y elixir (por gusto), js (por necesidad) y shell (por diversión).