Caminho do desenvolvedor

Olá! Meu nome é Alexey Skorobogaty. Em 2015, entrei na Lamoda como desenvolvedor. Agora sou arquiteto de sistemas de uma plataforma de e-commerce e também Líder Técnico da equipe CORE. Neste artigo, quero compartilhar as percepções que recebi ao longo desses 5 anos - no formato takeaways, com histórias, memes e links para a literatura.



imagem



Eu ficaria feliz em ter qualquer discussão nos comentários do artigo: perguntas, opiniões, refutações!



Existem conhecidos



Na Lamoda, juntei-me à equipe de suporte e desenvolvimento do sistema de processamento de pedidos. Nada é claro, mas terrivelmente interessante.



Depois de um web studio pequeno, mas ambicioso, onde trabalhei antes, fiquei impressionado com o senso de seriedade em uma grande empresa. Processos de desenvolvimento arranjados pareciam um mecanismo perfeitamente polido. As revisões de código rigorosas, mas de coaching, do líder e dos membros da equipe são essenciais para um sistema tão complexo e importante. Para mim, as tarefas pontuais voaram, afetando literalmente um ou dois arquivos, nada mais. A maior parte da base de código e do comportamento do sistema foi escondida de mim pela névoa da guerra.



Após cerca de um mês, concluí uma das primeiras tarefas relacionadas a fazer mudanças reais em um sistema de trabalho. Sua essência resumia-se a adicionar um campo ao relatório sobre a devolução de fundos ao cliente. Revisão de código, testes de unidade, engenheiro de controle de qualidade testando a versão - tudo parecia bem. Como o sistema era grande e complexo, éramos liberados duas vezes por semana, de acordo com o regulamento - e na quinta-feira minha tarefa passou para a produção. Na maior parte do dia, o engenheiro de lançamento estava ocupado construindo e implementando o código, seguido por uma alternância compulsiva entre as guias com gráficos de monitoramento, erros, filas, logs - tudo que pudesse indicar um problema. Mas tudo parecia ótimo. O código foi mesclado no branch master e disperso para lidar com outras tarefas.



O silêncio nos logs e monitoramento esconde um bug terrível: a consulta ao banco de dados retornou um número incorreto de linhas. O valor total a devolver foi várias vezes superior ao real ... Mas só descobrimos na segunda-feira. Ainda me lembro de como o líder técnico olhou para mim cansado e reprovador quando entramos no elevador do escritório na manhã seguinte. Ele pegou o bug até as três da manhã e preparou uma correção para o lançamento. E a empresa sofreu algum impacto com meu erro. Este foi meu primeiro bug crítico, mas está longe de ser o último. As pessoas cometem erros e o fazem o tempo todo.



Takeaway # 1:Processos de negócios e dados vêm em primeiro lugar. É importante prestar muita atenção aos dados com os quais o sistema funciona. Determine com o que você está lidando antes de fazer alterações. Compreenda o contexto em que os ajustes são feitos. Sempre considere o problema sendo resolvido da perspectiva do contexto acima do nível. Em outras palavras, entenda claramente o que está acontecendo em termos de processo de negócios e quem é o consumidor dos modelos afetados. A estrutura de um aplicativo pode ter quantas camadas de abstração você quiser e vários graus de qualidade das abstrações em si, mas isso não significa nada se o modelo ou o processo de negócios como um todo estiver quebrado.



Continuei trabalhando na mesma equipe, ganhei experiência e seis meses depois, no stand up da equipe, lancei uma frase que, no geral, entendia como funciona o nosso sistema de processamento de pedidos.



Claro que eu estava errado.



A complexidade de grandes sistemas nunca deve ser subestimada. O político americano Donald Rumsfeld disse muito bem sobre isso:

imagem... como sabemos, são famosos conhecidos; Existem coisas que sabemos, que as conhecemos. Também sabemos que existem desconhecidos conhecidos; ou seja, sabemos que existem algumas coisas que não sabemos. Mas também existem desconhecidos desconhecidos - aqueles que não conhecemos, que não os conhecemos. E se você olhar para a história do nosso país e de outros países livres, a última categoria geralmente é difícil.



