Olá, colegas.
Hoje, apresentamos a tradução do artigo de Tugberk Ugurlu, que se propôs a expor de maneira relativamente concisa os princípios de design de sistemas de software modernos. Aqui está o que o autor menciona sobre si mesmo de forma resumida:

Como é claramente impossível abranger em um artigo tão curto um tema colossal como padrões arquiteturais + padrões de design até 2019, recomendamos não apenas o texto do senhor Ugurlu, mas também os inúmeros links que ele gentilmente inseriu. Se você gostarem, publicaremos um texto mais especializado sobre o design de sistemas distribuídos.

Imagem do site Unsplash
Se você nunca teve que enfrentar desafios como o design de um sistema de software do zero, ao começar esse trabalho, pode ser até difícil saber por onde começar. Eu acredito que, primeiro, é necessário delinear os limites, para ter uma ideia do que exatamente você pretende projetar, e em seguida – arregaçar as mangas e trabalhar dentro desses limites. Um bom ponto de partida pode ser um produto ou serviço (idealmente, algo que você goste muito) e desvendar sua implementação. Você pode se surpreender com a simplicidade aparente deste produto e com a imensa complexidade que está realmente oculta nele. Não se esqueça: , e isso é normal.
Acho que o melhor conselho que posso dar a quem está começando a projetar um sistema é: não faça suposições! Desde o início, é preciso concretizar os fatos conhecidos sobre esse sistema e as expectativas associadas a ele. Aqui estão algumas boas perguntas cujas respostas ajudarão você a começar o design:
- Qual é o problema que estamos tentando resolver?
- Qual é o número máximo de usuários que interagirão com nosso sistema?
- Quais padrões de gravação e leitura de dados serão usados?
- Quais são os casos esperados de falhas, e como pretendemos lidar com eles?
- Quais expectativas existem em relação à consistência e disponibilidade do sistema?
- Devem ser considerados requisitos relacionados à auditoria externa e regulamentação durante o trabalho?
- Quais tipos de dados confidenciais pretendemos armazenar?
Essas são apenas algumas perguntas que foram úteis tanto para mim quanto para as equipes nas quais participei ao longo da minha carreira profissional. Se você souber as respostas para essas perguntas (e para outras que sejam relevantes no contexto em que você está trabalhando), então pode-se começar a aprofundar nos detalhes técnicos da tarefa.
Definindo o nível base
O que eu entendo aqui por "nível base"? De fato, na nossa época, a maioria dos problemas na indústria de software podem ser resolvidos com métodos e tecnologias já existentes. Assim, ao se orientar nesse cenário, você ganha uma vantagem ao enfrentar desafios que alguém já teve que resolver antes de você. Não esqueçamos que os programas são desenvolvidos para resolver problemas de negócios e usuários, portanto, buscamos abordar a tarefa da maneira mais direta e simples (do ponto de vista do usuário) possível. Por que isso é importante? Talvez, em sua perspectiva, você goste de encontrar soluções únicas para cada tarefa, acreditando que "que tipo de programador sou eu se sigo padrões em tudo"? Na verdade, a arte aqui reside em decidir onde e o que fazer. Certamente, todos nós temos que enfrentar problemas únicos de vez em quando, cada um dos quais é um verdadeiro desafio. No entanto, se nosso nível base estiver bem definido, saberemos onde investir nossos esforços: na busca de soluções prontas para a tarefa proposta ou em um estudo mais aprofundado e na compreensão mais profunda da mesma.
Acredito que consegui convencê-lo de que, se um especialista compreende bem a arquitetura de alguns sistemas de software notáveis, esse conhecimento será indispensável para dominar a arte de ser arquiteto e construir uma sólida base nesse campo.
Muito bem, por onde começar? No caso de , há um repositório no GitHub chamado , através do qual você poderá aprender a projetar sistemas em larga escala e se preparar para entrevistas sobre esse tema. No repositório, há uma seção com exemplos , onde, entre outras coisas, é abordado como algumas empresas bem conhecidas se aproximam do design de seus sistemas . No entanto, antes de passar para este material, vamos explorar mais detalhadamente os desafios arquitetônicos mais importantes que você enfrentará na prática. Isso é importante porque é necessário especificar MUITOS aspectos de um problema complexo e multifacetado e, em seguida, resolvê-lo dentro das regulamentações vigentes neste sistema.
Jackson Gabbard um vídeo de 50 minutos sobre entrevistas dedicadas ao design de sistemas um resumo Adquira conhecimento sobre armazenamento e recuperação de dados
Normalmente, sua decisão sobre como armazenar e fornecer seus dados a longo prazo tem um impacto crítico no desempenho do sistema. Portanto, você precisa entender primeiro as características esperadas de gravação e leitura de dados em seu sistema. Em seguida, é necessário avaliar esses indicadores e fazer escolhas com base nas avaliações feitas. No entanto, você só conseguirá lidar com essa tarefa de forma eficaz se entender os padrões existentes de armazenamento de dados. Isso implica ter um conhecimento firme relacionado à
escolha do banco de dados. .
Bancos de dados podem ser considerados estruturas de dados que possuem escalabilidade e durabilidade excepcionais. Portanto, o conhecimento sobre estruturas de dados deve ser bastante útil na escolha de um banco de dados específico. Por exemplo, – é um servidor de estruturas de dados que suporta vários tipos de valores. Ele permite trabalhar com estruturas de dados como listas e conjuntos, ler dados usando algoritmos conhecidos, como , organizando esse trabalho de forma duradoura e de alta disponibilidade.

