Hola, colegas.
Hoy se presenta para su consideración la traducción del artículo de Tugberk Ugurlu, quien se ha atrevido a exponer de manera relativamente concisa los principios del diseño de sistemas de software modernos. Esto es lo que el autor dice sobre sí mismo en un resumen.

Dado que es absolutamente imposible abordar en un artículo tan extenso un tema tan colosal como los patrones arquitectónicos + los patrones de diseño según el estado de 2019, recomendamos no solo el texto del señor Ugurlu, sino también los numerosos enlaces que ha amablemente incluido. Si les gusta, publicaremos un texto más especializado sobre el diseño de sistemas distribuidos.

Fotografía de Unsplash
Si nunca se ha enfrentado a desafíos como el diseño de un sistema de software desde cero, al comenzar un trabajo así, a veces ni siquiera sabe por dónde empezar. Creo que, en primer lugar, es necesario delinear los límites para tener una idea más o menos clara de qué es lo que se desea diseñar, y luego arremangarse y trabajar sin salirse de esos límites. Como punto de partida, se puede tomar algún producto o servicio (idealmente uno que le guste mucho) y analizar su implementación. Puede que se sorprenda de lo simple que parece este producto y de la gran complejidad que en realidad está oculta en él. No olvide: , y está bien.
Creo que el mejor consejo que puedo dar a quienes comienzan a diseñar un sistema es: ¡no hagan suposiciones! Desde el principio, es necesario concretar los hechos conocidos sobre este sistema y las expectativas relacionadas. Aquí hay algunas buenas preguntas cuyas respuestas lo ayudarán a comenzar el diseño:
- ¿Cuál es el problema que estamos tratando de resolver?
- ¿Cuál es la cantidad máxima de usuarios que interactuarán con nuestro sistema?
- ¿Qué patrones de escritura y lectura de datos utilizaremos?
- ¿Cuáles son los casos de fallos esperados y cómo planeamos manejarlos?
- ¿Cuáles son las expectativas sobre la coherencia y disponibilidad del sistema?
- ¿Es necesario tener en cuenta algún requisito relacionado con auditorías externas y regulaciones?
- ¿Qué tipos de datos confidenciales estamos planeando almacenar?
Estas son solo algunas preguntas que han sido útiles tanto para mí como para los equipos en los que he tenido la oportunidad de participar a lo largo de mi carrera profesional. Si conoces las respuestas a estas preguntas (y a cualquier otra que sea relevante en el contexto en el que trabajas), entonces puedes profundizar gradualmente en los detalles técnicos de la tarea.
Establecemos el nivel base
¿Qué entiendo aquí por «nivel base»? En nuestras épocas, la mayoría de los problemas en la industria del software se pueden resolver con los métodos y tecnologías ya existentes. Así, al orientarte en este paisaje, obtienes una ventaja al afrontar tareas que otros ya han resuelto antes que tú. No olvidemos que los programas se escriben para resolver problemas de negocios y usuarios, por lo que nos esforzamos por abordar el problema de la manera más directa y simple (desde la perspectiva del usuario). ¿Por qué es importante recordar esto? Tal vez, en tu sistema de coordenadas, prefieras buscar soluciones únicas para cada problema, ya que piensas: «¿Qué clase de programador soy si siempre sigo patrones?» En realidad, el arte aquí radica en tomar decisiones sobre dónde y qué hacer. Por supuesto, todos nosotros, de vez en cuando, nos enfrentamos a problemas únicos, cada uno de los cuales representa un verdadero desafío. Sin embargo, si nuestro nivel base está claramente delineado, sabemos en qué gastar nuestras energías: en buscar soluciones listas para la tarea que se nos ha encomendado, o en su estudio más profundo y comprensión.
Creo que he logrado convencerte de que, si un especialista comprende bien la arquitectura de ciertos sistemas de software notables, este conocimiento será invaluable para dominar el arte del arquitecto y construir una sólida base en este campo.
Bien, ¿por dónde empezar? tiene un repositorio en GitHub llamado , a partir del cual puedes aprender sobre el diseño de sistemas a gran escala y también prepararte para entrevistas sobre este tema. En el repositorio hay una sección con ejemplos , donde, en particular, se analiza cómo abordan el diseño de sus sistemas , por ejemplo, Twitter, Uber, etc.
Sin embargo, antes de abordar este material, profundicemos en los desafíos arquitectónicos más importantes que enfrentan en la práctica. Esto es crucial, ya que hay que especificar MUCHOS aspectos de un problema complejo y multifacético, y luego resolverlo dentro de la regulación vigente en este sistema. , ex empleado de Facebook, grabó , donde compartió su propia experiencia revisando cientos de solicitantes. Aunque el video se centra explícitamente en el diseño de grandes sistemas y en los criterios de éxito importantes al buscar un candidato para dicho puesto, seguirá siendo un recurso exhaustivo sobre qué aspectos son más relevantes al diseñar sistemas. También sugiero de este video.
Adquiere conocimientos sobre almacenamiento y recuperación de datos
En general, tu decisión sobre cómo almacenar y entregar tus datos a largo plazo afecta críticamente el rendimiento del sistema. Por lo tanto, primero debes entender las características esperadas de la escritura y lectura de datos en tu sistema. Luego, debes ser capaz de evaluar estos indicadores y tomar decisiones basadas en esas evaluaciones. Sin embargo, podrás manejar esta tarea de manera efectiva solo si comprendes los patrones existentes de almacenamiento de datos. En general, esto implica un conocimiento sólido relacionado con .
Las bases de datos pueden considerarse estructuras de datos que poseen una escalabilidad y durabilidad excepcionales. Por lo tanto, el conocimiento de las estructuras de datos debería ser muy útil también al elegir una base de datos específica. Por ejemplo, es un servidor de estructuras de datos que soporta varios tipos de valores. Permite trabajar con estructuras de datos como listas y conjuntos, y leer datos mediante algoritmos bien conocidos, por ejemplo, , organizando este trabajo de manera duradera y altamente disponible.

