
Alguns meses atrás eu trabalhei em uma equipe externa. Este não é um lugar onde você precisa de entusiasmo e fé no grande objetivo do projeto. Juntamente com a equipe, eles simplesmente me venderam aos clientes e, nas reuniões, era importante quantos ingressos eu fechasse. Ataques de perfeccionismo são algo muito ruim para esse lugar, mas eu não poderia fazer nada com eles. Paguei muito por um deles, entrei em uma crise infernal e passei as piores duas semanas da minha vida.
Minha empresa me pediu para ir a Moscou por duas semanas, ao escritório principal, para trabalhar com a equipe. O pedido é razoável, eu concordei. Alguns dias antes da partida, peguei outro ingresso. Era necessário adicionar um recurso ao SDK para uma dúzia de projetos nos quais estamos trabalhando. Esse SDK é um legado intransitável que ninguém em sã consciência toca. Existe um pântano tão grande que até engenheiros duros são batizados supersticiosamente - se tudo funcionasse, como funcionaria. Quando precisamos consertar algo ou adicionar um recurso, apoiamos cuidadosamente o código com outra muleta e, sem respirar, enviamos para as mãos do CI e do controle de qualidade.
Eu planejei fazer o mesmo. A essência da tarefa era simples. O SDK em si é um invólucro de um sistema binário muito inteligente que pode elevar uma VPN. Ela se comunica com o nosso back-end, recebe todos os tipos de configurações, autoriza o usuário, busca uma lista de países para VPN e assim por diante.
Eu só precisava adicionar outra solicitação ao back-end, que recebe uma lista de servidores. Parece extremamente simples - adicionou um método à API pública, solicitou o URL desejado, deu um tapa no modelo, analisou, deu de presente. Em seguida, ele ensinou os aplicativos clientes a usar essa solicitação e pronto. Eu fiz a tarefa em dois dias.
Um erro muito grande. Não há tarefas simples. Com um olho eu já estava examinando os bares de Moscou, onde precisava beber toda a cerveja, e com o outro vi o primeiro problema. Nós não apenas obtemos uma lista de servidores, também usamos um deles para criar um túnel de VPN. Anteriormente, usamos apenas países para isso. Mas algum gênio decidiu que seria uma ótima idéia armazenar os países como uma lista de strings. Obviamente, a essência de um nó VPN é algo muito amplo para caber em uma linha.
Como resultado, vários métodos surgiram no SDK que pegam uma string (código do país) e fazem alguma coisa lá, e agora todos esses métodos devem pegar um código do país ou um objeto de servidor - e fazer alguma coisa lá. Tudo o que fizemos no código SDK e nos aplicativos com os países, agora precisamos fazer tanto com os países quanto com os servidores.
Quando entendi isso, por algum motivo fiquei encantado. O escopo da tarefa agora me permitia refatorar levemente o pântano, cheio de merda em que nado o tempo todo. Eu declarei meu desejo, e agora tenho certeza - eles me deram o aval com uma expressão, como se tivessem prejudicado uma mulher com deficiência ao preço de Maserati. Concordei com um orçamento semanal e comecei a trabalhar.
Alguns dias antes da partida. A semana parecia um infinito inteiro. Decidi, até escrever o código, apenas abalo a decisão na minha cabeça e, assim que chegar, espalharei tudo rapidamente.
Quando uma pessoa normal faz uma viagem de negócios, ele compra os ingressos com antecedência, resolve o problema da moradia, avisa a esposa e geralmente faz tudo certo. Sou um idiota míope que pisou em Moscou com sua esposa e dois filhos. Eu tive que levar minha esposa porque contei a ela sobre a viagem três horas antes da partida. Em duas horas - comecei a procurar um motorista com uma minivan, porque meu carro quebrou. Aluguei um apartamento no mesmo momento. Seis horas de viagem com crianças gritando e uma esposa insatisfeita terminaram como deveriam - o apartamento era exatamente duas mil vezes menor do que parecia nas fotos. O pior cheiro era o cheiro da grama. A empregada que nos hospedou disse que envenenou as baratas (baratas !!!). Minha esposa acreditou nela, e dizer a minha esposa que eu distinguir o cheiro da grama do veneno de barata não é do meu interesse.
Eu vim para o escritório, eles me deram um laptop. Por meio dia, instalei o ambiente, conheci todos. Quando tudo baixado e instalado, começou a funcionar. A raiva do terrível movimento ainda não esfriou. Abri o projeto com o SDK, mais uma vez amaldiçoei-me firmemente e pensei: “Que diabos? Sim, aqui tudo para o inferno com cães deve ser jogado fora e refeito.
Eu contei ao líder sobre isso, e ele, é claro, respondeu: "Eu concordo, cara". Um projeto de 15 mil linhas, cada uma das quais é um crime contra a humanidade. Eu estava prestes a consertar isso em duas semanas. E se eu tivesse dez horas de viagem e três filhos, o que eu sugeriria uma pista? Inventar em uma semana um novo PL especificamente para o projeto?
Mas me pareceu que, se eu colocasse em ordem pelo menos alguma coisa - seria mais fácil para mim. Agora eu crucifico este govnokod, farei tudo como deveria, viveremos. Certa vez, li livros sobre como fazer refatoração profunda. Havia muitos pensamentos inteligentes sobre como você pinta etapas, escreve testes, pensa em suas ações para ter confiança a cada passo - o projeto funciona, nada é quebrado. Livros e práticas recomendadas, é muito legal, mas nunca aprendo com os erros dos outros. No começo da minha carreira, eu li muito sobre todos os tipos de coisas básicas, mas não acreditei nelas até precisar expandir a funcionalidade do meu primeiro projeto.
A tarefa de qualquer rake é dar-lhe uma testa. Até que suas decisões malsucedidas se importem com você pessoalmente, você não as considerará malsucedidas.
Comecei a refatorar sem confiar na prática. Dividi mentalmente o projeto em grandes partes lógicas. Isso não estava refletido em sua estrutura de arquivos, então levei essa estrutura para o inferno. Criei um pai de nível superior: aqui trabalhamos com as costas, trabalhamos com VPN, aqui ajudantes, há exceções. Testes de unidade existentes, eu também rejeitei. Então me pareceu que o govnokod não tinha direito à vida, e agora entendo que pulei do avião e não peguei o paraquedas, porque foi violado pelas instruções.
Comecei a transferir o govnokod de velhos pais para novos, colocando-os simultaneamente em ordem. Nada de especial, basta seguir as boas práticas. Há uma classe que descreve o modelo do usuário, que possui todas as propriedades opcionais, todas com setters. Transformando-o na hierarquia de herança de uma criança. Tudo ridonly, tudo através do construtor. Para que os usuários desta classe sempre saibam exatamente o que têm em suas mãos. Existe um método de governo em quatrocentas linhas - você acessa os sub-métodos. Você vê um arquivo com mil responsabilidades - você o transforma em mil arquivos com um dever. Há uma classe que possui o método Initialize, que sempre deve ser chamada imediatamente após a criação da classe - você aplica o padrão "state"
Os conceitos de código bom e ruim são muito vagos. Toda a minha vida vou aprender a distinguir entre eles. Mas, francamente, código de merda que posso ver agora. Veja e corrija. Tentei não escavar muito a arquitetura de nível superior e alterar a API do SDK externo o mínimo possível.
É uma péssima decisão permanecer no trabalho por algumas horas quando sua esposa está esperando por você em uma cidade estranha, na pior cabana do mundo, e ela tem dois filhos pequenos que rugem de estresse sem cessar. Fiquei sete horas. No primeiro dia de trabalho, fiquei sentado no escritório até uma da manhã e copiei dois por cento da força.
"Em casa", um merecido escândalo me esperava, de manhã - café instantâneo de merda. Aluguei um apartamento a cinco minutos do escritório, mas estava tão estranho e assustado nesta cidade terrível que nos três primeiros dias fui trabalhar de táxi.
Todos no escritório estavam muito alegres - as pessoas iam beber à noite. Esses moscovitas fazem isso todos os dias. Eles me ligaram também. Prometi tentar, embora eu próprio soubesse com certeza - não há opções. Ele começou a trabalhar novamente.
Então me pareceu que eu mesmo era o culpado por toda a merda da casa, porque eu pegava as coisas por conta própria. Era melhor procurar um apartamento, se preparar melhor, prever todos os problemas da família e da vida. Um monte de problemas que não poderiam ter sido. Olhando para o código, pensei - é a isso que meia medida leva.
Ele rapidamente decidiu que minha abordagem ontem era muito comprometida. Se você refazer, é tudo. Deixei de me limitar a renomear e dividir. Todos os arquivos que eu estava prestes a processar foram cuidadosamente analisados. Estou nesse projeto há algum tempo, entendo bem o que a empresa deseja aqui e o que nosso código deve fazer.
Mas aqui comecei a encontrar constantemente códigos que não entendo - que problema resolve e por que foi escrito. E tomei uma decisão - se não entendo por que o código é necessário, ele não é necessário. Felizmente comecei a enviar esse lixo digital para o submundo.
Essa abordagem deu origem a novos problemas. A API pública do projeto estava errada. Havia muitos métodos com uma assinatura absurda (por exemplo, um método pega uma string e um objeto que contém a mesma string). Muitos métodos tinham nomes idiotas. E, em geral, se você usar esse SDK com a API que tinha, poderá quebrar o aplicativo de dez mil maneiras.
Neste momento, eu já fui longe o suficiente. O projeto não estava indo, e não havia chance de ele ir nos próximos dias. Tudo o que eu mudo nele, só posso verificar no final do trabalho. E já que mudei muito, por que não mudar a API pública? Bem, fui esperto o suficiente para fazer cópias de repositórios do SDK e aplicativos, para poder duplicar as alterações de API nessas cópias e encontrar erros. Afinal, eu não conseguia nem compilar a versão principal do SDK.
Os problemas começaram imediatamente. Mudou a assinatura de um método? Captura mais duzentos erros de tempo de compilação nos aplicativos. Por causa das assinaturas incorretas, os parâmetros incorretos foram passados para os métodos e os aplicativos funcionaram. Ao mesmo tempo, você trabalha em quatro janelas IDE. Depois de alterar os três métodos e curar todos os erros com eles, pensei - já que o trabalho já foi feito, será tolice alterar apenas parte da API estúpida - precisamos refazê-lo ainda mais. E ele entrou no processo ainda mais fundo.
Eu constantemente tive que tomar decisões, principalmente éticas. Então, eu sei como algo deve funcionar e agora vejo o código que deve fazê-lo. Eu li e entendi que ele não. Mas esse código está em produção, passou no controle de qualidade. E quem é o tolo? Como posso assumir essa responsabilidade? No começo, pensei muito sobre cada caso, consultado um líder e uma equipe. Mas demorou muito tempo.
Percebi que estava trabalhando devagar porque tinha medo de quebrar alguma coisa, tentando descobrir em algum lugar, para ter cuidado. Então eu disse a mim mesmo: "Sou mais esperto do que quem escreveu essa merda, sei o que precisa ser feito, tenho uma tarefa e um orçamento para refatoração e tenho direito a tudo". Wimps entende e se preocupa, um homem sabe o que quer e faz sem fazer muitas perguntas.
Em algum momento, entrei em um estado estranho de um robô que processa metodicamente um arquivo com código após outro. Sem verificar nada, sem duvidar de nada. Eu vejo um código incorreto - mude. Essa cadeia gera novas áreas problemáticas, reparando-as. Em cada um, substituo o govnokod por algo tolerável.
Parece uma blitz no xadrez. Você joga um jogo em que o mais importante é pensar em todas as opções possíveis, mas tem tão pouco tempo que nem consegue pensar em quais opções valem a pena pensar sobre elas. Eu sempre perco blitz. No segundo dia eu fiz muito. Aqui está apenas um código que você não pode verificar - não é um código. E eu sabia disso.
Uma noite, lembrei-me de ter prometido a minha esposa ir à Ikea. O apartamento em que morávamos era terrível, e minha esposa queria comprar qualquer lixo aconchegante. Escrevi código o dia todo, meu cérebro estava exausto, mas tive que ir. Coloque compartilhamento de carro, o carro mais próximo ficava a vinte minutos. Liguei para um táxi para chegar ao carro. Imagine um beco sem saída típico de Moscou cheio de carros nos olhos. No final, Renault Kaptur estava me esperando. Depois de derrotar a interface do usuário do Delimobile, consegui abrir esse bucket. Havia uma surpresa esperando por mim - caixa de velocidades automática. Eu nunca dirigi uma máquina, mas pensei que poderia lidar com isso. Se você quiser avançar, precisará mover a alça para frente, se para trás - para trás. Não. Percebi que o carro não estava indo exatamente no momento em que ainda era possível salvar a situação.
Freio deprimido. Naturalmente, o pé errado, porque em uma máquina estúpida apenas dois pedais, e meu cérebro não entendeu tudo. Idiota selvagem, o carro se levantou. Dois milímetros para o Mercedes S-Class.
De alguma forma, eu me arrastei para fora do beco sem saída e percebi que todos os carros do mundo estavam ao meu redor, mas eu não tinha ideia de onde ou como ir. Eu dirigi até a "casa", levei minha esposa, dirigi a meia-noite pela cidade mais terrível do mundo, perdi uma dúzia de voltas, deixei uma fortuna na ikea.
Voltamos às quatro horas da manhã, meu cérebro desligou assim que meus olhos viram a cama.
Às oito da manhã, estava no trabalho novamente. Todo mundo está feliz de novo, discutindo os assuntos e bares de Moscou que não consigo alcançar. Eu tenho o SDK novamente. Com a cabeça pesada, eu olhei através das mudanças que fiz. Tudo está muito ruim. Amanhã o rali estava se arrastando, e eu preciso de mais trezentos anos para terminar.
Eu tenho uma boa habilidade - quando recebo um ingresso grande, sempre o decomponho em vários pequenos. Daí o meu fluxo de trabalho. Um ticket, um ou dois commits, uma solicitação pull. Portanto, em princípio, não sou capaz de dividir a tarefa em vários commits no processo de codificação - geralmente não preciso disso. Mas o estresse acabou comigo e a habilidade falhou. No processo, transformei uma tarefa pequena em uma tarefa gigante, mas comecei a trabalhar da mesma maneira que trabalharia em uma tarefa pequena. Sem um sistema, estupidamente onde vi o problema, eu o consertei lá. Ele não dividiu o processo em etapas lógicas, mas simplesmente no último mês de junho.
Você não pode voltar atrás. O principal problema permaneceu - eu não conseguia criar e executar toda a solução e não tinha ideia de como ela funcionaria. Foi muito assustador, no último dia eu olhei as diferenças e percebi que havia reescrito quase todo o projeto. Foi assustador.
Tudo sempre desliza no último dia. A viagem de negócios terminou, meu tempo prolongado para refatoração também. Minha esposa telefonou e disse que estávamos sendo despejados à uma hora da tarde, embora eu tenha concordado com o final da noite. Naturalmente, isso significava que eu não poderia terminar o último dia até o fim.
Juntamente com três litros de suor frio, o que veio a mim quando assumi essa tarefa, planejei refatorar, concordou em uma viagem de negócios, levou crianças, tirou um esconderijo por duas semanas - sou o idiota mais importante do mundo. Vale a pena os psiquiatras resolverem meus motivos, mas eu decidi ir até o fim. Para me punir, ou para alguma crença irracional de que estou fazendo tudo certo.
Com uma bunda ardente, congelo tudo em uma hora, lancei o CI e despejo em casa. Todo o caminho que percorro meu código na minha cabeça e tenho certeza absoluta de que nada funcionará. Muitas alterações, haverá cem bugs e nós recusaremos essa refatoração.
Quando voltei para casa, as notícias estavam me esperando - o projeto está funcionando. O chumbo corrigiu algumas pequenas coisas, minhas alterações foram aprovadas em autotestes e agora estão sendo testadas com êxito. Eu não acreditei nisso. Eu estraguei o código de um carrinho de mão em casa, coletei e verifiquei manualmente todos os scripts nos quais não confiava. Funcionou. Funcionou !!!
Eu estava tão orgulhosa de mim mesma. A qualidade da base de código aumentou muitas vezes, vários recursos apareceram, resolvi vários bugs que os testadores ainda não conseguiram acessar. Liba podia ser usado confortavelmente, e eu provei ser profissionalmente apto.
Rajadas de entusiasmo e trabalho abnegado - o monte de tolos ingênuos. Eu ficaria feliz em provar o contrário de mim mesmo com esta história. Mas alguns dias depois de voltar, mais notícias estavam esperando por mim.
O cliente decidiu abandonar o projeto. Quase cem pessoas da equipe (metade de toda a empresa) estavam "esperando por um novo projeto". Considere - limbicamente desempregado. E os remotores em tais assuntos são cortados em primeiro lugar. Disseram-me para me mudar permanentemente para Moscou e mudar para outro projeto. Ou então despedimos você.
Perguntei o que aconteceria com o projeto antigo.
Nesses momentos, as pessoas se tornam dolorosamente honestas. Bajulação, enfeites e ética corporativa não são mais necessários. Disseram-me que esse código não é mais necessário para ninguém no mundo inteiro, enviado para o caixote do lixo da história. Os produtos em si serão usados por muito tempo, mas ninguém suportará a base de código. Tudo isso é a qualidade e legibilidade do código, escalabilidade, facilidade de uso, comportamento inequívoco - tudo foi feito em vão.
Eu escuto e entendo que eu poderia apenas fazer uma reportagem e andar pelas barras. Mas eu me sentei à noite, não dormi, sofri escândalos por uma boa base de código que ninguém mais precisava. Entusiasmo é uma coisa mentirosa. Você diz que está pronto para trabalhar, mesmo que não haja ganho nisso. Mas quando eles dizem que sua maior gratuidade realmente não traz benefícios - por algum motivo, mata. Você esperava mudar com o seu impulso toda a injustiça universal.
Eu acho que entendi tudo perfeitamente desde o começo. Eu só não queria ser um cara pragmático.
Portanto, eu disse que eles poderiam me demitir para o inferno e deixar que suas mães fossem transportadas para a merda de Moscou, para que suas nádegas rasgassem a borracha para um bilhão de pedaços pequenos. Ele educadamente escreveu sobre isso e ficou em casa. Existem tasas suficientes no mundo que precisam ser feitas.