Desarrollo de aplicaciones web
Desarrollo de aplicaciones Laravel
Aplicaciones Laravel nuevas construidas para sobrevivir a su propio éxito - un esquema diseñado antes de que lleguen los datos, colas que nadie vigila, y un segundo año más barato que el primero.
Laravel hace fáciles los tres primeros meses, y ese es el problema. El framework le dejará entregar de buen grado una aplicación cuyo esquema se inventó una migración cada vez, cuyos trabajos suponen que solo se ejecutarán una vez, y cuya consulta más lenta es rápida porque la tabla tiene cuatrocientas filas.
Nada de eso se ve en el lanzamiento. Todo eso se ve a escala, y para entonces los datos están en producción y los arreglos son caídas.
Qué construimos
Aplicaciones en las que lo difícil es el comportamiento: plataformas SaaS multiinquilino, marketplaces con dinero moviéndose dentro, sistemas internos que sustituyen una década de hojas de cálculo, y back offices sobre los que un negocio funciona de verdad.
Cuando un problema tiene forma propia tiene página propia: la base de datos cuando la dificultad es el modelo de datos, las colas cuando el trabajo ocurre fuera de la petición, y las APIs cuando tiene que consumirlo otro. Esta página es el trabajo que todas comparten.
El esquema se decide antes que el código
La mayoría de las aplicaciones Laravel consiguen su base de datos por accidente. Se crea un modelo, le sigue una migración, se añade una relación cuando una pantalla la necesita, y dieciocho meses después hay cuatro columnas que guardan un estado y no hay dos que coincidan.
Lo diseñamos primero, sobre papel, y es la parte del encargo sobre la que tenemos más opinión:
- Restricciones en la base de datos, no solo en la aplicación. Una clave foránea que el esquema hace cumplir es un fallo que no puede llegar a producción. Una regla que solo vive en un form request es una regla que un trabajo en cola, un comando de artisan o un futuro desarrollador esquivarán sin saber que existía.
- Índices elegidos a partir de las consultas, no adivinados. Escritos cuando se escribe la consulta, mientras la razón sigue en la cabeza de alguien.
- Migraciones seguras sobre una tabla en producción. Añadir una columna es gratis; añadir una con valor por defecto, o un índice, es un bloqueo, y sobre una tabla con millones de filas un bloqueo es una caída con un despliegue enganchado.
- Dinero y tiempo guardados como es debido. Unidades menores enteras, moneda explícita, UTC, y una decisión sobre la presentación de zonas horarias escrita una vez en lugar de discutida por pantalla.
Eloquent, usado a propósito
Eloquent es productivo y esconde el coste de lo que hace, lo cual es un buen trato hasta el día en que deja de serlo.
Tratamos el número de consultas como una cifra de la que alguien es dueño. Las relaciones se cargan por adelantado porque el código lo dice, no porque una página pareciera lenta una vez. La carga perezosa se desactiva del todo en entornos que no son producción, de modo que un N+1 accidental es una prueba que falla y no un ticket de soporte. Los agregados que pertenecen al SQL se quedan en el SQL en lugar de traerse a memoria y contarse en PHP.
Nada de eso es exótico. Es la diferencia entre una aplicación que se degrada con elegancia y otra que se cae el día en que el marketing funcionó.
El trabajo que ocurre fuera de la petición
Todo lo lento, todo lo de terceros y todo lo que puede fallar pertenece a un trabajo y no a un controlador. Eso es fácil de decir y tiene consecuencias que conviene diseñar en lugar de descubrir:
Los trabajos se escriben para ser seguros de ejecutar dos veces, porque en algún momento todos lo serán. Un reintento no es un modo de fallo, es el caso normal, y un trabajo que cobra una tarjeta o envía un correo tiene que saberlo. Los fallos aterrizan donde un humano pueda verlos. El trabajo largo se trocea para que un despliegue no lo mate a mitad.
Pruebas, en la cantidad que se paga sola
Pruebas de funcionalidad sobre las rutas que importan, pruebas unitarias donde la lógica es de verdad intrincada, y una factory por modelo para que escribir la siguiente prueba salga barato. No cobertura del cien por cien, que compra lo equivocado a un precio alto.
La medida que usamos es si la suite atraparía el cambio que rompe el negocio. Una prueba que afirma que un controlador devuelve 200 no atrapa casi nada; una prueba que afirma que un pedido no puede pagarse dos veces atrapa lo que le habría costado una devolución y una reputación.
La forma del trabajo
Cuatro fases. Cada una termina con algo funcionando en una URL y no con algo descrito en un informe de estado.
- Alcance y esquema. El dominio escrito, las tablas y las restricciones que las sostienen, cada sistema con el que esto tiene que hablar, y la lista de trabajos que van a existir. Todo lo posterior se presupuesta contra lo que salga de aquí, y por eso produce un documento y no una presentación.
- La columna vertebral. Migraciones, modelos, autenticación, autorización, la disposición de colas, la tubería de despliegue, y una suite de pruebas corriendo en CI desde el primer commit. Nada parece terminado. Todo lo de debajo lo está.
- Dominios, el de más valor primero. Escritos según las convenciones que fijó la fase dos, pasados por su proceso de revisión si tiene ingenieros, y publicados al cierre de cada iteración en lugar de apilados detrás de una fecha de lanzamiento.
- Endurecimiento y traspaso. Pruebas de carga donde las cifras importan, un manual para las llamadas que llegan a las tres de la madrugada, el esquema escrito, y una sesión por dominio con quienes van a hacerse cargo.
Todo ocurre donde su equipo ya trabaja: su repositorio, su gestor de tareas, sus revisiones. El código que se queda dentro de nuestras herramientas hasta el día del lanzamiento es código que su equipo ve por primera vez el día en que ya es tarde para discutirlo.
Qué mueve la cifra de verdad
El framework no. Lo que decide cuánto dura una construcción en Laravel es lo mismo que decide cuánto dura cualquier construcción, y que le digan cuáles de esas cosas le aplican es más útil que una tarifa diaria:
- Con cuántos sistemas tiene que hablar. Un proveedor de pagos es una semana. Un proveedor de pagos, un ERP, una API de envíos y un formato de fichero bancario documentado en un PDF de 2011 es otro proyecto.
- Si las reglas están escritas en alguna parte. Construir contra un proceso que solo existe en la cabeza de una persona es la forma más fiable de construir la misma pantalla tres veces.
- Si ya hay algo en producción. Los datos que existen hay que migrarlos, y migrar datos que nadie ha validado es donde mueren los calendarios.
- Cuánto de esto es generación de informes. Los informes parecen baratos y no lo son: ahí viven el trabajo de consultas, la aritmética de fechas y las conversaciones que empiezan con «pero finanzas lo cuenta de otra manera».
Cuándo este es el encargo equivocado
Si ya existe una aplicación y el problema es que se ha vuelto difícil de cambiar o va varias versiones por detrás, eso es actualizaciones y rescate, y empieza leyendo en lugar de escribiendo.
Si funciona pero se cae bajo carga, eso es rendimiento y escalado.
Y cuando de verdad no sabe cuál de las dos tiene delante, para eso está la auditoría: dos semanas, precio cerrado, y bastante más barata que comprometer un trimestre al encargo equivocado.
Qué recibe
La aplicación y los cuatro documentos que hacen que otra gente pueda operarla: el esquema con el razonamiento de cada decisión que no era obvia, la topología de colas y qué puede hacer cada worker, el runbook de despliegue y la suite de pruebas con una nota sobre lo que deliberadamente no cubre.
Los pull requests son revisables y llegan de forma continua, así que lee el trabajo mientras ocurre en lugar de recibirlo al final. Si su equipo va a hacerse cargo, conviene que lo revise antes de ese día y no después.