Fotografía de Unsplash
Una vez que entiendas lo suficiente sobre los distintos patrones de almacenamiento de datos, pasa a estudiar la consistencia y disponibilidad de los datos. Primero, necesitarás asimilar al menos en términos generales, y luego perfeccionar ese conocimiento examinando más de cerca los patrones establecidos de y . Así, ampliarás tu perspectiva en este campo y comprenderás que la lectura y la escritura de datos son en realidad dos problemas muy diferentes, cada uno con sus propios desafíos. Armado con varios patrones para garantizar la consistencia y la disponibilidad, podrás aumentar significativamente el rendimiento del sistema, asegurando la entrega ininterrumpida de datos a tus aplicaciones.
Finalmente, al concluir la discusión sobre el almacenamiento de datos, es importante mencionar el almacenamiento en caché. ¿Debería realizarse simultáneamente en el cliente y en el servidor? ¿Qué datos tendrás en tu caché? ¿Y por qué? ¿Cómo organizarás la invalidación de la caché? ¿Se realizará regularmente, en intervalos de tiempo específicos? Si es así, ¿con qué frecuencia? Recomiendo comenzar a profundizar en estos temas con del mencionado manual sobre diseño de sistemas.
Patrones de comunicación
Los sistemas están compuestos por diversos componentes; estos pueden ser diferentes procesos que operan dentro de un mismo nodo físico o diferentes máquinas que actúan en distintas partes de tu red. Algunos de estos recursos dentro de tu red pueden ser privados, pero otros deben ser públicos y accesibles para los consumidores que se conectan a ellos desde el exterior.
Es necesario asegurar la comunicación entre estos recursos, así como el intercambio de información entre todo el sistema y el mundo exterior. En el contexto del diseño de sistemas, aquí de nuevo nos enfrentamos a un conjunto de nuevos desafíos únicos. Vamos a ver cómo pueden ser útiles , y cuáles son los.