Imagem do site Unsplash
Quando você já estiver familiarizado com os vários padrões de armazenamento de dados – comece a estudar a consistência e a disponibilidade dos dados. Primeiro, você precisará entender pelo menos de forma geral, e depois aperfeiçoar esse conhecimento, examinando mais detalhadamente os padrões estabelecidos de e . Assim, você ampliará sua visão nessa área e entenderá que ler e gravar dados são, na verdade, duas questões muito diferentes, cada uma com seus próprios desafios. Armado com alguns padrões que garantem consistência e disponibilidade, você poderá aumentar significativamente o desempenho do sistema, garantindo ao mesmo tempo um fornecimento ininterrupto de dados para suas aplicações.
Por fim, ao concluir a discussão sobre questões de armazenamento de dados, é importante mencionar a caching. Deve ser feito simultaneamente no cliente e no servidor? Quais dados você terá em cache? E por quê? Como você organizará a invalidação do cache? Será feita regularmente, em determinados intervalos de tempo? Se sim – com que frequência? Recomendo iniciar a discussão sobre esses tópicos com do mencionado manual de design de sistemas.
Padrões de comunicação
Os sistemas são compostos de vários componentes; podem ser diferentes processos operando dentro do mesmo nó físico ou diferentes máquinas atuando em partes diferentes da sua rede. Alguns desses recursos em sua rede podem ser privados, mas outros devem ser públicos e acessíveis a consumidores que os acessam externamente.
É necessário garantir a comunicação entre esses recursos, bem como a troca de informações entre todo o sistema e o mundo exterior. No contexto do design de sistemas, novamente nos deparamos com um conjunto de novos desafios únicos. Vamos entender como os , e quais são r.

