Matías Navarro Carter

Backend Web Developer @ Santiago, CL

3 Razones para evitar usar Laravel

No pocas veces he escuchado la frase “No importa, al final todos los frameworks son iguales” cuando he intentado convencer a otros desarrolladores de considerar las cualidades de un framework sobre otro. Tal respuesta es parte de una técnica ancestral: no hay mejor forma de aniquilar un debate que negar el hecho de que debería existir un debate en primer lugar. Si decimos que todo es igual, relativizamos el asunto en cuestión, y cortamos toda posibilidad de interacción. Es una falacia argumentativa tremenda, usada y abusada por muchos: “Todos las religiones son iguales”, “Todos los partidos políticos son iguales”, “Todos los puntos de vista son iguales”.

Esta falacia pasa desapercibida debido al hecho de que algo hay de verdad en ella. Lo que en verdad se quiere decir es que en realidad hay características que las cosas en cuestión comparten. Hay similitudes entre ellas. Esto es algo aceptable y razonable. Pero justamente, cuando el debate se trata de enfatizar las diferencias que, al final, hacen a tal o cual cosa superior a otra, la declaración de que no existen diferencias es algo que no podemos aceptar.

Es cierto, todos los frameworks HTTP, en alguna medida, poseen características similares. Esto es especialmente cierto de la funcionalidad que implementan. Abstracciones sobre HTTP, motores de plantillas, sesiones, abstracción sobre la base de datos, clientes HTTP, sistemas de cola, envío de correos, autenticación, etcétera. Pero, no es en términos de funcionalidad donde radican las diferencias entre uno y otro, sino, en la forma en como estas piezas están conectadas entre sí: su arquitectura.

La famosa historia de los tres cerditos debería habernos enseñado esta premisa: una casa hecha de ladrillo no es lo mismo que una casa hecha de paja. Los cerditos ingenuos pensaron que una casa de cualquier material sería suficiente. Al fin y al cabo, todas son casas y puedo encerrarme en ellas. De la misma forma, un framework sólido arquitectónicamente no es lo mismo que un framework de paja.

Esta es mi premisa: Laravel es un framework débil arquitectónicamente y por lo tanto, deberías evitar usarlo en un proyecto cuyo dominio es complejo. Y tengo tres razones fundamentales para afirmar esto que pasaré a exponer a continuación.

Sin embargo, antes de exponer cualquier cosa, debo dar lugar a una aclaración. Laravel es genial para prototipar aplicaciones de baja complejidad de una forma muy ágil. Tiene una curva de aprendizaje muy baja y todo puede hacerse de forma simple y directa. Estos son beneficios que los desarrolladores de Laravel conocen muy bien. Tampoco tiene significantes problemas relativos a performance, y en una época donde es tan fácil escalar horizontalmente, esta no es una razón para desechar una herramienta. Mi premisa no es “nunca uses Laravel”, sino “úsalo, pero en un contexto adecuado y sabiendo lo que ganas y pierdes”.

Habiendo dicho eso, presento mis razones:

Abuso de estado y comportamiento global

Una de las razones por las que Laravel es tan popular, es que es muy sencillo de usar. Y una de las razones por las cuales es muy sencillo de usar, es porque TODO puede accederse de manera global.

Por ejemplo, podría tener un modelo OrdenDeCompra y su constructor:

<?php

class OrdenDeCompra
{
    protected $idUsuario;

    public function __construct()
    {
        // Sacamos el id del usuario loggeado desde el sistema de
        // autenticación de Laravel
        $this->idUsuario = auth()->id();
    }
}

Esto tiene dos problemas: primero, estás acoplando tu lógica de negocio (dominio) a un método que solo está presente en un framework. Si fueras a poner esta clase fuera de Laravel para que funcione como una unidad, de manera aislada, no podría funcionar porque el método auth() no estaría definido. Como consecuencia de esto comienza nuestro segundo problema, y es que esta clase es extremadamente difícil de testear unitariamente (debido a que depende del boostraping de un framework internamente).

