← emrevarol.com Materials & Checklist →
A2SV · University of Rwanda

Sumário

Melhores Práticas de Codificação e Revisão Eficaz de Código

A2SV - University of Rwanda

Escrever código é fácil

Escrever código sustentável é difícil

Escrever código em que uma equipe pode confiar é engenharia de software

Sobre o que é realmente esta aula

Não é apenas sintaxe

Não é apenas “código limpo”

Não é apenas mecânica do GitHub

Esta aula é sobre disciplina de engenharia

Boa engenharia cria velocidade. Má engenharia cria caos.

Uma Verdade Difícil

Um projeto raramente falha porque as pessoas não conseguem escrever nenhum código.

Um projeto frequentemente falha porque o código se torna:

Incompreensível

Intestável

Irrevisável

Difícil de alterar

A Mentalidade Errada do Estudante

Pensamentos perigosos comuns:

“Funciona, então está bom o suficiente.”

“Podemos limpar depois.”

“Testes levam muito tempo.”

“Revisão não é necessária para pequenas mudanças.”

“Meus colegas vão entender.”

Por que isso é perigoso:

Depois geralmente nunca chega

Pequenos maus hábitos se tornam cultura da equipe

Cultura da equipe se torna qualidade do produto

A Mentalidade Correta de Engenharia

Um engenheiro profissional pergunta:

Outra pessoa consegue entender isso rapidamente?

Isso pode ser alterado com segurança no futuro?

Isso pode ser testado?

Isso pode ser bem revisado?

Isso vai tornar a equipe mais rápida ou mais lenta?

O Custo do Código Ruim

Código ruim causa:

Mais bugs

Integração mais lenta de novos membros

Depuração dolorosa

Trabalho duplicado

Funcionalidades quebradas após mudanças

Medo de mexer no código

O Benefício do Código Bom

Código bom proporciona:

Desenvolvimento mais rápido

Colaboração mais fácil

Refatoração mais segura

Melhores revisões

Mais confiança

Produtos mais consistentes

Mensagem Principal

“Seu código não é apenas para o computador. Seu código é para seus colegas de equipe, para o seu eu futuro e para o produto.”

Programação vs Engenharia de Software

Programação

Fazer o código funcionar

Engenharia de Software

Tornar o código confiável, sustentável, colaborativo e pronto para produção

Um Script Pode Funcionar. Um Sistema Deve Sobreviver.

Um script pode precisar apenas de:

Lógica correta

Um sistema precisa de:

Estrutura clara

Testes

Revisões

Controle de versão

Deploy previsível

Compreensão da equipe

Código É Lido Mais do que É Escrito

Realidade:

Você escreve uma função uma vez

Seus colegas a leem dezenas de vezes

O seu eu futuro a lê meses depois sem nenhuma lembrança

Portanto:

Legibilidade não é opcional

Legibilidade faz parte da correção

Exemplo Ruim: “Funciona” Não É Suficiente

def f(x, y, z):
    if x:
        if y > 0:
            return z * 0.2
    return 0

Problemas:

O que é f? O que ela calcula?

O que são x, y, z?

O que 0.2 representa?

Ninguém consegue revisar, testar ou manter isso com confiança

Exemplo Melhor: O Significado Deve Ser Visível

def calculate_discount(price, has_membership, loyalty_points):
    if not has_membership:
        return 0
    if loyalty_points <= 0:
        return 0
    return price * 0.2

O que melhorou:

O nome da função explica o propósito

Os parâmetros são significativos

A lógica se lê como uma frase

Um revisor pode verificar a correção imediatamente

Padrão de Engenharia

Não pergunte apenas: “Funciona?”

Pergunte também:

É legível?

É testável?

É seguro de alterar?

Eu aprovaria isso em um PR?

Princípio 1: Nomenclatura É uma Ferramenta de Design

Nomenclatura ruim cria confusão. Boa nomenclatura cria clareza.

Nomes devem revelar: o que algo é, o que faz, por que existe.

