Categoria: Geral

  • 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.

  • Conseguindo um emprego em TI

    Conseguindo um emprego em TI

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

    Neste artigo, vou falar sobre como conseguir um emprego em uma empresa de tecnologia. Vou colocar aqui algumas dicas partindo da visão de quem já esteve dos dois lados do balcão: o lado de alguém que já procurou uma vaga e o lado de quem já contratou profissionais de desenvolvimento de software.

    Também vou trazer alguns tópicos aqui para vocês terem atenção no momento em que vocês forem participar de um processo seletivo.

    Primeiro de tudo é preciso dizer que mesmo eu, que já tenho uma experiência grande em TI, ainda falho em alguns processos seletivos.

    Quando participa de um processo seletivo e não passa nele, a causa nem sempre é relacionada com a nossa capacidade técnica ou intelectual de trabalhar para aquela empresa.

    Geralmente, isso acontece quando a gente não tem um alinhamento cultural, alinhamento de posicionamentos ou outras características. Então, não passar em um processo seletivo não significa que você falhou, significa que você tem pontos que você pode melhorar ou aperfeiçoar. Sempre que você reprovar em um processo seletivo, entenda isso como uma oportunidade de melhorar para a próxima tentativa e não como uma incapacidade.

    Preparação

    Uma coisa importante para participar de processos seletivos é estar sempre se preparando, estudando, vendo quais tecnologias as empresas estão usando e acompanhando o mercado de vagas, entre outros.

    Quem está participando de processos seletivos também precisa manter sua presença na internet bem atualizada, ou seja, manter seu perfil no LinkedIn e no GitHub sempre bonito, organizado, com seus projetos mais importantes em destaque. Não se esqueça de deixar seus contatos disponíveis para os recrutadores conseguirem te encontrar mais fácil.

    Mantenha sempre seu currículo atualizado, revise sempre, peça recomendações para seus colegas de trabalho, atualize seus cursos, treinamentos e as atividades que você tem feito ultimamente. Isso sempre será útil quando um recrutador bater o olho no seu perfil.

    É legal manter sempre uma wishlist, uma lista de desejos, de empresas que você acha bacana. Empresas com um produto bacana, que usam tecnologias nas quais eu tenho interesse, que possuem uma cultura alinhada com seus valores, etc. Eu tenho uma lista dessas empresas que eu gostaria de trabalhar.

    Crie essa lista de desejos, mas entenda o momento da sua carreira. Se você é um iniciante e a empresa contrata pessoas mais experientes, é importante estar ciente de que o momento certo para tentar uma vaga ainda não chegou. Mas não deixe isso te intimidar também. Às vezes, é legal correr um certo risco. Vou falar um pouco mais sobre isso mais adiante.

    Processos Seletivos

    Quando estamos precisando muito de um emprego, é interessante participar de vários processos de forma simultânea e, para isso acontecer de forma saudável, é preciso tomar alguns cuidados:

    1. Priorize os processos de modo a conseguir dar a atenção necessária a todos eles;
    2. Limite o número de processos simultâneos (o meu limite é 3, o seu pode ser maior ou menor). Processos com testes práticos podem pedir projetos que exijam um tempo grande;
    3. Qualidade é mais importante que quantidade;
    4. Organize os processos seletivos em um Kanban.

    Faça um quadro no Kanban e crie um calendário dedicado. O Kanban pode ter as seguintes colunas:

    • Contactar – empresas que você ainda precisa contactar para uma vaga.
    • Entrevista Inicial – processos que já tem uma data/hora para a entrevista inicial.
    • Teste técnico – processos que já tem um teste prático com prazo para realização e finalização.
    • Entrevista Complementar – processos com outras entrevistas complementares.
    • Aguardando Resposta – processos finalizados onde você espera por uma resposta da empresa.
    • Aprovado – a vaga é sua!
    • Reprovado – a vaga ainda não é sua. Peça feedback do contratante e anote o motivo da rejeição. Se a empresa possibilitar um novo processo futuro, é bom anotar a data aqui.

    E se você está com uma dúvida entre duas ou mais empresas, tente manter a negociação com as duas empresas no mesmo pé, se você se sente confortável com isso. Lembre-se de que é legal informar para todos os recrutadores que você está participando de outros processos em paralelo.

    Entrevista

    Treine bastante para as entrevistas. As orientações são bem simples:

    1. Jamais minta. Omitir é permitido. Mas recrutadores são ótimos em trazer omissões para superfície.
    2. Tenha explicações claras e objetivas para eventuais “problemas” no seu curriculum:
      • Períodos de permanência muito curtos em empresas;
      • Intervalos vazios no curriculum;
    3. Algumas empresas ainda fazem perguntas pessoais para os candidatos (principalmente no Brasil). Gostaria de dizer que você não precisa responder elas, mas eu estaria mentindo. Se você não quiser responder algo, tente preparar uma resposta bem limitada.
    4. Passe a impressão de que você está no processo seletivo porque quer trabalhar na empresa. Falar mal de oportunidades anteriores sempre pode causar problemas.
    5. Fale sempre de suas experiências sem emitir juízo de valor. No lugar de “o processo lá era muito ruim e por isso os prazos estouravam”, prefira usar “era muito difícil cumprir os prazos lá. O processo de priorização era muito simples e era centralizado na gestão”. Note que você não qualifica os problemas, mas traz os fatos. O recrutador vai saber interpretar esses fatos e ver os problemas.
    6. Se pedirem a sua opinião sobre uma experiência anterior, é importante evitar julgamentos de valor ou qualificações rasteiras. No lugar de “eu acho que a gestão era uma porcaria e por isso as prioridades eram uma bagunça”, prefira usar “eu acho que era bem difícil entender bem as prioridades do time porque o gestor não colocava elas com clareza”.
    7. Atraia a atenção do recrutador para os pontos positivos do seu curriculum. Se ele pergunta algo sobre um projeto problemático, é importante responder e tentar complementar a resposta com um contraponto de outro projeto onde o problema não existia. Exemplo: “Vi aqui que você trabalhou só em um projeto nessa empresa, você teve alguma outra experiência além dessa?” e você responde: “Sim, eu trabalhei só nesse projeto porque ele era importante para a empresa e eu conhecia ele muito bem. Então era muito difícil para eles me colocarem em outros projetos… entretanto, na empresa XPTO eu me envolvi em vários projetos que precisavam ser criados… “.

    Entrevista Técnica ou Teste Prático

    Do mesmo jeito que recomendo treino para entrevistas, é interessante investir um tempo treinando para as entrevistas técnicas ou para os testes práticos.

    Treine algoritmos, estruturas de dados, linguagens, framework, POO, banco de dados, etc. Desenvolva projetos, brinque em sites de desafios técnicos, leia livros, e assim por diante. Programação é uma atividade de prática deliberada. Você não aprende a programar sem praticar.

    Nas entrevistas técnicas valem as mesmas dicas da entrevista convencional que mencionei acima. Mas vale alguns complementos:

    1. Alguns recrutadores fazem algumas perguntas que não possuem resposta correta ou possuem várias respostas satisfatórias. O objetivo dele não é a resposta e sim o desenvolvimento dessa resposta. Como você pensou para chegar a ela.
    2. Pense em voz alta. O recrutador não lê a sua mente e o seu raciocínio oferece dicas valiosas para ele te avaliar bem (ou te dar um feedback mais completo em caso de rejeição).
    3. Toda solução para um problema tem aspectos positivos e negativos. Ter consciência disso vai te ajudar bastante.

    Aprovação e Feedback

    Terminando as entrevistas e os testes a gente chega na fase final de aprovação e feedback. Nessa etapa é comum acertar os últimos detalhes sobre a vaga, empresa e candidato. Coisas como cargo, salário, carga horária, time, projetos, etc. entram na conversa.

    Algumas empresas oferecem um momento para que o candidato faça perguntas. Prepare-se de antemão para essa oportunidade. Monte uma lista de perguntas que demonstre o seu interesse na empresa, no produto, no mercado, na vaga, no time, nos projetos, nos processos, nas finanças, etc. Pesquise sobre a empresa e as tecnologias usadas na Internet e anote umas perguntas.

    Se a empresa não seguir adiante com o processo, é legal você solicitar um feedback técnico do recrutador. Peça, educadamente, indicações de material de estudo, quais pontos precisam ser melhorados, quando você poderá aplicar para uma vaga novamente, etc.

    Por fim, é importante lembrar que, às vezes, o salário não é tudo. É legal pesar isso. Se você é uma pessoa que gosta muito de dinheiro, realmente buscando isso, vá atrás de empresas grandes. Mas se você está buscando uma empresa mais familiar, onde você vai ter um ambiente de trabalho mais legal, não vai ter tanto estresse, às vezes vale a pena pesar um pouco isso na balança.

    Enfim, essas são algumas dicas que eu acredito que podem te ajudar na sua busca por um emprego em uma empresa de tecnologia. Espero que você tenha sucesso em sua jornada. Boa sorte!

  • Temperos de Arquitetura

    Temperos de Arquitetura

    Já faz alguns anos que eu estou trabalhando com modelagem de sistemas. Em alguns lugares chamam isso de “arquitetura”, mas uma colega arquiteta (CREA e “talz”) me explicou que não é muito adequado usar a palavra “arquitetura” para definir esse trabalho. Como não sou o especialista e nem estou interessado em me aprofundar nesse tipo de discussão resolvi aceitar os argumentos e não usar mais “arquitetura”.

    Minha forma de trabalho é muito intuitiva e baseada em experiências práticas com coisas que deram certo e coisas que não funcionaram bem. Muitas coisas que fiz usando pura intuição se mostraram, mais adiante, como coisas que já existiam e já eram muito estudadas. Só eu é que ignorava.

    Capa do livro Designing Data-Intensive Applications

    Estou lendo um livro chamado “Designing Data-Intensive Applications” (Martin Kleppmann) que descreve vários desafios e soluções para desenvolvimento de sistemas distribuídos e conforme vou avançando na leitura vou sendo surpreendido com coisas que eu já fiz sem nem saber que aquilo tinha um nome. 🙂

    Nesse artigo eu vou listar algumas técnicas que sempre uso para modelar sistemas em que estou trabalhando. É um ‘braindump’ de técnicas listadas sem nenhuma pretensão, estrutura, ou ordem de importância.

    Provavelmente não é uma lista completa também. Uma coisa é ter um repertório de técnicas para usar no dia-a-dia. Outra coisa é lembrar de todas elas para escrever um artigo. Sou péssimo para lembrar das coisas.

    As dicas de modelagem que apresentarei abaixo podem ser subdividas em duas categorias: Princípios e Práticas. Vamos dar uma olhada nelas.

    Princípios

    Os princípios que uso no meu trabalho são mais abstratos e servem para orientar minhas escolhas em um nível de abstração mais alto.

    Menos é mais

    Quando estou trabalhando na modelagem de um sistema eu gosto muito de limitar minhas ferramentas. Eu trabalho melhor com a restrição do que com a abundância. Eu também gosto de ser um pouco conservador nessa hora.

    Um exemplo de conservadorismo e restrição é: se eu preciso oferecer uma API para ser usada publicamente eu provavelmente especificarei uma API HTTP REST. É simples, todo mundo conhece e sabe usar, tem ferramentas infinitas para tudo e é bem elegante.

    Outro exemplo desse conservadorismo aparece sempre que eu preciso armazenar dados em algum lugar. As chances de eu escolher um banco de dados relacional (PostgreSQL, é claro 😉 ) para a solução é enorme. Eu escolho SQL porque esse modelo está “por aí” a décadas e tem um número incontável de pessoas usando. E servidores de banco de dados evoluíram absurdamente nos últimos anos.

    Se os prazos são um pouco mais apertados (quando eles não são?) eu também escolho ferramentas que eu tenho um domínio maior. Exemplo: se eu precisar desenvolver uma solução distribuída é bem provável que uma linguagem com o perfil de Elixir tenha o ‘fit’ perfeito. Mas eu não conheço Elixir tanto quanto conheço Python. Então é provável que eu vá de Python. Com Django porque eu conheço melhor também.

    Se essa escolha se mostrar equivocada (nunca aconteceu) a gente planeja a troca.

    Quando chega aquela hora de dizer o nome das ferramentas e tecnologias que vamos usar eu também dou preferência para serviços gerenciados por terceiros à serviços que eu tenha que manter eu mesmo.

    KISS

    O princípio KISS (Keep It Super Simple*) é bastante antigo e a primeira vez que ouvi falar dele foi quando estava aprendendo a usar Unix. Antes de usar o Unix eu costumava usar o (MS|DR|Novell|PC)-DOS. No DOS, quando eu precisava mostrar o conteúdo de um arquivo eu fazia:

    C:\> TYPE README.TXT

    Se o arquivo fosse muito grande ele ia rolar a tela até o final e, diferente de hoje onde conseguimos rolar a janela para ver o que aconteceu, não conseguíamos ver o que estava no início do arquivo. Para ver o conteúdo de um arquivo pausando tela por tela a gente fazia:

    C:\> TYPE README.TXT /P

    E pronto. Notem que o comando TYPE sabia mostrar o conteúdo do arquivo e pausar de tela em tela. Quando passei a trabalhar em um Unix (no estágio) me ensinaram que o comando usado para mostrar o conteúdo de um arquivo era o cat. Então fui lá e mandei um:

    % cat README.TXT
    cat: README.TXT: No such file or directory
    % cat README  # ops! aprendendo que o filesystem do Unix é case-sensitive! :)

    E então o conteúdo do arquivo despencou a rolar pela tela. Ótimo! Aprendi a ver o conteúdo do arquivo! Agora preciso ver qual o parâmetro para ele parar de tela em tela…

     % man cat

    … e nada… Pensei: “mas que bela porcaria esse sistema, hein?”. Foi quando o meu supervisor de estágio chegou e falou: “No Unix os comandos fazem só uma coisa. E fazem bem essa coisa. Se você quer pausar a saída do cat (ele falou monoespaçado assim mesmo 😛 ) você precisa jogar a saída dele pro more. Assim ó…”. E digitou:

     % cat README | more

    Pronto. Depois descobri que essa filosofia era chamada de KISS.

    Essa história toda serve para ilustrar o que eu faço quando estou modelando um sistema: tento manter cada componente (seja ele um pacote, classe, microsserviço, etc) muito simples.

    Esse princípio também pode ser chamado de “Single Responsibility Principle” (a letra “S” em SOLID). Eles dizem basicamente a mesma coisa mas o “Single Responsibility” formaliza mais o seu significado.

    Quando cada um desses componentes é simples e tem uma única responsabilidade eles inevitavelmente serão também mais coesos. E coesão é algo desejável em um bom componente.

    Baixo acoplamento e Alta coesão

    Um dos melhores livros de programação orientada à objetos que li é o “Fundamentals of object-oriented design in UML” (Meilir Page-Jones). Nesse livro ele bate bastante na tecla de que um bom “objeto” (componente, pacote, etc) precisa ter as seguintes características:

    Baixo acoplamento

    Se você precisa fazer uma alteração simples em apenas um único comportamento da sua aplicação, quantos componentes diferentes do código você precisa mexer? A resposta para essa pergunta fala bastante sobre o acoplamento da sua aplicação.

    O baixo acoplamento é desejável porque ele faz com que sua aplicação fique mais fácil de ser mantida e de ser estendida com novas funcionalidades. O melhor método de se chegar ao baixo acoplamento é por meio do processo de refactoring** constante.

    Tentar desenvolver código com baixo acoplamento logo de largada é difícil, demorado, e pode te aprisionar em todo tipo de problema relacionado à early abstraction. Então encare o “baixo acoplamento” como objetivo e não como requisito.

    Alta coesão

    Esse conceito é um pouquinho mais complicado de explicar, mas o significado do adjetivo “coeso” pode nos dar uma dica. Coeso, segundo alguns dicionários, significa:

    1. Que se relaciona através da coesão, por meio da lógica, de forma harmônica: fala coesa, proposta coesa, atitude coesa.
    2. Intimamente unido; ligado com intensidade.
    3. Disposto de maneira equilibrada, proporcional; ajustada. (figurado)
    4. Seguindo um raciocínio lógico, com nexo; coerente. (figurado)
    5. Sinônimos: coerente, harmônico, ajustado.

    Sei que avaliar um componente sob essa perspectiva é muito subjetivo e pode significar coisas diferentes para pessoas diferentes.

    Como eu faço isso? Eu olho para o código do componente e procuro por todo tipo de coisa que não deveria estar ali. Pergunto-me porque aquilo não deveria estar ali e penso em algum jeito de mover essa parte para um local mais adequado.

    Dividir para conquistar

    Na nossa vida de programador a gente está sempre resolvendo problemas. E problemas tem tamanho. Tem problema pequeno, médio, grande, … Resolver problemas pequenos costuma ser (nem sempre é) mais fácil do que resolver problemas grandes.

    Por isso um dos skills mais importantes que um bom programador precisa ter é a de dominar a arte de quebrar problemas.

    A dica aqui é simples de passar, mas difícil de dominar. Se está difícil resolver um problema:

    1. Pare
    2. Dê uns passos para trás
    3. Olhe para o problema e busque por pontos de quebra
    4. Quebre o problema
    5. Tente resolver uma parte
    6. Se funcionar: profit!
    7. Se não funcionar: volte para o passo 1.

    Trabalhei muito com comércio eletrônico ao longo na minha vida e, nesse contexto, sempre encontrei diversos tipos de problemas para resolver. Um desses problemas é: gerenciamento de produtos.

    É um problemão… tem questões de marca, especificações, preço, estoque, venda, promoções, kits, recomendações, etc. Não dá para resolver isso tudo de uma única vez e, mesmo se a gente dividir cada uma dessas coisas em várias, os problemas resultantes podem continuar gigantes.

    Mas vou falar sobre um fluxo básico: eu sou vendedor (seller) de um canal (channel) de marketplace e cadastro um produto no site para vender. Só que tem outro vendedor que vende o mesmo produto.

    Primeira vez que modelei esse problema eu fiz: SellerProduct e ChannelProduct. Tinha uma instância de SellerProduct para cada vendedor com seu respectivo estoque, e preço e um ChannelProduct no canal apontando para um desses produtos de um desses vendedores. A gente dizia que um desses vendedores estava ganhando a “buy box”.

    Quando o primeiro vendedor cadastrou o produto ele informou que aquele produto era bivolt. O segundo vendedor falou que esse mesmo produto era 220V. Que informação eu coloco no site? Quem está certo?

    Outro problema: o vendedor #1 é de Recife e o vendedor #2 é de POA o preço dos dois é igual e eles têm estoques parecidos. O cliente de Maceió chega no site para simular o valor do frete. É bem provável que o frete do vendedor #1 seja melhor, mas quem ‘ganhou a buy box’ foi o vendedor #2. Como calcular todos os fretes de todos os vendedores e escolher o melhor rapidamente? Perdemos a venda?

    Como vocês podem notar a modelagem não está dando conta do recado. Precisamos repensar ela. Talvez a gente precise quebrar esse problema ainda mais.

    Nesse processo a primeira coisa que ficou clara para gente é que “Produto” significa muitas coisas diferentes para pessoas e contextos diferentes.

    Para o vendedor um produto é “um item no seu estoque”. Ou um “SKU em seu portfólio”. Para uma marca/fabricante/importador um produto é “algo que ele produz com certas características”. Para o canal de venda um produto é “algo que eu estou ofertando”. E para o cliente o produto é “algo que ele compra”.

    Entenderam o raciocínio? O super problema “gerenciamento de produtos” precisa ser quebrado em problemas menores:

    1. Gestão de Portifólio (SKU e estoque)
    2. Gestão de Catálogo (características de um produto)
    3. Gestão de Ofertas/Distribuição (anúncios e vitrines)

    E cada um desses sub-problemas ainda pode passar por mais um processo de quebra.

    Lazy Preoccupation

    Esse princípio foi adicionado mais recentemente ao meu repertório. E eu mesmo que dei esse nome (então nem adianta procurar ele na internet 😛 ). Esse princípio deriva da minha experiência de trabalho com metodologias ágeis de desenvolvimento de software.

    O princípio da preocupação tardia (lazy preocupation) é: resolve o problema que tem para resolver agora e deixa os problemas futuros para serem resolvidos no futuro.

    Parece bobo de tão óbvio (e é), mas é muito interessante ver como eu ainda falho na aplicação desse princípio em certas ocasiões.

    A questão aqui é: se você já está trabalhando na solução do menor problema possível (ver tópico anterior) e está funcionando é provável que o mesmo aconteça com os futuros problemas quando chegar a vez deles serem resolvidos.

    Quando o futuro chegar, também, é muito provável que sua compreensão sobre o domínio do problema já esteja mais evoluída e solucionar ele fique até mais fácil.

    E mesmo nos casos onde isso não acontece e a solução do problema anterior trava a solução do problema futuro é só dar uns passos para trás e tentar outra abordagem. Agora você vai conseguir fazer isso de forma muito mais efetiva porque já tem conhecimentos complementares para te guiar.

    Também aplico esse princípio para lidar com questões de modelagem vs. implementação. Quando estou criando a modelagem de um sistema eu tento não me preocupar com características de implementação. Qual banco de dados vou usar? A API vai ser REST ou gRPC? Vou usar serviços ‘serverless’? Isso vai ficar lento?

    Esse tipo de preocupação, logo no começo, atrapalha demais o foco no problema e na modelagem na solução abstrata dele. O melhor momento para pensar na implementação da solução é no momento em que você for implementar ela.

    Práticas

    Abrace as falhas e as hostilidades

    Programadores tentam escrever softwares sem falhas. Eles estudam para melhorar suas habilidades e produzir código com mais qualidade. Aprendem a fazer testes automatizados tanto para melhorar o desenho das suas implementações (TDD) quanto para garantir que o software funcione conforme o esperado. O problema está aí “conforme esperado”. O que isso significa exatamente? O que acontece quando um software falha? E quando isso acontece de forma “inesperada”? É possível escrever um software infalível? Não. Não é.

    Se não é possível escrever software infalível porque a gente ainda escreve software esperando que o melhor aconteça? E porque a gente tenta esconder essas falhas dos clientes desse software?

    Acho que isso acontece porque a gente, como programador, considera a falha de um sistema como uma falha pessoal. Algo que é responsabilidade nossa. “Como eu não pensei nesse cenário? Como sou burro!”, não é mesmo?

    Ok… Mas se todos concordamos que é impossível escrever um software porque nos culpamos pelas falhas? Se todo sistema falha não seria melhor aceitar essas falhas de forma mais natural? Expor elas sempre que acontecerem? Falhar o mais rápido possível ao invés de segurar uma situação insustentável por mais tempo e aumentar o estrago?

    Quando estou desenhando uma solução eu sempre carrego a premissa de que todos os componentes que estou escrevendo ou usando vão falhar em algum momento.

    Resguardar todos esses pontos para garantir de que nenhum dessas partes irá causar um dano muito grande em caso de falha também é muito difícil. Talvez seja fundamentalmente impossível garantir isso (halting problem).

    Quanto mais queremos proteger e acrescentar redundâncias e proteções à nossa solução, mais custo e complexidade vamos adicionando nela… o que eu faço então?

    Eu sempre projeto sistemas que estejam prontos para continuar funcionando mesmo em cenários de falhas pontuais. Não dá para proteger todos os pontos, logo, se alguns componentes específicos falharem a coisa vai despencar completamente. À esses pontos então eu acrescento uma camada de redundância e uma camada de monitoramento e alertas mais rigorosos. Pronto.

    Na minha apresentação sobre a arquitetura de uma das empresas onde eu trabalhei os nossos “Calcanhares de Aquiles” eram:

    • PaaS (Heroku) – se o Heroku caísse dava bem ruim. Não tinha redundância então era só monitoramento mesmo. Também usávamos o PostgreSQL deles. Mas nesse caso tinha uma fina camada de redundância (dentro do próprio Heroku que não é o ideal).
    • AWS SNS – se esse falhasse despencava todas as operações ‘online’ da empresa. Só monitoramento.
    • AWS SQS – se esse caísse a gente perderia dados em um nível muito grave. Então tinha monitoramento e sempre garantia um bom número de workers para esvaziar essas filas.
    • AWS – Se a AWS inteira caísse… bom… ficaria complicado haha 🙂 Mas nesse caso a Internet inteira estaria com problemas.
    • DNS – Esse é sempre um problema para a Internet inteira.

    Qualquer outra coisa que ficasse fora do ar além dessas causaria alguma degradação ao sistema, mas ele se reestabeleceria com a normalização dos serviços. Tem mais detalhes sobre essa arquitetura nesses links aqui:

    Nessa arquitetura, se um serviço falhasse ele retornava um código de falha. Se fosse um erro 5XX era um erro 5XX e ponto final. Não é vergonha retornar um 500 Internal Server Error se de fato um Erro Interno no Servidor (Internal Server Error dã!) aconteceu, oras! Não precisamos “passar pano” para erro de servidor. Se o servidor estivesse fora do ar para manutenção? 503! Se tivesse lento? Timeout! E assim vai.

    Quando a gente retornava um erro para o cliente (ex. worker) ele pode decidir como lidar com aquele erro. Tentar outra vez? Descartar a mensagem? Guardar o erro em um log? Não importa. Ele vai saber que aquela operação não aconteceu. Agora imagina se o servidor falhou na operação e retornou um 200 Ok dizendo que tá tudo sobre controle?

    Então abracem as falhas. Os erros. Tratem seus serviços como falíveis e vocês vão sempre desenhar soluções mais robustas.

    Idempotência é sua amiga

    Eu disse no tópico anterior que se aconteceu uma falha no seu serviço você tem que deixar isso claro para seu cliente, certo? Mas não custa nada dar uma mãozinha para ele se recuperar dessa falha depois.

    Vamos supor que tenho um worker que pegou uma mensagem de uma fila e precisa mandar 15 requests para uma API baseado nessa mensagem. Ele manda o primeiro e “ok”. Manda o segundo e… “ok”. Manda o terceiro e “ERRO!”. Tento mandar o quarto e… “ERRO!” e assim vai até o fim.

    O que eu faço com os requests que falharam? Tento outra vez? E se continuarem a falhar? O que eu faço?

    Em teoria você precisaria de um lugar para “anotar” quais requests falharam e quais tiveram sucesso em algum lugar para retentar só aqueles requests que falharam? Mas o worker não guarda estado. Ele só pega mensagem de uma fila e procede com os requests.

    Criar um sistema só para guardar os requests que precisam ser feitos é muito complexo. E se esse sistema também ficar fora do ar? Entenderam o drama?

    Pois bem. Fizesse a tal API ser idempotente? Se você repetir um request que já aconteceu antes ela responderia algo tipo: 304 Not Modified ou 303 See Other (que são 2 códigos HTTP de sucesso?).

    Se sua API for implementada desse jeito o seu worker pode falhar completamente a transação (devolvendo a mensagem para a fila) porque quando ele precisar repetir essa operação ele vai repetir exatamente os mesmos 5 requests. E nenhuma informação vai ficar duplicada ou faltando do lado da API.

    Tente sempre fazer com que suas interfaces privilegiem operações idempotentes (mesmo que para isso precise fazer umas concessões aos padrões de POST e PATCH).

    HTTP é rei e a Web é uma API

    Duas das coisas mais difíceis em computação, para mim, é dominar a arte secreta de se escrever bons protocolos e boas linguagens de programação. Só os grandes gênios da computação conseguem fazer isso bem feito.

    Um dos protocolos mais elegantes que já vi é o HTTP. Ele é simples, poderoso, compreensível, escalável, bem conhecido e tem ótimas implementações disponíveis para todo mundo.

    Com a explosão no surgimento de APIs REST foi possível mostrar que o protocolo HTTP, por si só, permite implementar um número gigantesco de soluções mesmo sendo um protocolo muito básico com apenas um punhado de métodos (GETPOSTPUTPATCHDELETE, etc).

    É isso mesmo: APIs REST tem somente esses métodos definidos por RFCs. Então aqueles ‘verbos’ nas URLs (ex. /user/subscribe) da sua API são, no mínimo, uma licença poética 🙂

    O que eu acho interessante nessa “limitação” é justamente isso: ela me força a refletir melhor sobre os objetos (ou documento, ou resource, ou …) expostos na minha API. É uma limitação que me força a pensar uma solução que consiga funcionar na simplicidade do protocolo.

    Coisas como gRPC abrem esse leque de opções absurdamente e, apesar de facilitar o desenvolvimento e a entrega do produto final, exige muita cautela por parte do desenvolvedor para não criar um monstrengo de API com dezenas de métodos diferentes. E é aqui onde a gente reafirma o princípio do “Menos é mais” que listei lá em cima. Já interfaces com GraphQL tem um propósito muito específico: navegar por graphos e não deveriam ser abusadas para outros usos (até porque APIs GraphQL usam o protocolo HTTP de forma bem… estranha…).

    Na minha apresentação “A Web é uma API” eu ilustro alguns conceitos que demonstram como a Web já é uma API inerentemente REST e no Toy, um framework de brinquedo, eu experimento esse conceito:

    Event Sourcing / Fire and Forget

    Event Sourcing é um modelo de arquitetura de software que casa super bem com o princípio da Lazy Preocupation e com o princípio do Menos é mais. Adotar esse modelo também permite que a gente trabalhe com APIs mais “burras” (simples/KISS) e, como veremos adiante, isso é desejável.

    Em arquiteturas mais “tradicionais” é comum à um serviço comandar operações, ou seja, o serviço determina e chama as operações que precisam ser executadas indiferentemente de uma sequência específica (sync) ou não (async).

    Um sistema que de gerenciamento de pedidos de um site de comércio eletrônico, por exemplo, ao receber um novo pedido, precisa gravar esses dados em um banco de dados, mandar um e-mail para o consumidor para confirmar o recebimento do pedido, avisar o sistema de fulfillment que tem um pedido novo que precisa ser preparado, etc, etc.

    Note que nesse modelo o sistema de gerenciamento de pedidos precisa distribuir todas essas tarefas para sistemas externos e isso cria uma dependência de todos esses sistemas no sistema de gestão de pedidos.

    Imaginemos que, no futuro, esse mesmo sistema de pedidos precise executar uma operação que envia os dados desse pedido para um novo subsistema de BI. Você vai implementar/implantar esse sistema de BI e vai ter que tambémadicionar uma chamada para ele no sistema de gestão de pedidos. Notaram o acoplamento aparecendo aqui?

    Em uma arquitetura baseada em eventos (event sourcing) o sistema de gestão fica responsável apenas por registrar o novo pedido e avisar que tem um “pedido novo” à quem possa interessar publicando esse evento em um tópico (ou subject) de um barramento de mensagens (publish).

    Se um sistema de fulfillment tem interesse nesse novo pedido (bem provável) ele só assina (subscribe) o tópico sobre novos pedidos e faz o que tem que ser feito em cada novo pedido.

    Usar um sistema de filas persistentes para assinar esse tópico é bastante prudente porque facilita o processamento desses eventos mesmo em cenários de falhas de workers ou instabilidades.

    Quando o nosso sistema de BI estiver implantado é necessário apenas conectar ele ao sistema de pedidos através de outra assinatura ao tópico de novos pedidos e, desse modo, o sistema de gesrenciamento de pedidos nem precisa tomar conhecimento desse novo sistema. É só disparar e esquecer. Fire and Forget.

    APIs burras e autônomas, workers espertos e dependentes

    Para que a gente considere uma API HTTP boa ela precisa apresentar um conjunto muito grande qualidades. Características como robustês, estabilidade e performance são só algumas dessas qualidades.

    Quando uma API tem muitas responsabilidades e faz muitas coisas é bem provável que sua complexidade cresça demais e entregar essas qualidades começam a se tornar um desafio bem grande.

    E se as APIs delegassem essa complexidade para outros agentes da arquitetura? E se elas fizessem menos coisas? E se elas fizessem só o básico de validação de dados, armazenassem os dados que precisam ser armazenados e avisassem que essa operação aconteceu?

    Uma API que sabe validar, guardar e notificar o que aconteceu entrega tudo o que uma API precisa fazer. Mas ela precisa ser capaz de fazer isso sozinha. Se a validação de uma informação precisar de algum dado externo esse dado precisa ser “injetado” nessa API. Mesmo que isso cause uma duplicação (desnormalização).

    Se a função de uma API se restringir à essas 3 operações fica muito fácil implementar uma API simples, rápida, robusta e estável porque o código dela será muito simples. Quase nenhuma regra de negócio incorporada ao seu funcionamento.

    As regras de negócio mais complexas podem ficar em workers que estarão processando os eventos de uma fila (que assina um tópico) e terão todo o tempo do mundo para aplicar essas regras, fazer consultas em outras APIs, e gerar um resultado que será postado em outra API, na API originária, ou até mesmo em um tópico do barramento de mensagens.

    Idealmente um worker deve gerar uma única saída (ex. POST) para cada evento de entrada. Essa regra só pode ser violada nos casos onde a API que receberá essas saídas múltiplas for idempotente. Caso contrário você pode ter problemas com duplicação de registros.

    Deixe as decisões para quem detém mais contexto

    Quando a gente aplica o princípio da Lazy Preoccupation é bastante comum perceber que quanto mais um fluxo de processamento se adentra pelo sistema, mais informação de contexto ele carrega.

    Isso significa que quando você recebe uma entrada no sistema ela tem apenas os dados informados ali. Conforme esses dados vão passando por outros sistemas ele pode ser enriquecido com informações adicionais e essas informações adicionais são muito úteis para tomar decisões importantes no fluxo das suas regras de negócio.

    Então evite ao máximo lidar com problemas complexos logo no início dos fluxos. Se tá difícil resolver um problema em um determinado ponto desse fluxo é melhor deixar ele adentrar um pouco mais (lazy preoccupation) para que ele absorva mais dados de contexto que podem ajudar nas suas decisões relacionadas às regras de negócio.

    Interfaces e protocolos guiam implementações

    A sigla API significa “Application Programming Interface” e a palavra importante aqui é “Interface” em contraponto à palavra “Implementation”. Alterar implementações é fácil. Alterar interfaces não.

    Quando eu altero uma implementação difilcilmente eu quebro um sistema. Mas se alteramos uma interface é quase certo que teremos problemas.

    Então, ao desenvolver um sistema novo, dedique bastante tempo nessa etapa. Técnicas como TDD ajudam você a transitar por esse estágio quando não conhecemos muito bem o domínio do problema que estamos lidando.

    Comece a implementar o sistema somente depois que você estiver confortável com o desenho das interfaces e modelos expostos por ela.

    Append-only for the rescue

    Os sistemas modernos que operam em uma escala muito grande invariavelmente precisam ser implementados usando modelos distribuídos e, em sistemas distribuídos, você vai acabar tendo que lidar com locks e implementações de mutexes. Muitas vezes o seu banco de dados é quem vai ter que dar cabo dessas operações mas o fato é que os locks e mutexes estarão lá para ferir a performance do seu sistema.

    Uma forma de diminuir (e até mesmo evitar) algumas dessas travas é substituir operações de update por operações de insert no seu banco de dados. Quando atualizamos um registro em uma tabela o banco de dados vai ‘travar’ esse registro para escrita bloqueando outras transações que queiram fazer o mesmo***. Isso pode penalizar severamente a performance do seu sistema. Para o banco de dados, fazer um insert, é muito mais simples e as ‘travas’ vão ser usadas somente para atualização de índices.

    Mas isso tem um custo muito alto no processo de recuperar essas informações. No lugar de recuperar apenas um registro do banco de dados você precisa buscar todas as operações relacionadas àquele registro e consolidar elas para obter a informação necessária. Muito ineficiente.

    Para amenizar essa ineficiência é possível utilizar o design pattern CQRS (Command and Query Responsibility Segregation) que segrega as responsabilidades de escrita e leitura em dois segmentos diferentes do seu banco de dados permitindo escritas rápidas que serão ‘projetadas’ assíncronamente em um registro consolidado para consulta futura.

    Notas

    * Hoje traduzem esse acrônimo como “Keep It Super Simple” por causa da carga ruim que a palavra “Stupid” da tradução original (Keep It Simple Stupid) carrega.

    ** Refactoring é aperfeiçoar um pedaço do seu código sem alterar seu comportamento. O que garante que esse comportamento não está sendo alterado é um conjunto de testes automatizados. Ou seja, se não tem teste automatizado ou se o comportamento do software muda não é um refactoring. Se acontecer de algum teste quebrar durante um refactoring é interessante tentar entender se isso acontece porque seu código está mal implementado (ex. testando mais a implementação do que o comportamento) ou se a mudança está realmente mudando o comportamento do código. Vamos usar as palavras corretas para refactoring e para reescrita.

    *** Esse assunto é um tanto mais complexo que isso e recomendo a leitura do livro “Designing Data-Intensive Applications” (Martin Kleppmann) para mais detalhes sobre esse assunto.

  • Aprendendo POO

    Aprendendo POO

    Dia desses vi um tuíte onde uma pessoa contava que estava tendo dificuldades em aprender Programação Orientada a Objetos (POO ou Object-Oriented Programming – OOP) mesmo depois de já ter estudado bastante. O tuíte me fez lembrar que também foi difícil no meu caso.

    Se tem um assunto que me fascina é o aprendizado de computação. Nunca trabalhei com isso e nem sou um especialista mas sempre estou pesquisando sobre o assunto. Gosto desse assunto porque aprender computação sempre foi algo prazeroso pra mim e gostaria de entender porque isso acontece com algumas pessoas e com outras não. Queria saber se seria possível ensinar computação de um jeito que os aprendizes tivessem essa mesma sensação e esse mesmo tipo de emoção.

    Mas com o tempo fui entendendo que as pessoas são muito diferentes e a forma com que cada uma delas encara diferentes tipos de aprendizados também varia muito. Pode até ser possível personalizar uma experiência para uma pessoa mas certamente esse método não funcionaria com outra.

    Eu mesmo… sou péééssimo para aprender idiomas. E não é que eu não goste de estudar e aprender… é só que eu tenho que lutar muito mais que outras pessoas para avançar só um pouco. Cheguei até a achar que eu era só um “burrinho esforçado” mas hoje entendo que não existe gente burra. Tá… Pensando bem… Tem algumas que são burras sim… mas não é esse o ponto desse texto 🙂

    Mesmo na computação tem assuntos que me exigem mais do que outros para aprender. Por exemplo: aprender uma nova linguagem de programação em um paradigma que eu já conheça é super rápido. Como já tenho referências de outras linguagens é basicamente construir paralelos entre umas e outras: “Ah! A sintaxe do Java parece com a sintaxe do C/C++.” ou, “Essa parte entre colchetes do Objective-C lembra um pouco do Smalltalk”, e assim por diante.

    Mas quando é pra aprender um novo paradigma de programação, meu amigo, a coisa empaca muito. Já faz uns bons anos que bato na trave para aprender uma linguagem funcional mas não sai. A última “vítima” dessa tentativa foi Elixir. A linguagem parece incrível e me deixou super empolgado, mas… não evolui.

    E sabe de uma coisa? Está tudo bem. Hoje eu tenho maturidade para entender que uma hora ou outra sai. Porque foi assim que aconteceu quando dediquei tempo para aprender Programação Orientada a Objeto.

    No começo era o BASIC

    Nos anos 80, algumas crianças privilegiadas como eu, tiveram contato com os primeiros microcomputadores que apareceram no mercado brasileiro. Eles se tornaram “acessíveis” (bota aspas nisso…) para a população e eram vendidos, para os pais, como ótimas ferramentas de aprendizado para os seus filhos. Era a ferramenta perfeita para tirar o gênio da cabeça das crianças.

    Já para as crianças elas eram perfeitos videogames que ofereceriam horas e mais horas de diversão. No meu caso foi um pouquinho diferente: eu queria jogar meus próprios jogos e para isso eu precisava aprender a programar. E então tudo começou.

    Essas máquinas vinham quase sempre com algum dialeto de BASIC para programar. E como essas máquinas eram lentas e limitadas qualquer código BASIC rodava na velocidade de uma tartaruga. Com freio de mão puxado. E por isso meu sonho de criar meu jogo foi sendo postergado… e postergado… e…

    O jobzinho…

    Certo momento da vida apareceu uma oportunidade para trabalhar como programador em uma imobiliária. Comecei o desenvolvimento em BASIC mesmo mas logo tive contato com uma linguagem mais apropriada para desenvolvimento de software empresarial: Clipper (Summer’87).

    A linguagem Clipper era meio diferentona… não tinha número de linha nos programas. Não tinha comando GOTO para desviar o fluxo da execução… mas aos trancos e barrancos eu fui aprendendo…

    Engraçado lembrar que eu achava ela uma porcaria porque não tinha GOTO e me obrigava a ficar fazendo loop dentro de loop dentro de loop com flag1flag2flag3, … pra controlar a execução. Imagina a maçaroca que era esse código (por isso você não deve se culpar por fazer código ruim quando está aprendendo…).

    Logo depois desse trabalho eu tive contato com a linguagem Pascal e passei a focar mais em usar ela porque ela permitia desenvolver software gráfico (uma limitação do Clipper que só permitia gerar gráficos com bibliotecas proprietárias externas).

    Foi só quando aprendi Pascal que também aprendi que esse paradigma de programação que eu estava usando desde o Clipper se chamava “Programação Estruturada”.

    Foi também através do Pascal que tive meu primeiro contato com um paradigma “novo” que iria “revolucionar a forma de escrever software”: a Programação Orientada a Objetos.

    Lembrem: eu era um brasileiro, morava no interior, não sabia nem o que era Internet, etc. As únicas fontes de informações que a gente tinha do mundo da informática eram as revistas, os livros e os ‘pirateiros’, profissional que conseguia as ‘cópias do original’ dos softwares que a gente usava. Ah! E software pirata sem manual! 🙂

    O Turbo Pascal que a gente usava vinha com um negócio chamado “Turbo Vision” que era implementado com classes e objetos e permitia criar janelas em tela texto e usar com o mouse. Era bem massa… mas eu não conseguia usar porque não sabia direito nem o que era um “objeto”.

    Como as revistas só falavam dessa tal POO e eu não conseguia entender nem usar eu até comecei a pegar “ranço” do troço. E eu tentei (o primeiro código OO que escrevi sobreviveu e está aqui. Era uma interface para usar mouse no DOS).

    Mas não avancei daí mais. Pra mim, naquela época, objeto era um “struct com função dentro” (ou um “record com função dentro” pra quem prefere Pascal).

    Nessa época eu até comprei um livro sobre programação OO mas desisti da leitura logo no começo porque não estava entendendo nada. Guarde essa informação.

    Avança a fita e pula uma parte…

    Depois disso eu decidi sair da profissão de programador e deixar a programação mais como hobby e investi meu tempo e aprendizado em coisas de mais baixo nível. Foi quando aprendi C, Assembly, comecei uma BBS, fiz estágio com Unix, mexi com Linux, etc…

    Então tudo mudou novamente e fui trabalhar com Linux na Conectiva (com C) e conheci Python.

    Python pra que te quero

    Eu ainda pretendo escrever sobre a guinada que a linguagem Python proporcionou na minha carreira então vou economizar aqui.

    Quando aprendi Python e usei ele em um projeto fui me acostumando cada vez mais a programar usando objetos. Mas só aprendizado prático mesmo: como criar uma classe, como criar “objetos” (o nome certo seria instância) dessa classe, etc. Criava aquele programão estruturado tudo dentro de uma classe só e tal… mas o código funcionava e as entregas eram feitas.

    Lendo mais sobre Python e estudando mais Python eu acabei sendo exposto a mais e mais código orientado a objeto. E fui aprendendo, de forma orgânica, a programar assim.

    A melhor forma de estudar programação é lendo programas. A melhor forma de aprender a programar é programando.

    eu mesmo

    Eu ia desenvolvendo código OO intuitivamente e por ‘imitação’ do código dos outros e, em paralelo a isso, os livros que eu passei a consumir iriam deixar de ser livros sobre “Python” e passariam a ser livros sobre “Programação Orientada a Objetos”. Como livro é caro eu decidi dar uma chance para um livro que eu já tinha comprado muitos anos atrás: Fundamentos do Desenho Orientado a Objeto com UML – Meilir Page-Jones.

    Aquele livro que não fazia o menor sentido pra mim no passado consolidou todo aquele repertório que aprendi de forma orgânica programando em Python e “magicamente” a programação OO passou a fazer total sentido pra mim.

    A partir desse ponto minha carreira profissional teve várias turbulências e tive que trabalhar com Java (detestei) e com Smalltalk (adorei), duas linguagens que também são OO e que possuem uma comunidade com bons fundamentos nesse paradigma. Ou seja, aprendendo e trabalhando com essas linguagens fui enriquecendo ainda mais a minha experiência nesse paradigma.

    Quando trabalhei com Smalltalk li outros livros importante pra mim mas que não são específicos para POO:

    1. eXtremme Programming Explained – Kent Beck
    2. Design Patterns (ou Padrões de Projeto) – Gang of Four (esse é sobre POO)
    3. Test-Driven Development by Example – Kent Beck
    4. Refactoring – Martin Fowler
    5. The Object Primer – Scott Ambler (esse eu gostei menos)

    Seria interessante acrescentar um livro que ensine POO junto com uma linguagem à essa lista também. Mas isso varia muito de linguagem para linguagem então o melhor é perguntar entre os profissionais de cada uma delas qual é o livro mais indicado.

    Precisa ler tudo isso pra aprender POO? Certamente que não. Eu diria até que alguns desses livros nem fazem bem para quem está começando. O que é importante mesmo é:

    1. Ler muito código OO
    2. Programar muito código OO
    3. Ler uns livros, artigos, etc nas horinhas vagas
    4. Descansar bem e cultivar uma vida saudável

    Outra coisa que é muito importante reforçar também é que nem sempre o que serviu pra mim vai servir pra você. Se não estiver funcionando, tenha calma, dê um passo para trás, e tente outra abordagem. Tenha paciência com você mesmo e não desanime. O caminho tá cheio de frustrações para serem superadas.

    E me desejem sorte… vou ali tomar mais um pouco de surra do paradigma funcional do Elixir…

  • Analista de Sistemas

    Analista de Sistemas

    Quando eu comecei a trabalhar com computação o mercado contratava Digitadores, Programadores e Analistas de Sistemas. Os digitadores só digitavam e os programadores só programavam os sistemas especificados por um “Analista de Sistemas”. Esse era “O Cara”.

    Como vocês podem ver a divisão do trabalho e responsabilidades era bem diferente do que temos hoje. Hoje temos umas divisões meio esquisitas tipo “backend” e “frontend” e um eixo, e divisões bem nebulosas como “Júnior”, “Pleno” e “Sênior” em outro eixo. Tem uns caras que correm por fora também: “devops”, “architects”, “leaders”, …

    Na mesma época em que comecei a trabalhar também já estava rolando um movimento onde contratavam os “Analistas Programadores”. Um cara que sabia fazer a análise de sistemas e a programação. Obviamente, como vivemos em um sistema capitalista, o salário desse profissional nunca era a soma dos salários de um programador e de um analista. Tipo um programador ‘fullstack’ recebendo salário de ‘front’ ou ‘back’. Precarização nunca foi um assunto novo.

    Mas essa introdução toda é só pra falar que quando estudei Processamento de Dados (outro termo que foi caindo em desuso junto com CPD) em uma ETEC eu tinha uma matéria chamada “Análise de Sistemas”.

    Naquela época eu já trabalhava com programação então eu matava boa parte das aulas para aperfeiçoar minhas técnicas em coisas importantes como jogar Truco. Com certeza valeu a pena.

    Mas as aulas de “Análise de Sistemas” do professor Peccini eu fazia questão de assistir. Queria assistir porque logo nas primeiras aulas ele falou coisas bem intrigantes sobre “Sistemas”.

    Prof. Peccini

    Uma das coisas que ele disse foi que “Sistemas” não tem uma relação direta com computadores. Sistemas sempre existiram e sempre vão existir. Com computadores ou sem eles.

    O trabalho de um analista de sistemas, então, com o perdão da redundância, é analisar esses sistemas e, eventualmente, propor mudanças. Que tipo de mudanças? Mudanças que possam tornar os sistemas mais eficientes ou até mesmo extinguir eles completamente. Automatizar certos sistemas com o uso de computadores é apenas um tipo de mudança em um grande universo de possibilidades.

    Ele também falava coisas como “Você não transforma um sistema ruim em um sistema bom colocando computadores e automatizações nele”. Ele falava que fazer isso era só “automatizar a burocracia”.

    Temos vários exemplos disso em nossa vida. Basta ir em um cartório e ver quantos computadores eles tem lá dentro.

    Naquela época a gente era jovem e adorava ficar de frente para o computador “codando” as coisas. Mas as aulas do Prof. Peccini eram na sala de aula normal. E ele dava coisas em papel pra gente estudar.

    Modelagem de Dados

    Algumas coisas que o Prof. Peccini ensinou pra gente é modelagem e normalização de tabelas.

    Isso é uma folha do talão de pedidos. Espécie de antepassado do “carrinho de compras”

    Em uma das aulas ele pegou um “talão de pedidos” que ele tinha comprado em uma papelaria e levou para a sala de aula. Ele ia destacando as folhas do talão e entregando para cada um dos alunos da turma.

    Depois que cada um de nós tinha uma folha dessas ele disse: quero que vocês criem uma ou mais tabelas no dBase III Plus (outro professor já tinha ensinado isso em outra matéria) para guardar informações de pedidos.

    Muitos alunos da turma modelavam apenas uma tabela e repetiam os dados comuns em todos os registros. Não julguem! É um curso onde as pessoas estão aprendendo as coisas. Lembrem que o normal é não saber o certo até que se aprenda.

    Eu, como já disse, por já estar trabalhando na área, fiz a minha modelagem certinha (pequeno ajuste aqui e ali). Mas confesso que fazia essas coisas por pura intuição.

    O professor então revisou os trabalhos com cada aluno e foi dando as orientações necessárias para cada um deles pensar em melhorias. Ele só dava dicas e fazia perguntas para os alunos. Os próprios alunos acabavam chegando à modelagem mais adequada. Depois desse exercício ele corrigiu tudo e deu notas (boas) pra todo mundo.

    A partir daí ele deu algumas aulas com exercícios mais convencionais sobre “normalização” de tabelas e usava sempre os erros iniciais dos alunos para ilustrar cada uma das técnicas de normalização.

    As aulas eram incríveis. Melhor que as melhores partidas de Truco que disputei na escola.

    Dicionário de Dados

    Antigamente os analistas de sistemas produziam muitos documentos sobre… sistemas. Um desses artefatos era o Dicionário de Dados.

    Um dicionário de dados servia para dar nomes, tipos, descrição e outras informações sobre entidades, relacionamentos, atributos, propriedades e domínio dos negócios.

    Era um troço chato pra cacete de produzir. Mas era um ótimo exercício para “dar nome aos bois”. Servia para desambiguar nomenclaturas e chamar as coisas certas pelos nomes certos.

    Ele dizia que se tá difícil achar bons nomes para algo ou se tinha duas coisas diferentes com o mesmo nome isso era um sintoma de problema no sistema.

    Ele também falava que dar o mesmo nome para coisas diferentes em contextos ou com perspectivas diferentes era “ok”, mas o dicionário de dados devia deixar explícito esses contextos e perspectivas.

    Exemplo disso? A palavra de “Produto” tem significados diferentes para o estoquista, pro operário da linha de montagem, pro profissional do marketing, etc. Em um sistema que envolva todos esses atores é importante mapear todos esses usos e significados.

    Recentemente, no trabalho, um amigo citou um outro professor (Prof. Imre Simon da USP). Segundo esse amigo o Prof. Imre havia dito algo como “Um dos grandes problemas da computação é dar nomes diferentes para a mesma coisa e dar o mesmo nome para coisas diferentes” (não encontrei a citação original, então, me perdoem por eventuais equívocos).

    Na primeira edição do livro eXtreme Programming do Kent Beck e no livro Domain-Driven Design do Eric Evans também se fala um pouco sobre esse nivelamento de termos usando o conceito de metáforas de sistema (System Metaphor). Isso mostra que comunicar um sistema é um problema bastante antigo mas ainda presente e importante para o nosso trabalho.

    Modelagem de Sistemas em Software

    Se tem uma coisa que faço bem é modelar sistemas em software. Não consigo explicar porquê e nem tenho plena consciência do que eu faço para executar essa tarefa tão bem. A coisa simplesmente acontece. Acho que é o que chamam de “intuição”.

    Não sou infalível e já cometi muitos erros nessa tarefa. Mas na mediana eu tenho um saldo positivo.

    Sonho em, algum dia, ter uma consciência maior sobre o processo que acontece no meu cérebro quando estou modelando um software. Gostaria muito de escrever e ensinar isso para outras pessoas igual o Prof. Peccini fazia.

    Mas enquanto isso não acontece eu vou falar uma coisa ou duas aqui que eu acho que fazem parte desse conhecimento.

    Quando o professor falou que sistemas existem independentemente de computadores ele destravou algum circuito no meu cérebro que me permite observar um sistema funcionando e então partir desse sistema para guiar a minha modelagem. Independentemente de falhas e ineficiências ele é um sistema que já está sendo usado.

    Então eu sempre começo a modelar um sistema de software partindo do sistema real. Esse processo inclui a modelagem de dados, processos e o dicionário de dados.

    Aí eu lembro que o professor falou que colocar um software que reproduz problemas e ineficiências de um sistema é meramente “automatizar a burocracia”. A imagem de um cartório invade minha mente e eu inicio a busca por problemas, ineficiências e o que eu chamo de “armadilhas de modelagem”.

    Quando estamos modelando um sistema de software é bastante comum olhar para outros sistemas similares como referência (benchmark) e é bem comum a gente cair em armadilhas nessa brincadeira. Vou dar um exemplo.

    Uma vez (mentira… foram várias) precisei modelar um sistema de gestão de pedidos para um site de e-commerce. Pedidos nascem quando você finaliza sua compra e, geralmente, possuem um workflow que é implementado com uma máquina de estado. Então o pedido transiciona de “novo” para “pago” e para “faturado“, “enviado“, “entregue“, etc. Tem o estado “cancelado” também. Quase todo mundo modela assim e aí vários problemas começam a acontecer.

    Você percebe, por exemplo, que a gente não “envia um pedido”. A gente “envia pacotes com produtos pedidos”. Onde o estado “enviado” (e o “entregue”) deveria estar? No pedido? No “pacote”? A solução correta depende muito do significado de cada modelo de negócio. Mas a mensagem aqui é: pare para pensar no que acontece na vida real antes de colocar isso no seu software.

    Outro exemplo nesse mesmo sistema: cancelamento. Quando você para pensar na vida real você percebe que um pedido pode ser cancelado a qualquer hora. Pelo código de defesa do consumidor o cliente poderia cancelar esse pedido até 7 dias depois que o produto chegou na casa dele. Então a máquina de estado (bem simplificada) ficaria mais ou menos assim:

    Parece certo isso? Não, né? Ah! E as ações para cancelar um pedido variam dependendo da etapa em que ele foi cancelado. Imagine a complexidade disso.

    E se a gente quiser implementar o conceito de suspender um pedido sem cancelar (para conversar com o cliente sobre alguma dúvida que ele tenha)?

    Você vai modelar um sistema de gestão de pedido e quando olha em volta todo mundo modela mais ou menos desse jeito. É muito fácil cair nessa armadilha. Eu mesmo caí várias vezes.

    Talvez, e só talvez, “cancelado” não seja um estado dessa máquina de estado? Será que não poderíamos usar outro workflow/máquina-de-estado para gerenciar suspensões e cancelamentos?

    Outra armadilha no mesmo domínio de negócio tem relação com os termos usados para se conversar sobre o sistema. Uma frase como “Vou colocar o produto pra vender no site” pode induzir o analista de sistemas a criar uma entidade Product no site de comércio eletrônico quando na verdade você não tem um produto de verdade lá. O que a gente tem em um site de comércio eletrônico são anúncios de itens (SKUs – Stock Keeping Unit) de um produto (GTIN/EAN/ISBN) produzida por uma marca.

    Entendem o problema que a ambiguidade da palavra “produto” pode trazer pra sua análise?

    Óbvio que eu caí nessa armadilha inúmeras vezes. Honestamente eu caí nessa armadilha *todas as vezes* que tentei modelar esse software.

    Então… esse casos servem para ilustrar, na prática, algo que acontece intuitivamente no processo de análise de sistemas que eu faço. Como não consigo fundamentar essas explicações eu espero que os exemplos ajudem vocês de algum modo.

    É certo que tem mais técnicas e processos que eu uso e conforme eu for tomando consciência deles vou tentar trazer aqui pra vocês.

  • Comunicação Indolente

    Comunicação Indolente

    Sou extremamente entusiasmado com tecnologia e adoro até mesmo aquelas tecnologias que chegam pra quebrar tudo que já existe. Tecnologias disruptivas, na maioria das vezes, empurram a sociedade pra frente. Na terminologia usada na política eu seria chamado de “progressista”. O oposto de um “conservador”.

    Mas ser um progressista não deveria impedir as pessoas de apontarem os problemas causados por novas tecnologias. É necessário que isso aconteça para que a sociedade coloque essas novas tecnologias problemáticas como pauta para novos “progressos”.

    Tecnologias usadas nas redes sociais, os tais “algorítmos”, produtos construídos no bojo da Inteligência Artificial (Machine Learning, Deep Learning, etc), Deep Fake, e etc já estão se mostrando bastante problemáticas em muitas aplicações. Não quero que elas acabem (até porque seria impossível) mas precisamos entender elas melhor e ajustar o seu uso.

    Mas não pretendo tratar desses grandes tópicos aqui. Eu sequer teria capacidade para abordar esses assuntos. Vou tratar de uma tecnologia bem mais prosaica: as novas ferramentas de comunicação empresarial.

    Vou falar sobre o Slack mas acho que os pontos aqui também se aplicariam a ferramentas similares como o Teams, Rocket Chat, e até certo ponto, o Discord. E vou falar mais do Slack porque é a que tenho usado por mais de 5 anos infelizes.

    Comunicação

    Existe uma classe de medicamentos chamada de “genéricos”. A piada (ruim) diz que os medicamentos genéricos servem para curar problemas genéricos.

    Se existe uma classe de problemas genéricos essa classe é a dos “Problemas de Comunicação”.

    Eu aposto uma jujuba que em quase toda reunião de feedback, sprint review, ou post-mortem/lessons-learned, alguém vai logo dizer “ah! mas isso foi um problema de comunicação”, ou, “acho que é só a gente melhorar a comunicação”.

    A comunicação… ah essa malvada! Sempre essencial e importante e tantas vezes negligenciada.

    A comunicação é composta de vários elementos: emissores, receptores, mensagens e meios e para que ela funcione bem todos esses elementos precisam funcionar corretamente. Se tudo isso funcionar corretamente a gente acaba com uma comunicação efetiva.

    Não importa se a comunicação é síncrona, assíncrona, rápida, lenta, detalhada, superficial, urgente, importante, online, offline, etc. Tudo isso pode variar e mesmo assim você pode ter uma comunicação efetiva.

    Vai falar que comunicação assíncrona é melhor para aquele cara que quer avisar que o sistema principal da empresa caiu. Uma plataforma de chat, um mensageiro eletrônico ou até mesmo um telefone são muito mais adequados para comunicar essa ocorrência do que um e-mail em um grupo de discussões, um telegrama ou uma carta.

    O oposto disso seria o processo de comunicação necessário na criação de um novo produto. Não me parece que usar um chat seja o melhor lugar para conduzir a comunicação necessária nesse processo.

    Imagine todas aquelas informações importantes sobre o projeto morrendo na timeline do chat como se fossem lágrimas na chuva.

    Nesse caso uma reunião presencial (quando possível), uma reunião online com um documento compartilhado ou uma thread em um bom fórum/grupo de e-mail funcionaria bem melhor. No caso do fórum/grupo você ainda incluiria aquele coleguinha que não pôde participar da reunião por um motivo qualquer (ex. férias, doença, compromisso pessoal, …).

    Indolência

    Eu comecei esse artigo com uma reclamação no Twitter. Logo vi que parte das pessoas não entenderam muito bem o meu ponto por lá. Sabe porque? Porque o Twitter é uma péssima ferramenta de comunicação para expressar tudo o que estou colocando aqui.

    Por esse motivo achei importante escrever exatamente o que eu penso aqui. Um meio muito mais adequado para comunicar ideias mais elaboradas. Eu precisei ser menos indolente (slack) e menos negligente (slack) na minha comunicação.

  • A Virtude da Paciência

    A Virtude da Paciência

    Eu tenho dois filhos que fazem parte das gerações Z e Alpha. Essas últimas gerações tem algumas características em comum e uma delas é a de que eles querem tudo na hora, só clicando um botão. Eles não querem profundidade. Preferem respostas rápidas. On-demand. Just in Time.

    Eu sou de outra geração (acho que é a Gen X) mas já tinha essa mesma ansiedade. Quando eu era criança falava que iria aprender tudo o que a humanidade sabia. Achava que todo o conhecimento da humanidade era o que estava dentro dos 10 volumes da Enciclopédia Trópico que a gente tinha em casa. Era bastante coisa para uma criança mas, ei!, eu tinha uma vida toda pela frente!

    Todo o conhecimento da humanidade

    Aí a criança cresceu e o mundo foi crescendo junto. Os horizontes se expandiram. Começou a ficar claro que a humanidade sabe muito mais coisas do que aquilo que estava na Trópico. O entusiasmo de aprender tudo virou um: ih! fodeu!

    Acabei deixando meu plano de saber tudo o que a humanidade sabe on hold (mais um na lista de projetos paralelos sem finalizar) e optei por desenvolver um MVP: aprender tudo sobre computação. Como já dá pra ver a primeira característica de um bom programador já estava presente: subestimar o tamanho dos problemas.

    Trinta anos depois de ter estabelecido essa meta eu posso dizer com tranquilidade: tá foda! 🙂 Não desisti ainda, mas preciso dizer para todo mundo que está começando na computação que não é fácil e leva tempo.

    Não conheço muito sobre outras áreas e profissões mas imagino que não seja muito diferente. Se embrenhar por uma carreira sempre vai exigir dedicação e tempo.

    É claro que hoje eu consigo aprender uma nova linguagem de programação muito mais rápido do que acontecia 20 anos atrás. Também consigo entender o que uma ferramenta faz com poucos parágrafos de texto ou em uma boa conversa no boteco com amigos da área (saudades disso!).

    Porque eu consigo entender e aprender algumas dessas ferramentas tão rápido? Porque depois desse tempo todo eu adquiri experiência.

    Experiência é o produto de dois fatores: prática deliberada e tempo.

    Sem a prática deliberada você não ganha experiência. Sem tempo você também não ganha experiência.

    Oportunidades

    Grandes Oportunidades requerem Grandes Experiências

    Tio Benedito (eu acho)

    Já faz algum tempo que o setor de Tecnologia da Informação anda muito aquecido. Tem um mundo vagas abertas para diversos tipos de posições e com o aumento de oportunidades de trabalho remoto esse mercado expandiu ainda mais.

    Por conta dessa efervescência tem muitas pessoas chegando ou migrando para a área de TI. E eu acho isso ótimo! Pra falar a verdade eu acho até que “tá pouco, manda mais”!

    Nesse processo tem chegado todo tipo de pessoas com todo tipo de experiências, expectativas, e necessidades. Para alguns é uma jornada para a vida. Para outros é só mais uma ‘corrida pelo ouro’. Pra ser honesto eu não ligo muito para as motivações dessas pessoas porque cada um sabe quando o boleto vence.

    Mas no meio desse pessoal que está chegando tem um grupo que me preocupa um pouco mais: os jovens que anseiam por resultados rápidos.

    Eles me preocupam porque, como meus filhos, eles anseiam por resultados e respostas rápidas para tudo. Inclusive para suas carreiras. E é mais provável que esses resultados não cheguem tão rápido para quem está só começando. Bons resultados surgem com boas oportunidades e a probabilidade de uma boa oportunidade surgir para uma pessoa com pouca experiência é muito baixa.

    Então é preciso adquirir muita XP antes de encarar os chefões do jogo.

    É fácil. Mas é Difícil.

    Sempre que alguém me pergunta se é muito difícil aprender a programar eu respondo: é fácil mas é difícil. Obviamente, depois da brincadeira boba, eu explico melhor.

    Para se tornar um programador é necessário dominar várias técnicas (ex. dividir um problema grande em problemas menores, experimentação, etc), algumas ferramentas (ex. computador, linguagem de programação, editor de texto, controle de versão, banco de dados, etc) e algumas práticas (ex. escrever testes, revisar código, etc).

    Como você pode ver um programador não aprende só programação. Tem um portfólio completo de coisas que precisam ser estudadas em maior ou menor profundidade para se tornar um programador melhor e melhor.

    Algumas dessas coisas vão ser fáceis de aprender e entender. Outras serão bem desafiadoras. E eu não consigo fazer uma lista classificando quais são fáceis e quais são difíceis porque isso varia muito de pessoa para pessoa. Eu sofri para aprender programação OO. Amigos meus ‘sacaram’ o paradigma lendo um livro.

    Mas insisto em dizer que todo mundo consegue se tornar um programador mas não espere que seja só fazer um curso mágico e pimba! Sou um programador! Nem mesmo uma boa universidade sozinha vai fazer isso pra você.

    Se você pode fazer uma boa universidade aproveite a oportunidade e faça. Vai te ajudar muito na sua jornada. Mas lembre-se de que a jornada é sua e é você que precisa praticar programação.

    Aprender programação se parece muito com aprender uma arte marcial. Você não aprende Kung fu lendo um livro ou assistindo vídeo de aulas no Youtube. A menos que você seja o Neo no filme Matrix você só aprenderá Kung fu praticando.

    Señor Developer

    Foto de um fazendeiro mexicano usando chapeu e com um bigode bem grosso com a legenda "Respect! I'm a señor developer"

    O que eu disse até aqui não tem relação com a discussão infrutífera sobre “Senior Developer” que vez ou outra explode em algumas redes sociais.

    Essa classificação de senioridade é muito aberta e subjetiva. Ela varia de empresa para empresa e de programador para programador.

    Eu tenho minha definição sobre o que é um programador Senior e ela inclui o atributo experiência (ter um bigode grosso é outra coisa que conta para senioridade… brincadeirinha 🙂). Mas para outras empresas ou até mesmo para outros amigos meus isso não é tão relevante. E tudo bem!

    Algumas pessoas atribuem senioridade para programadores com experiências relevantes, outros definem que um profissional senior é capaz de ajudar outros colegas de trabalho. Como eu disse, isso varia muito e ficar discutindo o assunto é pura perda de tempo.

    Não seja fiscal de senioridade. Se importar muito com isso é um sinal de que algo precisa melhorar em você.

    Ceja Bem Vindos!

    Foto de uma fachada de restaurante com uma placa escrito: "Ceja bem vindo e esprimente a linguiça"

    No mais eu gostaria de dizer à todos que estão chegando e deixar aberto minhas redes sociais para todos vocês que sentirem que precisam de alguma ajuda nesse processo.

  • Bastidores de um Processo Seletivo…

    Bastidores de um Processo Seletivo…

    … para pessoas programadoras

    Como sou programador eu procuro sempre ter uma abordagem voltada para solução de problemas. Mesmo quando o problema que se apresenta não seja solucionável com software.

    No momento que a empresa onde eu trabalhava precisou aumentar a equipe fiquei de frente com alguns problemas importantes: como encontrar e contratar profissionais com o perfil que a gente precisava? Qual o perfil de profissional que a gente precisava?

    A empresa estava construindo os alicerces de uma plataforma de software. A pequena equipe que já trabalhava com a gente era muito qualificada e experiente. Também valorizavam a qualidade das práticas e processos de desenvolvimento para entregar sempre o melhor resultado.

    Então a gente tinha que contratar programadores que prezam a qualidade das soluções desenvolvidas e fazer essas contratações em ritmo bom.

    Perceberam que os dois requisitos podem soar contraditórios? Qualidade ou velocidade? Ambos!… Nessas situação a gente travou um limiar no aspecto qualidade e criou um processo que pudesse agilizar e uniformizar todas as contratações.

    Processos & Práticas

    Nesse artigo eu vou descrever o processo de seleção que construi, junto com minha equipe e o departamento de Recursos Humanos da empresa. Essa é a versão do processo que estava em uso até o momento que eu deixei a empresa. Não sei se eles ainda estão usando mas eu suspeito que não.

    O processo não é perfeito e, como disse, prioriza um perfil de profissional bastante específico: profissionais apaixonados por programação que querem trabalhar em uma equipe que desenvolve software. São profissionais que priorizam muita qualidade e boas práticas.

    Falei esse monte de coisas aqui em cima mas o que eu realmente queria fazer era criar o ambiente perfeito para o programador que existe em mim amaria trabalhar. ?

    Esse processo não é muito eficaz para empresas que precisam crescer o seu time de desenvolvimento de forma muito rápida ou que estejam em um estágio onde o mais importante é criar soluções rápidas para os problemas que se apresentam. E vocês verão que ele é bem longo.

    O processo todo é dividido em 8 fases. Cada prospecto/candidato tinha um card no JIRA que tinha algumas customizações que exigia o preenchimento de certas informações fossem feitas antes de se avançar para a próxima fase. Cada fase do processo era representado por uma coluna no JIRA.

    Aviso para candidatos

    Algumas informações desse artigo podem ser muito valiosas para vocês também. Entender como um desse processos funciona te permite fazer engenharia reversa e hackear o sistema. Espero que vocês façam bom uso desse material.

    Etapas do processo

    Etapa 0: Captação

    Antigamente as empresas descreviam as vagas com seus requisitos, colocavam em alguns forums e sites de emprego e ficavam esperando a enxurada de candidatos. Aí era só jogar todos esse candidatos nos diversos filtros, avaliar eles e escolher o mais adequado entre todos os finalistas. Essa abordagem passiva para contratar programadores não funciona mais tão bem.

    Hoje é muito difícil contratar bons programadores. Contratar bons programadores com experiência está se tornando quase impossível. Não sei se isso vai ser assim pra sempre mas já é uma realidade faz vários anos.

    Por conta disso a abordagem passiva para buscar candidatos precisa ser modificada e as empresas, agora, precisam ser pró-ativos na captação de bons prospectos/candidatos (leads). Uma vez que você encontra esses candidatos devemos iniciar o processo de “venda” da vaga para ele.

    Na empresa onde eu trabalhava a gente tinha diversas técnicas de captação. Eu vivia me embrenhando em redes sociais e grupos de desenvolvimento de software em busca de projetos bacanas e sempre que esbarrava em um programador interessante eu criava um card no JIRA com as referências desse prospecto.

    A empresa também incentivava (e financiava) os programadores da nossa equipe a participar de eventos de tecnologia e levar a palav… digo… apresentar as oportunidades que trabalho que a gente tinha aberto. A gente também tinha um orçamento para patrocinar esses eventos e poder ter uma presença mais marcante nessas ocasiões.

    A equipe de RH também ajudava muito na captação buscando leads em plataformas como Linkedin, Stackoverflow, etc.

    Eu fiz um breve “treinamento” (uma reunião rápida pra passar umas dicas) com a equipe de recrutadores explicando como abordar esse leads sem soar muito intrusivos. Ensinando a não ter nenhuma abordagem massiva (spam, mail marketing, etc) e sempre abordar cada lead depois de ter lido perfil e se informado sobre o possível candidato. Também expliquei como se comportar em comunidades de FLOSS e nunca postar uma vaga sem antes se apresentar e perguntar quais são as regras daquele grupo para anunciar vagas abertas.

    As descrições das vagas precisam “vender o produto”. Então elas precisam ser muito completas e contar até mesmo detalhes das tecnologias, processos, benefícios, etc. Apesar disso, nessa empresa, a gente não anunciava a faixa salarial e sempre dávamos respostas vagas como ‘acima da média de mercado praticadas no Glassdoor’. Não consegui convencer todo mundo sobre a importância de divulgar a faixa salarial. Mas esse assunto é complicado o suficiente e provavelmente merece um artigo só sobre ele.

    O processo todo deveria ter como alicerce o respeito total com os candidatos. Respeito com a pessoa, com o tempo da pessoa, e com a dedicação dela ao processo.

    Etapa 1: Entrevista Inicial

    Com o contato do prospecto e o estudo prévio dele já podemos entrar em contato e marcar a entrevista preliminar caso ele tenha interesse em nos atender.

    O dia e horário que você marcar essa entrevista já vai dizer um pouco sobre o ritmo de trabalho da empresa. Então fique esperto com entrevistas em horários bizarros como fins-de-semana ou tarde da noite. A menos que o candidato peça um horário diferente tente falar com ele em horário comercial.

    Se ele topou envie o convite por e-mail e marque em sua agenda e JAMAIS se atrase para essa entrevista. É crucial que você respeite o candidato desde o primeiro contato. Lembre que é a sua empresa que precisa dele.

    Essa parte do processo é a que vou detalhar menos porque ela era conduzida majoritariamente pelas psicólogas do RH da empresa que, por questões de ética profissional, não podiam detalhar o que faziam. Recomendo muito usar profissionais de psicologia no processo de recrutamento das empresas. A quantidade de informações úteis que eles conseguem trazer para o processo é incrível.

    Na entrevista inicial uma das psicólogas iniciava o contato online com o candidato, fazia algumas perguntas para ver se o candidato se encaixava no perfil de profissional que a empresa dava preferência e começava algumas anotações sobre pontos de atenção para serem explorados nas próximas etapas.

    Um exemplo: a empresa tem trabalho remoto e o candidato diz que nunca trabalhou remoto antes. Isso obviamente não desclassifica o candidato mas prepara os avaliadores das próximas etapas para ver se o candidato consegue se desenrolar bem nessa modalidade de trabalho.

    Aliás, essa etapa dificilmente ‘desclassificava’ alguém. Ela era muito mais útil para fornecer subsídios para os avaliadores. Em alguns raros casos a recrutadora era desrespeitada durante essa entrevista e, nestes casos, obviamente, o candidato caia por ali mesmo.

    Uma vez que a psicóloga estava confortável pra enviar o candidato para a próxima fase ela já apresentava o teste técnico (próxima fase), explicava como proceder com o teste e já deixava um contato para eventuais dúvidas. O teste não tinha prazo máximo pra ser feito mas a psicóloga contactava o candidato regularmente (semanalmente) pra perguntar se estava tudo ok com o teste. Algumas vezes os candidatos abortavam o processo e não avisavam nada pra gente e essas ligações serviam pra gente mover o card desse candidato pra coluna de finalização.

    Uma observação importante: a recrutadora também era a coordenadora do processo de cada candidato. Ela que “batia o bumbo” para que os processos andassem e os prazos fossem cumpridos. Ela também centralizava a comunicação com o candidato para garantir que ela estava dentro dos padrões.

    Etapa 2: Teste Técnico (Candidato)

    Eu não gosto de testes de quadro branco e acho esses testes de sites como HackerHank bastante limitados. Por mais que seja bem difícil e trabalhoso especificar um teste técnico que consiga abranger a avaliação de todas as habilidades importantes em um candidato eu acho que vale o investimento.

    O teste técnico é peça muito importante de todo o processo. Não só porque ele vai avaliar se o candidato tem o mínimo de conhecimento para trabalhar nos projetos que a empresa precisa. O teste técnico serve como subsídio para algumas etapas posteriores.

    O teste técnico que criamos possuíam as seguintes características:

    1. Venda seu peixe. O documento com o teste é uma boa oportunidade para mostrar como vai ser legal trabalhar junto com você na empresa.
    2. Projeto completo. O teste tem que pedir um projeto completo. Do desenvolvimento até o deployment em produção. Indique sites que possibilitem o deploy gratuito desse teste para o candidato (ex. Heroku).
    3. Definição de escopo e requisitos objetiva. O teste tem que ser enviado para o candidato com um único documento contendo todo o escopo do projeto. Se você espera que o candidato saiba inglês, por exemplo, envie esse documento em inglês. O documento deve especificar apenas o Quê precisa ser feito. Nunca diga como fazer à menos que isso faça parte das práticas que o candidato precise dominar mas que seja muito difícil ou demorado para ensinar. Exemplos de coisas que você pode pedir:
      1. Código com strings e identificadores em inglês;
      2. Usar alguma linguagem que a empresa use (para que possa ser avaliado);
      3. Testes automatizados;
      4. Documentação (no idioma que você quer avaliar no candidato);
      5. Armazenado em controle de versão;
      6. Seguir um coding style específico;
      7. Praticar conceitos de 12 Factor-App;
      8. API em um estilo específico (ex. REST, GraphQL, gRPC, etc)
    4. Simples e factível em 1 dia. Bons profissionais, geralmente, já estão trabalhando. É importante entender que eles não tem tempo para investir em um teste longo e trabalhoso.
    5. Não-relacionado à atividade da empresa. Não faz muito tempo algumas empresas usavam testes técnicos para obter desenvolvimento gratuito de candidatos. Por conta disso programadores são bastante desconfiados de testes que pedem o desenvolvimento de algo que a empresa possa usar sem pagar.
    6. Código aberto por padrão. Exceto em casos onde o candidato pede explicitamente para manter o teste dele fechado deixe ele como opensource. Isso diminui as dúvidas sobre o uso do código sem pagamento. Algumas pessoas me perguntavam se isso não pode ser usado por outros candidatos para copiar testes. Sim. E tudo bem, afinal, todo desenvolvedor sempre acaba copiando um código aqui e ali. Nas etapas seguintes é possível levantar o que foi copiado e a motivação para isso. Se foi plágio completo você consegue detectar fácil.
    7. Exercitar vários aspectos do trabalho. O teste pode ter uma regra de negócio elaborada, implementar uma API REST, armazenar os dados em um DB, ter modelos diferentes interagindo, etc. Problemas pontuais com coisas como carrinho de compras, gestão de assinaturas e pagamentos, gestão de conteúdo, logística e entregas, etc são ótimas fontes de ‘problemas de negócio’ que podem ser explorados para criar um teste. Lembre apenas de limitar bem o escopo para que seja possível criar algo em um dia.
    8. Validade limitada. O teste tem que ter uma validade limitada. A validade serve para que você reabilite candidatos que eventualmente não foram selecionados em um processo anterior a participar novamente. Ele fez o teste-1 e não foi adiante 6 meses atrás mas ele estudou os pontos que você indicou e quer aplicar para uma vaga novamente. Se o teste mudou ele pode reaplicar.
    9. Produzir contexto extra-código. O teste precisa permitir que o programador trabalhe nele como ele trabalharia na sua empresa porque não devemos avaliar apenas o código produzido. Precisamos ver a documentação do projeto, a linha do tempo dos commits e as mensagens de commit, abordagens alternativas para solução do problema, etc.
    10. Sem prazo para entrega. É importante deixar claro para o candidato que o objetivo dele é fazer o melhor teste que ele puder e não o tempo que ele leva para fazer isso. O tempo para realizar o teste precisa ser descartado completamente da avaliação porque cada candidato tem uma situação completamente diferente de outro candidato. Tem candidato que tem emprego e outro que não tem. Tem candidato que tem atividades paralelas e outros que não tem. Tem candidato que está estudando um tópico novo para fazer o teste e outros que já sabem tal tópico. É importantíssimo reforçar isso para o candidato sempre que entrarmos em contato com ele para que esse contato não se pareça com alguma forma de pressão por entrega. Diga que ele será avaliado pelo que ele entregar e não pelo tempo que ele levou pra entregar.

    Abaixo você consegue ver um exemplo de teste técnico:

    Assim que o candidato concluir o teste e enviar o material pra você a próxima etapa começa. Chegou a hora de avaliar o teste.

    Etapa 3: Avaliação Técnica

    A avaliação do teste precisa ser feita por um programador da equipe ou gestor que tenha trabalhado como programador da equipe. Ele vai pegar o código do candidato e uma ficha de avaliação com perguntas claras e objetivas sobre tudo o que a empresa espera do candidato e preencher essa avaliação.

    Mais do que a avaliação em si, nesse momento é bem importante que apareçam dúvidas na cabeça do avaliador. Essas dúvidas precisam ser anotadas juntamente com os resultados da avaliação porque elas serão extremamente úteis na próxima etapa do processo seletivo.

    Na empresa onde implementamos esse processo a gente criou uma planilha com um questionário com perguntas bem objetivas agrupadas em tópicos. Cada pergunta dessa gerava uma nota entre 0 (min) e 3 (max). Cada nota dessas tinha um peso variando entre 1 e 3 que posteriormente era usada em uma média ponderada.

    No final a gente gerava um gráfico do tipo radar com um eixo em cada tópico (ex. Documentação, Modelagem de Banco, Commits, etc) e uma lista de notas e observações do avaliador.

    Você pode baixar um modelo dessa avaliação aqui:

    Quando o volume era menor a gente colocava dois programadores para avaliar o mesmo teste e depois fazia uma ‘acareação’ mediada entre os avaliadores para evitar problemas de interpretação. Mas em um determinado momento o volume de testes para revisar ficou grande demais e só um programador fazia a avaliação de cada teste.

    Fizemos essa mudança porque raramente encontrávamos divergências muito grande e em todas as vezes o motivo da divergência era a falta de objetividade na pergunta do questionário que era prontamente corrigido.

    Essa avaliação não pode demorar muito pra ser feita e, se isso acontecer por algum motivo, é importante manter o candidato informado.

    Em alguns casos o candidato vai muito mal e recebe avaliações muito ruins e seguir com o processo provavelmente seria um desperdício de tempo para todos.

    Nesses casos é muito importante devolver uma resposta para o candidato e, se possível, indicar os pontos de estudo e melhoria para ele. Eu tinha uma lista de links para artigos ou livros para indicar que ajudariam o candidato a cobrir todos os pontos onde ele precisava melhorar.

    Esse feedback precisa ser mais abrangente do que específico:

    From: [email protected]
     
    Olá [candidato],
    
    Após a avaliação do seu teste técnico [url do
    teste] nós optamos por não seguir adiante com
    seu processo seletivo nesse momento.
    
    Agradecemos o seu tempo e dedicação até aqui e
    gostaríamos de vê-lo novamente no futuro quando
    lançarmos um novo teste técnico para a vaga.
    
    Para isso gostaríamos de sugerir a leitura dos
    seguintes materiais:
    
    * [link para um artigo sobre apis rest]
    * [link para um livro sobre modelagem OO]
    * [link para livro sobre TDD]
    * [link para um bom curso de Python no youtube]
    
    Se você tiver qualquer dúvida ou tiver
    interesse em nos dar um feedback sobre
    o processo até aqui é só entrar em contato.
    
    Obrigado,
    Equipe Empresa Co.
    

    Esse e-mail não é o lugar para escrever coisas como ‘você não foi aprovado porque a sua modelagem de banco estava toda errada’. Prefira indicar um bom livro sobre modelagem relacional. Dê preferência para conteúdo gratuito. Lembrem-se que o candidato pode estar numa situação financeira complicada.

    Na empresa onde eu trabalhei eu pedi verba para comprar ebooks e enviar para candidatos que não eram aprovados. Mas a verba não foi aprovada.

    Etapa 4: Entrevista Técnica

    Assim que a avaliação do teste técnico ficava pronta um gestor de tecnologia poderia prosseguir com o agendamento da entrevista técnica com o candidato. Ele fazia isso sempre buscando o melhor horário para o candidato. A entrevista também precisava ter uma duração fixa pré-determinada. Deve-se evitar dividir essa entrevista em etapas distintas. Ter ela em uma única sessão garante que você vai avaliar o candidato em sua plenitude de humores.

    Conduzir uma boa entrevista exige mais técnica do que experiência. Pode ser que eu escreva só sobre isso em um artigo futuro então vou só pontuar algumas coisas que a gente fazia lá.

    Antes de ir para a entrevista técnica o gestor já se preparava usando as informações das avaliações feitas pela recrutadora na entrevista inicial, as anotações da avaliação técnica e dando uma conferida no Linkedin ou no Github do candidato. Eu evitava redes sociais não profissionais (Twitter, Instagram, Facebook, etc) porque nas poucas vezes que olhei essas redes acabei sentindo que a entrevista ficou enviesada de forma negativa.

    Os gestores que faziam essas entrevistas já tinham alguma experiência com processos de recrutamento mas, mesmo assim, a gente ainda sugeria certos procedimentos para tentar padronizar a experiência. A gente sugeria que o entrevistador criasse um plano para a entrevista com algumas perguntas-guia para fazer para o candidato. Meus planos geralmente tinham umas 3 perguntas padrão que giravam em torno de relacionamento com equipe, processos e experiências anteriores, e umas 2 ou 3 perguntas que variavam em função do resultado das avaliações. Nem sempre eu usava essas perguntas mas sabia que elas estavam lá caso a entrevista ficasse meio truncada.

    Condução da entrevista

    Essa etapa não era muito padronizada então vou descrever como eu conduzia as minhas entrevistas. Como eu já disse eu iniciava a entrevista com um plano construído sobre as avaliações anteriores e uma breve olhada nas redes sociais profissionais do candidato.

    Sabendo que essa entrevista costuma ser a que deixa os candidatos mais nervosos e que muitos candidatos, mesmo aqueles com muita experiência, podem ‘travar’ nesse momento eu dedicava um bocado de tempo no começo só para deixar o ambiente mais leve e as coisas mais calmas. Você precisa que o candidato esteja tranquilo para conseguir uma boa entrevista.

    A entrevista técnica sempre começava com algumas perguntas básicas e despretensiosas sobre o candidato. Começar a conversa perguntando sobre algum hobby ou coisas positivas que surgiram na entrevista inicial tira o peso da entrevista e diminuíam o nervosismo do candidato.

    Um exemplo do que eu fazia era só perguntar coisas que o candidato sabe como responder com 100% de certeza. Perguntas como: “Qual seu nome?” ou “Qual sua idade?” estão nessa categoria. “Quais linguagens de programação você gosta?” não está nessa categoria porque o candidato vai começar a pensar sobre qual é a resposta que o entrevistador quer ouvir.

    Eu tomava muito cuidado com perguntas sobre a intimidade do candidato (ex. “Você é tem namorada(o)?”). Até pra perguntar se o candidato era casado(a) ou tinha filhos eu evitava. Se eu não estivesse 100% certo de que essas perguntas eram seguras eu não fazia. Por isso o planejamento prévio é essencial.

    Uma dica que sempre dou para quem está começando a fazer entrevistas é: você não precisa ser algo que você não é. Se você não é engraçado não precisa ser engraçado. Só tente ter empatia pelo candidato para poder ajudar ele.

    Quando você sentir que o candidato está mais calmo você pode serguir com o seu plano para a entrevista. Chegou a hora de falar pouco e ouvir muito.

    Aqui eu partia para as perguntas técnicas. É muito comum que programadores estejam mais confortáveis com a parte de hard skills então a transição para essas perguntas acontecia de modo mais natural.

    Eu usava o teste do candidato para formular questões bem objetivas. Perguntas do tipo: “Aqui nesse ponto do seu código você fez isso. Porque você fez assim e não assado?” (ex. “Vi aqui nessa parte do seu teste que você modelou esse relacionamento em 1-para-N… mas e se essa entidade estiver em M contextos, não seria melhor um N-para-M?”).

    Eu prestava atenção no que estava sendo dito (ex. “eu optei por modelar 1-para-N porque na descrição do problema não existia o requisito que pediria uma modelagem N-para-M”), mas também observe o que não está sendo dito. No exemplo anterior dá pra inferir que o candidato segue bem as especificações mas pode não ser muito pró-ativo em questionar essas especificações. Eu encadeava mais perguntas pra dirimir essa dúvida e não ficar só com a minha “inferência”.

    Também gostava de fazer perguntas que podiam ser respondidas corretamente de vários modos diferentes e emendar uma segunda pergunta contrapondo a resposta. Exemplo: “Se você tivesse desenvolvendo um ORM como você faria pra persistir um objeto no banco de dados? Faria obj.save() ou storage.save(obj)?” e a próxima pergunta seria: “Mas [a outra abordagem] não teria a vantagem de [vantagem da outra abordagem]?”. Esse tipo de pergunta permite ver o candidato reagindo à uma situação de argumentação e defesa de seus pontos de vista. Alguns candidatos até explicaram a teoria e as referências para as duas abordagens (Active Records vs. Data Mappers). Esse foi contratado, né? ?

    Uma vez que as questões técnicas foram esclarecidas eu partia para as “perguntas difíceis”. Aqui eu queria entender mais sobre os soft skills do candidato. Nesse momento o candidato estava mais amaciado com as coisas que ele (teoricamente) sabia e conseguiria responder com a guarda mais baixa.

    Eu voltava então a fazer perguntas relacionadas ao comportamento e relacionamento do candidato com as equipes que ele teve.

    Queria saber como era a relação dele com gestores, o que ele gostava no trabalho, o que ele detestava, o que ele gostaria de mudar, o que ele conseguiu mudar, o que ele não conseguiu mudar, porque ele não conseguiu mudar, etc.

    Eu sempre tomava notas durante a entrevista. Precisava fazer isso para alimentar o nosso relatório sobre o candidato.

    Finalmente chegamos ao fim da entrevista. Você agradece o candidato e avisa que ele receberá um retorno num prazo específico. Cumpra esse prazo.

    Retorno

    O retorno para o candidato podia ser de 2 tipos:

    1. Paramos: agradecíamos o candidato pelo tempo investido no processo, informávamos que ele pode voltar a tentar a vaga no futuro, indicávamos caminhos que ele poderia tomar para ser melhor sucedido na próxima oportunidade, e deixávamos um canal sempre aberto para comunicação com ele. Esse retorno era por e-mail mas eventualmente o RH entrava em contato direto com o candidato.
    2. Continuamos: parabenizávamos o candidato e informávamos que a próxima etapa seria uma dinâmica de Pair Programming remoto com um dos nossos desenvolvedores. Pedíamos um espaço na agenda do candidato para essa atividade.

    Etapa 5: Dinâmica de Pair Programming Remoto

    A equipe de tecnologia da empresa onde implementamos esse processo sempre trabalhou remotamente. Trabalhar remoto é uma atividade que pede certos soft skills importantes (ex. auto-gestão, auto-organização, etc) e o nosso processo precisava avaliar se o candidato tinha essas características, se era necessário desenvolvê-las, ou se a empresa seria incapaz de desenvolver essas qualidades no profissional caso ele fosse contratado.

    Quebramos a cabeça pra descobrir um modo de fazer essa avaliação e, certo dia, participando de um Coding Dojo com alguns amigos eu tive a ideia de tentar algo parecido para avaliar a dinâmica de trabalho remoto do candidato. Deu super certo e se tornou a etapa que me deixava mais entusiasmado com os resultados.

    Montamos um servidor remoto (usando AWS Cloud9) com a linguagem Python, framework de teste, editor de textos e conectávamos um desenvolvedor da nossa equipe e o candidato para fazer pair programming. Além dos dois programadores um gestor (geralmente o mesmo que fez a entrevista técnica) ficava na audiência coordenando a atividade e observando a dinâmica.

    O gestor então apresentava o problema que seria abordado na dinâmica. Eram problemas de Coding Dojo já conhecidos (ex. mostrar números decimais com algarismos romanos). Nenhum dos programadores pode saber qual vai ser o problema de antemão. Tem que ser uma surpresa para ambos.

    É muito importante deixar claro para ambos que o objetivo da dinâmica é ver a dupla trabalhando e não a resolução do problema. Deixe claro para o candidato que se não der tempo de resolver o problema está tudo bem.

    Uma vez apresentado o problema os programadores começavam a trabalhar nele usando TDD e baby steps. Em intervalos de 5 minutos (cronometrados) os programadores são obrigados a trocar de posições como piloto e co-piloto do teclado.

    Assim que o timebox foi atingido o programador pode deixar a sala e o gestor pode conversar com o candidato sobre a dinâmica.

    A gente usava essa oportunidade para perguntar sobre situações que aconteceram durante a sessão de pair programming. Fazíamos muitas perguntas sobre comportamento (ex. “naquele momento o [nome-do-dev] propôs algo que você não concordou/entendeu e mesmo assim você seguiu com a proposta dele, porque você não parou pra questionar ele sobre a decisão?”).

    Também é possível ver se o candidato consegue expressar bem suas ideias e propostas.

    Essa etapa tem que ter duração fixa e não precisa ser longa. Na empresa a duração dessa etapa começou com uma hora de duração e foi diminuindo até durar 40min.

    Algumas vezes a gente colhia as impressões do programador da nossa equipe que fez pareou com o candidato para complementar nossa avaliação.

    Era muito raro um candidato cair nessa etapa. Se o candidato foi muito mal e a gente entendesse que não daria para prosseguir a gente falava que ele receberia o feedback em alguns dias e procedia com o e-mail de agradecimento e etc.

    Se o candidato tivesse ido bem nessa etapa ele já recebia uma lista de dias e horários para a entrevista final com o CEO. Era a única ocasião onde o candidato não tinha o controle total sobre a agenda do processo. Infelizmente a agenda do CEO era uma selva e tinha muito poucos buracos para ocupar com as entrevistas com candidatos. Mas ele fazia questão de entrevistar todo mundo de todos os setores da empresa.

    Etapa 6: Entrevista Final

    A entrevista final com o CEO era a etapa de consolidação & arremate do processo. Ela existia para determinar se o candidato tinha fit com a cultura da empresa mas também era usada para dirimir alguns questionamentos que ainda estavam aberto sobre o candidato.

    Para isso o CEO recebia um “dossiê” com tudo o que foi levantado sobre o candidato nas etapas anteriores bem como alguns pontos de atenção que a gente detectou nas etapas anteriores. A gente chamava esses pontos de atenção de red flags (bandeiras vermelhas).

    Uma das coisas que essa entrevista tentava avaliar era o nível de comprometimento com a empresa que a gente podia esperar do candidato. Para a empresa era importante que o candidato fosse trabalhar lá com um certo nível de comprometimento e não chegar lá como um trampolim para outra vaga que pagasse mais. Afinal o time dessa empresa era muito reconhecido no mercado e passar por ele “valorizava o passe” de qualquer profissional.

    Nessa etapa todos os candidatos já chegavam travados pelo nervosismo. Afinal, era o CEO da empresa… Então o CEO com a maior calma e paciência ia acalmando o candidato antes de partir para as perguntas.

    Durante a entrevista o CEO contrapunha as resposta do candidato com anotações do relatório que ele tinha recebido para tentar encontrar, explorar e esclarecer divergências.

    Assim que a entrevista terminava o candidato era avisado de que ele receberia o resultado final do processo em alguns dias. Geralmente era no dia seguinte mesmo. Assim que o CEO terminava a entrevista com o candidato era bem comum ele já reunir o comitê que iria decidir sobre a contratação.

    Decisão Final

    Essa etapa era rápida e a decisão era colegiada. Um candidato só era contratado se houvesse unanimidade desse colegiado que era formado por todos os gestores e recrutadores que participaram do processo daquele candidato.

    A decisão era rápida porque todos já tinham tido acesso ao relatório final com todas as informações levantadas ao longo de todo o processo. Bastava avaliar as forças e fraquezas de cada candidato, traçar um plano para potencializar as forças e lidar com os pontos de atenção do candidato e decidir sobre a contratação.

    Feedback

    A etapa de feedback tem duas versões. O feedback para o candidato que foi contratado e o feedback para o candidato que não vai seguir para contratação naquele momento.

    Para os candidatos que não seguiriam a gente enviava um e-mail bastante completo para informar que a gente não seguiria adiante com a contratação, agradecíamos a dedicação do candidato, indicávamos alguns caminhos para futuras tentativas e deixávamos uma linha de comunicação aberta para esse candidato.

    Na linha do respeito ao candidato, algumas vezes, a gente entrava em contato direto com o candidato. Geralmente quando eram candidatos muito jovens que, eventualmente, não conseguiriam lidar muito bem com a não-contratação. As psicólogas avaliavam se isso era necessário ou não e por isso disse que ter esse tipo de profissional envolvido no processo é super importante.

    Para os candidatos que foram aprovados a gente mandava um e-mail de congratulações com as primeiras instruções do nosso processo de on boarding que, modéstia à parte, também ficou lindão (e provavelmente vou descrever aqui).

    É possível que o candidato recuse a oferta nessa etapa. Esteja preparado para isso e peça, educadamente, que, se possível, o candidato explique o motivo da recusa para ver se é possível melhorar algo no processo. Lembrem que o feedback é uma via de mão dupla e o candidato é o protagonista.

    A gente também colhia feedback dos candidatos contratados durante o on boarding. A gente tinha um formulário (Google Forms) interno onde o novo funcionário preenchia suas impressões, apontava problemas e sugeria melhorias. As recrutadoras do RH colhiam essas informações e traziam os feedbacks de forma anônima para nossas reuniões de processos.

  • Palestrante

    Palestrante

    Hoje eu estava lendo o artigo Stepping Back from Speaking do Martin Fowler e me identifiquei com muitas coisas que ele disse. Na verdade parece um artigo que eu teria escrito para falar sobre o assunto. Exceto pelo fato dele ser “O” Martin Fowler e eu ser só o Osvaldo, eu passo (ou passava) por tudo o que ele diz ter passado para dar palestras em eventos de tecnologia.

    Quando eu era mais novo costumava ser bastante introvertido. Isso mudou quando uma professora de educação artística notou que meu talento para trabalhos manuais era bem limitado e decidiu organizar grupos de teatro na minha turma. Fiz ou ajudei a fazer do roteiro à cenografia e até atuei no palco. Ali eu pude perceber que conseguiria me apresentar para uma audiência.

    O tempo passou e a vida aconteceu… veio o trabalho como programador e pude voltar a ser o cara que fica ali no canto, de cabeça baixa, codando.

    Mas aí surgiu o meu envolvimento com as comunidades de FLOSS e, principalmente, com a comunidade Python. Nessas comunidades eu achava super importante compartilhar as coisas que eu aprendia. E a forma de fazer isso quase sempre envolvia falar para uma grande audiência (qualquer coisa maior que uma mesa de bar já conta como ‘grande audiência’ pra mim).

    E aí acontece aquilo: as primeiras apresentações são péssimas, vão melhorando para ficarem muito ruins e um dia, quando menos se espera, eu estava mandando bem.

    Uma das coisas que a gente aprende fazendo palestras é que é muito importante respeitar a audiência. Respeitar a audiência é garantir que você fez o seu melhor para trazer algo relevante para eles. Fazer isso com muito carinho e muita qualidade. Tem gente ali que investiu tempo e dinheiro que vão faltar mais na frente na esperança de ter um retorno por esse investimento. Eu me sinto obrigado a fazer valer esse investimento.

    Em eventos de tecnologia é bastante comum ver os palestrantes montando suas apresentações em slides poucas horas antes de apresentar. Tem gente que tem esse talento mas eu não tenho. Sempre cheguei com minhas apresentações preparadas e ‘testadas’ (algumas vezes testava em encontros locais ou eventos menores). O dia antes da apresentação era só pra atualizar uma ou outra informação que eventualmente tinha surgido desde a última revisão.

    Causo: durante a PythonBrasil de São Paulo alguns ladrões de notebooks entraram no evento e roubaram meu notebook (e mais um outro da minha amiga Karyn). Minha apresentação estava nele e infelizmente, por negligência minha, não estava sincronizado na nuvem. Eu pedi para retirarem a minha apresentação do evento porque eu não conseguiria fazer ela mesmo conhecendo bem o conteúdo dos slides. Eu entrei em pânico com a ideia de não entregar uma boa apresentação.

    No dia em que tenho que fazer a minha apresentação, tal como acontece com o Martin Fowler, eu entro em um estado tão estressante e fico tão ansioso que fica parecendo que estou tendo um ataque de pânico. Eu chego a ter problemas intestinais nos momentos que antecedem a minha fala.

    Não abandono o plano porque já sei, por experiências prévias, que essa sensação dura só até os primeiros minutos no palco. Nesse momento eu entro em flow com o conteúdo e consigo superar o mal estar.

    Quando a apresentação acaba eu só peço para anotarem a placa do caminhão. Estou exausto e, algumas vezes, até com dores físicas.

    Muitas vezes eu cogitei “tomar algumas” (“fumar” poderia funcionar também) para ver se quebrava um pouco a ansiedade mas desistia da ideia por respeito à audiência. Eu não sei exatamente o que aconteceria mas não me perdoaria se a apresentação ficasse ruim porque eu estava alterado.

    Apesar disso tudo e, diferentemente do Martin Fowler, eu pretendo continuar fazendo apresentações. Sinto que devo isso à comunidade que me trouxe muitas coisas boas na vida e na profissão. Entretanto, tentarei restringir os convites que aceito e, provavelmente, enviarei propostas para poucos eventos.

    Para iniciantes

    Se tem algo que eu gostaria de trazer para quem vai começar a se apresentar em eventos, é que eles entendam que esse nervosismo é normal e bem comum. Até mesmo aquela pessoa no palco, que você admira muito, pode estar passando por essa provação.

    Se você quer encarar essas experiências entenda que pode acontecer esses contratempos ao longo do caminho. E se você não quiser, ou não puder, encarar essas dificuldades tá tudo bem também.