¿Laravel o no Laravel?

TL;DR

Laravel es un framework full-stack en PHP muy bueno para desarrollar sistemas web de manera muy rápida tanto por lo simple del lenguaje PHP como por los «atajos» que Laravel le provee al programador.

No tengo ninguna duda de que utilizar Laravel/PHP es una buena decisión para ejecutar un proyecto web de manera rápida y con una baja exigencia de conocimientos por parte del desarrollador.

Sin embargo, si el objetivo es desarrollar una colección de aplicaciones con intención de reutilizar un modelo del domino, tener una operación de bajo costo, y desarrollar  funcionalidades que van más allá de casos de uso de gestión de información (CRUDs), entonces Laravel/PHP no es la mejor opción.

Introducción

Estamos pronto por llegar al 25% del siglo XXI y los requerimientos para una herramienta para desarrollo de software han cambiado mucho en los últimos años. Es por esto sensato preguntarse si la herramienta que funcionaba muy bien para desarrollar aplicaciones hace cinco (5) años, lo sigue haciendo hoy.

Este artículo describe las razones más importantes por las cuales descarto la opción de Laravel como herramienta para el desarrollo de aplicaciones.

Es importante aclarar que el contexto bajo el cual se «evalúan» los puntos que compartiré a continuación es que se busca identificar la herramienta con la cual desarrollar un conjunto de productos SAAS cumpliendo las siguientes premisas:

  • Desarrollo rápido
  • Multicanal «mobile-app first»
  • Reutilización de activos (código, componentes, servicios, etc.)
  • Bajo costo de operación (ideal auto mantenible, serverless)
  • Simple, sin requerimiento de gran experiencia «echando código».

Si bien todas estas premisas se derivan de las necesidades puntuales de la empresa para la que trabajo, sin duda alguna son representativas de las necesidades de cualquier organización que desee seleccionar su herramienta de desarrollo para sus próximos proyectos.

Hallazgos