Exemplo de Nomenclatura Ruim

def calc(a, b):
    return a * b

Problemas:

O que calc calcula?

O que são a e b?

Pode ser área, preço, qualquer coisa - impossível saber

Um revisor não consegue verificar a correção

Exemplo de Nomenclatura Melhor

def calculate_total_price(unit_price, quantity):
    return unit_price * quantity

Benefícios:

O propósito é imediatamente claro

Os parâmetros se explicam sozinhos

O revisor pode verificar: “Sim, preço total = preço unitário × quantidade”

Desenvolvedores futuros não usarão esta função incorretamente

O que uma Boa Nomenclatura Previne

Reduz confusão ao ler código desconhecido

Previne suposições erradas sobre o comportamento da função

Previne uso incorreto de parâmetros

Previne bugs futuros por mal-entendidos

Se você precisa de um comentário para explicar o que uma variável é, o nome provavelmente está errado.

Princípio 2: Uma Função Deve Fazer Uma Coisa Clara

Quando uma função faz muitas coisas, testar se torna difícil, reutilização se torna impossível e depurar se torna doloroso.

Exemplo Ruim: Muitas Responsabilidades

def register_user(user):
    validate_user(user)
    save_user_to_database(user)
    send_welcome_email(user)
    log_activity(user)
    notify_admin(user)

Problemas:

Cinco responsabilidades em uma única função

Não é possível testar o registro sem enviar e-mail

Se o e-mail falhar, o usuário ainda é salvo?

Impossível reutilizar qualquer etapa individualmente

Exemplo Melhor: Separar Responsabilidades

def register_user(user):
    validate_user(user)
    save_user_to_database(user)

def onboard_user(user):
    send_welcome_email(user)
    log_activity(user)

def handle_registration(user):
    register_user(user)
    onboard_user(user)
    notify_admin(user)

Benefícios:

Cada função tem um propósito claro e único

Cada uma pode ser testada independentemente

O tratamento de falhas se torna gerenciável

Princípio 3: Duplicação É uma Fábrica de Bugs

Lógica duplicada significa correções perdidas, inconsistência no código e manutenção cara.

Exemplo Ruim: Lógica Repetida

# In checkout.py
final_price = price - price * 0.1

# In invoice.py
final_price = price - price * 0.1

# In report.py
final_price = price - price * 0.1
Se isso aparece em 7 lugares e a taxa de desconto muda para 0.15, você precisa encontrar e atualizar todos os 7. Esqueceu um? Você tem um bug silencioso.

Exemplo Melhor: Centralizar Lógica Compartilhada

def apply_discount(price, discount_rate):
    return price * (1 - discount_rate)

# Em todos os lugares:
final_price = apply_discount(price, 0.1)

Benefícios:

Fonte única da verdade

Altere uma vez, corrija em todos os lugares

Fácil de testar

Fácil de encontrar e auditar

Princípio 4: Testabilidade Deve Influenciar o Design

Se seu código é difícil de testar, provavelmente está mal projetado.

Código testável é modular, explícito e tem entradas e saídas claras.

Exemplo de Código Difícil de Testar

def process_order(order_id):
    order = db.get_order(order_id)         # database call
    user = db.get_user(order.user_id)      # database call
    send_email(user.email, order.summary)  # side effect
    db.mark_processed(order_id)            # database call

Problemas:

Não é possível testar sem um banco de dados real

Não é possível testar sem enviar e-mails reais

Todos os efeitos colaterais estão fortemente acoplados

Design Mais Testável

def process_order(order, user, email_sender, db):
    email_sender.send(user.email, order.summary)
    db.mark_processed(order.id)

Benefícios:

Dependências são injetadas - fácil de simular

Cada dependência pode ser testada independentemente

A lógica é separada da infraestrutura

A assinatura da função diz exatamente o que ela precisa

Princípio 5: Falhe Claramente, Não Silenciosamente

Falhas silenciosas são o tipo mais perigoso de bug.