Conclusão nº 2: ao trabalhar com sistemas complexos, é importante entender o que sabemos sobre eles, o que não sabemos e qual é o seu comportamento nem mesmo adivinhando. E não se trata apenas de ferramentas e de seguir a tendência de “Monitoramento para a Observabilidade” , mas também de gerenciamento de dependências e avaliação de riscos no projeto. Por exemplo, antes de decidir usar um banco de dados de tendências legal para um sistema crítico, recomendo fortemente que você se atenha a este site boringtechnology.club



Tudo está quebrado



Após dois anos trabalhando com o sistema de processamento de pedidos, poderia dizer que conheço cerca de 80% do aplicativo com segurança. Ou seja, sobre cada módulo do sistema eu entendo como funciona e posso fazer alterações. Eu sei quais processos de negócios são refletidos em um modelo específico, como eles estão interconectados e afetam uns aos outros. Realizei integração com um sistema de processamento de pagamentos projetado por uma equipe vizinha. Além da integração, era preciso me livrar do legado do código antigo, já que os pagamentos faziam parte do nosso sistema - essa tarefa foi minha última e maior refatoração de um grande módulo. Tudo correu tão bem que nem foi interessante.



Ao mesmo tempo, um conflito estava se formando dentro de mim, como desenvolvedor. Sinceramente, não entendia por que nosso sistema de processamento de pedidos, tão crítico para a operação de todo o nosso negócio, era tão frágil. Os grandes sistemas vizinhos eram igualmente frágeis. De toda a experiência que ganhei em dois anos de trabalho, parecia que algum tipo de confiabilidade de sistemas complexos pode ser esperado apenas ao realizar casos de teste padrão. E quando você tenta fazer as mudanças que seu negócio exige, as coisas desmoronam na primeira manobra drástica de um desenvolvedor azarado.



Refletindo sobre tudo isso, me deparei com o artigo Everything is broken , em que o autor escreve sobre o mesmo problema, mas em uma escala ainda maior (e também sobre o mesmo, mas de um ângulo diferente - Desencanto do software) Toda vez que fico animado quando encontro uma confirmação externa de meus sentimentos internos - então, naquele momento, depois de ler o artigo, eu finalmente senti como meu vago descontentamento se transformou em um insight brilhante e óbvio:

O software é tão ruim porque é muito complexo.



Não precisamos ir muito longe para dar um exemplo em nosso trabalho: justo naquele momento, adicionando apenas alguns postes, quebramos completamente a criação de um pedido por um tempo.



Nossos sistemas grandes e importantes são tão ruins porque não cabem em nossas cabeças! E todos os processos de negócios fechados dentro dos sistemas não cabem nas cabeças dos gerentes e analistas - e em geral não existe tal pessoa que entenderia como tudo funciona junto.



Conclusão nº 3: ao projetar sistemas, é importante considerar sua carga cognitiva. Consiste na complexidade das soluções técnicas, bem como nos modelos e processos da área temática. Sistemas bem projetados têm uma alta carga cognitiva na área de assunto e poucas soluções técnicas.Idealmente, um único sistema deve ter uma carga cognitiva que uma pessoa possa suportar.



Ok, o problema é claro. Mas suponha que tenhamos a oportunidade de reescrever um sistema excessivamente complexo e, portanto, ruim, simplificando-o. Em que mais você deve prestar atenção? Na cibernética, existe o teorema de Conant-Ashby:



um bom regulador de um sistema deve ter um modelo desse sistema. Bom regulador



O significado deste teorema é que se quisermos controlar algum objeto, precisamos de um bom modelo (preciso e compreensível) desse objeto. E quanto mais complexo o objeto ou quanto menos informação sobre ele, mais difícil será obter um bom modelo dele - e isso afeta negativamente a gestão.