Imagem do site Unsplash
Ao organizar a comunicação com o mundo exterior, é sempre muito importante , para a qual também é necessário abordar com a máxima seriedade e atuar ativamente.
Distribuição de conexões
Não tenho certeza se destacar este tópico em uma seção independente será justificado para todos. No entanto, vou expor essa concepção de forma abrangente e considero que o material desta seção é mais bem descrito pelo termo "distribuição de conexões" (connection distribution).
Os sistemas se formam por meio da conexão correta de vários componentes, e a comunicação entre eles é frequentemente organizada com base em protocolos estabelecidos, como TCP e UDP. No entanto, esses protocolos, por si só, muitas vezes não são suficientes para atender todas as necessidades dos sistemas modernos, que frequentemente operam sob alta carga e também dependem muito das necessidades dos usuários. Muitas vezes, é necessário encontrar maneiras de distribuir conexões para lidar com cargas tão altas no sistema.
Na base dessa distribuição está a bem conhecida (DNS). Esse sistema permite transformar um nome de domínio, por exemplo, um algoritmo de rotação ponderada (weighted round robin) e métodos baseados em latências, ajudando a distribuir a carga.
é fundamental, e praticamente qualquer sistema grande na Internet com o qual lidamos hoje está atrás de um ou mais balanceadores de carga. Os balanceadores de carga ajudam a distribuir as solicitações dos clientes entre várias instâncias disponíveis. Os balanceadores de carga podem ser tanto de hardware quanto de software, mas, na prática, frequentemente lidamos mais com os de software, como o e . também são conceitualmente muito semelhantes aos balanceadores de carga, embora haja uma série de . Essas diferenças devem ser consideradas ao projetar um sistema que atenda às suas necessidades.
Também é importante conhecer as (CDN). A CDN é uma rede de servidores proxy distribuída globalmente, que fornece informações a partir de nós localizados geograficamente mais próximos de um usuário específico. Redes CDN são preferíveis quando você está lidando com arquivos estáticos escritos em JavaScript, CSS e HTML. Além disso, hoje são comuns serviços em nuvem que oferecem gerenciadores de tráfego, como , que garantem distribuição global e latências reduzidas ao trabalhar com conteúdo dinâmico. No entanto, tais serviços costumam ser úteis em casos onde é necessário trabalhar com web services sem estado.
Vamos falar sobre a lógica de negócios. Estruturar a lógica de negócios, fluxos de tarefas e componentes
Então, já discutimos vários aspectos de infraestrutura do sistema. Provavelmente, o usuário nem pensa em todos esses elementos do seu sistema e, francamente, não se preocupa com eles. O que interessa ao usuário é como é interagir com o seu sistema, o que é possível realizar ao agir dessa forma, e também como o sistema executa os comandos do usuário, o que ele faz e como manipula os dados do usuário.
Como é evidente pelo título deste artigo, eu planejava falar sobre arquitetura de software e design de sistemas. Portanto, não planejei abordar padrões de design de software, que descrevem como os componentes de software são criados. Contudo, quanto mais eu reflito sobre isso, mais parece que a linha entre padrões de design de software e padrões arquiteturais é muito tênue, e essas duas concepções estão intimamente ligadas. Vamos considerar, por exemplo, (event sourcing). Assim que você adota esse padrão arquitetural, ele impacta praticamente todos os aspectos do seu sistema: armazenamento de dados a longo prazo, nível de consistência aplicado no seu sistema, a estrutura de seus componentes, etc., e assim por diante. Portanto, decidi mencionar alguns padrões arquiteturais que estão diretamente relacionados à lógica de negócios. Mesmo que neste artigo esteja restrito a uma simples lista, recomendo que você se familiarize com ela e reflita sobre as ideias associadas a esses padrões. Aqui está:
- Conceitos , em particular, ,
Abordagens colaborativas
É extremamente improvável que você seja o membro do projeto que individualmente é responsável pelo processo de design do sistema. Pelo contrário, é mais provável que você tenha que interagir com colegas que trabalham tanto dentro da sua tarefa quanto além dela. Nessa situação, pode ser necessário avaliar as soluções tecnológicas escolhidas em conjunto com seus colegas, identificar as necessidades de negócios e entender como melhor paralelizar as tarefas.

Imagem do site Unsplash
Em primeiro lugar, será necessário desenvolver uma compreensão precisa e amplamente reconhecida de qual é o objetivo de negócios que você está tentando alcançar e com quais elementos dinâmicos você terá que lidar. Técnicas de modelagem em grupo, em particular, ajudam a acelerar significativamente esse processo e aumentam suas chances de sucesso. Esse trabalho pode ser realizado antes ou depois de você delinear , e então aprofundá-lo à medida que o produto amadurece. Com base no nível de concordância que será alcançado aqui, você também poderá formular para o contexto restrito em que você está trabalhando. Quando precisar falar sobre a arquitetura do seu sistema, uma , sugerido , especialmente quando precisar entender até que ponto você terá que se aprofundar nos detalhes do problema, visualizando as coisas que deseja comunicar.
Provavelmente, nesta questão também existe outra tecnologia madura, tão útil quanto o design orientado a domínio. No entanto, de qualquer forma, voltamos à compreensão do domínio, portanto, conhecimentos e experiências na área devem ser úteis para você.
Fonte: habr.com