Quando algo dá errado, faça com que seja alto e óbvio.

Tratamento de Erro Ruim

def get_user_age(user):
    if user is None:
        return None
    if user.birthday is None:
        return None
    return calculate_age(user.birthday)

Risco:

O chamador recebe None e não sabe por quê

O bug está oculto e se propaga silenciosamente

Depurar se torna um jogo de adivinhação

Tratamento de Erro Mais Claro

def get_user_age(user):
    if user is None:
        raise ValueError("User must not be None")
    if user.birthday is None:
        raise ValueError("User birthday is missing")
    return calculate_age(user.birthday)

Benefícios:

O erro é imediatamente visível

A mensagem diz exatamente o que está errado

O bug é capturado cedo, não mais adiante

Princípio 6: Complexidade É Cara

Código complicado não é inteligente. É caro de manter, revisar e depurar.

Exemplo Complexo

def get_price(user, product):
    if user.is_member:
        if product.on_sale:
            if user.loyalty_points > 100:
                return product.price * 0.7
            else:
                return product.price * 0.8
        else:
            return product.price * 0.9
    else:
        if product.on_sale:
            return product.price * 0.95
        else:
            return product.price

Profundamente aninhado, difícil de seguir, fácil de introduzir bugs

Exemplo Mais Simples

def get_discount_rate(user, product):
    if not user.is_member and not product.on_sale:
        return 0
    if not user.is_member and product.on_sale:
        return 0.05
    if user.is_member and not product.on_sale:
        return 0.1
    if user.loyalty_points > 100:
        return 0.3
    return 0.2

def get_price(user, product):
    return product.price * (1 - get_discount_rate(user, product))

Plano, legível, cada caso é explícito e testável

Princípio 7: Mudanças Pequenas Vencem Mudanças Grandes e Bagunçadas

Mudanças grandes:

Difíceis de revisar

Alto risco de bugs

Dolorosas para fazer merge

Histórico git confuso

Mudanças pequenas:

Fáceis de revisar

Baixo risco

Rápidas para fazer merge

Histórico claro

Regra de Engenharia

Prefira:

Funções menores

Commits menores

PRs menores

Unidades de revisão menores

Mudanças pequenas e focadas são mais fáceis de entender, revisar, testar e reverter.

Fluxo de Trabalho Git e GitHub

Sem um fluxo de trabalho, equipes criam:
código sobrescrito, mudanças não revisadas, branches main quebradas, confusão.

O Fluxo de Trabalho Básico Correto

main criar branch de feature escrever código commitar mudanças pequenas abrir PR revisão melhorar merge para main
Isso não é opcional. Este é o fluxo de trabalho profissional mínimo.

Nunca Trabalhe Diretamente na Main

Main deve sempre estar pronta para deploy

Commits diretos pulam a revisão

Conflitos de merge se tornam destrutivos

Nenhuma forma de reverter de forma limpa

A equipe perde confiança no código

Se a main está quebrada, todos ficam bloqueados. Proteja-a.

O que uma Branch Representa

Nomes ruins de branch:

fix
my-branch
test123
update

Nomes melhores de branch:

feature/user-registration
fix/login-redirect-bug
chore/update-dependencies
refactor/split-order-service

O nome de uma branch deve descrever a intenção do trabalho

Commits Devem Contar uma História

Mensagens de commit ruins:

fix
update
wip
asdf
changed stuff

Boas mensagens de commit:

fix: redirect to login after session timeout
feat: add email validation to registration
refactor: extract discount logic into helper
test: add edge cases for price calculator
docs: update API authentication section

Um Bom PR É Revisável

Pequeno e focado em uma coisa

Tem um título e descrição claros

Explica por que a mudança foi feita

Inclui testes quando aplicável

Não mistura mudanças não relacionadas

Uma boa descrição de PR responde: O que mudou? Por quê? Como testar?

PR Ruim vs PR Bom

PR Ruim:

Título: “atualizações”

Sem descrição

47 arquivos alterados