Acho que muito poucas pessoas discordariam de que todos os nossos serviços são modelos. Mas o que estamos modelando? É muito importante prestar atenção aos processos de negócios, para modelar não apenas o estado, mas também o comportamento.



No final de 2017, mudei para a nova equipe CORE. Essa equipe foi então formada especificamente para realizar as tarefas da estratégia de TI para a decomposição de sistemas monolíticos. Nosso objetivo principal era cortar aquele grande, mas frágil sistema de processamento de pedidos (locução: então o samurai não sabia que esse caminho tinha um começo, mas não tinha fim!).

Foi uma experiência nova para mim. Uma equipe com princípios e formas de pensar totalmente diferentes. As decisões foram tomadas rapidamente, houve experiências e o direito de cometer erros. O equilíbrio saiu perfeito: tentamos e retrocedemos onde o impacto era mínimo, mas prescrevemos cada etapa em detalhes para momentos críticos.



Escrevemos um novo serviço para criar pedidos do zero em outra linguagem (sendo desenvolvedores php, mudamos para golang). Avaliamos o primeiro resultado e o reescrevemos novamente. A ênfase estava na simplicidade e confiabilidade. Eles colocaram o modelo de dados no centro e construíram toda a arquitetura ao redor. O resultado é um serviço confiável e resiliente. Conseguimos colocá-lo em funcionamento sem falhas usando o mecanismo experimental. Com o tempo, o sistema construído mostrou seu valor mais de uma vez.



imagem



Takeaway # 4:Todos os modelos estão errados, mas alguns são úteis. Modelar estados não é suficiente para construir sistemas corretos e estáveis. É necessário olhar para o comportamento: padrões de comunicação, fluxos de eventos, quem é responsável por este ou aquele dado. Você deve procurar relacionamentos entre dados e prestar atenção às razões para esses relacionamentos.



É tudo sobre o dum dum da da dum dum



Na minha universidade havia um curso de análise matemática, ministrado por um professor associado e doutorado. Elena Nikolaevna. Ela era muito rígida, mas justa. Em testes de vez em quando deparava-se com problemas, para cuja solução era necessário “torcer” um pouco as aulas - dar um passo independente para a compreensão do material. E no exame final, que, aliás, passei pela segunda vez, tive que mostrar flexibilidade de pensamento e usar minha intuição para resolver o problema como “bom”. Aqui está a regra de que E.N. ela nos contou todo o curso, e que estou usando dez anos depois:

Quando você não sabe o que fazer, faça o que sabe.



É por isso que tenho orgulho de saber que é bom. Porque de acordo com os padrões da E.N. não basta conhecer o material, mas também é importante entendê-lo, para poder sintetizar algo novo.



Conclusão nº 5: quanto mais você avança, mais responsabilidade precisa assumir e mais decisões precisa tomar. Em certo momento, a confiança absoluta desaparece como categoria, mas em vez disso surge a arte do equilíbrio seguindo a coragem de dar um passo.



Chega um momento em que não há nenhuma pessoa certa ao seu redor que possa remover a incerteza existente. Você deve avaliar os riscos sozinho e assumir a responsabilidade por si mesmo. Tome decisões diante da incerteza.



No segundo semestre de 2018, nossa equipe assumiu a liderança no projeto de Vale Presente. Inicialmente, fui responsável pelo desenvolvimento em torno do processamento. Posteriormente, no final do ano, a liderança técnica de todo o projeto assumiu a mim junto com a tarefa de restaurar o equilíbrio de poder após a saída de parte da equipe.



As regras existentes na cabeça e na ordem mundial do desenvolvedor estavam explodindo pelas costuras e finalmente entraram em colapso. A responsabilidade por um projeto grande e complexo tirou de mim as ideias idealistas sobre o mundo do desenvolvimento com conceitos e um arco-íris. O mundo cruel de restrições e soluções suficientes exigiam uma compreensão e revisão de todas as abordagens e regras que eu seguia.



imagem



Takeaway # 6:Síndrome do Impostor. E se eu ficar exposto? Claro que eles vão expor se nada for feito. Se você faz algo importante, depois de um tempo, percebe que não há ninguém para expô-lo.



