🏋️‍♂️ Exercícios Práticos - Aula 04: Pair Programming

Disciplina: Desenvolvimento de Sistemas II
Professor: Ricardo Pires
Turma: 3º Técnico em Desenvolvimento de Sistemas
Tempo Total: 70 minutos de atividades práticas


🎯 Objetivos dos Exercícios

Competências a Desenvolver:

  • Aplicar técnicas de TDD em duplas com alternância eficaz de papéis
  • Praticar debugging colaborativo para identificação rápida de problemas
  • Implementar comunicação técnica eficaz durante programação em par
  • Experienciar benefícios de qualidade através de revisão contínua

Habilidades Comportamentais:

  • Humildade intelectual para aceitar feedback em tempo real
  • Assertividade construtiva para questionar decisões técnicas
  • Paciência pedagógica para explicar raciocínio durante coding

🧪 Exercício 1: TDD Colaborativo - Calculadora

⏱️ Tempo: 35 minutos | 👥 Formato: Duplas | 🔄 Level: Fundamental

📋 Contexto e Objetivo

Vocês implementarão uma calculadora científica usando TDD estrito em duplas, alternando papéis conforme metodologia Driver-Navigator a cada ciclo Red→Green→Refactor.

🎯 User Stories

Feature: Calculadora Científica
  Como estudante de matemática
  Quero realizar operações básicas e avançadas
  Para resolver problemas matemáticos rapidamente
 
Scenario: Operações Básicas
  Given uma calculadora limpa
  When executo operação de soma
  Then resultado deve ser preciso com decimais
 
Scenario: Divisão por Zero
  Given dois números sendo segundo igual a zero
  When executo divisão
  Then sistema deve lançar exceção adequada

🔄 Metodologia Detalhada

Rodada 1 (15 min): Navigator A + Driver B

// Navigator A guidance:
// 1. "Vamos começar com o teste mais simples - soma"
// 2. "Red: Escreva teste que falha"
// 3. "Green: Implementação mínima para passar"
// 4. "Refactor: Podemos melhorar alguma coisa?"
 
@Test
@DisplayName("Deve somar dois números inteiros corretamente")
void deveSomarDoisNumeros() {
    // Navigator sugere structure, Driver implementa
    Calculadora calc = new Calculadora();
    double resultado = calc.somar(2.5, 3.7);
    assertEquals(6.2, resultado, 0.001);
}

Rodada 2 (15 min): Navigator B + Driver A

// Navigator B agora lidera:
// "E se tentarmos subtração com números negativos?"
// "Como tratamos overflow em multiplicações grandes?"
 
@Test
@DisplayName("Deve subtrair números negativos adequadamente")
void deveSubtrairNumerosNegativos() {
    // Troca de papéis: B navega estratégia, A implementa
}

Rodada 3 (5 min): Ambos Colaboram em Refatoração

// Ambos discutem:
// "Podemos extrair validação de parâmetros?"
// "Faz sentido uma interface ICalculadora?"
// "Como structure código para extensibilidade?"

💡 Acceptance Criteria Técnicas

  • Soma de dois doubles com precisão 0.001
  • Subtração incluindo números negativos
  • Multiplicação com validation de overflow
  • Divisão com exception handling para zero
  • Raiz quadrada com validation de números negativos
  • Potenciação para expoentes inteiros

🎯 Success Metrics

  • 100% cobertura pelos testes implementados
  • Mínimo 6 testes escritos em colaboração
  • Alternância respeitada a cada 5-7 minutos
  • Código refatorado ao menos 2 vezes

🐞 Exercício 2: Debug Colaborativo Intensivo

⏱️ Tempo: 25 minutos | 👥 Formato: Duplas | 🔄 Level: Investigativo

📋 Cenário: Sistema de Blog com Bugs Ocultos

Vocês receberam um sistema de blog legado com 3-4 bugs sutis que estão causando comportamentos inesperados em produção. Usem pair programming para identificar, explicar e corrigir cada problema.