Mistura feature + refatoração + correção de estilo

Sem testes

PR Bom:

Título: “feat: add email validation to registration”

Descrição explica a abordagem

4 arquivos alterados

Focado em uma feature

Inclui testes unitários

Um Repositório Profissional Não É Apenas Código

Um repositório sério inclui estrutura, documentação, configuração e padrões - não apenas arquivos fonte.

Exemplo de Estrutura de Repositório

project/
├── src/
│   ├── models/
│   ├── services/
│   ├── routes/
│   └── utils/
├── tests/
│   ├── unit/
│   └── integration/
├── .github/
│   └── workflows/
│       └── ci.yml
├── .gitignore
├── README.md
├── requirements.txt
├── Makefile
└── .env.example

Por que o README Importa

Um README deve dizer a um novo membro da equipe:

O que o projeto faz

Como configurá-lo

Como executá-lo

Como rodar os testes

Como contribuir

Um repositório sem README é um repositório que diz: “Descubra sozinho.”

Um Bom README Inclui

Nome do projeto e descrição em uma linha

Pré-requisitos (versão do Python, dependências)

Passos de instalação

Como executar localmente

Como rodar os testes

Variáveis de ambiente necessárias

Visão geral da estrutura do projeto

Diretrizes de contribuição

Se Seu Repositório É Confuso, Sua Equipe Desacelera

Cada minuto que um colega gasta tentando entender a estrutura do seu projeto é um minuto que ele não está construindo features.

Clareza no repositório é uma forma de respeito pela sua equipe.

Cultura de Testes

Desculpas comuns:

“Não temos tempo para testes”

“Funciona na minha máquina”

“Testes nos atrasam”

Realidade:

Você não tem tempo para não testar

Precisa funcionar em todas as máquinas

Testes te salvam de desacelerar depois

O que os Testes Realmente Te Dão

Confiança para alterar código

Depuração mais rápida - testes mostram onde as coisas quebraram

Documentação do comportamento esperado

Rede de segurança para refatoração

Prova de que seu código funciona

Testes não atrasam equipes fortes. Eles permitem que equipes fortes avancem rápido com segurança.

Um Exemplo Bem Simples

def add(a, b):
    return a + b

Função simples. Como sabemos que funciona corretamente?

Escrevemos um teste.

Exemplo Básico com Pytest

def test_add_returns_sum():
    assert add(2, 3) == 5

Claro, legível, rápido de executar

Se add algum dia quebrar, este teste captura imediatamente

Qualquer pessoa pode entender o que este teste verifica

Bons Testes Verificam Mais que o Caminho Feliz

O que mais devemos testar?

Números negativos

Valores zero

Números muito grandes

Incompatibilidades de tipo (se aplicável)

Condições de contorno

Casos de erro

O caminho feliz é onde os bugs não se escondem. Casos extremos é onde eles vivem.

Exemplo: Testes Mais Úteis

def test_add_positive_numbers():
    assert add(2, 3) == 5

def test_add_negative_numbers():
    assert add(-1, -2) == -3

def test_add_with_zero():
    assert add(0, 5) == 5
    assert add(5, 0) == 5

def test_add_mixed_signs():
    assert add(-3, 5) == 2

Cada teste tem um nome claro descrevendo o que verifica

O que Acontece Sem Testes

Bugs chegam à produção

Refatoração se torna aterrorizante

Ninguém sabe se uma mudança quebrou algo

Testes manuais são lentos e não confiáveis

Regressões continuam voltando

A equipe perde confiança no código

O que Acontece Com Testes

Bugs são capturados antes do merge

Refatoração é segura e rápida

CI captura regressões automaticamente

Novos membros da equipe entendem o comportamento esperado

Deploys são feitos com confiança

A velocidade da equipe aumenta com o tempo

CI/CD e Gates de Qualidade

CI = Integração Contínua

Verifique automaticamente cada mudança antes que ela chegue à branch main.

Por que CI Importa

CI previne:

Código quebrado chegando à main

