[go: up one dir, main page]

Blog

  • Dominando Processos Seletivos

    Dominando Processos Seletivos

    Artigo baseado na apresentação feita durante a PythonBrasil 2025 em São Paulo.

    Por Que Isso Importa

    Dominar processos seletivos é uma habilidade específica — e essa habilidade não tem nada a ver com trabalhar. Você pode ser um excelente profissional e ser péssimo em processos seletivos, e vice-versa. São competências distintas.

    As coisas são como são

    Esse texto não vai tentar idealizar o assunto. Os processos seletivos são injustos, falhos e desgastantes e nós, candidatos, sempre estamos na situação mais vulnerável.

    Aceitar isso é o primeiro passo. O jogo tem regras, e conhecê-las é a sua vantagem.

    Marketing & Venda

    No processo seletivo o produto é você. E como qualquer produto, ele precisa ser bem posicionado e bem apresentado.

    Durante um processo seletivo, o candidato precisa demonstrar interesse genuíno pela vaga (nem que seja pelo salário), que se preparou para aquela oportunidade específica, que tem as habilidades necessárias para o trabalho, que vai entregar o que é esperado, que cresce continuamente, e que sabe trabalhar com pessoas.

    Cada ponto desses não precisa ser declarado explicitamente, precisa transparecer na sua postura e nas suas respostas ao longo de todo o processo.

    Todo processo seletivo envolve muitas pessoas e uma característica humana importante é a de gostar de ouvir histórias. Por conta disso, uma forma bastante efetiva para trabalhar o seu marketing e seu processo de vendas é o storytelling.

    Se você conseguir embalar suas qualidades, suas limitações e seus diferenciais dentro de boas histórias, as suas chances aumentarão absurdamente.

    A Preparação

    Existe uma expressão antiga que diz:

    “Me dê seis horas para derrubar uma árvore e eu passarei as quatro primeiras afiando o machado.” — Abraham Lincoln(?)

    Todo bom profissional precisa investir tempo na preparação. Uma boa preparação poupa muitas dores de cabeça e frustrações na nossa carreira e não é diferente para encarar uma jornada de processos seletivos.

    “Cabeça”

    O ponto mais importante de toda a preparação é mental: prepare-se para ser rejeitado. Processos seletivos são, na prática, um teste da sua capacidade de lidar com rejeição. O processo inteiro é feito de rejeições, afinal, quando você para de ser rejeitado é porque o processo está terminando.

    A minha dica é tentar encarar cada “não” como “alguma outra pessoa tinha uma correspondência melhor com essa vaga”, não como “você é incapaz”. Você não é um conjunto de habilidades laborais. É uma dica mais fácil de oferecer do que praticar mas com o tempo você vai ficando melhor nisso.

    Currículo e Presença Online

    Tenha um Curriculum Vitae base genérico (ex. “Desenvolvedor Backend”), sem nível hierárquico, de uma ou duas páginas, focado no seu principal ponto forte, com contatos e sem firulas. Esse CV servirá de base para ser adaptado conforme a vaga.

    Seu perfil no LinkedIn deve estar em Português e Inglês, com as experiências descritas usando a Técnica STAR (mais sobre ela abaixo). Complete o perfil com um hub de redes sociais profissionais como site pessoal e perfil no GitHub. Lembre-se de manter somente conteúdo profissional nessas redes. Política eleitoral, futebol e tretas ficam fora.

    Não é obrigatório mas pode ser adequado fechar o seu perfil em suas redes sociais pessoais durante essa etapa. Não é incomum que recrutadores dêem uma espiada nas redes sociais pessoais dos candidatos. Eu sei que isso não é legal e não deveriam influenciar na sua candidatura mas, como eu disse, as coisas são como são e (ainda) não é o momento de lutar para mudá-las.

    Técnica STAR para Descrever Experiências

    A Técnica STAR é a forma mais eficaz de descrever experiências técnicas, tanto no LinkedIn quanto em entrevistas. A sigla representa Situação, Tarefa, Ação e Resultado:

    • Situação: O sistema de deploy da empresa era manual e causava erros frequentes.
    • Tarefa: Automatizar o processo para reduzir falhas e tempo de entrega.
    • Ação: Implantei um pipeline de CI/CD no GitHub Actions com testes automatizados e integração ao Cloud Run.
    • Resultado: O tempo de deploy caiu 70% e os incidentes pós-release reduziram em 90%.

    O padrão funciona porque força você a contextualizar o problema, mostrar sua contribuição concreta e quantificar o impacto, exatamente o que um recrutador ou entrevistador quer ouvir.

    Carta de Apresentação

    Tenha um modelo de carta de apresentação pronto para ser personalizado. Um modelo eficaz é simples e direto:

    Olá [nome do(a) recrutador(a)],
    
    Meu nome é [...] e estou entrando em contato sobre a vaga [...] pois acredito que tenho as habilidades necessárias para contribuir com a [nome da empresa] no desenvolvimento de produtos como [lista de produtos
    que você buscou no site da empresa].
    
    Gostaria de participar do processo seletivo e ter a oportunidade de descrever minha experiência em [lista de experiências específicas relevantes para a vaga].
    
    Em anexo segue meu CV e meu perfil no LinkedIn pode ser visualizado em [...].
    
    Obrigado,
    [seu nome]

    Organizando os Processos

    Mantenha um Kanban com as colunas Vaga, Contatado, Em Processo, Resultado. Em cada card, registre o link da vaga e o nome do contato.

    Use uma agenda dedicada exclusivamente para compromissos de processos seletivos e nunca deixe uma entrevista passar despercebida. Perder a hora de uma entrevista pode ser fatal.

    Equipamento para Entrevistas Remotas

    Mesa, cadeira e computador: nada de celular.

    A máquina deve estar estável (nada de software Alfa/Beta), com terminal e navegador abertos e prontos para uso, ou seja, esteja com o machado afiado e pronto para a ação mesmo se tentarem te pegar de surpresa.

    A câmera deve estar posicionada na frente ou levemente acima do rosto, para que você olhe o recrutador nos olhos.

    A iluminação deve ser direta para o rosto. A luz natural de uma janela funciona bem mas não descarte a possibilidade de uma iluminação dedicada.

    Para o áudio, use microfone, fone ou headset com fio: bluetooth acabando a bateria no meio da entrevista é constrangedor.

    Mantenha um fundo limpo ou um background virtual estático e neutro. Se tiver um fundo que deixe alguns hobbies aparentes tudo bem. Mas lembre-se: esses elementos do fundo podem causar distração no recrutador e tirar ele do que realmente importa: você.

    Entre na sala de reunião alguns minutos antes e teste imagem e som. Tenha papel e caneta à mão para anotar perguntas.

    A Prospecção

    Onde Buscar Vagas

    O LinkedIn, ao menos para programadores, continua sendo a fonte mais eficaz. O plano Premium ajuda, mas mesmo sem ele dá para filtrar boas oportunidades. Em seguida vêm os sites de vagas, depois networking e eventos, e por último indicações.

    As vagas por indicações geralmente têm as melhores chances mas infelizmente são mais raras.

    Tipos de Oportunidades

    Nem toda vaga é igual. Eu classifico as vagas em três categorias:

    • Vagas dos sonhos: são aquelas onde a empresa, o projeto ou o salário são exatamente o que você quer, mas a aderência às suas habilidades ainda não é total.
    • Vagas qualificadas: são muito alinhadas com o que você sabe fazer, mas sem muita empolgação com a empresa ou remuneração.
    • Vagas fraudulentas: geralmente são criadas para aplicação de golpes ou criação de base de dados. Fuja delas.

    O Processo

    Defina um número máximo de processos simultâneos: se estiver desempregado, quatro é um bom limite; se estiver trabalhando, dois. Gerencie tudo no Kanban e revise todos os cards toda manhã.

    Nunca se atrase para compromissos, mas esteja preparado para atrasos do recrutador. Sempre mencione que você está em outros processos, mesmo que não esteja. Se estiver empregado, garanta que o recrutador saiba disso também.

    Seja transparente com os recrutadores sobre o andamento desses processos e caso tenha algum imprevisto que te impeça de participar de alguma reunião avise o recrutador o mais rápido possível.

    A Entrevista

    Storytelling

    A melhor forma de lidar com uma entrevista é embrulhar ela em uma boa história que descreva a sua jornada com seus avanços, obstáculos, superações, etc. Lembre-se que o recrutador é um ser humano como a gente.

    Então, ao interagir com ele, apresente-se profissionalmente e construa uma narrativa de crescimento com as suas experiências. Se for seu primeiro emprego ou uma mudança de área, experiências indiretas também valem.

    Respeito também é fundamental. O recrutador é um trabalhador tal como você e não um adversário.

    Se você fica nervoso com entrevistas eu recomendo que você treine com um amigo antes de entrevistas importantes e não use LLMs durante a conversa, a menos que o entrevistador peça explicitamente.

    Durante a entrevista tem uma regra: não minta. Mas se precisar omitir algo, vá em frente. “Enfeitar” pode 😛

    Tenha “portos seguros” preparados para perguntas difíceis. Tenha um bom exemplo de trabalho em equipe, de superação, de aprendizado técnico, de colaboração, de projeto bem sucedido e de projeto fracassado. Quando uma pergunta difícil chegar é só sacar a carta certa e mostrar.

    Invente um motivo alinhado com o contratante para o seu interesse na vaga: “preciso pagar as contas” tem que virar “vi que vocês estão trabalhando bastante com a tecnologia X e é exatamente a área em que quero focar minha carreira”.

    Nunca fale mal de experiências anteriores. Resignifique essa experiência para algo como “uma experiência importante onde cresci muito com a ajuda do time”. Uma demissão injustificada se transforma em algo que “te deixou triste, pois tinha planos de ficar por muito tempo”.

    Tenha também uma explicação natural para períodos de desemprego: estudando um idioma, sabático, empreendendo, etc.

    Se for um problema de saúde pode mencionar mas lembre-se que ainda existe muito preconceito com alguns tipos de problemas (principalmente psicológicos/psiquiátricos). É uma merda, eu sei, mas… “As coisas são como elas são”.

    Sempre que a entrevista abrir espaço, faça perguntas sobre a empresa. Ao menos uma pergunta para cada área:

    • Pessoas: tamanho e perfil do time, organização das equipes, plano de carreira.
    • Processos: metodologia ágil, pipeline de tarefas, time de produto.
    • Tecnologia: stack, CI/CD, modelo de deploy, testes automatizados, code review.

    Red Flags na Entrevista

    Alguns comportamentos durante a entrevista indicam uma vaga problemática (aka vaga arrombada):

    • Perguntas sobre filhos ou planos para tê-los (especialmente para mulheres)
    • Comentários ou perguntas sobre aparência física
    • Questões de foro íntimo: relacionamento, moradia, política
    • Perguntas sobre saúde
    • Histórico de layoffs recorrentes na empresa
    • Sinais de precarização do contrato: PJ obrigatório, sistemas de tracking de trabalho, cultura de “trabalho duro” como valor

    Se mesmo assim você precisar muito da vaga: omita planos de maternidade/paternidade, use roupa neutra, evite comentar sobre família ou tratamentos. E comece a procurar outro emprego assim que for contratado.

    O Teste

    Existem diferentes tipos de entrevistas técnicas e dinâmicas de avaliação técnica. Se algumas empresas adotam uma entrevista simples outras poderão pedir para você programar alguma coisa (live coding) ou até mesmo entregar algum projeto completo.

    Entrevista Técnica

    Tudo o que falamos sobre participar de uma entrevista com um recrutador e a importância de conduzir um bom storytelling se aplica também na entrevista técnica.

    Para ter um bom resultado nessa fase é importante que você chegue sabendo tudo sobre as tecnologias usadas pela empresa. Também é importante que você “perceba” o seu entrevistador, por exemplo, programadores podem ser péssimos entrevistadores, ou o entrevistador pode ter menos experiência do que você. Nesses casos é importante que você faça a entrevista render bem. Você precisa ser mais proativo em expor suas habilidades.

    Alguns entrevistadores querem ver como você trabalha; outros se importam mais com o seu conhecimento sobre ferramentas específicas.

    Em toda a entrevista técnica é importante sempre pensar em voz alta. Mais do que saber sobre as coisas que você já sabe o entrevistador também está avaliando sua capacidade de pensar sobre os assuntos.

    Ao longo da minha experiência eu consegui distinguir três tipos de perguntas técnicas nessa fase:

    • Perguntas abertas: perguntas tais como “como você modelaria um CRUD de Clientes?” pedem que você percorra um raciocínio, não que chegue a uma resposta perfeita.
    • Perguntas fechadas: são aquelas como “o que esse código imprime na tela?”. Elas têm uma resposta certa. Para esse tipo de pergunta é possível responder “não sei, precisaria consultar” sempre que você não souber a resposta.
    • Perguntas opinativas: são feitas para saber se suas opiniões estão alinhadas com os valores da equipe, por exemplo, “o que você acha de SOLID?”. A resposta adequada para essas perguntas pedem que você seja genérico e equilibrado: “sei o que é, já trabalhei em projetos que usam e em outros que não. Como em tudo, tem prós e contras.”

    Duas respostas curingas que salvam: “Não sei, mas imagino que…” e “Depende, pode me falar mais sobre…”.

    Por último é importante evitar polêmicas sobre as escolhas técnicas da empresa, mesmo que eles deem abertura.

    Live Coding

    Treino é treino e jogo é jogo. Live coding é jogo. Pratique em plataformas como LeetCode, HackerRank, CodeWars ou Advent of Code.

    No momento da prova, pergunte se o entrevistador quer ver testes automatizados ou só o código. Se ele pedir testes esteja preparado para escrever testes.

    Como eu disse logo acima é importante que você diga tudo o que está pensando e fazendo em voz alta para o avaliador conseguir entender o seu jeito de trabalhar.

    Quando estiver trabalhando no problema sempre faça o código funcionar primeiro, mesmo com um algoritmo ingênuo ou ineficiente, para depois tentar otimizar e melhorar. Deixe claro para o avaliador que você vai fazer isso: “vou resolver dessa forma mais simples para garantir que entendi o problema; depois eu otimizo.” Se conseguir explicar a ineficiência em termos de complexidade algorítmica (Big-O), melhor ainda.

    Teste de Projeto

    Este tipo de avaliação está caindo em desuso, mas ainda pode ser encontrada por aí.

    Sempre “cobre” para fazer o teste. Empresas estrangeiras pagam por eles mas se a empresa não paga pelo teste peça que pelo menos você coloque o resultado no seu portfólio pessoal no Github. E fique atento a empresas que usam testes como trabalho gratuito.

    Faça somente o que o enunciado pede, ou seja, cuidado com over-engineering. É muito comum que o candidato, por querer mostrar todos os seus conhecimentos de Design Pattern, SOLID, etc encha o código de complexidade desnecessária.

    Foque no que é importante e poucas pessoas fazem: documentação, testes automatizados, arquivos de configuração, e padronização de código.

    Esse projeto costuma subsidiar alguma entrevista futura então esteja consciente do que você programou e lembre-se que é muito difícil ter essa consciência quando o código foi escrito por um modelo de IA.

    Red Flags no Teste

    Fique atento a três comportamentos problemáticos durante avaliações técnicas:

    • Dogmatismo: “só um modelo/linguagem/arquitetura presta, o resto é lixo” sem uma explicação ou justificativa sólidas.
    • Desleixo: desprezo declarado pelas boas práticas de engenharia de software.
    • Compartimentação extrema: times ou indivíduos muito segregados em funções específicas, o famoso “super-herói”.

    A Negociação

    Passadas todas as etapas do processo é chegada a hora da conclusão e da negociação.

    Em Caso de Recusa

    Agradeça o tempo e a oportunidade e não se esqueça de pedir feedback técnico: “poderia me dizer quais pontos não me qualificaram para que eu possa estudar mais sobre eles?” Pergunte sobre futuras oportunidades: “existe alguma política para aplicar a vagas futuras?”

    O objetivo dessas perguntas é simples: registrar que você realmente queria a vaga.

    Em Caso de Contratação

    Ninguém está fazendo favor para ninguém. O seu trabalho tem valor e precisa ser remunerado adequadamente.

    A pretensão salarial é sua.

    Diga ela, qualquer que seja. É função do contratante decidir o que fazer com essa informação. Negocie sempre o salário e trate benefícios, bônus, ações/options, e outros adicionais como brindes.

    Sobre PJ vs. CLT

    Faça as contas direito considerando rescisões, impostos, multas e garantias. Pergunte-se sempre o motivo pelo qual o empregador prefere o risco trabalhista de uma contratação PJ? Porque vai te pagar mais ou porque vai gastar menos?

    Se a empresa tiver um orçamento menor do que sua pretensão, negocie revisões salariais preventivamente: “aceito entrar por X, mas quero uma garantia para chegar em Y em Z meses.”


    Créditos da imagem em destaque: JOB INTERVIEW ..” by Bill Strain, CC BY 2.0

  • A Bunda do Cavalo do Unix

    A Bunda do Cavalo do Unix

    Tem uma anedota que correlaciona o tamanho dos ônibus espaciais à largura da bunda dos cavalos. Se você pesquisar por esses termos vai encontrar várias referências a essa história que, claramente, é uma bobagem.

    No mundo da computação a gente tem algumas dessas características que influenciam nossas vidas até hoje. Uma das mais óbvias é o teclado QWERTY que usamos até hoje (aliás, a história das teclas serem afastadas para evitar enroscos também é potencialmente falsa).

    Muitos anos atrás, antes mesmo de eu ter sequer nascido, existiam computadores gigantescos chamados mainframes e uns computadores “menores” que eram chamados de minicomputadores.

    Apesar de serem “mini” eles ainda eram enormes para os nossos padrões atuais.

    Uma coisa interessante dos computadores dessa época é que a gente precisava usar um outro equipamento para interagir com eles: o terminal.

    Os primeiros terminais se pareciam muito com uma máquina de escrever ou, para quem não conhece uma máquina de escrever, é só imaginar um teclado montado junto com uma impressora.

    Você digitava os comandos para o computador no teclado e esses comandos eram impressos em um papel que vinha de uma espécie de bobina contínua (ou em formulário contínuo com picote, remalina, etc). As respostas do computador também eram impressas nesse formulário.

    Para quem se perguntou por que os caracteres ASCII especiais \r se chamam “carriage return” (retorno de carro), \n “new line” (nova linha), entre outros, é porque eles comandavam essa impressora a retornar o carro para a coluna inicial e avançar o papel para uma linha nova em branco.

    Com a evolução da tecnologia os terminais foram evoluindo e deixaram de usar papel para usar vídeo e, hoje, textos dentro de uma janela de um aplicativo de… “terminal”.

    O sistema operacional Unix (papai do Linux e vovô do macOS) nasceu no mundo dos minicomputadores e foi desenvolvido inicialmente com terminais convencionais chamados de teletype (teletipo).

    O Unix mapeia os dispositivos em arquivos. E o arquivo para mandar informações de/para um terminal TTY (teletype) é /dev/tty até os dias de hoje mesmo usando um terminal dentro de uma janela do nosso ambiente gráfico.

    Nessa mesma época os usuários do Unix precisavam editar arquivos para fazer coisas básicas como, por exemplo, programar. O editor que eles usavam era o editor (sim, eles eram pouco criativos para nomes).

    Imagine que em um teletipo não tem o conceito de navegar com um cursor pelo texto. Toda a edição era feita através de comandos para o ed.

    Uma das coisas que todo editor precisa oferecer é uma ferramenta de busca de texto em um arquivo inteiro. Para fazer uma operação em um arquivo inteiro no ed eles usavam o comando g (global).

    Para fazer uma busca de um texto não tem nada mais poderoso do que usar uma expressão regular (sim, elas já existiam naquela época). Então a gente delimitava uma expressão regular com um par de barras: /.../. Por último, a gente precisava instruir o ed sobre o que fazer quando ele encontrava o texto procurado. Uma ação comum era pedir pro ed imprimir a linha, ou seja, (print).

    Então recapitulando os passos ficaria: global, /regular expression (re)/, print.

    g/re/p

    Se precisasse fazer isso na linha de comando, que nome eu daria para esse comando? grep!

    E se eu precisasse aplicar comandos do ed em um stream de texto ao invés de só interagir com um arquivo? Eu criaria um stream editor ou somente sed.

    Como vocês puderam ver, decisões de muitos anos atrás ainda influenciam o nosso dia a dia até hoje.

  • Gramática e Programação

    Gramática e Programação

    Eu sempre detestei aprender línguas. Só me esforço para aprender o básico de um idioma quando realmente não há outra forma de sobreviver sem ele. Foi assim que acabei aprendendo o suficiente de inglês e português.

    Lembro que, na escola, eu odiava as aulas de português. A única parte que eu realmente curtia era Literatura. Todo o resto era um verdadeiro martírio.

    Mas o destino, com seu senso de humor peculiar, colocou meus dois professores de português como vizinhos de muro. Em anos pares, eu tinha aula com uma professora; em anos ímpares, com um professor.

    Como eu sempre ficava de recuperação nessa matéria, minha mãe acabava pagando aulas particulares — com o professor do outro ano. O resultado? Eu tinha o dobro de aulas de português com os dois vizinhos ao longo do ano inteiro.

    Por conta disso, acabei aprendendo algumas coisas “úteis completamente inúteis”. Por exemplo, sei que toda paroxítona terminada em ditongo crescente era acentuada, mas que, com a nova reforma ortográfica, isso deixou de ser verdade. Se antes “idéia” tinha acento, agora não tem mais.

    Outra coisa que aprendi, à base de muita dor e sofrimento, foi análise sintática. Toda aquela parte que disseca as sentenças e mostra como elas são compostas: os sujeitos e predicados, os verbos com suas “transitividades”, os objetos, e por aí vai. Tudo isso foi entendido, ainda que sem compreender o mais importante: por que, afinal, eu estava aprendendo isso?

    Nessa época, eu já sabia programar e até tinha começado a trabalhar profissionalmente com programação (sim, comecei bem antes da lei permitir). Mesmo assim, eu não conseguia “conectar os pontos” e enxergar as relações entre a gramática e a programação.

    Programação

    Programar é comunicar. E, para comunicar, precisamos de uma linguagem comum entre todos os envolvidos no processo.

    Ao longo dos anos, a computação desenvolveu uma infinidade de linguagens de programação, cada uma com suas próprias características e propósitos. Essas linguagens facilitam a comunicação entre programadores e computadores, além de permitir que os programadores se entendam entre si.

    Por exemplo, qualquer programador que conheça Python e um computador com um interpretador Python será capaz de entender e executar códigos escritos nessa linguagem.

    Assim como os idiomas e linguagens naturais, as linguagens de programação possuem gramática. Elas se preocupam com sintaxe, semântica, pragmática, entre outros aspectos que fazem parte do estudo das línguas. Além disso, também possuem um léxico e vocabulário próprios que, se não estão estritamente sob o guarda-chuva da gramática, fazem parte do domínio linguístico.

    Python, assim como muitas outras linguagens de programação, é uma linguagem imperativa. Isso significa que você escreve comandos para instruir “como” as coisas devem acontecer. Nesse paradigma, o foco está em ações e etapas específicas.

    Por outro lado, linguagens que seguem outros paradigmas — como funcional, declarativo, lógico ou de marcação — não se preocupam tanto com o “como”, mas sim com o “o quê” deve ser feito.

    Aqui é possível traçar um paralelo interessante entre o paradigma imperativo na programação e o modo verbal imperativo na língua portuguesa: ambos lidam com comandos e ordens. No português, a conjugação dos verbos no imperativo é usada para instruir ou demandar ações — exatamente o que fazemos ao escrever código em uma linguagem de programação imperativa.

    Tá, e daí?

    Se programar é comunicar e usamos linguagens para transmitir algo, será que os conhecimentos de gramática de uma linguagem natural (português, inglês, alemão, etc.) podem ajudar a melhorar o nosso código?

    Eu acredito que sim. E, a seguir, vou listar algumas práticas que adoto ao desenvolver meus projetos.

    Vale lembrar: estou falando de projetos de software escritos em linguagens de programação imperativas, não de uma obra literária. As sugestões que vou apresentar podem melhorar o seu código, mas provavelmente seriam péssimas escolhas para seu conto, romance ou artigo acadêmico.

    Sentenças simples

    Escrever sentenças simples facilita a compreensão. A estrutura mais básica de uma sentença segue o padrão:

    Sujeito — Verbo — Complemento

    O sujeito pode assumir várias formas, mas geralmente é representado por um substantivo (nome/noun). Em linguagens orientadas a objeto, o sujeito é (quase) sempre um objeto. Assim, uma sentença simples em código poderia ser algo como:

    objeto.verbo(complemento)  # ou...
    objeto.verboComplemento()

    Parece óbvio, não? Sim, é básico, mas dito dessa forma, fica claro que os métodos de um objeto devem necessariamente ser verbos, e que os parâmetros passados ao método funcionam como complementos — nos moldes da análise sintática da transitividade dos verbos:

    • Verbo Transitivo: Requer um complemento (objeto direto ou indireto) para completar seu sentido.

    Exemplo: “Ela comprou um livro.” (complemento: “um livro”).

    • Verbo Intransitivo: Não precisa de complemento, pois possui sentido completo por si só.

    Exemplo: “Ela dormiu.”

    Se o verbo usado no nome do método for transitivo, é importante lembrar que ele exige um complemento para que a ação faça sentido. Essa escolha ajuda a tornar o código mais intuitivo e compreensível.

    Single Responsibility

    Observe que a sentença usada como exemplo contém apenas um verbo. Mantendo essa estrutura, também garantimos que cada método realiza apenas uma ação:

    1 verbo → 1 ação → 1 responsabilidade

    Trabalhar dessa forma nos ajuda a garantir que nossos métodos respeitem o Princípio da Responsabilidade Única (Single Responsibility Principle – SRP), que estabelece que cada método ou função deve ter apenas uma responsabilidade clara e bem definida.

    Interfaces REST HTTP

    Interfaces são um meio de disponibilizar o acesso a componentes do seu sistema. Existem diversos tipos de interfaces que podemos utilizar, e uma delas são as APIs REST, que usam o protocolo HTTP.

    O protocolo HTTP trabalha de forma stateless: um cliente faz uma requisição (request) para um recurso/documento/objeto em um servidor, e o servidor retorna uma resposta (response) para o cliente. O formato de uma requisição HTTP é aproximadamente assim:

    METHOD /url
    Header1: ...
    HeaderN: ...
    
    <payload>

    Alguns dos METHODs disponíveis são: GETPOSTPUTPATCHDELETE, etc. Perceba que todos os métodos são verbos, ou seja, indicam ações requisitando algo do servidor. Seguindo nossa lógica gramatical, podemos inferir que a /url é o complemento (geralmente representado por um substantivo).

    Como mencionado anteriormente, é importante manter as sentenças simples, ou seja, com apenas um verbo por requisição. Uma boa interface deveria seguir este padrão:

    GET /users/1
    POST /users
    DELETE /users/c0ffe

    No entanto, é comum encontrar requisições que apresentam dois verbos na mesma sentença:

    POST /contracts/1/remove
    GET /documents/2/cancel

    Percebe como isso soa estranho? Casos como esse geralmente aparecem quando a ação envolve processos mais complexos. Por exemplo, cancelar um contrato pode exigir várias etapas, e um simples DELETE /contracts/1 pode não ser suficiente. Quando isso acontece, uma boa prática é transformar o segundo verbo em um substantivo, tratando o processo como um objeto.

    Por exemplo, ao invés de usar algo como:

    POST /contracts/1/cancel  # verbo + verbo

    Eu prefiro reestruturar assim:

    POST /contracts/1/cancellation  # verbo + substantivo

    Essa abordagem não só torna a requisição mais natural, como também reflete melhor a lógica gramatical e mantém a consistência da interface.

  • Economia dos Testes

    Economia dos Testes

    No mundo dos testes automatizados, os testes são classificados por níveis de validação. Testes que validam uma pequena unidade de código são chamados de testes unitários (unit tests). Quando validam a integração entre componentes, são chamados de testes de integração (integration tests).

    Esses dois tipos de testes são os mais comuns. No entanto, também existem testes que simulam a interação real do usuário com a aplicação, conhecidos como testes end-to-end.

    Cada tipo de teste gera custos de desenvolvimento, manutenção e execução ao longo da vida de um sistema. Em linhas gerais, quanto mais simples e pequeno um teste, mais barato é escrevê-lo e mantê-lo. Por exemplo, testes unitários são mais baratos que testes de integração.

    O tempo de execução dos testes varia e isso também influencia no custo dele. Testes unitários são rápidos, enquanto testes funcionais ou end-to-end demoram mais devido à etapa de preparação que costuma ser bem longa.

    Testes bem escritos custam mais para serem desenvolvidos, mas reduzem os custos de manutenção. O oposto também é verdade: testes mal escritos podem até ser mais baratos para serem escritos, mas custam caro para serem mantidos.

    Os testes unitários são fáceis de escrever e manter se o código estiver bem desacoplado, pois testam apenas uma pequena unidade de código. Testes de integração, embora mais caros, garantem que a comunicação entre partes do sistema funcione corretamente sem que o tempo de execução aumente.

    Com os testes funcionais ou testes end-to-end avaliam a capacidade do software de resolver problemas reais. Como o nome diz eles testam se o software “funciona”. Embora desejáveis, são difíceis de escrever corretamente e são os mais caros de desenvolver, manter e executar.

    Entendendo a relação entre o custo e os benefícios que cada tipo de teste trás, como distribuir o “orçamento” que você tem para escrever testes?

    Minha estratégia

    Minha estratégia favorita é escrever muitos testes unitários, alcançando alta cobertura.

    Exemplo: 235 passed in 100s; 99.98% coverage

    Também escrevo testes de integração para cenários ideais (happy path) e de falhas esperadas.

    Exemplo:

    1. Teste acessar perfil público do usuário @publico
    2. Teste falha ao acessar perfil privado do usuário @privado
    3. Teste falha ao acessar qualquer perfil sem autenticação

    Não faria um teste de integração para “Falha ao acessar um usuário com nome inválido” porque um teste unitário já deveria garantir isso. Se a regra mudar, não preciso alterar testes em vários lugares.

    Para os testes funcionais ou end-to-end, foco nos fluxos fundamentais do sistema.

    Exemplo:

    1. Fluxo de Cadastro (sign up): se esse fluxo quebrar, novos clientes não serão convertidos.
    2. Fluxo de Registro (sign in): se esse fluxo quebrar, clientes não conseguirão usar o produto.
    3. Fluxo de Compra (check out): se esse fluxo quebrar, em um e-commerce, não venderíamos.

    Ou seja, escrevo testes funcionais ou end-to-end apenas para garantir que, se algo falhar, a aplicação não se torne completamente inútil.

  • Transpire Qualidade

    Transpire Qualidade

    Na biografia do Steve Jobs escrita pelo Walter Isaacson, tem um trecho em que o biografado fala sobre a influência que o pai dele deixou para ele na criação de produtos.

    Ele conta que o pai gostava de fazer alguns trabalhos de marcenaria por passatempo e que um dia ele estava corrigindo um pequeno defeito na parte interna de um guarda-roupa que ele havia terminado de construir.

    O Jobs vê o pai investindo um esforço enorme naquele conserto, pergunta:

    — Pai, esse defeito está do lado de dentro… ninguém vai ver ou se importar com isso.

    No que o pai dele responde algo como:

    — Eu vi e por isso me importo.

    O mito e as histórias criadas sobre o Steve Jobs mostram que ele sempre foi obsessivo pelos detalhes dos produtos que ele ajudou a criar até os mínimos detalhes internos das placas de circuito impresso.

    Ele fazia isso porque ele entendia que o cuidado com as todos os aspectos do produto “transpiravam” para a qualidade geral dele. Ele também fazia isso porque era um tremendo babaca, mas isso a gente pode discutir em outro momento.

    Seu código transpira

    Várias vezes ao longo da minha carreira esbarrei com empresários, gestores, profissionais da área de produto e até mesmo desenvolvedores que diziam que a qualidade do código não era tão importante quanto o fato do produto estar “funcionando” e “entregando valor para o cliente”.

    Será mesmo? Será que teu cliente sabe que aquele software porcaria que ele está usando poderia ser muito melhor, mais eficiente, mais estável, etc.?

    Vamos ser honestos… vocês não estão de saco cheio de usar software lento e cheio de problemas? Vocês já tentaram comprar passagem aérea recentemente? Fazer um PIX no aplicativo do seu banco? Já tentaram resolver um problema com seu pedido em um site de e-commerce?

    Sabe porque a nossa vida é miserável assim? Porque toda a engenharia de software está mais comprometida em desenvolver software do que refatorar software.

    Afinal de contas, todos os “stakeholders” estão interessados em vender mais, faturar mais, aumentar o “market share” e se, por exemplo, aquele sisteminha de rastreamento de encomenda está mal-feito ou com uns bugs que afetam só 1% dos usuários pode deixar lá.

    O custo de refatorar esse sistema para ele funcionar melhor seria muito alto e esses recursos seriam melhor empregados implementando um sistema de venda de publicidade para aumentar as vendas no site, não é mesmo? E aqueles 1% dos usuários afetados pelo problema já compraram, não é mesmo?

    Para os “stakeholders” é melhor investir em uma funcionalidade que aumenta o faturamento em 5% imediato do que arrumar um sistema que afeta somente 1% do que já foi faturado.

    Aquele pequeno “TODO”

    E se você está pensando que estou falando apenas dos grandes sistemas e serviços, você está enganado. Estou falando daqueles “TODO” e “FIXME” espalhados pelo seu código.

    Estou falando daquele backlog de consertos e refatorações que nunca é priorizado pelo time. Daquele código “vizinho” ao seu que está cheio de problemas e que não será melhorado porque está fora do escopo da sua tarefa.

    Quando eu trabalhava diretamente com software livre e open-source era muito comum você encontrar melhorias para fazer no código conforme você ia desenvolvendo seu próprio código. Se você mandasse seu código sem melhorar o outro código vizinho provavelmente rejeitariam sua contribuição até que você fizesse tudo direito.

    Fazer isso em uma empresa tem se mostrado quase impossível.

  • Publique-se!

    Publique-se!

    Eu produzo conteúdo técnico sobre programação e carreira desde que esse negócio de “produzir conteúdo” se chamava blogar.

    Nunca fui um blogueiro prolífico, mas sempre tentei deixar meus aprendizados e ensinamentos públicos ao longo do tempo. O meu blog pessoal mudou de nome e propósito várias vezes nessa jornada. Ele já se chamou “aCiDBaSe” (o meu ‘nome hacker’ da era IRC), Pythonologia (na minha época “Python Promoter”), Blog da Triveos (quando tive minha empresa) e, hoje, ele é só um humilde blog WordPress com 5 plugins e tema padrão rodando na minha humilde (mas excelente) hospedagem (link com meu referral) compartilhada onde também hospedo meus e-mails longe de provedores que podem decidir fechar minha conta unilateralmente.

    Sempre desejei produzir conteúdo e compartilhar as coisas que aprendi. Mas desenvolver a disciplina para fazer isso com regularidade e uma boa frequência sempre foi um problema.

    Ainda não sou o cara que gostaria de ser e não produzo tudo o que gostaria de produzir, mas recentemente eu comecei a me sentir melhor comigo mesmo nessa tarefa e, como consequência, a disciplina foi melhorando.

    Como sou um nerd que gosta de listas, eu vou enumerar aqui as mudanças que fiz na minha vida e nos meus processos que fizeram tudo ficar melhor e mais fácil:

    Me respeitar

    Eu me sentia mal por não produzir conteúdo. Me pressionava o tempo todo sobre isso e me sentia mal quando não conseguia corresponder às minhas próprias expectativas.

    Quando comecei a trabalhar isso na terapia, eu fui me dando conta que isso não é uma obrigação e que não atender a essa necessidade era algo compreensível. A angústia foi diminuindo e hoje eu estou bem melhor com o volume de coisas que faço.

    Significa que é fácil ou que tiro isso tudo de letra? Nem de perto. Mas quando a angústia e a ansiedade surgem eu consigo buscar a origem dela e trabalhar melhor o problema.

    Remover distrações

    Eu comecei a fazer isso bem antes do meu diagnóstico de TDAH, mas certamente foi um divisor de águas no processo. Mesmo sem saber do TDAH, eu já tinha percebido que uma fonte de impedimentos para minha produção eram as distrações.

    Que tipo de distração? Com ferramentas.

    Yak Shaving

    Toda vez que eu tinha uma ideia sobre algo para postar no blog, eu entrava na interface de admin, atualizava tudo, trocava o tema, tentava exportar o conteúdo para outro CMS, testava YA-ferramenta-geradora-de-sites-estáticos, testava um plugin novo, conferia o SEO e analytics do site… um processo infinito de Yak Shaving.

    Como eu disse acima: hoje eu uso WordPress na minha hospedagem (que oferece one-click-installation de WordPress) no meu domínio onde já rodo meus e-mails. Deixo autoatualização ligada para tudo. Tenho só uns poucos plugins de segurança e backup ligados. Coloco tudo por trás do Cloudflare (pacote gratuito) para ter `https` sem ter que ficar instalando/renovando certificados SSL. E uso o tema padrão do WordPress (que muda nos updates major e eu só aperto “accept” do meu lado).

    Não tenho que criar, habilitar, configurar, etc. nada para colocar o site no ar e publicar meus textos. Nada de GitHub Actions, static file generation, S3, Cloudfronts, CDNs, etc. (exceto o Cloudflare por comodidade para ter https).

    Também não tenho Analytics instalados exceto por um bem básico que vem no plugin Jetpack e um gerado pelo Cloudfront.

    A ideia é tornar o processo tão simples quanto clicar em “Novo Post”, escrever, e clicar em “Publicar”.

    Conforto

    Eu sempre gostei de escrever. Texto mesmo. Escrevi no meu blog, no meu livro, nas minhas redes sociais, etc. Acho que, por gostar de ler, eu sempre gostei de escrever. Na infância até ganhei uns concursos de redação do jornal da cidade.

    Mas senti que as novas gerações não estavam mais muito ligadas em conteúdo texto. Decidi me aventurar em novos meios: vídeos.

    Investi uma grana pesada porque eu sou (burro) assim: se é para fazer algo, tem que ser perfeito.

    Estúdio “profissional” com equipamento de primeira linha (na foto não aparece mas tem câmera profissional, GoPro, DJI Osmo e até um Drone eu comprei)

    Até a chácara da família foi desenhada para ser usada como um estúdio para conteúdos mais “maker” que eu pretendia (ainda pretendo) fazer.

    Futuro estúd… digo… chácara da família.

    Mas deu tudo errado. Eu descobri que não gosto de produzir vídeos. As únicas coisas dos meus vídeos que me deixavam satisfeitos eram os roteiros. Porque eram textos. Depois dessa etapa era tudo horrível. Principalmente a edição (eu odeio editar video…)

    Dei um pause (ainda não sei se é definitivo) no canal. É provável que eu volte a produzir coisas ali só quando eu quiser mostrar meus aspectos mais “make“. E quando eu tiver condições de pagar alguém para editar (repito: eu odeio editar video).

    Eu me sinto confortável com texto. É com ele que eu vou trabalhar. Se as pessoas não curtem texto é uma pena. Mas não vou sair do meu conforto para elas. E já tem muita gente boa fazendo video.

    Ótimo é inimigo do bom

    Eu sou muito chato com o que escrevo. Tudo tem que estar perfeito, completo, com referências, revisado, … Impecável. Isso é um baita muro na minha produção.

    Ter começado a publicar coisas incompletas, com erros (que são corrigidas quando apontadas), ou com a qualidade “mais-ou-menos-para-mais” e mesmo assim receber feedback positivo da audiência foi libertador para mim.

    Vencer meu preconceito com certas ferramentas, e nem estou falando de IA (ainda), me tornou muito mais produtivo.

    Ainda não consegui estudar o suficiente para adotar uma ferramenta de IA no meu fluxo de trabalho, mas é quase certo que vou adotar uma logo. Mais para me ajudar na revisão (e edição) do que na autoria. Por uma questão filosófica, eu (ainda) tenho um certo preconceito com o uso desses geradores na autoria do meu conteúdo (ele seria meu ainda?).

    Eu já falei um pouco sobre isso em um post aqui mesmo no LinkedIn. Lá eu falo sobre usar o LanguageTool para revisar e eliminar erros mais básicos do texto.

    Seu conteúdo na sua casa

    Sempre que o conteúdo que eu produzo se apresenta de uma forma relevante, eu publico ele no meu blog, no meu domínio, na minha hospedagem (ok, não é minha, mas eles não são uma big-tech que ganha dinheiro com meu trabalho).

    Esse artigo foi publicado inicialmente no LinkedIn, mas logo coloquei ele aqui também. Na verdade, esse é o primeiro artigo que escrevo primeiro no LinkedIn e só fiz isso porque queria conhecer melhor a ferramenta deles (curti).

    Mas a minha recomendação é: tudo o que você produz deveria estar na sua “casa”. E a sua casa deveria ser uma casa própria.

    Publique e mantenha seu conteúdo no seu site, na sua hospedagem, no seu domínio, sob suas regras e sob seu controle.

    Conhecimento precisa ser livre

    Esse item se relaciona um pouco com anterior porque quando produzimos um conteúdo em uma plataforma proprietária como aqui, Medium, Twitter, YouTube, Spotify, etc. a gente entrega o nosso trabalho para um terceiro que passa a ter mais controle do que você sobre esse trabalho.

    Não se aprisione. Use essas redes e plataformas para referenciar ou até mesmo replicar o seu trabalho.

    Não recomendo muito a replicação por questões de SEO e “findability“, mas se você estiver buscando uma presença nessas plataformas a replicação pode ser uma boa estratégia.

    E, quando estiver com seu conteúdo no ar, torne ele facilmente compartilhável. Se você faz seu conhecimento facilmente compartilhável, ele alcança mais pessoas e circula mais livremente.

    Mas ele tem que ser compartilhável por meios abertos e com padrões abertos também. Não somente em redes fechadas e proprietárias.

    RSS (Really Simple Syndication)

    A maneira que eu defendo (e promovo/agrego) o compartilhamento do seu conteúdo é através do RSS. Mas eu só considero um RSS correto quando ele é completo e não somente um resumo com um link de “leia mais/read more”.

    Aaron Swartz, grande ativista do compartilhamento livre, um dos criadores do RSS

    Todos os sistemas de publicação sérios suportam RSS (ou Atom que dá no mesmo).

    Disponibilizar seu conteúdo por RSS/Atom é mais do que só compartilhar. É um ato político no sentido de retomar a Internet das mãos das grandes empresas de tecnologia.

    O formato RSS foi co-criado pelo ativista Aaron Swartz, que acreditava e defendia a liberdade e a democratização do acesso ao conhecimento. Ele morreu por isso.

  • Nem certo e nem errado

    Nem certo e nem errado

    Se tem uma área do conhecimento onde os debates são quase sempre bem acalorados, essa área é a do desenvolvimento de software. Tem todo tipo de disputa, das mais bobas como Tab vs. Espaço, temas claros ou escuros, 80 colunas ou não, etc. até as mais complicadas: tipos estáticos ou dinâmicos (ou qualquer variante doida), OO ou funcional, código aberto ou software livre, etc.

    Em comum com todas essas discussões é a tendência entre os debatedores de apelar para conclusões binárias: “é isso aqui ou está errado.”

    Essa postura também aparece quando as pessoas que estão habituadas a um conjunto de conceitos precisa se adaptar a outros conceitos. Um exemplo: a pessoa que usa Windows (ou Linux) reclamando do botão de maximizar janela do macOS. Ela com certeza vai reclamar e dizer que aquilo está errado. Mas se você lembrar que a primeira empresa a lançar uma interface baseada em janelas para o grande público foi a Apple e só depois o Windows e o Linux surgiram fazendo diferente, quem está “errado” nessa história?

    No meio do desenvolvimento de software, talvez porque computadores eletrônicos que usamos sejam binários, adoramos a segurança das respostas absolutas. Isso é certo. Aquilo é certo. Isso é errado. Aquilo é errado.

    No mundo Python onde eu trabalho tem até um termo (que eu detesto) para isso: pythônico. Todo mundo ouve, mas ninguém sabe o que é.

    Mas o tempo me ensinou que as coisas podem simplesmente “ser”. Nem certas e nem erradas. Provavelmente diferentes, provavelmente similares.

    Indiferente das alternativas se parecerem ou não, uma coisa é certa: cada uma das opções tem os seus pontos favoráveis (prós) e seus pontos desfavoráveis (contras). E, quando escolhemos uma opção, temos que renunciar às outras. É a tragédia (e a beleza) da vida.

    Entrevista de emprego

    Toda essa introdução serviu para falar sobre uma coisa que eu sempre faço quando estou entrevistando um candidato para uma vaga: perguntas específicas com poucas alternativas de respostas onde nenhuma das alternativas é certa ou errada.

    Vou dar um exemplo com a minha famosa pergunta sobre ORMs.

    Um ORM (Object-Relational Mapper) são softwares que servem para conectar o mundo dos objetos em um sistema orientado a objetos aos registros (linhas, tuplas, etc.) de um banco de dados relacional.

    Esse tipo de software é bem complicadinho de se escrever porque o modelo relacional tem algumas diferenças fundamentais com o modelo orientado a objetos e lidar com essas diferenças sempre força o desenvolvedor a fazer certas escolhas em detrimento de outras.

    Não vou detalhar muito essas diferenças e nem as alternativas aqui porque elas não são tão importantes para a pergunta e nem para a resposta, mas recomendo a leitura dos artigos que falam sobre esse tópico. Certamente vai te tornar um programador melhor.

    Quando estou com o candidato eu mando um diálogo parecido com esse:

    — Você sabe o que é um ORM?
    — [se o candidato disser que não, eu pulo para outra pergunta parecida, senão eu prossigo… se o candidato estiver meio nervoso, eu também aviso que a próxima pergunta não tem uma resposta certa e nem errada e que eu só quero entender como ele pensa sobre programação orientada a objetos].
    — Suponha que eu te peça para implementar um ORM em Python para usarmos em nosso sistema e eu te mostre dois ORMs diferentes para você se inspirar (ex. Django, SQLAlchemy). Tudo bem?
    — Sim… entendo…
    — No ORM do Django, se eu quero persistir um objeto no banco de dados, eu faço: modelo.save(). Mas no SQLAlchemy, se eu quero fazer o mesmo, eu faço algo parecido com storage.add(modelo). Ou seja, no Django o método que persiste o modelo no próprio modelo e no SQLAlchemy a responsabilidade de persistir o modelo é do objeto Storage. Qual desses modos você escolheria?

    E aí o candidato teria algumas opções de resposta:

    1. Não sei, preciso estudar mais as opções: boa resposta, mostra que entrei num assunto que ele desconhece, mas que ele tem interesse em se aprofundar.
    2. Eu faria igual ao Django: resposta boa. Mas me leva à linha de contestar a escolha e perguntar se não seria responsabilidade demais para o objeto modelo cuidar das regras de negócio e da persistência dos dados no banco?
    3. Eu faria igual ao SQLAlchemy: resposta boa também. Mas eu contestaria a escolha perguntando se a opção do Django não seria mais simples e conveniente para o uso mais comum onde precisamos somente gravar um objeto no banco sem ter que se preocupar com storages e afins?
      • Algumas vezes recebi boas respostas onde o candidato implementaria o ORM para funcionar no modo SQLAlchemy, mas implementaria um método helper .save() também nos modelos que faria algo do tipo: storage.add(self). Não posso negar que eu ficava bem feliz com essa resposta porque seria a minha resposta (mostrando que ela é a resposta certa 😛).
    4. Eu faria diferente de ambos e faria [assim]: pode ser uma resposta boa aqui, mas, na prática, eu nunca recebi uma alternativa muito consistente nesses casos. Quase sempre foram respostas que mostravam o desconhecimento do candidato sobre o que é e como um ORM funciona.

    Notem que a pergunta é só um ponto de partida para entender como o candidato pensa e faz as suas escolhas quando está programando. Quando ele faz uma escolha e, portanto, uma renúncia, eu apresento sempre um contraponto à escolha dele para compreender se ele fez essa escolha porque ele julga ela a escolha certa e a outra errada ou se ele, de fato, ponderou as diferenças, prós e contras das opções apresentadas para dar a resposta.

    Profissionais que sempre estão refletindo sobre seu próprio trabalho estão sempre em crescimento. Aqueles que estão presos aos seus dogmas e tradições sempre estarão limitados por conceitos colocados por terceiros como sendo o certo.

  • Código Cabuloso

    Código Cabuloso

    Esse artigo é quase um repeteco dos artigos Dicas para um bom programa em Python e o Personal Python Style Guide. Mas aqui mostro como uso o processo de refatoração do código para estudar e entendê-lo.

    Estou tentando entender um código bem intrincado e importante do trabalho… é um código bem crítico que resolve um problema bem difícil (merge de objetos) e foi desenvolvido “sob demanda”, ou seja, fizeram uma versão básica e foram incrementando ele com cenários diversos que foram sendo descobertos com o tempo.

    Todo mundo na empresa tem medo de mexer com esse código porque, apesar dele ter até uma certa cobertura de testes, não sabemos se esses testes realmente cobrem todos os cenários reais.

    Mas preciso entender esse código para fazer uma otimização (ele executa um UPDATE muito demorado no nosso banco de dados e eu preciso remover esse UPDATE).

    Eu não sei onde esse UPDATE acontece porque o código é todo elaborado com execuções tardias (lazy) das operações. Então preciso ler tudo para entender onde essa operação está sendo agendada para execução.

    Como tenho TDAH é muito difícil, para mim, somente ler o código para entendê-lo. Quando o código é curto e simples tudo bem, mas não é esse o caso. O que eu geralmente faço é um processo de refatoração do estilo do código. Não só em termos de formatação (porque tem ferramentas para isso que já rodam no nosso sistema de integração contínua), mas também em estilo estrutural.

    Vou separando cada bloco de refatoração ou função refatorada em um commit em um branch criado especificamente para esse trabalho.

    Uma vez que terminei tudo e entendi o funcionamento do código crio um PR (em modo draft) com uma descrição detalhada do que fiz, da separação em commits, necessidade de revisar, como revisar, etc. para meus colegas de trabalho avaliarem e até mesmo responder algumas das minhas dúvidas. Mas o mais importante: inicio a descrição do PR explicando que a aceitação dele é totalmente opcional e até mesmo não indicada por conta dos riscos envolvidos.

    Para todo esse processo é imprescindível o uso de uma ferramenta de refatoração automática que possibilite renomear identificadores, extrair funções/métodos, inversão de lógica em ifs, etc. Senão o seu trabalho será miserável.

    Munido de todos os requisitos passo a alterar o código da seguinte maneira…

    Nomes melhores

    Entender um código onde os identificadores são chamados obj, data, tmp, etc. é complicado. Ter identificadores com nomes como “foo_json” que tem um dict() e não uma JSON-string também não ajuda muito.

    Renomeie variáveis, funções, métodos, classes, etc. para terem sempre o nome correto. Se estiver difícil escolher um nome para o identificador é porque o código tem outro tipo de problema ou ainda falta compreensão sobre ele.

    Early Return

    Uso early return pattern para reduzir o volume de indentação do código e o embaraçamento dele (tangled). O objetivo é linearizar os fluxos e criar blocos segmentados com lógica de processamento. Sou um “Never Nester Developer”. 😀

    Como já comentei nesse artigo aqui, de modo bem simplificado, o código abaixo:

    def f(c1, ..., cN):
        if c1 and... cN:
            ... faz um monte de coisas ...
            return 1
        return 0

    Vira algo do tipo:

    def f(c1, ..., cN):
        # cenário excepcional 1
        if not c1:
            return 0
    
        ...
    
        # cenário excepcional N
        if not cN:
            return 0
    
        ... faz um monte de coisas ...
    
        return 1

    O código fica mais longo, mas é possível identificar bloco a bloco quais são as condições excepcionais da função em cada bloco.

    Lembrem-se que o objetivo aqui não é eficiência e sim a legibilidade e compreensão do código.

    Ajustes de if‘s, elif‘s e else‘s

    Nessa etapa o objetivo é eliminar o máximo de if‘s, elif‘s e else‘s do código (e adicionar else‘s quando temos algum elif‘s inevitável).

    Uma forma de fazer isso é inicializando valores em certas variáveis e só modificá-los dentro do if. Mas nem sempre isso basta e, em alguns casos, quando cada bloco é muito grande ou tem chamadas de funções, etc. sequer é possível de ser feito.

    Um exemplo bem simplório só para ilustrar o que estou dizendo:

    if cond:
       v = f()
    else:
       v = default

    Vira algo tipo:

    v = default
    if cond:
        v = f()

    Dessa forma deixo no fluxo normal a condição padrão e crio um branch só para tratar de uma excepcionalidade.

    Essa refatoração pode realmente ficar enorme e o resultado também pode ficar pior que o original, logo, use com moderação.

    Outra refatoração que faço não tem relação somente com a compreensão do código, mas até mesmo com o funcionamento correto dele: se você tem if e elif é prudente ter um else. Mesmo que seja para levantar um erro. Afinal, se você pensou em mais de um cenário, o que acontece com aquele cenário que você não pensou?

    Falo sobre isso abordagem aqui e aqui.

    Extração de código

    Outra refatoração que ajuda bastante a melhorar a legibilidade do código é conhecida como Extract Method. Ela possibilita trocar um trecho de código por uma chamada de função que descreve o que esse código faz.

    Para fazer essa refatoração é bem útil ter uma ferramenta que automatize o processo. A IDE que uso no dia a dia oferece essa refatoração, mas é provável que existam plugins para vários outros editores e IDEs.

    Essa é fácil de ilustrar:

    def f(x, y):
        # Verifica se o objeto x é válido
        valid = False
        if x.a and x.a == 0:
            valid = True
    
        if x.compare(y):
            valid = True
    
        if valid:
            ... faz algo ...

    Vira algo assim:

    def is_valid(x, y):
        if not x.a or x.a != 0:
            return False
    
        if not x.compare(y):
            return False
    
        return True
    
    
    def f(x, y):
        if not is_valid(x,y):
            return
    
        ... faz algo ...

    Quando você está lendo o código de f(x,y) você, sabe que o objeto x é validado primeiro e o resto da função só será executado quando o objeto x for válido.

    Exceções devem ser exceptions

    É muito comum ver funções retornando flags (ex. None) quando ela precisa sinalizar um problema, um erro ou uma exceção.

    Considerando que idealmente uma função (ou método) deve retornar sempre objetos de um mesmo tipo, o retorno de None deveria ser algo ruim, certo?

    Quando retornamos None em nossas funções precisamos ficar verificando todos os valores retornados antes de usá-los, ou seja, toda hora vemos os famigerados:

    ret = f()
    if ret:
       ... faz algo ...
    else:
       ... trata o erro ...

    Em linguagens com suporte a exceções podemos usá-las para sinalizar problemas ou… excepcionalidades!

    try:
        ret = f()
    exception UmaExcecaoBemEspecificaQueFPodeGerar:
        ... trata o erro ...
    
    ... faz algo ...

    Essa refatoração melhora a legibilidade do código porque deixa o tratamento da exceção bem perto do código que pode gerar ela. E para isso ser verdade é importante que o bloco try/except realmente seja pequeno e restrito ao trecho onde a exceção pode acontecer.

    Também é importante que a exceção gerada (e tratada) sejam sempre bem específicas para o erro gerado para evitar tratar o erro inadequadamente.

    Usar bem a linguagem

    O código da empresa onde trabalho é escrito em Python e então eu refatoro ele para ficar mais “pythônico” (o que quer que isso signifique para mim).

    Legibilidade é melhor que eficiência nesse momento.

    Prefiro um belo “if-zão” bem legível a uma “ifexpression” toda muvucada.

    Um loop pode funcionar melhor que um comprehension… estou ajustando o código para ler e entendê-lo e não para que ele rode um femtossegundo mais rápido.

    Tipos

    Tipos (e eventualmente anotação de tipos) podem auxiliar na compreensão do código, bem como as ferramentas de refatoração automática.

    Tente padronizar os tipos de parâmetros e retornos das funções. Tente fazer com que eles sempre recebam e retornem objetos dos mesmos tipos. E lembre-se também que None é do tipo NoneType e não do mesmo tipo dos objetos que você está querendo usar. 😜

    Uma função que busca uma pessoa pelo nome:

    def get_pessoa(name):
       pessoas = Pessoa.filter(name=name)
       if not pessoas:
           return None
       return pessoas[0]

    Ficaria assim:

    def get_pessoa(name: str) -> Pessoa:
        pessoas = Pessoa.filter(name=name)
    
        if not pessoas:
           raise PessoaNaoEncontrada(name)
    
        if len(pessoa) > 1:
           raise MultiplasPessoasComNome(name)
    
        return pessoa

    Namespaces para contextualizar

    Quando esbarro com muitos nomes que vem do mesmo módulo, tento refatorar o uso deles para incluir o nome do módulo de origem no namespace:

    from contants import (
        FOO,
        BAR,
        BAZ,
        QUX,
        DUX,
    )
    
    def f(x):
        if x == FOO: ...
        if x == BAR: ...
        if x == BAZ: ...
        if x == QUX: ...
        if x == DUX: ...

    Vira:

    import constants
    
    def f(x):
        if x == constants.FOO: ...
        if x == constants.BAR: ...
        if x == constants.BAZ: ...
        if x == constants.QUX: ...
        if x == constants.DUX: ...

    Dessa forma trago o contexto de qual módulo os identificadores vem.

    Métodos próximos dos objetos

    Esse faço pouco porque o time onde trabalho não curte “Fat Models” do mesmo jeito que eu gosto.

    Mas essencialmente transformo quaisquer funções auxiliares que lidam especificamente com um tipo de objeto em um método do próprio objeto e tiro da frente especificidades que aquele objeto pode encapsular para mim.

    Mover trechos de código e funções que lidam com um tipo específico de objeto como método do próprio objeto.

    def nome_completo(pessoa):
        return f"{pessoa.primeiro_nome} {pessoa.ultimo_nome}"
    
    def etiqueta(pessoa):
        return {
            "nome": nome_completo(pessoa),
            "endereco": pessoa.endereco,
        }

    Fica:

    class Pessoa:
        @property
        def nome_completo(self):
            return f"{self.primeiro_nome} {self.ultimo_nome}"
    
    def etiqueta(pessoa):
        return {
            "nome": pessoa.nome_completo,
            "endereco": pessoa.endereco,
        }

    Assim, ao analisar a função etiqueta() foco especificamente em como ela funciona sem me distrair com código de concatenação de nomes.

    OOP e não DOP

    Dicionários são estruturas de dados tão poderosas em Python que é bem fácil a gente começar a usá-las para tudo em nosso código. Mas isso começa a se tornar um problema com o tempo porque é quase impossível encapsular os dados de um dicionário com o objetivo garantir a consistência deles.

    Enquanto estou fazendo a refatoração de um código, começo a usar namedtuples, dataclasses ou até mesmo uma classe “convencional” (com métodos e tudo) para substituir os dicionários que ficam espalhados pelo código.

    def grava_pessoa(dados_pessoa: dict) -> int:
        if not valida_dados_pessoa(dados_pessoa):
            raise DadosInvalidos(dados_pessoa)
    
        # se tem 'id' já existe no DB
        if dados_pessoa.get("id"):
            return update(dados_pessoa)  # retorna o id
    
        return insert(dados_pessoa)  # retorna o id

    Ficaria mais ou menos assim:

    class Pessoa:
        def __init__(self, nome, ...):
            self.nome = nome
            ...
    
        def valida(self):
            ...  # valida dados do objeto
    
    def grava_pessoa(pessoa: Pessoa) -> int:  # ou Pessoa
        if not pessoa.valida():
            raise DadosInvalidos(pessoa)
        
        if pessoa.id:
            return update(pessoa)  # retorna id ou Pessoa()
    
        return insert(pessoa)  # retorna id ou Pessoa()

    A lógica de validação do objeto não fica me distraindo do que a função grava_pessoa() faz: inserir ou atualizar os dados da pessoa no banco de dados.

    TODO/FIXME

    Uso comentários TODO/FIXME com dúvidas que não consigo solucionar lendo somente o código que estou mexendo e que não posso esquecer de perguntar para algum colega em algum momento no futuro (lembrem que tenho TDAH e esquecerei as dúvidas que tenho).

    # Ignora registro de pessoas afetados pelo bug de migração
    if 32000 > pessoa.id > 10000:
       return

    Provavelmente vira algo assim:

    # TODO (osantana): o código abaixo ainda é necessário mesmo
                       após a migração?
    # Ignora registro de pessoas afetados pelo bug de migração
    if 32000 > pessoa.id > 10000:
       return

    Estilo de código

    Por último, quando não vejo muita coisa para melhorar no código, eu mudo só algumas coisas menores no estilo de código para forçar algum tipo de formatação pelas ferramentas automáticas de formatação.

    # formatador faz algo assim:
    x = funcao_com_nome_longo_e_muitos_parametros(
            a="foo", b="bar", c="baz", d="qux)

    Coloco uma “,” para forçar a indentação abaixo:

    # formatador faz algo assim:
    x = funcao_com_nome_longo_e_muitos_parametros(
        a="foo",
        b="bar",
        c="baz",
        d="qux,
    )

    Conclusão

    Vocês têm alguma outra coisa que você também faça para poder entender algum código mais cabuloso?

  • Como começar em TI

    Como começar em TI

    Esse artigo é uma adaptação do meu vídeo no YouTube.

    Com bastante frequência eu recebo pedidos de dicas de pessoas que pretendem começar a trabalhar em TI. Por conta disso eu reuni aqui várias dicas e recomendações para essas pessoas.

    Tentei ser bem pragmático no plano. O objetivo dele é otimizar o caminho do zero ao primeiro emprego como iniciante. Eu falo só sobre o início do percurso e espero que consiga te preparar para decidir o restante do trajeto por conta própria.

    Várias dicas que eu vou passar aqui foram acumuladas nos meus vários anos de experiência desenvolvendo software e participando de processos seletivos dos “dois lados do balcão”. É…! Já fui candidato para uma vaga várias vezes na vida e também já fui o contratante que escolhia os candidatos.

    As dicas vão ser mais focadas na carreira de programador, mas algumas podem até servir para quem pretende trabalhar com outras áreas da tecnologia. Então se você pretende trabalhar com Data Science ou DevOps, tenta ver se tem alguma dica útil para você também.

    Aprender programação não é Fácil. Mas é possível.

    Bom galera, a primeira dica que vou dar é super importante e é pesada: não romantizem o trabalho de programador. Aprender a programar não! É! Fácil!

    Balde de água fria, né? Foi mal aí… mas eu não poderia começar essas dicas sem mandar a real para vocês.

    Diferente do que vocês vão ver nas propagandas de cursos e nos discursos de “coaches”, não é fácil aprender a programar. Você tem que estar preparado para investir muito tempo e dedicação nesse processo.

    Mas por favor não me entendam mal! Eu não estou dizendo que você não consegue. Todo mundo consegue aprender a programar. Mas não tem como aprender a programar só lendo uns livros e fazendo uns cursos por aí. Cursos caros ou uma faculdade não te tornarão programador. Programar vai.

    Só a prática deliberada da programação é que pode te tornar um programador.

    Um livro ou um curso pode até te levar pelo começo da estrada e te ensinar como usar as ferramentas de programação, mas você vai ter que trilhar esse caminho por conta própria depois disso.

    Como? Escrevendo muito código! Você precisa escrever muito código no processo porque esse é o único caminho que vai te ensinar a programar.

    E vai ter vezes que vai ser frustrante. Outras vezes vai ser cansativo. Outras vezes vai ser desesperador. E algumas vezes vai dar medo. Mas mesmo assim você vai ter que seguir.

    Mó papo de “coach” isso, né? Mas é a real.

    E tem mais! Os primeiros códigos que você escrever vão ser uma tremenda porcaria… e tá tudo bem! É só jogar ele fora e tentar escrever outro melhor. Essa é a beleza do software, você tem matéria-prima infinita para trabalhar…

    Seguindo por esse caminho, quanto mais tempo, foco e disciplina você tiver, mais rápido você se capacita para tentar uma vaga bacana.

    Ah! E não importa o que aquele “guru de finanças e carreira” te disse: você não vai conseguir um emprego de programador sem se esforçar para isso. Provavelmente não vai ser rápido também. E provavelmente o salário não será no nível que eles prometem.

    Não tem mágica e nem milagre. Se fosse fácil, não teria vaga sobrando, certo?

    Tá, mas você deve estar perguntando: “Ok, mas quanto tempo vai levar para eu conseguir um trampo bacana?”.

    Olha… não tenho uma resposta para essa pergunta. Depende muito de quanto tempo você dedicar todo dia para praticar e de um punhado de sorte.
    Mas se você consegue se dedicar umas duas horas por dia, as coisas provavelmente vão caminhar mais rápido do que se você se dedicar duas horas por semana.

    — Mas… dá para otimizar isso?
    — Sim! Dá! Principalmente se você escolher bem os temas para focar seus estudos. Você não pode desperdiçar tempo com coisas que não serão úteis no início da sua carreira.

    Ainda assim o processo todo pode levar um tempo considerável. E por isso eu gostaria de deixar a segunda dica: você não vai ganhar bem no começo!

    Você não vai ganhar bem

    — Orra! Você disse na abertura do vídeo que as vagas pagam bem e agora diz que a gente não ganha bem?
    — Exato. No começo nem todo mundo ganha bem. Pode ser que você dê sorte, mas via de regra não é o que acontece com a maioria dos candidatos.

    As vagas que pagam bem são aquelas para programadores mais experientes. E… óbvio… você não vai ter experiência no começo.

    Pode acontecer que o salário de um iniciante seja maior que a sua renda atual. Nesse caso o seu salário inicial vai “parecer” alto, mas não necessariamente ele “será” alto.

    Por conta dessa situação, eu daria a terceira dica: se você já tem um trabalho, continue nele.

    Mantenha seu emprego

    Se você já está trabalhando em algum lugar, mantenha esse emprego. Não assuma riscos altos sem motivo. Lembre o que eu disse: a vaga pode demorar para chegar.

    Sei que é bem difícil ter ânimo para estudar programação depois de um dia cansativo de trabalho. Se esse for o seu caso, tente organizar seu dia para ter um tempo antes de começar o expediente. Uma horinha por dia já dá um adianto.

    Se você aproveitar esse tempo, mesmo curto, para estudar computação da melhor maneira, as coisas vão funcionar.

    E isso leva à quarta dica: Como estudar computação.

    Estude

    Como mencionei agora a pouco, se você acha que basta fazer alguns cursos para aprender a programar, você não poderia estar mais enganado.

    Um curso de computação, geralmente, tem um conjunto de assuntos limitado e alguns exercícios prontos para você exercitar seus conhecimentos sobre o conteúdo apresentado.

    No fim do curso você receberá um diploma dizendo que você consegue resolver os exercícios do curso. E eu te pergunto: isso te torna um programador desejável?

    O trabalho de um programador é resolver problemas. Problemas com complexidades distintas, tamanhos diferentes, etc. O mundo real é muito mais complicado que o ambiente controlado de um curso de programação.

    Aprender a programar exige que você procure por problemas que podem ser resolvidos com software e se arriscar a escrever seus próprios programas para solucionar eles.

    Esses programas vão funcionar? É provável que, no início, não. Mas trabalhando em um programa ruim atrás de outro você vai entendendo o quê que funciona e o quê que não funciona.

    Você aprende o que é bom e o que é ruim em contextos diferentes, aprende a encontrar bugs no seu software e resolver esses bugs, quebra a cabeça e se desespera até perceber que uma pausa e um pouco de descanso era tudo o que você precisava para terminar o projeto.

    Ou seja, faça alguns cursos, mas, depois que você concluir alguns deles, tente se arriscar por conta própria e desenvolva seus próprios projetinhos.

    Desenvolver esses projetinhos vai te ajudar agora e mais lá na frente quando algum recrutador pedir para você mostrar seu código para ele.

    Se estiver sem ideia para projetos, é só olhar por perto e ver algumas coisas que você precisa no seu dia-a-dia… tipo um controle de despesas… ou no seu trabalho atual… tipo gerar um relatório no Excel.

    Faça programinhas que te ajude em casa, na escola, no trabalho, no seu hobby, … qualquer coisa. E não se limite, planeje um sistema completo com todas as funcionalidades que você gostaria de ver. Mesmo que você não faça a mínima ideia de como desenvolver elas.

    Você também pode procurar por listas com ideias de projetos na Internet:

    Forme uma rede de suporte

    Enquanto você está nesse processo de aprendizado é sempre legal ter a ajuda de alguém. E é aí que vai a quinta dica: converse com outros programadores.

    Tente sempre participar de eventos e encontros sobre as tecnologias que você está estudando. Comece seu networking dentro das comunidades de tecnologia.

    Você evolui como programador conversando com essas pessoas e já vai cavando as suas oportunidades de trabalho desenvolvendo uma rede de relacionamentos no mercado.

    Uma grande dúvida das pessoas que estão começando é sobre qual linguagem escolher? Qual framework? Backend? Frontend? Data Science?

    A minha sugestão é: forme sua rede de suporte primeiro. Comece com as mesmas ferramentas que eles usam. Nesse momento você deveria estar preocupado em aprender a programar e não com o mercado de trabalho ou onde tem mais oportunidades.

    Se você não souber programar em nada, nenhuma oportunidade servirá para você.

    Foco

    E pensando em comunidade, programadores e networking, eu já gostaria de puxar a sexta dica que eu considero uma das mais importantes e é aqui que a gente começa a realmente otimizar o processo: foco em uma única coisa por vez.

    Quando você for pesquisar vagas para trabalhar, você vai notar um mar de opções. Tem vaga para Data Science, Desenvolvedor Junior, Pleno, Sr, DevOps, Security, Tech Lead, Java, Python, PHP, Javascript, Go, etc, etc. Um buzilhão de tecnologias em uma sopa de siglas e termos técnicos que pode deixar qualquer um em pânico. Você se pergunta:

    — Será que eu vou ter que aprender essa p* toda? Eu estou f*!

    E pode piorar! Quando você olha tudo isso, você pode cair na tentação de guiar seus estudos pelo que o mercado está pedindo:

    — Ah! Ouvi que Python é melhor! Ah! Tem muito mais vaga de front! Ah! O esquema agora é Data Science para Machine Learn…

    Isso é um problemão! Lembre que você tem vários fatores limitando o seu desenvolvimento, mas só um deles não tem como mudar: o tempo.

    Melhorar o uso do seu tempo é fator principal para encurtar o período de transição da sua carreira.

    Otimizar o uso do tempo é o fator principal para encurtar o prazo até o novo emprego.

    Você não pode se dar o direito de desperdiçar seu tempo com distrações. Você precisa ser um sniper, e não o Rambo atirando para todo lado com uma metralhadora.

    Então escolha uma única profissão e uma única pilha de tecnologia e mexa só com ela. Escolha ser “Programador de uma única linguagem” e foque nisso.

    — Mas e se eu não gostar de ser programador?
    — Depois você muda. Primeiro você vira alguma coisa. Depois você muda.

    Se você quiser ser cientista de dados, você inicia o processo de migração já em um emprego que paga bem e com conhecimentos de programação que serão muito úteis na sua carreira como cientista de dados. Saber programar é uma habilidade que ajuda em várias profissões em tecnologia.

    Ah! E repito: não se distraia com ofertas de emprego com outras tecnologias. Elas vão aparecer aos montes e você vai achar que escolheu a tecnologia errada sempre que ver qualquer vaga de outra linguagem. Acredite: tem vagas sobrando para todas as tecnologias. Você vai encontrar uma.

    Além disso, conforme você for ganhando experiência com os fundamentos da programação você vai ver que aprender novas tecnologias e linguagens vai ficando cada vez mais fácil e rápido.

    É tudo CRUD1

    Já vimos uma dica para otimizar o tempo e a próxima dica, a sétima, é sobre otimização dos estudos: para se tornar um programador não é necessário dominar todo o campo da computação. Até porque isso é impossível.

    Se você dominar bem o básico de alguns tópicos principais, já é possível desenrolar vários tipos de problemas de trabalho e, com isso, conseguir preencher uma vaga como programador.

    Tem uma brincadeira entre programadores que diz que no fim das contas todos os programas são CRUD1. É uma super simplificação, mas não é totalmente mentira… a maioria do software é isso mesmo e saber fazer CRUD você já pode trabalhar com TI.

    Os tópicos que te preparam para construir softwares completos podem variar um pouco dependendo do tipo de vaga que você está procurando, mas se você aprender a:

    • Programar em uma linguagem de programação como Python, JS, PHP, Go ou Java;
    • Modelar software Orientado a Objetos (ou software funcional em uma linguagem funcional);
    • Usar algum framework dessa linguagem;
    • Modelar tabelas em bancos de dados relacionais e fazer queries SQL;
    • Usar e criar APIs/Websites (ao menos) com protocolo HTTP/REST;
    • Usar ferramentas de desenvolvimento como Editor de Texto ou IDEs, git, Docker e ter familiaridade com terminal Linux/Mac;

    … você já está pronto para as batalhas e já consegue preencher bem a grande maioria das vagas para programador Junior do mercado.

    Parece muita coisa, né? E é haha 🤷🏻‍♂️

    Mas se você consegue lidar com esses tópicos, você já cobre a grande maioria dos conhecimentos necessários para desenrolar o trampo. Fazer CRUDs e tal…

    E também não precisa ser “mestre” em todos esses tópicos. Sabendo preparar um arroz com feijão com cada um deles já tá de bom tamanho. No início! Para evoluir na carreira tem que dominar bem todos eles e mais alguns outros.

    Outro conhecimento que é muito útil e importante, mas não tem relação com computação, é o inglês. Saber ler em inglês é a coisa que mais vai te ajudar a estudar isso aí tudo. Não é uma obrigação porque dá para “quebrar galho” com tradutores automatizados, mas, como o nome diz, isso é só um “quebra galho”.

    No fim desse artigo eu coloquei algumas indicações de estudo e leitura. Infelizmente nem todas as indicações estão em português e boa parte delas é recomendação de leitura porque é o meu jeito favorito de estudar. Se você conhecer outros conteúdos em outros formatos, deixa aí nos comentários.

    Muito bem, todas as dicas agora serviram para te ajudar a otimizar o processo de aprendizado, mas e a vaga? E o emprego?

    Aplique para as vagas

    Pois bem, a oitava dica é: aplique para as vagas. Só isso mesmo… brincadeira… Aplique para todas as vagas que você achar interessante. Mesmo para aquelas que você não atende aos requisitos. Se a vaga pede algum tipo de teste prático, é ainda mais legal.

    Cuide só para não aplicar para vagas demais e acabar atrasando o desenvolvimento dos testes práticos. Sempre que eu estou aplicando para muitas vagas, eu gerencio o fluxo das atividades em um quadro no Trello para não me perder nas tarefas. No artigo Conseguindo um emprego em TI eu falo muito mais detalhadamente sobre esse assunto.

    Se você estiver se sentindo confiante, também pode tentar pegar alguns servicinhos tipo freelance em sites dedicados à isso. Tem vários e como nunca usei nenhum deles não vou indicar nenhum específico. Busque no Google e procure referências com alguém que tenha trabalhado com esses sites.

    Outra coisa para tomar cuidado é: tem umas poucas empresas ‘falcatruas’ que colocam trabalho de verdade como se fossem testes. Se o teste é fechado e os caras não são muito transparentes sobre o que farão com ele: desconfie.

    É importante lembrar que, mesmo que você não passe no processo, você treinou e ainda pode receber um feedback da empresa com dicas para te ajudar na priorização dos estudos.

    Ah! E você vai reprovar em muitos processos. Sei que é difícil, mas, não desanime. E, se der certo e você for contratado, já sabe, conta pra gente!

    Se puder, faça (ou termine a) faculdade

    A última dica é bônus porque, diferente das outras, essa pode não servir para todo mundo: se você está na faculdade, continue. Mesmo se ela não for de TI.

    É muito comum, em TI, trabalhar com programação mesmo sem ter diploma. Por conta disso, tem muito “guru” recomendando que você abandone a faculdade para focar em estudar programação.

    Se você não consegue se manter na faculdade por algum motivo, tudo bem. Mas se não for esse o caso, continue. As estatísticas mostram que pessoas formadas tem mais oportunidades e renda maior no mercado. Para quê abrir mão disso, não é?

    Então essas são as dicas para você que quer mudar de área. Boa sorte na jornada e se precisar de ajuda manda nos comentários.

    1. Sistema Operacional e Ferramentas (Linux/MacOS, editor de textos, git, terminal, shell e linha de comando, etc)
      1. https://osantana.me/tutorial-linux/
      2. Livro: Programação Shell Linux – https://amzn.to/3GJroMK
    2. Linguagem (dê preferência em linguagens que você tenha amigos que programem. Se não tiver nenhuma vá de Python ou JS porque a quantidade de material gratuito é enorme)
      1. Livro: Introdução à Programação com Python: https://amzn.to/3NfMyEy
      2. Canal Youtube: https://www.youtube.com/c/dunossauro
      3. Livro: Fluent Python https://amzn.to/38LU5fu (intermediário/avançado)
    3. Modelagem e programação Orientada a Objetos
      1. Livro: Object Oriented Python: https://amzn.to/3FbNlTT (Python)
      2. Livro: Building Skills OO Design Book: https://slott56.github.io/building-skills-oo-design-book/build/html/index.html (Python/gratuíto)
      3. Livro: Sams Teach Yourself Object Oriented Programming in 21 Days https://amzn.to/3MkaiX6 (Java)
      4. Livro: Head First Object-Oriented Analysis and Design https://amzn.to/3NQZikZ (Java)
      5. Livro: Fundamentos do Desenho OO com UML https://www.estantevirtual.com.br/livros/meilir-page-jones/fundamentos-do-desenho-orientado-a-objeto-com-uml/3383501357 (avançado/fora-de-impressão)
    4. Web/HTTP/REST API:
      1. https://developer.mozilla.org/pt-BR/docs/Web/HTTP – Tutorial HTTP Web API da MDN (tem vários outros tutoriais bacanas sobre Web nesse site… dá uma passeada nele…)
      2. https://restfulapi.net – site que fala sobre APIs REST (HTTP). A parte que fala sobre hipermedia/HATEOAS você pode pular porque ninguém usa isso  
      3. https://github.com/Developer-Y/cs-video-courses#web-programming-and-internet-technologies – cursos completos sobre programação web
      4. https://www.slideshare.net/osantana/a-web-uma-api essa é uma apresentação que eu fiz online (infelizmente não tenho video dela). Ela é um pouco mais avançada mas acho que o comecinho dela pode ajudar.
      5. https://www.slideshare.net/osantana/contruindo-um-framework-web-de-brinquedo-s-com-python – essa é uma outra apresentação que fiz onde eu crio um framework web em Python. Essa é avançada mesmo. Deixe ela por último.
    5. SQL e modelagem de Banco de Dados Relacional
      1. Livro: Introdução a Sistemas de Bancos de Dados https://amzn.to/3xcgU5t (livro muito completo e não fala de nenhum banco de dados específico)
      2. Livro: PostgreSQL Up & Running https://amzn.to/3ah8iRW (esse foi o que li para aprender mas tem outros livros que também parecem bons da editora Novatec e Casa do Código)
    6. Programar, programar e programar mais
      1. https://github.com/practical-tutorials/project-based-learning#python – ideias de projeto para colocar em prática o que aprendeu
    7. Continuar estudando pra sempre
      1. https://roadmap.sh – Esse site aqui tem vários roadmaps de carreira. Siga pelo de Backend e depois pelo de Python. Os roadmaps são assustadoramente grandes mas não se desespere porque não precisa ir atrás de tudo aquilo (nem eu sei tudo o que está neles). Siga as caixinhas com um “check” roxo e foque em 5 grandes tópicos. Foque só neles e não se distraia com outras linguagens ou tecnologias nesse momento.

    [1] CRUD é uma sigla para Create (Criar), Read (Ler), Update (Atualizar), Delete (Remover) que são as operações básicas que fazemos em qualquer sistema de cadastro.

    Imagem destacada: (c) 2013 http://www.exampapersplus.co.uk/

  • How I (do) Code Review

    How I (do) Code Review

    Este post está em inglês porque compartilho ele com meus colegas de trabalho que não leem em português.

    When I am reviewing your code, I love to learn and help you with proposals that I believe that should improve it. When you read my reviews, keep in mind that:

    1. The code is yours. You can disagree with me, and I am completely fine with that.
    2. My comments are about your code and not about you.
    3. When I ask something, I do it to understand the full context of your work to write better proposals.
    4. I am dumb and make mistakes (a lot of them). I tried my best and failed? Just point me the problem and I will fix it.
    5. I am not a native English speaker, and code review is mostly made with limited text messages. If you don’t understand or feel bad reading something that I wrote, it is my fault and I apologize for that in advance. I probably wrote something in a bad way and I would be grateful if you point me out these things. It will help me to improve.

    I have four types of comments:

    1. Recommendation / Suggestions (see more about this below)
    2. Questions. I can ask questions to:
      • Get additional information about the context (Is it a critical bug? Something urgent? Worth a bigger refactoring?);
      • Understand the issue that you are solving.
    3. Code Suggestion. For small things that I can edit directly during the review process.
    4. 💀 Dead code is dead. We use VCS/git, and we don’t need to commit commented code 🙂

    When I am reviewing the code, I have three levels of recommendations (and an off-by-one level 😛):

    1. Ignore: I see something that should be improved, but I know that it would lead to a massive refactoring that it’s not worth it. Sometime it will generate a proposal for the team that leads to an RFC or a card on the board. Occasionally, I just ignore and keep on 🙂
    2. Format: Things that Black & Ruff should fix automatically for us. Regularly, I use the 💄 emoji to point out these suggestions.
    3. Style: Coding style. Things that go beyond code formatting but are still something that should improve, at least, code readability. Those recommendations are completely personal, and It is not fair to force it into the team. I can also use the 💄 emoji in these comments. Some things that I (emphasis) (dis)like:
      • I prefer return-early pattern;
      • I don’t like to use dict() for data structures;
      • I “hate” elif‘s and else‘s (I am a OOP-guy and that polymorphism-thing 🙂);
      • I am scared of if/elif with no else;
      • I don’t like to return None as an exceptional return (unless I am coding in C or Go);
      • I don’t like to use flag variables to control the flow of the code.
      • [Some other things that I will add here when I remember].
    4. Fix: these recommendation points for real problems in the code.