Divergência e Convergência



De acordo com a cronologia do meu “Caminho do Desenvolvedor” deveria haver uma história interessante do ponto de vista técnico sobre o projeto de políticas pessoais. Neste projeto, implementamos o processamento de dados em tempo real e, em tempo real, mudamos os próprios princípios da arquitetura do sistema, passando para a Arquitetura Orientada a Eventos. Mas sobre isso, já tenho um relatório separado da conferência Highload '19 (e um artigo aqui sobre Habré). Portanto, prefiro falar sobre os “pontos altos” da técnica e não muito gerencial.



Quando um desenvolvedor chega à posição de sênior, que deve ser lida como "pronto para assumir responsabilidades e saber como tomar decisões de forma autônoma", o próximo passo clássico é o líder da equipe. Um líder de equipe é a pessoa que é principalmente responsável pela equipe, ou seja, para pessoas e processos de desenvolvimento. O cliente não vai até o desenvolvedor, ele vai até o líder da equipe e pede obrigações ao líder também.



Acontece uma coisa paradoxal - assim que um desenvolvedor amadurece para trabalhar de forma independente como engenheiro, ele é lançado em uma tempestade chamada gerenciamento.

Não, talvez para alguém este caminho pareça bastante confortável, e a transição de algoritmos e protocolos extremamente inequívocos para a interação de sistemas de computador para a coordenação de um grupo de pessoas pareça lógica. Mas me parece que não é à toa que a maioria das conversas em chats de perfil e em conferências para líderes de equipe giram em torno do conceito de “dor”.



Qual é a dor de um líder de equipe? Não é porque um engenheiro se encarrega da gestão ?! Não, por que isso acontece é compreensível - não temos uma escola de gestão técnica propriamente dita, e presume-se que um engenheiro de TI seja um super-homem que pode descobrir tudo, incluindo algo tão “simples” como gerenciamento.



Mas decidi ir por outro caminho e escolhi a posição de líder de tecnologia como o próximo passo na carreira. Como arquiteto, trabalho com equipes de desenvolvimento e agora ouço dos caras o que eu mesmo disse aos gerentes um ano atrás:

Por que os requisitos são tão mal desenvolvidos? Soluções de muleta! Que duas semanas ?! Aqui trabalho por um mês.



Mas ehehei, agora é minha tarefa resolver esses problemas. Mas assim que você traduz seu pensamento para o paradigma de custo e benefício, você percebe que todos esses problemas não podem ser resolvidos - você está falando sobre sua vida!



Takeaway # 7: Abertura! Os gerentes não lidam com a solução de problemas; eles gerenciam a desordem.



Como líder técnico, meu trabalho é remover a incerteza da equipe de desenvolvimento. Requisitos não funcionaram? Soluções de muleta? A arquitetura não fornece? Todos esses são sinais de fragilidade e divergência do sistema.



Digamos que a configuração da tarefa no serviço de criação de pedidos se pareça com isto: Você

precisa adicionar o campo X e o campo Y. É necessário que o valor no campo Y 'na saída seja igual ao valor Z se X for 1.



O problema está na própria declaração de requisitos. O erro aqui é que não está totalmente claro qual estado do sistema você deseja alcançar. Etapas totalmente definidas na declaração levam à incerteza durante a implementação e operação.

Depois de várias dessas tarefas, o serviço de criação de pedidos estará em um estado bastante frágil - e casos como aquele em que adicionamos alguns campos e tudo quebrou começará a acontecer.



Objetivo: garantir a convergência dos estados dos sistemas, a consistência do enunciado das tarefas e a redução da incerteza para alcançar a estabilidade.



imagem



As pessoas que trabalham na linha de representação estão constantemente construindo e atualizando seus modelos do que está além da linha. Essas atividades são críticas para a resiliência dos sistemas da Internet e são uma importante fonte de capacidade adaptativa. Acima da linha, abaixo da linha