Fotografía de Unsplash
Al organizar la comunicación con el mundo exterior, siempre es muy importante , para lo cual también se debe abordar con seriedad y dedicarle atención activa.
Distribución de conexiones
No estoy seguro de que llevar este tema a una sección independiente sea justificado para todos. Sin embargo, aquí expondré esta concepción de manera detallada, considerando que el material de esta sección se describe con mayor precisión con el término «distribución de conexiones» (connection distribution).
Los sistemas se forman mediante la correcta conexión de múltiples componentes, y su comunicación entre sí a menudo se organiza sobre la base de protocolos establecidos, como TCP y UDP. Sin embargo, estos protocolos por sí solos a menudo no son suficientes para satisfacer todas las necesidades de los sistemas modernos, que a menudo operan bajo una alta carga, y dependen en gran medida de las necesidades de los usuarios. A menudo es necesario buscar formas de distribuir conexiones para manejar tales altas cargas en el sistema.
En la base de tal distribución se encuentra un bien conocido (DNS). Este sistema permite transformar un nombre de dominio, por ejemplo, un algoritmo cíclico ponderado (weighted round robin) y métodos basados en latencias que ayudan a distribuir la carga.
es fundamental, y prácticamente cualquier sistema grande en Internet con el que tratemos hoy se encuentra detrás de uno o varios balanceadores de carga. Los balanceadores de carga ayudan a distribuir las solicitudes de los clientes entre múltiples instancias disponibles. Existen balanceadores de carga tanto hardware como software, sin embargo, en la práctica, a menudo se trata con software, como el y . conceptualmente también son muy similares a los balanceadores de carga, aunque entre los primeros y los segundos hay una serie de . Estas diferencias deben tenerse en cuenta al diseñar un sistema según sus necesidades.
También es importante conocer sobre las (CDN). Un CDN es una red global distribuida de servidores proxy que entrega información desde los nodos que están geográficamente más cerca de un usuario en particular. Se prefiere utilizar redes CDN si se trabaja con archivos estáticos escritos en JavaScript, CSS y HTML. Además, hoy en día son comunes los servicios en la nube que proporcionan gestores de tráfico, como el , que le proporcionan distribución global y menor latencia al trabajar con contenido dinámico. Sin embargo, estos servicios son generalmente útiles en situaciones donde se trabaja con servicios web sin estado.
Hablemos de la lógica empresarial. Estructuración de la lógica empresarial, flujos de tareas y componentes
Así que hemos discutido varios aspectos infraestructurales del sistema. Es probable que el usuario ni siquiera piense en todos esos elementos de su sistema y, honestamente, no le importan en lo más mínimo. Al usuario le interesa saber cómo es interactuar con su sistema, qué se puede lograr haciéndolo de una manera específica, y cómo el sistema ejecuta los comandos del usuario, qué hace y cómo maneja los datos del usuario.
Como se puede deducir por el título de este artículo, tenía la intención de hablar sobre la arquitectura del software y el diseño de sistemas. Por lo tanto, no planeaba abordar los patrones de diseño de software que describen cómo se crean los componentes de software. Sin embargo, cuanto más reflexiono sobre ello, más me parece que la frontera entre los patrones de diseño de software y los patrones arquitectónicos es muy difusa, y ambas concepciones están estrechamente relacionadas. Tomemos, por ejemplo, (event sourcing). Una vez que adopte este patrón arquitectónico, afectará prácticamente todos los aspectos de su sistema: almacenamiento a largo plazo de datos, el nivel de consistencia adoptado en su sistema, la estructura de los componentes en él, etc. Por lo tanto, decidí mencionar algunos patrones arquitectónicos que se relacionan directamente con la lógica empresarial. Aunque en este artículo tendré que limitarme a una simple lista, le recomiendo que se familiarice con ella y reflexione sobre las ideas relacionadas con estos patrones. Aquí tienen:
- Conceptos , en particular, ,
Enfoques colaborativos
Es muy improbable que seas el único responsable del diseño del sistema en el proyecto. Por el contrario, lo más probable es que tengas que interactuar con colegas que trabajan tanto dentro de tu tarea como fuera de ella. En este caso, puede ser necesario evaluar las soluciones tecnológicas elegidas junto con tus compañeros, identificar las necesidades del negocio y comprender cómo dividir mejor las tareas.

Fotografía de Unsplash
Primero se deberá desarrollar una comprensión precisa y común de cuál es el objetivo empresarial que intentas alcanzar y con qué elementos variables tendrás que lidiar. Las técnicas de modelado grupal, en particular, (event storming) ayudan a acelerar significativamente este proceso y aumentan tus posibilidades de éxito. Este trabajo se puede realizar antes o después de delinear , y luego profundizar en ellos a medida que el producto madure. Basándote en el nivel de consenso que se logre aquí, también podrás formular un para el contexto limitado en el que trabajas. Cuando se necesite hablar sobre la arquitectura de tu sistema, puede ser útil contar con un , propuesto por , especialmente cuando se necesita entender hasta qué punto es necesario profundizar en los detalles del problema, visualizando las cosas que deseas comunicar.
Probablemente haya otra tecnología madura en este tema, tan útil como el diseño orientado a objetos. Sin embargo, volvemos a la comprensión del dominio, por lo que los conocimientos y la experiencia en deben ser útiles.
Fuente: habr.com
