Muchos programadores han escuchado que a veces el código debe asignarse a bibliotecas separadas para su posterior reutilización. Sin embargo, la pregunta de qué tipo de código debe destacarse como entidad separada confunde a muchos desarrolladores. Al leer artículos / conversaciones sobre este tema, generalmente se recuerda el problema de la generalización prematura.
Los programadores experimentados generalmente tienen sus propias reglas, según las cuales entienden si el código debe distinguirse como reutilizable. Por ejemplo, si tal código (o muy similar) se usa en tres lugares o más. Sin embargo, todas las personas con las que he tenido ocasión de hablar sobre este tema están de acuerdo en que debe existir un código tan reutilizable, su creación es una bendición y vale la pena pasar su tiempo.
Quiero plantear el tema de la reutilización de código en el contexto de la creación de una arquitectura orientada a servicios y microservicios.
¿Qué es el código reutilizable?
El código reutilizable es un código aislado en una entidad separada, llamada de manera diferente en diferentes idiomas: biblioteca, paquete, dependencia, etc. Normalmente, dicho código se almacena en un repositorio separado, y hay documentación para conectar y usar este código (README.md). Además, el código puede estar cubierto por pruebas, puede haber instrucciones para realizar cambios (CONTRIBUTING.md) y se puede configurar CI. Varias insignias adjuntas a la descripción solo mejoran la representación visual de la madurez de una entidad determinada, y el número de estrellas asignadas indicará la popularidad de esta solución. No tiene que ir muy lejos para obtener ejemplos: solo abra la página de github de cualquiera de los marcos populares en su idioma favorito, por ejemplo
vue.js. En general, los métodos de diseño de alta calidad de las bibliotecas son un vagón y un pequeño carro.
Servicios y microservicios.
En este artículo, un servicio es una entidad completa que realiza un conjunto específico de tareas específicas en su dominio de responsabilidad y proporciona una interfaz para la interacción. El servicio o microservicio en este artículo desde un punto de vista arquitectónico pueden ser conceptos idénticos, la pregunta es solo a escala. Un servicio puede consistir en un conjunto de microservicios que implementan su sector de lógica de negocios, o ser un microservicio orgulloso.
La arquitectura orientada a servicios supone que cada servicio está mínimamente conectado con otros. Sin embargo, la interacción entre servicios no está excluida, sino que solo se supone que debe minimizarse. Para recibir solicitudes, un servicio generalmente implementa alguna API estandarizada. Puede ser cualquier cosa: REST, SOAP, JSONRPC o la nueva GraphQL.
Convencionalmente, los servicios se pueden dividir en infraestructura y supermercados. Los servicios de productos son aquellos que implementan la lógica de un producto cliente. Por ejemplo, trabajan con aplicaciones para su conexión, u organizan soporte para este producto durante todo el ciclo de vida de un cliente. Los servicios de infraestructura tratan más sobre la funcionalidad básica de una empresa (o proyecto), por ejemplo, un servicio que contiene información del cliente o un servicio que almacena información sobre ciertos pedidos. Además, los servicios de infraestructura incluyen servicios que implementan una funcionalidad auxiliar, por ejemplo, un servicio de información al cliente (envío de mensajes push o SMS) o un servicio para interactuar con los datos.
Una pequeña fantasía
Supongamos que hay una hipotética tienda en línea construida sobre una arquitectura orientada a servicios. Los desarrolladores de este milagro de ingeniería pudieron ponerse de acuerdo entre ellos y llegaron a la conclusión de que todos sus servicios funcionarán como API, por ejemplo, utilizando el protocolo jsonrpc. Sin embargo, dado que la tienda en línea es grande, no se detiene y se está desarrollando activamente, hay varios grupos de desarrollo allí, que sean más de dos, dos de diseño, uno acompañado de lo que ya se ha escrito. Además, para mejorar el efecto, todos los equipos escriben en la misma pila.
La arquitectura de una hipotética tienda en línea:
Solo el servicio API que sobresale en Internet proporciona acceso a todos los sistemas front-end: la interfaz web de la tienda en línea, así como las aplicaciones móviles.
El servicio de información al cliente almacena información sobre los clientes, sabe cómo iniciarlos, autorizarlos, emitir la información necesaria sobre ellos.
El servicio de información de productos almacena información sobre productos, sus saldos y disponibilidad para pedidos, también proporciona métodos para obtener convenientemente la información necesaria.
El servicio de pedidos opera con pedidos. Aquí está la lógica de la formación del pedido, su confirmación, la elección del tipo de pago y la dirección de entrega, etc.
El servicio de información al cliente puede enviar PUSH / SMS / mensajes de correo electrónico. El tipo de comunicación, por ejemplo, depende de la configuración de un cliente en particular, y el cliente también puede establecer el tiempo deseado para recibir notificaciones.
Estos servicios son de infraestructura condicional, porque sin ellos una tienda en línea no puede funcionar como tal.
Se supone que los servicios de promociones y ofertas y la distribución del resumen se desarrollarán en un futuro próximo por los equipos del proyecto. Estos servicios son condicionalmente comestibles.
Obviamente, en cualquier caso, cualquier servicio de producto nuevo no podrá existir sin interacción con los servicios de infraestructura; lo más probable es que tenga que recibir información sobre los clientes o enviar notificaciones.
En el ejemplo descrito anteriormente, los detalles de la implementación de cada servicio se ocultan intencionalmente. Entonces, por ejemplo, un servicio de información del cliente probablemente tenga un mecanismo de ejecución de código retrasado, como una cola de ejecución, y un servicio de información del producto puede tener su propio panel de administración para una gestión conveniente de los productos, y la API para sistemas front-end probablemente tenga varias réplicas. Además, la arquitectura descrita puede no ser óptima; simplemente se toma de la cabeza.
En el contexto de la arquitectura propuesta, queda claro de inmediato que las bibliotecas preparadas son esenciales para el rápido desarrollo del producto. Por lo tanto, es importante contar con una implementación preparada del servidor jsonrpc, así como del cliente, ya que este es el protocolo principal para organizar la interacción entre servicios. También en este ejemplo, el problema de documentar la API aumenta a su máximo potencial. Obviamente, los equipos también deben tener una herramienta preparada para generar documentación. Si suponemos que todavía hay una herramienta lista para generar esquemas smd para servidores jsonrpc, entonces la velocidad de desarrollo de nuevos servicios puede aumentar aún más. Como resultado, dentro de la empresa, idealmente, debería haber un conjunto de bibliotecas listas para usar que todos los equipos usan para realizar tareas típicas. Estas bibliotecas pueden ser propietarias o de código abierto, lo principal es que realizan bien sus tareas. Obviamente, un equipo que está en la pila general y escribe servicios utilizando bibliotecas listas para usar será más efectivo que un equipo que realiza ciclos constantemente. La presencia de un marco único y una base de datos única de bibliotecas que se utilizan en todos los equipos del proyecto, llamo un ecosistema único.
¿Y las grandes empresas?
En las grandes empresas, hay muchos más servicios de infraestructura, así como los protocolos de interacción utilizados. El número de bibliotecas terminadas puede llegar a decenas o incluso cientos. Destacar aquí el código reutilizable es aún más relevante.
Dio la casualidad de que tengo experiencia en una empresa que emplea a unos 200 desarrolladores que escriben en diferentes idiomas: java, c #, php, python, go, js, etc. Sorprendentemente, el ecosistema común, en el contexto de una sola pila, lejos de todos los equipos de desarrollo tienen y usan. Parecería que lo obvio, preparar el código reutilizable, formatearlo correctamente y usarlo, está lejos de ser obvio. Por supuesto, los equipos de desarrollo resuelven sus problemas. Alguien usa una plantilla de servicio, un conjunto de código que constituye el núcleo de cada nuevo servicio, del cual se desecha todo lo innecesario y se agrega el necesario.
Otros equipos de desarrollo usan sus propias bicicletas, las copian y las pegan de un proyecto a otro, y no les importa documentarlas y probarlas. En general, hay mucha desunión en las herramientas y los enfoques utilizados dentro de la misma pila en una empresa. Por otra parte, geográficamente ubicado en una ciudad.
Los beneficios de un ecosistema único
La formación de un ecosistema único puede resolver muchas dificultades y tiene un enorme potencial para aumentar la productividad de una gran empresa. De hecho, esta práctica está tomada de la comunidad de código abierto: las mejores soluciones en su campo sobreviven y son las más populares. Ahora es suficiente para abrir cualquier administrador de dependencias y simplemente sorprenderse de la abundancia de las soluciones propuestas. Pero tal enfoque puede implementarse dentro de la empresa. Las ventajas de este enfoque al implementar un nuevo servicio son las siguientes:
- Alta estabilidad: el uso de bibliotecas bien documentadas y cubiertas por pruebas aumenta la estabilidad del servicio en su conjunto;
- Fácil rotación de colegas entre equipos: si todos los equipos están dentro de un solo ecosistema, entonces, al pasar de un equipo a otro, el desarrollador no tendrá que pasar mucho tiempo para conocer las herramientas utilizadas, porque ya las conoce;
- Concentración en la lógica empresarial: de hecho, el desarrollo de un nuevo servicio se reduce a la necesidad de reforzar las dependencias necesarias que resuelven todas las tareas de infraestructura y escriben solo la lógica empresarial;
- Aceleración del desarrollo: no hay necesidad de hacer un ciclo, todo está listo, excepto la lógica de negocios;
- Simplificación de las pruebas: solo es necesario probar la lógica empresarial, porque las bibliotecas ya se han probado;
Volar en la pomada
Está claro que para lograr este enfoque, se deben seguir algunas prácticas, a saber, desarrollar bibliotecas utilizando versiones semánticas, cuidar la documentación y las pruebas, y tener ci configurado. Este es un tipo de indicador de madurez no solo del equipo de desarrollo, sino también de los desarrolladores de la empresa en su conjunto.
PS
Y el enfoque orientado a paquetes es solo porque el código reutilizable en mi pila se llama paquete. Bueno, eso suena gracioso. Recientemente, tuve un diálogo con uno de mis colegas que me impulsó a escribir este artículo:
- Colega: te conviertes en cajero en cinco
- yo: significado?)
- Colega: pronto preguntarás "¿necesitas un paquete?"
- I: por favor abre un pensamiento. no entiendo
- Colega: bueno, por enésima vez tienes un paquete listo para resolver mi problema
Lo que pasa es que en nuestra comunidad de desarrolladores dentro de la empresa hay alrededor de 20 piezas de paquetes listos para usar, y la creación de un nuevo servicio se traduce en extraer las dependencias necesarias, así como en escribir la lógica comercial. El costo de vinculación en términos de escribir código está casi anulado.