🚨 Código com Bugs Intencionais

public class GerenciadorBlog {
    private List<Post> posts;
    private boolean moderacao;
 
    public GerenciadorBlog() {
        this.posts = null;  // 🚨 Bug 1: Initiative problem
        this.moderacao = true;
    }
 
    public void adicionarPost(Post post) {
        if (posts.size() > 0) {  // 🚨 Bug 2: NullPointer waiting to happen
            posts.add(post);
        }
    }
 
    public List<Post> getPostsPublicos() {
        List<Post> publicos = new ArrayList<>();
        for (Post post : posts) {
            if (post.isPublico() = true) {  // 🚨 Bug 3: Assignment vs comparison
                publicos.add(post);
            }
        }
        return publicos;
    }
 
    public void moderarPost(String titulo) {
        for (Post post : posts) {
            if (post.getTitulo().equals(titulo)) {  // 🚨 Bug 4: null handling missing
                post.setPublico(false);
                break;
            }
        }
    }
 
    public int getQuantidadePosts() {
        return posts.length;  // 🚨 Bug 5: Wrong method for Lists
    }
 
    public Post getPostMaisRecente() {
        if (posts.size() > 0) {
            return posts.get(posts.size() - 1);
        }
        return new Post("", "", false);  // 🚨 Bug 6: Should return null or Optional
    }
}

🎯 Metodologia de Debug Colaborativo

Etapa 1: Análise Estática (8 min)

// Navigator mission: "Vamos ler o código linha por linha"
// Driver mission: "Eu anoto cada suspeita que você levantar"
 
// Navigator questions para fazer:
// 1. "O que acontece se posts for null aqui?"
// 2. "Esse = deveria ser ==?"
// 3. "Como sabemos se titulo pode vir null?"
// 4. "Lists têm .length ou .size()?"

Etapa 2: Testes para Provar Bugs (12 min)

// Driver agora implementa testes para confirmar cada bug:
 
@Test
@DisplayName("Bug 1: Constructor deve inicializar lista")
void deveInicializarListaNaoNull() {
    GerenciadorBlog blog = new GerenciadorBlog();
    assertDoesNotThrow(() -> blog.adicionarPost(new Post()));
}
 
@Test
@DisplayName("Bug 3: Comparison assignment confusion")
void deveUsarComparisonNaoAssignment() {
    // Driver implementa, Navigator valida lógica
}

Etapa 3: Correções Colaborativas (5 min)

// Ambos discutem cada fix:
// Navigator: "Para o bug 1, inicializar ArrayList vazio?"
// Driver: "Sim, e para bug 6, Optional<Post> seria melhor?"

🏆 Success Criteria

  • Identificar mínimo 4 bugs diferentes
  • Escrever teste que reproduz cada bug
  • Implementar correção para cada problema
  • Validar correção com teste passing
  • Ambos conseguem explicar cada bug identificado

🔧 Exercício 3: Pair Programming com Feature Complexa

⏱️ Tempo: 10 minutos | 👥 Formato: Duplas | 🔄 Level: Aplicação Real

📋 Mini-Feature: Sistema de Login com Rate Limiting

Implementem em 10 minutos uma pequena feature que combina múltiplas complexidades exigindo colaboração intensa.

🎯 Requirements

Feature: Login com Rate Limiting
  Como sistema de segurança
  Quero limitar tentativas de login
  Para prevenir ataques de força bruta
 
Scenario: Usuário válido login sucesso
  Given credenciais corretas
  When tenta fazer login
  Then acesso é permitido
 
Scenario: Múltiplas tentativas inválidas
  Given usuário com 3 tentativas falhadas
  When tenta nova tentativa
  Then conta é temporariamente bloqueada

🚀 Starter Code

public class LoginService {
    // TODO: Implementar rate limiting via pair programming
    private Map<String, Integer> tentativasFalhadas;
    private Map<String, LocalDateTime> ultimoBloqueio;
 
