Pular para o conteúdo principal

Blog do Dunossauro

Aprendi a programar e agora? Uma breve descrição sobre o ciclo de desenvolvimento.

Table of Contents

# Preâmbulo

Nesses últimos tempos, tenho pensado bastante sobre as “capacidades” que considero importantes em uma pessoa que desenvolve software. Sem nenhuma razão específica, acredito eu. Na verdade, essa pulga apareceu na minha cabeça após ter lido o texto incrível da Iris Meredith intitulado “Becoming an AI-proof software engineer”, ou, em bom português, “Tornando-se um engenheiro de software à prova de IA”. Embora o foco principal da postagem seja falar sobre a insanidade do mercado a respeito de papagaios estocásticos, meus pensamentos convergem com o texto da Iris, mas não são relacionados com LLMs. Eles giram em torno da questão que mais ouvi nessa vida ensinando programação: “aprendi a programar e agora?”

Observação importante: escrevo esse texto pensando única e exclusivamente para pessoas que são ou desejam seguir na área “profissional”, interprize buzines, da programação. Front-end, back-end, engenharia de software, ou qualquer outra coisa que o valha.

Outra observação: pessoas que fazem da programação um hobby, programam de forma criativa, áreas que usam programação como auxiliar à vida rotineira, etc. Esse texto não tenta conversar sobre isso. Embora, acredito que tenham insights para quem quiser saber mais sobre a área.

# Aprendi a programar e agora?

Quero me aprofundar um pouco nessa pergunta. Porque se você é uma pessoa mais experiente por aqui, sabe que essa é a manifestação óbvia e clara de Dunning-Kruger. Mas quem está projetando um início de carreira de desenvolvimento ainda não entendeu.

“Aprender a programar” é o primeiro passo, ótimo. Você aprendeu pensamento computacional, você aprendeu a sintaxe de uma ou algumas linguagens de programação, você sabe estruturas condicionais, blocos de repetição, funções, arranha uns objetos, entende alguns algoritmos. Não me entenda mal, isso é ótimo. De verdade. Parabéns, isso é estranhamente abstrato e complicado.

Mas, como diria Ferreira Gullar: “a vida bate”. Porque esse “e agora” nunca é sobre o que vem depois do básico, o “a seguir”, o que se prossegue. Lembre-se, a premissa é “aprendi”, parte do pressuposto de que a pessoa, no caso você, já sabe o suficiente.

Contudo, não quero entrar em um jogo linguístico aqui. As pessoas que dizem “e agora”, quase sempre, querem uma posição de trabalho, um emprego (formal ou informal) para desenvolver software.

Porque, claro: disseram que isso dá muito dinheiro! Obviamente, dá, pensando na realidade do Brasil. Mas, infelizmente, você vai ter que cair 7 vezes, como diria Leminski, antes de entender o tamanho do buraco.

Se você veio parar na programação pelo sonho do dinheiro fácil, vamos a um dado real do ensino formal. O que está contido nesse “aprendi a programar” é uma matéria de 40 horas de um bacharelado que tem no mínimo 2.400 horas. Dá pra notar que existe um grande “gap” aqui. Mas claro, o ensino formal não é um pré-requisito pro mercado. Mesmo pra quem vem de uma graduação, olhar o que o mercado de trabalho exige pode ser meio assustador.

Vamos olhar algumas vagas para a posição de Júnior em algumas grandes empresas brasileiras:

Requisitos da vaga 1:

  • Experiência com Python ou outra linguagem orientada a objetos (Go, Ruby)
  • Conhecimento em Microsserviços, Design Patterns e Arquitetura de Software
  • Conhecimento de bancos de dados relacionais e cache distribuídos
  • Experiência com testes automatizados (unitários e de integração)
  • Conhecimento em CI/CD, monitoramento, observabilidade, análises e alertas
  • Boas práticas de qualidade de software

Requisitos da vaga 2:

  • Linguagem de programação PHP
  • Frameworks Laravel, Lumen, Swoole + HyperF
  • Armazenamento de dados em bancos relacionais ou Mongo/DB (ou outros bancos não relacionais)
  • Ambiente de desenvolvimento com Docker
  • Atenção para a qualidade de código e design patterns
  • Desenvolvimento orientado a testes
  • Versionamento de códigos utilizando Git