Esto puede tener consecuencias desastrozas para tu aplicación. Cuando el escribir tests se vuelve caro (complejo) entonces éstos terminan por nunca escribirse. Una aplicación sin testear es extremadamente débil ante cualquier cambio (es decir, introducirás bugs sin darte cuenta). Si a esto le sumas que llamadas a las funciones globales de Laravel como app() o auth() podrían estar modificando estado en otras clases, entonces no introducir bugs y tratar de encontrarlos se volerá una tarea demasiado titánica. Y cuando algo se vuelve difícil, nuevamente, los programadores optamos por tomar la ruta fácil y rápida en vez de invertir el tiempo necesario para corregirlo (que en el caso de Laravel es más estado global). En poco tiempo, este camino incrementará tanto la deuda técnica de tu aplicación, que hacer cualquier cambio se volverá imposible.

Covención sobre Configuración

Cuando un framework tiene muchos componentes que funcionan por defecto, significa que alguien ha tomado muchas desiciones por ti. Por ejemplo, alguien ha instalado las herramientas que juzga mejores para tal o cual cosa. Sin embargo, cuando un framework hace eso, debe proveer a sus usuarios la flexibilidad sufiente para personalizar ese proceso, de ser necesario.

A nadie le gusta estar llenando interminables archivos de configuración, y leer documentación relativa a qué es lo que hace cada cosa. Es un proceso que consume mucho tiempo. Entonces, frameworks como Laravel establecen una convención por ti, y toman muchas decisiones por ti. Por ejemplo, que el sistema de colas usará Redis, o que usaremos el sistema de archivos local, o que la persistencia será MySQL.

El problema con esto es que, como desarrollador, nunca aprendes cómo funciona una abstracción de sistema de archivos, o un motor de persistencia, o un sistema de colas. Vienen con el framework, y funciona prácticamente por arte de magia. El problema surge cuando éstos dejan de funcionar o de plano, necesitan ser reemplazados por otra tecnología.

Como nunca aprendiste cómo funcionan estos componentes, y en qué consisten, realizar una implementación personalizada del mismo es imposible para ti. Te has convertido en un mero usuario de un framework, pero no un programador.

Una vez que aprendes como conectar diversos componentes (incluso de librerías totalmente distintas) y hacerlos trabajar juntos para lograr algo hermoso, felicidades: ya no eres un usuario de frameworks, sino un programador.

Filosofía

La filosofía detrás de Laravel es hacer las cosas fáciles y simples para el programador. Esto es un objetivo encomiable, sin embargo, da una idea errónea al programador de que la programación debería ser fácil, cuando en realidad no lo es.

Modelar un dominio y hacer software personalizado no es tarea para nada sencilla. Requiere comunicación, testeo, buenas prácticas y un montón de habilidades que van más allá de lograr realizar un CRUD. Esto es cierto especialmente de dominios complejos. Si vas a hacer un blog, ¡usa Laravel! ¿Para qué complicarte la vida? Pero si estás desarrollando un sistema de shipping internacional, con reglas de enrutamiento personalizadas y con un tracking de itinerario, creo que modelar el dominio y testearlo apropiadamente es fundamental para el éxito de tu aplicación. Y debes tomarte tu tiempo para eso.

Conclusión

En resumen, un framework es una herramienta: su pertinencia dependerá mucho de para qué se quiere usar. Si necesitas clavar un clavo, no usarás un destornillador, sino un martillo. Si necesitas construir una casa, usarás maquinaria pesada.

Laravel es genial para aplicaciones que no planean cambiar mucho en el tiempo. Pero no es el caso para aplicaciones cuyos dominios son complejos: éstos siempre están cambiando y necesitan de la mayor flexibilidad posible, además de la posibilidad de ser testeados unitariamente sin mucha complejidad.

<< Older