    public boolean autenticar(String usuario, String senha) {
        // Navigator + Driver: implementar lógica
        return false;
    }
 
    private boolean isContaBloqueada(String usuario) {
        // Navigator + Driver: implementar verification
        return false;
    }
}

💯 Quick Success Metrics

  • Working solution básica que compila
  • Driver explanation do que está implementando
  • Navigator questions sobre edge cases
  • Both agree na estratégia antes implementation

🎯 Exercício 4: Reflection sobre Pair Programming

⏱️ Tempo: 5 minutos | 👥 Formato: Individual → Discussão

📝 Auto-Avaliação Individual

Respondam individualmente primeiro, depois discutam:

Questões de Reflexão:

  1. Qualidade do código: “O código final ficou melhor do que eu teria escrito sozinho?” Por quê?

  2. Aprendizagem: “O que aprendi com meu par que não descobriria sozinho?”

  3. Comunicação: “Em que momentos a comunicação técnica foi mais eficaz?”

  4. Alternância: “Prefiro ser Driver ou Navigator?” “Em que situações cada papel foi mais confortável?”

  5. Eficiência: “Em que tipos de problemas pair programming seria mais útil no mercado?”

🗣️ Sharing em Grupo

Compartilhem insights mais importantes:

  • 1 aprendizagem técnica significativa
  • 1 melhoria comportamental identificada
  • 1 situação real onde applications pair programming

📊 Critérios de Avaliação

🎯 Avaliação Formativa (Observacional)

CritérioDesenvolvidoEm DesenvolvimentoPrecisa Melhorar
Alternância eficazTroca natural de papéisTroca quando lembradoDominação de um papel
Comunicação técnicaExplica claramente decisõesExplicação básicaAssume sem explicar
Colaboração ativaAmbos contribuem igualmenteUm lidera, outro segueParticipação desigual
TDD em duplaRed-Green-Refactor fluenteBásico mas funcionalTesta depois de implementar
Debug colaborativoIdentifica bugs rapidamenteEncontra com orientaçãoDificuldade para detectar

💡 Feedback Construtivo

  • Pontos fortes observados durante exercícios
  • Áreas de melhoria para próximas práticas
  • Strategies para otimizar pair programming

🔗 Recursos Complementares

📚 Para Prática Extra:

🎮 Plataformas para Prática:

  • HackerRank - pair programming mode
  • Replit - collaborative coding environment
  • CodeSandbox - browser-based pair coding

📝 Lição de Casa

🎯 Desafio Individual

Pratique pair programming “simulado”:

  1. Escolha 1 exercício de programação online
  2. Grave você explicando cada linha antes de escrever (simule Navigator)
  3. Implemente explicando verbalmente (simule Driver)
  4. Reflita: “Essa prática me ajudou a detectar problemas mais cedo?”

📊 Entregável:

  • Relatório de 200 palavras sobre a experiência
  • 1 insight sobre benefícios da verbalização durante coding
  • 1 suggestion para melhorar pair programming em equipes

Entrega: Próxima aula (06/04/2026) via Google Classroom


Checklist de Conclusão

Para o Aluno:

  • Participei ativamente em todos os exercícios de pair programming
  • Experimentei ambos os papéis (Driver e Navigator) efetivamente
  • Pratiquei TDD colaborativo com alternância estruturada
  • Identifiquei bugs através de debugging colaborativo
  • Refleti sobre aplicações práticas no mercado de trabalho
  • Compreendo when to use vs when NOT to use pair programming

Para o Professor:

  • Observei cada dupla durante pelo menos 5 minutos de interaction
  • Forneci feedback específico sobre comunicação técnica
  • Identifiquei alunos que se destacaram em collaborative skills
  • Documentei insights para melhorar próximas aplicações
  • Avaliei readiness da turma para próxima aula (Design Patterns)

🎯 Próxima Aula: Design Patterns via Collaborative Design Decisions