Requisitos da vaga 3:

  • Linguagens de programação: Python e .NET
  • Uso de ferramentas AWS
  • Conceitos de CI/CD, versionamento e boas práticas de segurança
  • Entendimento básico de integrações
  • Uso de IA no desenvolvimento, apoiando aprendizado e análises técnicas
  • Testes unitários
  • Automação de atividades

Se você prospecta o front ou mobile, me desculpe por isso. Meu lado “back web” pesou bastante na escolha das vagas. Mas, ao final, o ponto aqui é o mesmo.

Notou uma coisa em particular? Nenhuma das vagas tem como requisito “programação”. Elas cobram coisas bastante objetivas: Tecnologias específicas, conceitos específicos e vivências específicas.

E antes que você pense “Ah… talvez isso tudo não seja pra mim”. O objetivo aqui não é desanimar você, muito pelo contrário, é tentar mostrar o tamanho do buraco. A distância entre você agora e o que o mercado prospecta em vagas de nível júnior. É construir uma perspectiva realista do mercado. Quem sabe dar uma “palavra amiga”, ou um blogpost todo… hahahaha

Inicialmente, parece muita coisa (e é), mas todos esses requisitos juntos explicam muito mais sobre a cultura atual de “engenheirar” software do que exatamente as capacidades específicas e super técnicas de ferramentas.

# A confiança de um ser profissional

Vamos construir um cenário hipotético que já fez parte da vida de todos nós. Suponhamos que precisamos contratar uma pessoa para prestar um serviço. Não sei, um encanador, talvez. Quando você contrata esse profissional, você espera diversas coisas do serviço, mas o mais óbvio é que a pessoa saiba usar uma “chave inglesa” nesse nosso exemplo.

Como você se sentiria se um encanador entrasse no seu banheiro e abrisse um vídeo no YouTube “como trocar uma torneira”? Isso seria bastante estranho, não? Eu acharia. Mas esse cenário meio que faz parte do estado da vida da pessoa iniciante em programação. “Como fazer X coisa no VSCode”, “Como criar um ambiente virtual”. Se você nunca googlou isso, sério… Pode admitir. Eu sempre faço :)

Se você vai cortar lenha, é bom confiar que seu machado está afiado. Como você resolve isso? Afiando!

Onde quero chegar com isso? A primeira habilidade e a mais óbvia que “se espera” de uma pessoa profissional é que ela “saiba trabalhar”, que você conheça o seu ferramental de trabalho. Você precisa de autonomia e domínio do seu editor de texto. Não importa se ele for o GNU/Emacs, o Vim, o Helix, o maligno VSCode, o Kate… Não importa. Ele é seu parceiro de trabalho, sua ferramenta. Você tem que AMASSAR com ele, usar a seu favor.

Você precisa conhecer seu sistema operacional, independente de qual seja, e dominar o shell dele. Fora isso, no escopo da sua linguagem, você precisa dominar o gerenciamento de pacotes, como instalar e desinstalar bibliotecas, como compilar algo, como gerar um pacote, etc. Entender as boas práticas de formatação (code style), como pegar erros antes com seus linters e LSPs. Você precisa dominar seu ferramental.

Isso vai além do técnico, da ferramenta em si. É sobre confiança. Saber como usar, entender os resultados que serão gerados, aprender onde erros são apontados, como interpretar essas mensagens, como as ferramentas se comportam em situações diferentes, etc.

É sobre ser proficiente no seu ambiente de trabalho. Pense em um mecânico de carro, no meio de todo aquele mundaréu de ferramentas, ele sabe onde elas estão e o que cada uma delas faz, o que elas resolvem. Reforçando, não é sobre a tecnologia, é sobre a confiança de conhecê-las. É sobre ser “funcional” fazendo o que você sabe fazer. É sobre autonomia no seu trabalho.

Essa parte foi fortemente inspirada no texto da Iris, leia, vale a pena!

E isso não está em vaga nenhuma, obviamente. Você é profissional, é esperado que se comporte à altura.

# Software como uma entidade viva

Embora somente uma das três vagas que selecionei cite diretamente versionamento, todas elas citam indiretamente e é bom ficar claro que raios isso quer dizer.

Em algum momento, o “git” vai bater na sua porta. Mas “aprendi git” é o “aprendi a programar” central nesse texto. É só a ferramenta. Versionamento de software quer basicamente dizer que nenhum software fica pronto nunca. Ele é vivo: vive de atualizações e manutenção constante. E saber lidar com versionamento é entender que sempre vai existir uma “próxima versão”.