Código não testado sendo mergeado

Inconsistências de estilo

Problemas de “funciona na minha máquina”

CI proporciona:

Verificações de qualidade automatizadas

Feedback rápido em cada PR

Padrões consistentes

Confiança da equipe

Verificações Comuns de CI

Executar todos os testes (unitários + integração)

Verificar formatação de código (black, prettier, etc.)

Executar linter (pylint, eslint, flake8)

Verificar anotações de tipo (mypy)

Medir cobertura de testes

Varredura de segurança

Verificação de build (o projeto compila/builda?)

Exemplo de GitHub Actions

name: Python Checks
on:
  pull_request:
  push:
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - run: pip install -r requirements.txt
      - run: pytest

O que Isso Alcança

Cada PR executa testes automaticamente

PRs quebrados não podem ser mergeados (com proteção de branch)

A equipe não precisa lembrar de rodar os testes

O feedback é rápido e consistente

CI é como um guarda no portão. Ele não deixa código quebrado entrar na sua branch main.

Verificações de Cobertura

Cobertura de testes mede quanto do seu código é exercitado pelos testes.

Alta cobertura não significa ausência de bugs

Baixa cobertura significa grandes áreas não testadas

Cobertura é uma diretriz, não uma garantia

Cuidado: Não persiga 100% de cobertura. Foque em testar lógica importante e casos extremos, não getters e setters triviais.

Regra Prática de Qualidade

Boas metas para a maioria dos projetos:

70-85% de cobertura de testes como linha de base

Toda lógica de negócio crítica testada

Todos os casos extremos das funções centrais testados

CI deve passar antes do merge (sem exceções)

Verificações de linter e formatador em cada PR

Gates de qualidade não são burocracia. São infraestrutura de engenharia.

Revisão Eficaz de Código

Revisão de código não é:

Uma formalidade

Um carimbo de aprovação

Uma demonstração de poder

Revisão de código é:

Uma conversa de qualidade

Uma oportunidade de aprendizado

Um mecanismo de defesa da equipe

Por que Equipes Revisam Código

Capturar bugs antes que cheguem à produção

Compartilhar conhecimento na equipe

Manter qualidade consistente do código

Distribuir a responsabilidade pelo código

Ensinar e aprender uns com os outros

Construir confiança na equipe

Uma Revisão Fraca vs uma Revisão Eficaz

Revisão fraca:

Olhar o diff por 30 segundos

Clicar em “Aprovar”

Não deixar comentários

Não executar o código

Revisão eficaz:

Ler cada linha alterada

Verificar lógica e casos extremos

Fazer perguntas de esclarecimento

Sugerir melhorias respeitosamente

Verificar se existem testes

Como Fazer uma Revisão de Código Eficaz

Verifique:

Correção - a lógica faz o que deveria?

Legibilidade - você consegue entender sem perguntar?

Nomenclatura - os nomes são claros e precisos?

Duplicação - algo está repetido desnecessariamente?

Tratamento de erros - os casos extremos estão cobertos?

Testes - existem testes para a nova lógica?

Escopo - o PR se mantém focado?

Mentalidade do Revisor

Durante uma revisão, responda estas perguntas:

Eu entendo o que este código faz?

Eu me sentiria confortável mantendo isso?

Existe algo que possa quebrar silenciosamente?

Existem testes faltando?

A descrição do PR é precisa?

Um novo membro da equipe entenderia isso?

Comentário de Revisão Ruim

“Isso está errado.”

Por que é fraco:

Não explica o que está errado

Não explica por que está errado

Não sugere uma melhoria

Parece um ataque, não um feedback

Desperdiça o tempo do autor

Comentário de Revisão Melhor

“Esta função retorna None quando o usuário não é encontrado, mas o chamador na linha 42 não verifica None. Isso pode causar um AttributeError em tempo de execução. Poderíamos lançar uma exceção aqui ou adicionar uma verificação de None no chamador?”

Por que funciona:

Explica o problema

Mostra o impacto