O arquiteto deve compreender a unidade do sistema sociotécnico. Ser capaz de coordenar processos acima da linha de apresentação para que os sistemas abaixo da linha de apresentação atendam às restrições de correção, estabilidade e adaptabilidade.



imagem



Conclusão nº 8: se as regras param de funcionar, parabéns, você atingiu as condições-limite sob as quais o modelo atual para de funcionar. É hora de revisar suas ideias e encontrar um novo modelo que atenderá às restrições atuais e permitirá que você crie processos e regras adequados.



Macio é simples, as pessoas são duras!



Não mesmo. Isso é o que foi escrito em um livro sobre arquitetura. E parece que, quanto mais longe eu vou, mais freqüentemente repito este livro.



Conceitos técnicos, algoritmos e padrões são claros - você só precisa pegar e descobrir de forma consistente. Não estou tentando descartar o trabalho dos engenheiros - algoritmos para sistemas distribuídos são extremamente complexos se você não construir tais sistemas diariamente. Porém, na maioria das vezes, a principal dificuldade que enfrentamos no processo de trabalho surge quando precisamos entender por que este ou aquele serviço requer tal nível de abstração para o domínio. E o problema geralmente é agravado pelo fato de que a pessoa que escreveu o serviço não está por perto.



Algoritmos simples de implementar são mais bem-sucedidos do que os matematicamente precisos. O Paxos é matematicamente preciso, mas apenas com a descrição do protocolo Raft, mais fácil de implementar, foi desenvolvida a aplicação prática de algoritmos de consenso.

A linguagem Golang é criticada por ser muito limitada. Mas é nele que o Docker, o Kubernetes e muitos outros sistemas distribuídos são escritos. Um sistema de restrições bem projetado serve como base para sistemas de sucesso.



Tudo seria muito mais fácil se a tecnologia não tivesse que contar com o fator humano. Mas eles precisam. Qualquer sistema de TI, em construção e manutenção do qual esteja envolvida mais de uma pessoa, deve levar em consideração o fator humano.



E aqui as tecnologias emergem na interseção de software e pessoas, projetadas para estruturar o caos e descrever interações complexas. Domain Driven Design, microsserviços, Agile - todos eles criam restrições que descrevem os princípios e regras de interação. Surgem estruturas com as quais fica claro como trabalhar. Mas nem sempre isso fica melhor com o advento dessas tecnologias. Muitas vezes acontece o contrário - O que o dinheiro não pode comprar .



Conclusão nº 9: os programas podem e devem ser simples. Para fazer isso, você precisa aplicar força à formação de uma cultura de engenharia. É ela quem, em última análise, determina a execução dos serviços.



imagem



Lista de leitura



Livros



O Caminho do Gerente: Um Guia para Líderes de Tecnologia Navegando no Crescimento e Mudança, Camille Fournier - link



The Elegant Puzzle: Systems of Engineering Management, Will Larson - Link



Team Topologies: Organizing Business and Technology Teams for Fast Flow, Manuel Pais e Matthew Skelton - ligação



corrigir Software, Juval Lowy - ligação



de Pensar em Sistemas: a Primer, Donella Meadows - referência



os artigos



modelos mentais, Rua Geral Fernam - ligação



Complexidade viés: por que nós preferimos complicado simples. Fernam Street - link



O que o dinheiro não pode comprar, menos errado - link



Tornando-se incomumente orientado para a verdade, menos errado -link



Leis e realidade da programação: Nós sabemos o que pensamos que sabemos? - link



No Silver Bullet Essence e Accidents of Software Engineering - link



The Art Of Troubleshooting - link



De software frágil para antifrágil - link Os



computadores podem ser compreendidos - link



Tuckman estava errado! (Sobre as equipas) - referência



Como falhar em quase tudo e ainda ganhar muito - ligação



Simplicidade Antes Generalidade Use antes de reutilizá - ligação

Simplicidade, por favor - Um Manifesto para Software Development - Fazer a ligação



Design de Software é Relacionamentos Humanos - link



All Articles