Versões em uma empresa querem dizer muitas coisas escondidas que são muito mais do que Git. É sobre lidar com muitas pessoas “commitando” código no mesmo repositório ao mesmo tempo. Mudanças conflitantes, em linhas do tempo diferentes, adicionando, removendo, alterando… É o caos!

Fora o conhecimento “básico” da ferramenta git, entram requisitos “semânticos” silenciosos como:

Em conjunto com isso, parte sendo validada no seu ambiente pessoal por hooks de pré-commit, com suas ferramentas específicas, e sendo validado na estrutura completa em um ambiente de integração contínua que usam linguagens de configurações diferentes a depender da plataforma.

Que, no final, o produto disso será uma release versionada, um artefato do sistema, que precisa dos seus registros de alteração (changelogs) e deve seguir um padrão de versionamento como SemVer ou CalVer.

Como disse, um caos. De todos, acho que esse é o requisito mais “maldito” porque ele aparece de forma tão sutil, mas quer dizer TANTA COISA!

Mas lembra do papo da confiança do tópico passado? Isso ainda é a mesmíssima coisa. Só que ao nível coletivo. Como confiamos que juntos, cada um no seu ambiente, andamos em sincronia e falamos a mesma língua? A parte invisível do “versionamento” é exatamente sobre isso.

# A confiança no construído

Seguindo nos requisitos, uma coisa que apareceu nas três vagas, e de passagem o tópico que sou mais apaixonado nesse mundo da programação, são os testes!

Durante toda a formação de uma pessoa que desenvolve software, esse talvez seja o tópico mais subestimado de todos. Porque, afinal, testes são uma coisa meio óbvia. “Você vai escrever um código que seja capaz de validar se o código que está no programa faz o que deveria fazer”. Ao mesmo tempo em que isso é óbvio, isso passa silenciosamente por nós. Já ouvi papos assustadores como: “quem testa é o cliente”, “fui eu que fiz, funciona” ou então o mais assustador de todos: “testes atrasam o desenvolvimento”.

Por conta de papos como esses, a cultura de testes não é tão difundida em toda a nossa comunidade. Mas… pensa comigo. Garantir que o que você fez funciona não é o mínimo do mínimo? Chega a ser bizarro ter que falar sobre isso. Mas, você TEM QUE TESTAR e fazer isso com código que também vai ser commitado.

Vamos imaginar o cenário do tópico anterior: “várias pessoas juntas trabalhando no mesmo repositório”. Como conseguimos garantir que qualquer uma das pessoas não alterou o comportamento do sistema a ponto de ele não fazer o que deveria? E… olha só, os testes poderiam garantir isso a cada alteração. É o que chamamos de “regressão”. Garantir que, nas interações das pessoas com o repositório, o comportamento não “regrida”. Basicamente, funciona como foi feito pra funcionar.

Mas, embora esse assunto seja meio óbvio, e que constatar sua importância não seja nada difícil, imagina ouvir que isso “atrasa o desenvolvimento”.

É por esse motivo que vemos “testes”, “qualidade” em praticamente todas as vagas e em todos os níveis.

Embora esse tópico seja um dos que pareçam simples: “Escrever um bloco de código que garante que outro bloco de código faz o que deveria fazer”, esse assunto é um universo por si só no mundo da engenharia de software. Ele é tão importante que existe uma profissão na nossa área dedicada a esse assunto, os “testers”. Que não, não estão ali para escrever seus testes. Mas pra auxiliar o funcionamento de toda a estrutura distribuída de se construir um software.

Vários tópicos são muito importantes nesse assunto. Se o código de produção tem padrões, os testes também têm, existem formas de simular comportamentos com dublês, existem proporções de granularidade, têm seus próprios problemas, sua própria ordem de inicialização e finalização, sua organização, etc.

Como é possível ver, tem muita técnica envolvida. As ferramentas ajudam aqui? Claro que sim, frameworks, bibliotecas. Mas é muito sobre “feeling”. Coisas que, quanto mais você testa, mais você aprende a detectar possíveis problemas na sua aplicação, a entender como fazer códigos mais testáveis, e assim por diante.

Aqui é outro processo de construção de confiança, não pessoal, mas no produto final. A garantia de que aquilo faz o que deveria fazer.