Luego de ver detenidamente el tutorial publicado en Laracast en forma de 66 mini-videos de aproximadamente 5-6 min c/u (https://laracasts.com/series/laravel-6-from-scratch), y de revisar en la documentación de Laravel, logré identificar los siguientes elementos que no me gustaron de Laravel.

Es importante resaltar que no probé de manera práctica lo que el tutorial de Laracast y el manual  indicaron, lo asumí como hecho por ser documentación oficial. Tampoco consideré información publicada en portales de soporte comunitario como Stackexchange.

A. Impide el re-uso de un modelo del dominio

Premisa:  Las entidades de negocio en Laravel se declaran a través de dos artefactos: una clase que hereda de la clase «Model», la cual contiene los métodos de la Entidad tanto aquellos relacionados con el CRUD de la Entidad, como los relacionados con cualquier lógica de negocio que aplique; el otro artefacto es un archivo de «migración» de datos el cual expresa las expresiones de creación de la entidad en el RDBMS. Es decir, la declaración de los atributos no ocurre de manera explícita en Laravel, sino exclusivamente en la RDBMS.

Corolario: El «Modelo» que representa una Entidad de Negocio en de hecho un DAO (Data Access Object) y no un BO (Business Object).

UML-clases-1024x493-2

Implicaciones:

  1. Al ser PHP un lenguaje que no soporta múltiples-herencias (lo cual es MUY BUENO para PHP), y Laravel obligar que las clases que representan Entidades hereden de «Model», entonces no es posible reutilizar Clases que pertenezcan a un modelo de clases simple (modelos OO simples siempre incluyen herencias).
  2. Asumamos entonces por un momento que el «modelo del dominio» sea una colección de conceptos atómicos sin herencia (no me imagino que eso sea posible), lo cual pudiese ser reutilizado en una aplicación Laravel; en este caso el hecho de el DAO y el BO son el mismo artefacto, entonces el artefacto que documenta la creación de la base de datos (en Laravel llamado «migrations») DEBE formar parte del modelo del dominio asociado de alguna forma al artefacto BO en el repositorio de gestión de código fuente que sea utilizado. La sincronización de ambas estructuras dentro del repositorio no ocurre de manera automática, por lo que es reponsabilidad del programado garantizar la sincronización de las versiones correspondientes de ambos instrumentos dentro del repo.
  3. Adicionalmente, de manera de poder ser utilizado un BO (aunque atómico sin herencia alguna), el script de DDE (Migrations) almacenado de manera conjunta en el Repo debe expresarse siempre desde la premisa de que la tabla relacional no existe y debe construirse en tu totalidad desde el Drop Table.
  4. Como consecuencia de lo anterior, cada vez que se realice un cambio en el dataschema, el pase a producción de la nueva versión debe implicar la recreación completa de la base de datos (con drop-table de todas las tablas) y luego de que se creen las nuevas tablas, se debe aplicar un mecanismo de migración de datos de la versión anterior a la nueva, lo cual está fuera del alcance de Laravel.

Ergo

  1. Como no es práctico reutilizar el modelo de dominio (independientemente de su utilidad dada la restricción de no-herencia), entonces no se reutiliza.

Conclusión

Laravel no permite el reuso de un modelo de dominio.

Dudas remanentes

  • ¿Obliga el uso de RDBMS exclusivamente?

B. Complica y encarece la operación

Premisa: De manera natural, el uso de los «migrations» tiene una advertencia que alerta que si no es ejecutado con cuidado, es posible la pérdida de datos. Incluso es explícitamente indicado en el tutorial al que hago referencia al inicio de este documento.

Corolario: Esto significa que cada vez que se haga un cambio de versión, se debe realizar lo siguiente:

  1. En preparación para el Pase a producción:
    1. Crear un protocolo de prueba de consistencia de la data
    2. Generar un ambiente de QA con el clon de producción incluyendo el repositorio de datos con la data existente en ese momento.
    3. Realizar la migración en el ambiente de QA
    4. Aplicar el protocolo de prueba de consistencia de datos en QA (esto aparte del protocolo de pruebas funcionales)
  2. Para el Pase a producción:
    1. Freeze de la atención del servicio
    2. Backup del ambiente de producción
    3. Aplicación del protocolo de pruebas de consistencia de datos en producción
    4. Si las pruebas de consistencia son exitosas, levantar el Freeze de atención del servicio. FIN.
    5. Si las pruebas de consistencia NO son exitosas, se realiza el rollback tanto del repositorio de datos como del aplicativo.
    6. Se aplica el protocolo de pruebas funcionales y consistencia de Datos para asegurar que el restore del respaldo de datos y app fue exitoso.
    7. Se levantar el Freeze de atención del servicio, y se analiza qué ocurrió mal.

Todo esto es algo que definitivamente toma tiempo, de una persona, minuciosa, con criterios de calidad y que además de manejar los temas de pruebas, debe manejar temas de operación.

Conclusión

La gestión de pases a producción es riesgoso (puede fallar) y costoso (por la persona y recursos necesarios para evitar que impacte negativamente el ambiente productivo.

C. Arriesga la operación del ambiente productivo

Premisa: La creación del modelo físico ocurre directamente en la base de datos pero a través de un DDL propietario de Laravel el cual es utilizado por el programado. Este lenguaje simplifica el DDL Estándar de SQL (ISO/IEC 9075:2016) con sentencias que describen una a una cada sentencia DDL estándar, pero eliminando la necesidad (o capacidad) de declarar los atributos que caracterizan cada campo de la tabla.

Corolario: Este DDL propietario representa la abstracción del DAO (Eloquent) y siendo implementado apenas a través de una simplificación del DDL, el impacto en rendimiento y flexibilidad de la traducción del DDL propietario al DDL estándar genera un castigo importante en el desempeño del acceso a la base de datos cuya reacción ante carga puede crece con decaimiento exponencial (curva hiperbólica).

En palabras más simples, en la medida que el programador requiera ser más selectivo y requiera el uso de queries más exigentes en rendimiento, o agregaciones más complejas, mientras el DDL propietario se presenta como que todo funciona OK, la traducción del DDL propietario al estándar podría forzar al DBMS a cometer suicidio lentamente.

Conclusión

Si bien en lo personal no tengo problemas con que las bases de datos comentan suicidio (hey! de algo sirven las lecciones aprendidas de la experiencia de usar granjas de máquinas Windows… claro, más nos vale que en este caso el DBMS pueda trabajar en cluster, y que tengamos el presupuesto para disponer de ellas), hay que recordar que todo eso es la posible consecuencia de un DDL más «limpio», pero DDL al fin.

Si me dicen que me evita el DDL, bravo por Laravel! pero no es el caso; así que sugiero ampliamente evitar este riesgo. Además, nunca me ha gustado compensar ineficiencia del software con sobredosis de hardware.

Por cierto, quizás este análisis que acabo de hacer explica por qué Laravel está en la posición 335 de rendimiento en comparación con otros frameworks. Vean en la siguiente figura.

long
Fuente del benchmark: techempower.com

D. No permite crear recursos de plataforma de manera dinámica a tiempo de ejecución

Premisa: Para crear una cola, hay que configurarla en el archivo config/queue.php (junto con los conectores posibles que se puedan asociar a cada cola). En la documentación no sólo es inexistente un API para hacer esta gestión a tiempo de ejecución, sino que en todos los ejemplos y casos de uso utilizados para hablar de su capacidad hacen referencia de colas para atender canal de comunicación diferenciados por los conectores que habilitan el procesamiento automático de la cola, y cuando la documentación plantea múltiples colas, el ejemplo reiterativo de multiplicidad de colas es para manejo de prioridades para un mismo «conector», usando generalmente en los ejemplos tres (3) colas, una para prioridad ALTA, otra para MEDIA y una última para BAJA.

Corolario: Si una aplicación requiere crear colas, debe modificar directamente el archivo queue.php lo cual muy probablemente no se puede hacer, y si fuese posible, no es aconsejable por seguridad. Y en el caso de que si fuese posible Laravel al detectar el cambio debe crear la cola como una tarea de bootstrap (propio de las funciones de adecuación de containers como el de Laravel).

Nota: Laravel maneja aspectos transaccionales que protegen la acidez de las transacciones contra el RDBMS, pero esto es exclusivamente con la RDBMS. No aplica para las comunicaciones a través de servicios web.

Implicaciones:

  1. En este momento tengo que desarrollar una aplicación que conversa con cientos de clientes, conversando con cada cliente a tiempos, velocidades, momentos, y estados diferentes, por lo que requiere de manejar entre otros recursos, una cola de comunicación para el intercambio de mensajería con cada uno. Como las colas corresponden con sesiones omni-canales éstas aparecen y desaparecen dinámicamente en la medida que aparece un cliente, y hace time-out su sesión omnicanal.
  2. Más allá del caso puntual de conversaciones omni-canales indicado en el punto anterior, el uso de colas que Laravel no habilita es fundamental para hacer persistencia de las transacciones que representan el consumo y respuesta de los servicios REST expuestos y/o consumidos por la aplicación en ambientes con una mínima necesidad de persistencia transaccional. Y ojo! ni siquiera estoy hablando de implementar un CORE Bancario, basta con querer implementar un servicio que haga manejo de balances como por ejemplo, Uber, en cuyo caso al no tener garantía transaccional en la comunicación entre el servidor y los clientes (porque entre el servidor y la base de datos no hay este problema), el sistema se expone a inconsistencias que si bien pueden ser manejadas con una capa superior de Business Activity Monitoring (BAM), siempre dejará sabor amargo en la boca de los usuarios cada vez que sean testigos de una inconsistencia en su balance.

Conclusión

Laravel no permite que las aplicaciones hagan gestión de ciclo de vida de las colas a tiempo de ejecución. No permite la herramienta fundamental para la garantía transaccional en la conversación entre un servidor implementado en Laravel y clientes que conversen con él.

E. Sólo web

Premisa: Laravel genera boileplates sólo para la capa de presentación Web.

Conclusión

Asumiendo que todos los puntos anteriores fuesen despreciables, Laravel sólo ayudaría para generar la atención de los casos de uso vía Web. No apoya en la implementación de las aplicaciones móviles, que en las premisas de este documento se presenta como de mayor prioridad.

Conclusión final

Es evidente que para cumplir con la premisa, todos los hallazgos documentados en este artículo nos llevan a la conclusión de Laravel no es una herramienta adecuada para el trabajo.

Por último, dejando atrás el análisis pragmático, al hacer un análisis estructural de Laravel me atrevo a decir que la razón MEDULAR por lo cual se tiene como consecuencia todos estos «problemas» mencionados en este artículo, es que Laravel no separa la lógica de negocio de la lógica de datos, perdiendo la flexibilidad que la arquitectura básica a tres (3) capas provee.

3-tier-architecture-009

Alternativa

Ahora bien, no es justo para usted que lee este artículo, yo matar a Laravel sin presentar una alternativa viable.

En este momento no voy a realizar mi recomendación, al menos no de manera completa, pero sí voy a compartir la mitad de la solución, y dedicaré a otro post para compartir la otra mitad de la solución.

Sin hacer referencias a cuántas capas tiene la arquitectura ideal de una solución, desde el punto de vista del usuario, existen dos (2) macro-componentes. Uno es el «front-end» que está a la vista, y el otro es el «back-end» que no se ve, tal como se evidencia en la siguiente figura.

b6a68e15aa0bd12fe5c19526a0bfa5f9

Pues en este momento le simplifico la vida, y le recomiendo la framework para front-end que he seleccionado para mis desarrollo de aquí en adelante: Flutter (de Google).

Con éste único framework, y escribiendo un único código (sólo una vez), genera los objeto para atender de manera nativa en todas las pantallas que hoy en día se tienen que «atender», y de manera consistente.  De esta manera usted logra generar aplicaciones para el Web, dispositivos Móviles (Android y iOS) y Desktop de manera más productiva, que corren más rápido, y más hermosas… bueno, eso es lo que dice Google! (jajaja) en pocos meses les contaré si es verdad 🙂

Muchas gracias por su tiempo; espero le sea de ayuda. Cualquier pregunta o sugerencia, no duden en hacerla a través de los comentarios.

Deja un comentario