Ir al contenido

Migración de plataforma

Migración de PHP heredado a Laravel

CodeIgniter, Zend, Symfony 2 o ningún framework - movidos a Laravel de forma incremental, detrás de un router que manda cada ruta al sistema que hoy es su dueño.

Una aplicación escrita en CodeIgniter en 2014, o en Zend, o en Symfony 2, o sin framework ninguno: sigue funcionando, sigue ganando dinero, y ahora es cara de una manera concreta. Nadie la toca, la gente que la escribió se fue, y la versión de PHP que necesita está fuera de soporte.

La propuesta que suele llegar es una reescritura. Tiene la forma equivocada para este problema y es como fracasan estos proyectos.

Por qué la reescritura es el riesgo

Reescribir significa construir un segundo sistema al lado del primero y cambiar cuando esté listo. De ahí se siguen tres cosas, y las tres son predecibles.

El negocio deja de recibir cambios durante todo ese tiempo, porque cada hora dedicada al sistema antiguo se tira. La línea de meta se mueve, porque los requisitos nunca se escribieron y se van redescubriendo desde el código según se tropieza con ellos. Y el cambio es un único día en el que todas las reglas que nadie recordaba se prueban en producción a la vez.

Las reglas son el problema. Un sistema que lleva una década funcionando codifica decisiones que no existen en ningún otro sitio: por qué ese grupo de clientes está exento, por qué la exportación corre a las 03:40, por qué se ignora un campo de precio. Una reescritura las encuentra a razón de una queja cada vez.

Mover ruta por ruta en su lugar

Ponga un router delante de los dos sistemas. Manda cada petición a la aplicación que ahora mismo es dueña de esa ruta: Laravel para lo que se ha movido, la aplicación heredada para todo lo demás.