# Quanto antes, melhor!

Sabe o que é engraçado? As vagas pediam CI (Integração contínua) e é nesse ponto em que você entende que o processo realmente converge. Sim, as coisas são coerentes. A ideia de integração contínua é mais simples do que o nome técnico sugere.

Imagina que estamos trabalhando em grupo, porque claro, estamos! Commitando a todo momento, cada um no seu quadrado, cada um nos seus testes. A integração contínua é o momento de garantir que todas essas mudanças continuam funcionando juntas. Integrando mais e mais alterações continuamente. Uma ferramenta de CI é responsável por pegar o individual feito e tentar juntar. Ela vai rodar diversas validações pra ver se a alteração A combina com a B. Isso inclui analisadores estáticos, aqueles mesmos que você tem no seu ambiente pessoal, para garantir uma conformidade do time. Um código “unificado” que parece do time, com os padrões do time. Em code style, em qualidade, executando os testes, validando a semântica dos commits e tudo mais.

E assim que um push é feito, toda a magia vem à tona. É a confiança de que todos os passos até agora seguem um padrão único, validados programaticamente. É sobre a conformidade do time sendo validada a toda hora. Podemos integrar? Quebrou algo? Fugiu na regressão?

# Seu ambiente é o de produção!

E, ao mesmo tempo, as vagas pedem em conjunto CD (Deploy contínuo) e Docker. Mas, o que essas coisas querem dizer exatamente?

Docker é sobre containers de aplicação. Ou seja, ambientes isolados, geralmente Linux, construídos programaticamente. Ao mesmo tempo em que todas as pessoas têm autonomia para gerir seu ambiente particular da forma que quiserem e se sentirem mais confortáveis. A aplicação fica isolada nesse container e, por ele ser definido programaticamente, sua configuração vira código no próprio repositório. É exatamente o mesmo ambiente para todas as pessoas do time.

Ou seja, vai funcionar igual em todos os contextos. Em todas as máquinas. Com isso, podemos pegar essa coisa fechada, com suas próprias dependências, e rodá-la contra os testes na etapa de CI. Garantindo que, após todas as validações, essa “coisa isolada” possa ser criada sem erros.

O papo aqui é que ninguém tem que “provar nada”, funciona igual pra todos, é determinístico. Essa é a garantia, a confiança de que “não funciona diferente na minha máquina”.

E talvez o ponto mais legal da engenharia moderna venha do ponto em que o resultado desses containers é exatamente as coisas que vão ser executadas em produção. Aí entra a parte de deploy contínuo.

Que nada mais é que pegar esse “artefato gerado”, rodar os testes e terminar o ciclo de versionamento. Colocar um número de versão e “TCHARAM!” colocar no ambiente produtivo. Exatamente da mesma forma que ele é executado na máquina de desenvolvimento.

Não é muito doido isso? Ou tô ficando maluco. É um ciclo foda! Convenhamos. hahahaha

# Sempre ao seu lado

Bom… Depois disso, o ciclo continua, mas tem mais coisas que precisamos falar aqui, coisas que também se escondem nos requisitos. Apareceu só na primeira vaga. Que é o acompanhamento da aplicação quando ela “vai pro mundo”, o depois do deploy.

Existem formas de “saber o que a aplicação está fazendo enquanto está rodando em produção”. Chamamos isso de observabilidade: a arte de entender a “saúde” da aplicação em tempo real. Via:

  • Logs: registros de eventos ocorridos com a aplicação. Algo como: “Deu ruim quando user 72gd6st12 emitiu um boleto”
  • Métricas: valores quantitativos da aplicação. Quantidade de acessos, de erros, pessoas conectadas, conexões do banco, latência de resposta, etc.
  • Rastreamento: quais partes da aplicação/das aplicações foram executadas em uma ação de um usuário, quanto tempo levou em cada uma, onde exatamente um erro aconteceu, com quais dados, em qual parte do fluxo, …
  • Monitoramento e alertas: mecanismos que avisam quando alguma coisa merece atenção ou até mesmo intervenção.

O acompanhamento da aplicação gera novas versões, detecta comportamentos estranhos, aponta problemas… Coisas que serão priorizadas em um novo ciclo do desenvolvimento do software vivo que temos. Fornecendo possíveis correções, lugares onde precisamos de mais atenção, validações.