Sugere uma correção concreta

Trata o autor como um colaborador

Use Perguntas para Reduzir Fricção

Em vez de comandos, use perguntas curiosas:

“O que acontece se esta entrada for negativa?”

“Poderíamos simplificar isso com um retorno antecipado?”

“Existe alguma razão para não usarmos o helper existente para isso?”

“Seria mais claro extrair isso em uma função separada?”

Perguntas convidam ao diálogo. Comandos criam resistência.

Exemplos de Foco Forte em Revisão

Um bom revisor percebe:

Números mágicos sem explicação

Tratamento de erro ausente para casos extremos

Lógica duplicada que deveria ser extraída

Funções fazendo mais de uma coisa

Convenções de nomenclatura inconsistentes

Testes ausentes ou insuficientes

Preocupações de segurança (segredos hardcoded, SQL injection, etc.)

Leia Este Código Como um Revisor

def calc(items):
    t = 0
    for i in items:
        if i["type"] == "book":
            t += i["price"] * 0.9
        else:
            t += i["price"]
    return t

Como revisor, pergunte:

O que calc calcula?

O que 0.9 significa? Por que livros especificamente?

O que acontece se um item não tiver a chave “type” ou “price”?

Onde estão os testes?

Uma Versão Mais Revisável

BOOK_DISCOUNT_RATE = 0.1

def get_item_price(item):
    price = item["price"]
    if item["type"] == "book":
        return price * (1 - BOOK_DISCOUNT_RATE)
    return price

def calculate_cart_total(items):
    return sum(get_item_price(item) for item in items)

Melhorias:

Número mágico substituído por constante nomeada

Lógica de precificação extraída em sua própria função

Cada função é testável independentemente

O que Revisores Não Devem Fazer

Pegar no pé de estilo quando existe um linter para isso

Reescrever o código do autor no seu próprio estilo

Aprovar sem ler

Bloquear um PR por preferência pessoal (não correção)

Ser condescendente ou desdenhoso

Atrasar revisões por dias sem comunicação

Se Você Não Entende o Código, Não Aprove

“Se você não entende o código, não aprove.”

Aprovação significa responsabilidade.
Se esse código causar um bug, você compartilha a responsabilidade.

Como Receber Revisão Profissionalmente

Não faça:

Levar feedback para o lado pessoal

Discutir sem ouvir

Descartar sugestões imediatamente

Se sentir atacado

Faça:

Ler cada comentário com cuidado

Pedir esclarecimentos se necessário

Agradecer aos revisores pelo tempo

Explicar seu raciocínio respeitosamente

Fazer mudanças prontamente

Resposta Ruim à Revisão

“Funciona perfeitamente. Eu testei.”
“Isso é apenas uma preferência de estilo.”
“Não temos tempo para isso.”
“Você pode simplesmente aprovar?”

Essas respostas encerram a colaboração e corroem a confiança

Boa Resposta à Revisão

“Boa observação - eu perdi esse caso extremo. Corrigido no último commit.”
“Entendo seu ponto. Eu escolhi essa abordagem porque [motivo]. Fico feliz em mudar se você ainda achar melhor.”
“Obrigado pela revisão detalhada. Aprendi algo novo aqui.”

Essas respostas constroem confiança e fortalecem a equipe

Revisão Não É Sobre Vencer

O objetivo não é:

Provar que você está certo

Defender seu ego

Ser aprovado rapidamente

O objetivo é:

Entregar código melhor

Aprender uns com os outros

Construir um produto confiável

Crescer como engenheiros

Como se Beneficiar do GenAI

IA pode tornar engenheiros mais rápidos, mas também mais desleixados.

Use IA como um assistente, não como substituto do julgamento de engenharia.

Bons Usos do GenAI

Gerar código boilerplate para economizar tempo

Elaborar casos de teste para funções existentes

Explicar código ou bibliotecas desconhecidas

Sugerir abordagens alternativas

Ajudar a escrever documentação

Auxiliar na depuração analisando mensagens de erro