location /account/ { proxy_pass http://laravel; }
location /         { proxy_pass http://legacy; }

Ahora una migración es una secuencia de despliegues pequeños en lugar de uno grande. Cada ruta que se mueve está viva la misma semana en que se escribe, cada una se puede devolver revirtiendo una línea, y el negocio sigue entregando todo el tiempo.

Lo que hace que funcione en la práctica es el orden:

  1. Primero el inventario. Cada ruta, cada tarea programada, cada integración, y qué toca cada una. Construido desde el código y la base de datos, no desde lo que alguien recuerda.
  2. Sesiones y autenticación compartidas. Los dos sistemas tienen que estar de acuerdo sobre quién ha iniciado sesión desde el primer día, o un usuario que cruce la frontera se queda fuera. Normalmente un almacén de sesiones compartido y un sistema dueño del login.
  3. La base de datos se queda. Las dos aplicaciones leen las mismas tablas. El esquema se mejora después, por su cuenta, para que una regresión sea atribuible a un cambio y no a dos.
  4. Primero las rutas hoja. Algo autocontenido y de poco tráfico, para demostrar el enrutado, el despliegue y la vuelta atrás antes de que algo importante dependa de ellos.
  5. Después por valor. Las rutas que más se cambian, porque ahí es donde se está pagando de verdad el coste del sistema antiguo.
  6. El trabajo programado y las integraciones al final. No tienen usuarios mirando y son las que más estado oculto guardan.

Las partes que son genuinamente difíciles

Las sesiones. Dos frameworks, dos formatos de sesión. O un sistema lee el formato del otro, o los dos se mudan a un almacén compartido con una serialización común. Esto se decide antes de mover la primera ruta, no lo descubre un cliente al que han echado la sesión.

Los hashes de contraseña antiguos. No puede convertir lo que no puede leer. Laravel verifica contra el algoritmo antiguo en el login y vuelve a hashear al tener éxito, de modo que la base de datos se convierte sola según la gente entra, en lugar de mediante un correo de restablecimiento enviado a todos a la vez.

Tablas que dio forma el ORM del sistema antiguo. Claves compuestas, sin marcas de tiempo, una clave primaria con otro nombre, un booleano guardado como 'Y'. Los modelos de Eloquent se configuran a esas tablas en lugar de cambiar las tablas para que le encajen a Eloquent; eso viene después, si es que viene.

Dos bases de código escribiendo las mismas filas. La regla es que un solo sistema es dueño de cada camino de escritura en cada momento. Que los dos escriban la misma tabla es de donde sale la corrupción de datos en estos proyectos.

Lo que no hacemos

No movemos todo. Algunos de estos proyectos terminan con una pequeña aplicación heredada sirviendo todavía un puñado de rutas que nadie necesita cambiar, y eso es un final legítimo: el objetivo era detener el coste, no llegar a un número.

No mejoramos el comportamiento mientras lo movemos. Una ruta se mueve para hacer exactamente lo que hacía, fallos incluidos, y se mejora en un commit aparte después. Cambiar comportamiento y ubicación a la vez significa que una regresión tiene dos causas posibles y ninguna forma barata de distinguirlas.

Cómo transcurre un encargo

Lo primero que necesitamos es la tabla de rutas de lo que hay ahora, y una respuesta honesta sobre qué partes ya no entiende nadie.

De ahí sale un inventario de rutas y un alcance por fases con un precio para cada una. Dice qué rutas se mueven primero, qué sigue funcionando al lado durante el movimiento, y qué partes le recomendamos no migrar en absoluto. Ese documento es a lo que se engancha el contrato.

Después las fases. Las dos aplicaciones corren juntas hasta que se mueve la última ruta, y cada fase termina con algo en producción.

Qué recibe

Una capa de enrutado con un mapa explícito de qué sistema es dueño de qué, el inventario del que salió ese mapa, las rutas movidas con las pruebas escritas al moverlas, y una secuencia para el resto con el razonamiento adjunto.

Si la aplicación ya es Laravel y solo está varias versiones por detrás, este no es el trabajo que necesita: actualizaciones y rescate lo es, y es un encargo más pequeño.

Alcance y condiciones

Modelo de colaboración
Alcance cerrado, acordado por escrito antes de empezar. No es una tarifa por día contra una lista abierta.
Precio y plazo
Los dos se fijan por proyecto, una vez fijado el alcance. Se ofertan juntos, antes de construir nada.
Qué necesitamos de usted
Una persona que pueda aprobar decisiones, y acceso a su repositorio y a su gestor de incidencias.
No incluido
Todo lo que quede fuera del alcance acordado. Pasa a ser su propio alcance, no una modificación.
Costes de terceros
El alojamiento, las licencias, las tarifas de API y las suscripciones SaaS los contrata y paga usted.
Facturación
Codefacture Yazılım A.Ş., Türkiye. EUR, USD o GBP por transferencia, sin IVA turco en servicios exportados.

Preguntas frecuentes

¿Esto es distinto de una reescritura?
Sí, y la diferencia es lo que lo hace sobrevivible. Una reescritura construye un reemplazo al lado del original y cambia cuando está terminado, lo que significa un periodo largo sin entregas y un día de lanzamiento que descubre todas las reglas no documentadas a la vez. Esto mueve una ruta cada vez, en producción, con los dos sistemas funcionando.
¿Cuánto tiempo conviven los dos sistemas?
Meses, normalmente, y eso es el diseño y no un fracaso del diseño. El sistema antiguo sigue sirviendo lo que aún no se ha movido, así que nunca hay un punto en el que el negocio espere a que termine la migración para poder entregar otra cosa.
¿Qué pasa con la base de datos?
Se queda donde está, al principio. Los dos sistemas leen las mismas tablas, y eso es lo que permite mover una ruta sin mover datos. Las mejoras de esquema vienen después de que el código se haya movido, no durante - cambiar las dos cosas a la vez le quita la capacidad de saber qué cambio rompió algo.
Nuestra aplicación no tiene pruebas ni documentación.
Esa es la condición normal de un sistema lo bastante viejo como para necesitar esto. La primera fase registra lo que hace hoy, a partir de las rutas y de la base de datos y no de la memoria de nadie, y de ese inventario sale la secuencia.
Llamar+1 848 272 7583WhatsApp+90 850 308 5436Correoinfo@codefacture.comPágina de contacto