Tudo isso se conecta, fechando um enorme ciclo de desenvolvimento. Gerando novas demandas, novas interações entre times, entre diferentes projetos. Aqui o papo de confiança continua. Porque é a certeza de que vamos saber mapear um problema que não vimos durante o desenvolvimento, que seremos alertados o mais rápido possível. É sobre entender o impacto que nossa aplicação tem no contexto da vida das pessoas, de outras empresas, etc.

# Concluindo: Tá, mas falei tudo isso por quê mesmo?

Talvez tudo que tenha tentado escrever aqui é que, no final, embora tudo seja extremamente técnico e leve um tempo demasiado pra se aprender, o que as vagas estão pedindo não é uma coisa de “outro planeta”. Todos esses requisitos poderiam ser reduzidos a um único: “Operar em um ciclo completo de desenvolvimento”.

Para ser bem honesto, eu nem sei se concordo com esse nível de exigência. Cobrar essa quantidade de conceitos de infraestrutura, arquitetura e processos de quem está tentando cavar uma vaga de Júnior chega a ser bizarro. É reflexo de um mercado doente, com toda certeza. Mas, jovem… aceite que as vagas são o que são. E a grande verdade por trás de toda essa sopa de letrinhas é que ninguém espera que você seja uma pessoa especialista em tudo isso. O mercado só quer alguém que consiga “rodar” a engrenagem. Alguém que entenda que seu código não é um bloco isolado, mas sim parte de um ecossistema vivo.

Oferecendo meu ombro amigo, é pensar que o que precisa ser “desenvolvido” ao nível de carreira não é necessariamente aprender um novo framework do momento, fazer mais um curso esse fim de semana, um “olá mundo” em uma nova linguagem. Todas essas coisas são ótimas e podem ser incrivelmente divertidas.

Pensando ao nível de mercado, talvez a maior preocupação deveria ser em como desenvolver um projeto “vivo”, algo que não “morre” na sua máquina, que escorre pro mundo. Isso pode acontecer de diversas formas. Talvez o padrão “ouro” seja tentar contribuir em um projeto de código aberto, que tenha um guia bem definido de contribuição. Mas, ao mesmo tempo, todas essas “técnicas” podem ser adquiridas em projetos pessoais, tirando a parte “grupo” da equação.

Qualquer plataforma moderna de repositórios (codeberg, gitlab, github) pode te oferecer o ferramental completo até a integração contínua. De forma gratuita e oferecendo uma boa documentação. Já pra colocar em produção, você pode procurar por clouds que ofereçam planos gratuitos para deploy e monitoramento. Desde uma coisa mais simples como PaaS para diminuir o atrito, que comumente oferecem até mesmo dashboards prontos para monitorar, até VPSs completas onde o trabalho é mais manual, mas podem te oferecer mais proximidade com a infraestrutura por trás das coisas.

O problema aqui é mudar a chavinha na cabeça, porque o buraco é extremamente mais fundo que os vendedores de sonhos costumam mostrar. Sei que isso não é fácil, é barulhento e, às vezes, é o caos puro.

Mas quando você vê esse ciclo acontecendo, quando aquelas linhas do seu editor chegam até uma aplicação rodando em produção, pessoas acessando, versões sendo construídas, você entende que “engenheirar” software é muito mais sobre o “adorno” em volta do código, sobre a garupa lateral da moto.

Então o “aprendi a programar e agora” se torna uma jornada determinística de técnicas e de aprendizado contínuo. Ainda é sobre escrever código, sobre seu framework favorito, sobre resolver problemas. Mas em um contexto amplo e diverso. Que vai muito além do “executei, funciona”.

# Uma última coisa…

Lembra que lá no preâmbulo citei o texto da Iris sobre se tornar um engenheiro à prova de IA?

Usa a caixola um pouco: você realmente acha que uma ferramenta que foi feita única e exclusivamente para prever a próxima palavra com base em estatística vai roubar o seu emprego porque ela consegue gerar código?

O menor problema do ciclo de desenvolvimento de software é o código.

Então… se tá chegando agora. Não, a IA não vai roubar seu emprego. Não se preocupe!



Comentários

Responda esse post por e-mail ✉️
Você também pode responder via fediverso:

Ao comentar nesse toot, seus comentários aparecerão na página

https://bolha.us/@dunossauro/116632471173639974