Hola Soy Valery Laptev, Jefe de Desarrollo de LM en Rusia. Durante dos años tuve que crear un departamento enorme, y fue una experiencia bastante interesante.
El hecho es que Leroy Merlin está en muchos países. La empresa matriz en Francia se llama ADEO. Escriben código para Francia, Italia, España y Rusia. Nuestros modelos de negocio son diferentes: si mantenemos los precios más bajos en el mercado ruso (por debajo de todos los competidores en monitoreo), en Europa todo es diferente. De hecho, el mar es diferente, desde las características del lugar hasta otra legislación. Hay características de la infraestructura de Rusia (las mismas demoras muy grandes para Khabarovsk) y otro ciclo de vida para realizar un pedido. Todo esto da lugar a un código tan infernal que consiste en enormes bloques IF:

Hace dos años, teníamos 60 tiendas y muchas, muchas funciones de lista de deseos. Rodaron en unos seis meses y no siempre correctamente. La gota que colmó el vaso después de un montón de características rechazadas por baja prioridad fue una solicitud para ingresar un campo de fila en el orden, de modo que lo analizáramos más tarde. Esto era necesario para las características de entrega en Rusia, ya que el país es más grande que otros países de presencia de LM. Nos rechazaron esto, o más bien, dijeron que sería en algún lugar en siete u ocho meses.
El ciclo de medio año de la empresa matriz pausada no nos convenía. Naturalmente, sugerimos escribir nuestro propio código, enviarlo a la revisión y esperar la implementación ... Es cierto, nada bueno salió de esto.
¿Por qué las características se implementaron lentamente?
La historia es muy simple: a pesar de nuestras docenas de tiendas, no somos los primeros en el mundo. Hay necesidades de Francia (donde está la organización matriz), hay necesidades de otros países. Se priorizan según la posible reducción de beneficios o costos para un grupo de empresas y se ejecutan en este orden. Es decir, nuestras funciones se hacen casi nunca, a menos que sean muy afortunadas y en algún tipo de sprint alguien termine su parte antes y vaya a desmontar la parte inferior del trabajo atrasado.
La segunda característica es que cuando coloca cualquier característica en la rama maestra (aquí en este código IF-IF-IF heredado), debe verificar cómo se comporta en otros países. Déjame citar
441869 de Bash:
Programador: Bueno, imagina que eres escritor y apoyas el proyecto "Guerra y paz". Tienes conocimientos tradicionales: escribe un capítulo sobre cómo Natasha Rostova caminó por el parque bajo la lluvia. Usted escribe: "estaba lloviendo", guarde, el mensaje de error sale volando: "Natasha Rostova ha muerto, la continuación es imposible". ¿Por qué está muerta? Empiezas a entender. Resulta que los zapatos resbaladizos de Pierre Bezukhov cayeron, su arma cayó al suelo y disparó contra un poste, y la bala del pilar rebotó en Natasha. Que hacer ¿Cargar la pistola inactiva? ¿Cambiar zapatos? Decidimos quitar el pilar. Recibimos el mensaje: "El teniente Rzhevsky ha muerto". Resulta que en el próximo capítulo se apoya en un pilar que ya no está ...
En general, cuando presentamos algo para la taquilla rusa, en algún lugar de Brasil, alguien puede recuperarse.
Esto significa una cobertura de prueba muy grande, largos procedimientos previos al lanzamiento y, en general, renuencia a mantener el código que está creciendo rápidamente. Por lo tanto, cuantas menos características, mejor. Pero aguanta ahí.
La posición en su conjunto es muy comprensible, y yo haría exactamente eso en el sitio de la empresa matriz. Porque es racional.
Resolución de problemas
El primer enfoque fue en la frente: sugerimos abrir un código para que hagamos solicitudes de extracción allí. Se suponía que habría unos 10 desarrolladores sentados allí que codificarían rápida y rápidamente las funciones críticas del negocio, se las darían a los franceses y las probarían de acuerdo con su propio procedimiento, y todo estaría bien.
En realidad, estas personas ya lo estaban: nos comprometimos a eliminar la lógica comercial adicional que obtuvimos de otros países, como varios descuentos acumulativos y acciones inusuales (que son simplemente imposibles con nuestro modelo de negocios), y pusimos dummies en este lugar.
Los franceses en ADEO querían un ciclo de lanzamiento para lanzar e instalar nuevas versiones a través de ellos mismos. Aceptó nuestra oferta sobre una rama para experimentos.
Dio acceso, comenzó a tomar el código para la revisión. Resultó ser lento de todos modos. Lanzamientos durante varios meses: este no es el caso. Bien ganó unas pocas semanas, pero aún así el proceso no encajó.
Luego, durante seis meses, no apareció una característica importante para nosotros en la parte del contenido (administrar los datos del producto que el cliente ve). Nos sentamos durante seis meses sin una liberación. O su función no funcionó, o las pruebas no pasaron, entonces no se dieron cuenta exactamente de lo que necesitábamos. Como resultado, nos sentamos en un sistema clave durante mucho tiempo sin actualizaciones. Había NodeJS + PostgreSQL + Couchbase + Elasticsearch + Angular en el frente. En el código, debido a una serie de capas arqueológicas, se han encontrado cosas como el mal uso de la base de datos SQL y la base de datos no relacional. En uno de los lugares, se tomó una gran cantidad de datos maestros, se insertó en un campo de la base de datos SQL y luego se dividió en entidades en la base de datos NoSQL. En una página del sitio con la exhibición de productos había decenas y cientos de tales solicitudes. Con más lecturas de este legado, el cabello en diferentes partes del cuerpo comenzó a moverse. Entendimos a qué peculiaridades del legado de capas se enfrenta la sección de la cabeza.
Desarrollo propio
La primera idea fue hacer funciones juntas. En el acto, es decir, en Francia. Los cuatro fuimos a Francia y comenzamos a sentarnos junto a nuestros colegas para comprender todo juntos y hacer lo que necesitábamos.
No funcionó. De todos modos, todo fue muy lento.
La segunda idea era bifurcar todo lo que ya existe y gradualmente terminarlo. Nos sentamos junto al comité de arquitectura, evaluamos las perspectivas, calculamos los planes de desarrollo aproximados y nos dimos cuenta de que debíamos elegir un método diferente. Específicamente, sí, para bifurcar, pero no para desarrollar el código existente, sino para dividir el monolito en partes y poner microservicios donde sea necesario.
Es decir, planeamos reescribir bloques completos de lógica en forma de nuestro código. Y para esto comenzaron a cambiar parte de los servicios a lo que podría hacerse con nosotros. Comenzamos a reclutar desarrolladores. Luego seguimos completamente la pila de la empresa matriz: Java, Spring y todo está cerca, en lugar de Couchbase era Mongo (esta es una base NoSQL similar).
A medida que se desarrolló el proyecto, nos dimos cuenta de que necesitábamos hacer muchas cosas a nuestra manera (porque es más rápido y fácil para no soportar el legado que no necesitamos, en particular), y comenzamos a expandirnos a otras tecnologías. Luego estaban Java 7, Wildfly (anteriormente JBoss) y SVN. Preguntamos por qué no están migrando a Java 8, GIT y Tomcat. Resultó que no les importaría, pero después de un par de años. Mientras tanto, queridos, escriban en la pila anterior. Así que palabra por palabra y decidimos separarnos por completo. El negocio resolvió la pregunta, cuáles son los pros y los contras, y la apoyó por completo.
Casi de inmediato arrojó alrededor del 30 por ciento del código, escribió muchos de sus microservicios. Por el hecho de que no se tocaron, es casi todo el núcleo de la transacción de los procesos comerciales por dinero.
Naturalmente, lo primero que pensamos fue cómo distinguir entre áreas de desarrollo. También hablaría de esto por separado, pero en términos generales, el esquema es el siguiente:

Horizontal es un área de negocios. Por ejemplo, todo lo relacionado con las relaciones con los clientes (la primera celda verde) es un área y hay un conjunto de aplicaciones de un departamento. Esta separación de la función objetivo crea varios duplicados del código en diferentes lugares y requiere un buen bus corporativo (una vez más, una historia separada), pero le permite encontrar claramente los extremos y resolver el problema hasta el resultado. Mirando esto después de casi tres años, puedo decir que la arquitectura fue elegida correctamente, pero si supiera lo que sé ahora, haría un par de cambios.
Ahora hemos llegado a la conclusión de que en la estructura general hay muchos equipos de características que conforman grandes equipos de productos. Al mismo tiempo, el equipo del producto incluye no solo a los propios desarrolladores, sino también a diseñadores y representantes comerciales. Dado que el objetivo final de cualquier departamento de TI de una empresa es aumentar la velocidad del desarrollo comercial o reducir los costos debido a la automatización, necesitamos representantes comerciales dentro de estos equipos. El comercio minorista se trata de TI. No hay un solo proceso que pueda llamarse "inaccesible".
Un equipo de características es un pequeño grupo de personas (generalmente un analista, probador, desarrollador de back-end y desarrollador de front-end, ops). El analista generalmente desempeña el papel del propietario del producto o una persona del negocio llega a este lugar. El propietario tiene una acumulación, prioridad, tareas. Él dicta su desarrollo. El desarrollador elige la opción de implementación por sí mismo, discutiendo en el equipo qué se hará y cómo. No tenemos un líder de equipo para la evaluación de tareas, la codificación y la toma de decisiones. Todos hacen de todo. Por lo general, los miembros del equipo más experimentados dan opiniones en las que muchos están dispuestos a confiar. Pero cualquiera puede tomar una decisión. Por supuesto, hay conflictos cuando dos desarrolladores no pueden ponerse de acuerdo sobre la implementación de una función. Si el conflicto se convirtió en personalidad, necesita una escalada en la cabeza. Pero la mayor parte es la elección de una solución para la implementación. Luego, todos se paran y se acercan al tablero hasta que encuentran una opción que se adapte a todos. Por lo general, resulta rápido, pero hubo casos en que discutieron todo el día. Cuando el argumento se detiene, a menudo se llama al árbitro: una persona de otro equipo cuya opinión todos confían. Explican la esencia del problema, resuelve. Incluso un junio o un aprendiz pueden participar en teoría en esta disputa, pero solo conozco un par de estos casos, por lo general, los joons tienen un mentor al que escuchan.
Un ejemplo de un equipo destacado: tenemos una plataforma de servicio que le permite comprar un servicio con un contratista junto con productos. Por ejemplo, compré una puerta: puede colocarla inmediatamente en la canasta y la instalación, de modo que un maestro independiente venga y lo haga de acuerdo con nuestro estándar. Comprobaremos y pagaremos, daremos una garantía. Entonces, este equipo crea un producto, para esto escribe soluciones de TI y toma decisiones comerciales, cambia los procesos en las tiendas. De acuerdo con los contratistas. Allí: el propietario del producto de la empresa, el empleado de las tiendas, el arquitecto, los desarrolladores, los analistas y el probador. Inmediatamente usan nuestra plataforma API corporativa para entregar todos los datos de un lado a otro y escribir un microservicio. Tal enfoque, gente operativa y comercial inmediata junto con desarrolladores y un pequeño equipo, le permite crear rápidamente un producto. Pero, creo, es mejor que ellos mismos te cuenten cómo se ve desde adentro.
Inicialmente, no queríamos hacer probadores por separado: había una tendencia de que el desarrollador debía seguir la metodología TDD o probar su código hasta el final él mismo. De hecho, no fue muy efectivo. Al principio todo salió bien: escribió: usted responde. Necesita pruebas para que su aplicación funcione correctamente. Pero luego, mientras más tareas y aplicaciones se volvían, más difícil era. Algunas aplicaciones se extinguieron, algunas fueron al producto y no cambiaron durante meses. Se hizo difícil escribir pruebas, mantenerlas, etc. Los analistas del equipo han cambiado. Hace relativamente poco, acordaron que estaban equivocados: se necesitan evaluadores. Pero los desarrolladores no dejan de escribir pruebas y, a veces, de hacer TDD. Nos dimos cuenta de que las pruebas que verifican la funcionalidad (la aplicación funciona correctamente) y las pruebas que verifican que la aplicación funciona en situaciones problemáticas deben ser realizadas por diferentes personas. Y para el segundo, se necesitan probadores, porque cubren posibles casos extraños no solo con pruebas unitarias.
Ahora hay 60 desarrolladores puros: back, front, full stacks. También hay analistas, probadores y soporte. Y además de otros siete devops más. Pero aún así, no se reclutan 200 personas planificadas del título, por lo que ahora estamos buscando nuevas personas, porque el campo de trabajo es enorme. Hay vacantes en
mi círculo , si eso. Es decir, desde el desarrollo ahora tenemos 74 de aproximadamente 200.
InnerSource
Dado que tenemos muchos equipos independientes solo en Rusia, y todavía hay equipos que vieron algo similar en muchos otros países, nos estamos moviendo en la dirección de la
fuente . Esto es muy similar al código abierto dentro de un grupo limitado de personas.
Dentro del grupo ADEO de todas las divisiones de países, todo el código se encuentra en el github de la nube. El proyecto se elabora de acuerdo con reglas de diseño uniformes. No hay restricciones de estilo, tecnología y herramientas. Cuando tiene código fuente abierto y reglas de diseño claras, cualquier desarrollador en la pila puede contribuir. Para copiarlo en el código, debe leer el dock, clonar el repositorio, hacer una edición, enviar una solicitud de extracción.
Actualmente, Brasil, Rusia y Francia utilizan muy activamente esta base común.
Ahora estamos tratando de transferir todo el código de contratistas (y tenemos muchos de ellos en diferentes direcciones) a InnerSource. En el análisis, creamos un mapa en dos ejes: la complejidad técnica de la transferencia al modo del círculo interno en un eje y el segundo eje, cuánto es generalmente útil la transferencia al círculo interno. Si el código es único y se necesita solo en un lugar, quizás ni siquiera tenga que tocarlo. Pero si muchos equipos usan este sitio, definitivamente es necesario.
Todo esto generalmente mejora la cultura del desarrollo. Y acelera la velocidad de varios equipos, porque puede escribir una solicitud de fusión para cualquier función que necesite. Será apropiado por el equipo propietario y probado por el contribuyente. Una de las condiciones importantes es la disponibilidad de pruebas automáticas y descripciones de cualquier código en el repositorio.
Algunos matices más
Cuando comenzaron, no había nada en absoluto. En paralelo con los desarrolladores, reclutaron devops. Ahora los servicios de devobs se proporcionan como un servicio (para aquellos que lo necesitan) o el equipo del producto tiene sus propias operaciones, que ya determinan qué y cómo.
El ensamblaje se realiza en Jenkins, el código se ejecuta en Sonar (más precisamente, ya SonarQube). Fallo de sonda: no hay lanzamiento. Los probadores escriben pruebas automáticas, propietarios de códigos, pruebas funcionales. La base de datos es dada como un servicio por ingenieros de infraestructura. La prueba de carga completa se realiza en casos raros, ya que la estructura de la base de prueba y la principal son diferentes: en el preprod, tenemos datos caóticos y no datos reales anónimos (este es uno de los pasos en el futuro), por lo que debe rodarlo suavemente y no todos a la vez.
Pronto deberíamos ir a Kubernetes (y algunos de los nuevos productos como el
mercado ya
están allí inicialmente), tan pronto como descubramos el plan de transición y acordamos todos los detalles de la infraestructura.
Mis colegas y yo continuaremos hablando sobre cómo se organiza la parte del trabajo, porque en casi todas partes puedes continuar infinitamente. Bueno, puedes seguir nuestro reality show (porque todo se está construyendo y cambiando rápidamente) y apostar si lo arruinamos o no.