Pré-revisar código antes de submeter um PR

Uso Fraco do GenAI

Usar IA sem entender:

“Me escreva um sistema de login” → copiar-colar → push
“Corrija este erro” → aplicar sugestão cegamente
“Gere todos os meus testes” → nunca lê-los

Se você não consegue explicar o código, você não é dono dele

Código gerado por IA com bugs que você não entende é pior do que nenhum código

Uso Forte do GenAI

Melhores prompts, melhores resultados:

“Revise esta função para casos extremos que eu possa ter perdido”
“Gere testes pytest para esta função, incluindo números negativos e entrada vazia”
“Refatore isso para usar retornos antecipados em vez de condições aninhadas”

Prompts específicos e focados produzem saídas úteis e revisáveis

Exemplo de Bom Prompt para Geração de Testes

# Prompt to AI:
"Write pytest tests for this function.
Include: happy path, negative input, zero, empty list, and type error.
Use descriptive test names."

# Function:
def calculate_average(numbers):
    if not numbers:
        raise ValueError("Cannot average empty list")
    return sum(numbers) / len(numbers)

O prompt é específico sobre o que testar e como nomear os testes

Você ainda revisa e ajusta os testes gerados

Exemplo de Bom Prompt para Revisão de Código

# Prompt to AI:
"Review this function as a senior engineer.
Check for:
- edge cases
- naming clarity
- error handling
- testability
- any potential bugs

Be specific and suggest improvements."

Use IA como um “primeiro revisor” antes que seu colega revise

Isso captura problemas óbvios e economiza tempo do revisor

Integrações com VS Code e Editores

Ferramentas de IA úteis para desenvolvimento:

GitHub Copilot - sugestões de código inline

Claude Code (CLI) - assistente de IA no terminal

Cursor - editor de código nativo com IA

Codeium - autocompletar gratuito com IA

Bons casos de uso:

Autocompletar padrões repetitivos

Gerar docstrings

Explicar seções complexas de código

Sugerir estrutura de testes

A Regra para Código Gerado por IA

Antes de mergear qualquer código gerado por IA, você deve:

Entendê-lo - ler cada linha

Explicá-lo - ser capaz de descrever o que faz e por quê

Testá-lo - verificar com seus próprios testes

Aprová-lo - tratá-lo como se você o tivesse escrito no seu PR

Se seu nome está no commit, você é dono do código. Não importa quem ou o que o gerou.

Demonstração ao Vivo: Revisando um Pull Request Ruim

Vamos inspecionar um PR real juntos e identificar:

• Nomenclatura ruim
• Tratamento de erro ausente
• Lógica duplicada
• Testes ausentes
• Mensagens de commit pouco claras
• Escopo descontrolado

Objetivo da Demonstração ao Vivo

Após esta demonstração, você deve ser capaz de:

Ler um diff de PR criticamente

Identificar pelo menos 5 tipos de problemas

Escrever comentários de revisão construtivos

Sugerir melhorias específicas

Distinguir entre problemas bloqueantes e sugestões

Revisar código é uma habilidade. Como qualquer habilidade, melhora com prática deliberada.

Tarefa de Casa: Revise um Pull Request Como um Engenheiro

Atividade:

Encontre um PR de código aberto no GitHub (ou use um fornecido pelo instrutor)

Escreva uma revisão com pelo menos 5 comentários substantivos

Cada comentário deve identificar um problema específico e sugerir uma melhoria

Requisitos de entrega:

Link para o PR que você revisou

Seus comentários de revisão (captura de tela ou markdown)

Uma breve reflexão: o que você aprendeu ao revisar o código de outra pessoa?

Mensagem Final

“Grandes engenheiros não apenas fazem o código funcionar. Eles tornam o código compreensível, testável, revisável e confiável.”

Obrigado

“O código que você está ocupado demais para limpar hoje se torna o problema que domina sua equipe amanhã.”

Emre Varol · A2SV · University of Rwanda

emrevarol.com