🏋️♂️ 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:
-
Qualidade do código: “O código final ficou melhor do que eu teria escrito sozinho?” Por quê?
-
Aprendizagem: “O que aprendi com meu par que não descobriria sozinho?”
-
Comunicação: “Em que momentos a comunicação técnica foi mais eficaz?”
-
Alternância: “Prefiro ser Driver ou Navigator?” “Em que situações cada papel foi mais confortável?”
-
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ério | Desenvolvido | Em Desenvolvimento | Precisa Melhorar |
|---|---|---|---|
| Alternância eficaz | Troca natural de papéis | Troca quando lembrado | Dominação de um papel |
| Comunicação técnica | Explica claramente decisões | Explicação básica | Assume sem explicar |
| Colaboração ativa | Ambos contribuem igualmente | Um lidera, outro segue | Participação desigual |
| TDD em dupla | Red-Green-Refactor fluente | Básico mas funcional | Testa depois de implementar |
| Debug colaborativo | Identifica bugs rapidamente | Encontra com orientação | Dificuldade 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”:
- Escolha 1 exercício de programação online
- Grave você explicando cada linha antes de escrever (simule Navigator)
- Implemente explicando verbalmente (simule Driver)
- 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