👥 Aula 04

Pair Programming

Colaboração técnica com qualidade superior

Desenvolvimento de Sistemas II
Prof. Ricardo Pires
3º Técnico DS | 30/03/2026


🎯 Objetivos da Aula

Conceituais

  • Compreender princípios do Pair Programming
  • Identificar papéis Driver e Navigator
  • Conhecer benefícios de colaboração técnica

Práticos

  • Aplicar TDD colaborativo em duplas
  • Executar debugging conjunto
  • Praticar alternância de papéis eficiente

Atitudinais

  • Valorizar qualidade coletiva sobre velocidade individual
  • Desenvolver comunicação técnica eficaz
  • Cultivar humildade intelectual e feedback construtivo

📈 Meta de sucesso:

90%+ dos alunos relatam experiência positiva com pair programming

🚨 O Problema: Bug de Produção

😰 Cenário Real - Deploy Quebrado

// Dev A trabalha na API
@RestController
public class PedidoController {
 
    @PostMapping("/pedidos")
    public ResponseEntity<String> criar(@RequestBody PedidoDTO dto) {
        // A retorna formato: {"status": "success", "id": 123}
        return ResponseEntity.ok("{\"status\":\"success\",\"id\":" +
                                  pedido.getId() + "}");
    }
}
 
// Dev B trabalha no Frontend (sem comunicação)
fetch('/api/pedidos', {
    method: 'POST',
    body: JSON.stringify(pedido)
})
.then(response => response.json())
.then(data => {
    // B espera formato: {"pedidoId": 123, "resultado": "ok"}
    const pedidoId = data.pedidoId; // ❌ UNDEFINED!
    window.location = `/pedidos/${pedidoId}`; // ❌ QUEBRA!
});

💸 Custo do Bug:

  • 3 horas para descobrir incompatibilidade
  • 2 hotfixes em produção
  • Rollback do release planejado
  • Cliente sem conseguir fazer pedidos

🎯 Solução: Pair Programming

// Com pair programming:
// Navigator: "Que formato a API vai retornar?"
// Driver: "Vamos definir juntos no contrato..."
 
interface PedidoResponse {
    pedidoId: number;
    status: 'success' | 'error';
    timestamp: string;
}
// ✅ Contract definido em conjunto!

🔍 O que é Pair Programming?

Definição Formal

“Duas pessoas trabalhando juntas num mesmo computador para resolver o mesmo problema ao mesmo tempo.”

👥 Características:

  • Duas mentes focadas no mesmo objetivo
  • Revisão contínua de decisões técnicas
  • Compartilhamento de conhecimento em tempo real
  • Qualidade superior através de colaboração ativa

⚖️ Pair vs. Code Review Tradicional

PAIR PROGRAMMING:
✅ Revisão em tempo real
✅ Discussão durante implementação
✅ Decisões conjuntas
✅ Bugs evitados durante escrita
CODE REVIEW TARDIO:
⚠️ Revisão após implementação
⚠️ Resistência a mudanças grandes
⚠️ Feedback assíncrono
⚠️ Retrabalho custoso

👨‍💻 Papéis: Driver vs. Navigator

🚗 Driver (Motorista)

Responsabilidades:

  • Escrever o código ativamente
  • Implementar decisões técnicas
  • Explicar while coding
  • Focar na sintaxe e detalhes

Skills desenvolvidas:

  • Coding fluente under observation
  • Explicação técnica clara
  • Implementação eficiente
  • Concentração sobre pressure

🧭 Navigator (Navegador)

Responsabilidades:

  • Revisar código em tempo real
  • Sugerir melhorias e alternativas
  • Antecipar problemas potenciais
  • Pensar estrategicamente

Skills desenvolvidas:

  • Code review ativo
  • Visão arquitetural
  • Detecção de bugs
  • Comunicação construtiva

🔄 Alternância Essencial:

Trocar papéis a cada 15-20 minutos para aprendizagem equilibrada

🧪 Test-Driven Development + Pair Programming

🔴 RED Phase - Navigator Leading

// Navigator sugere: "Vamos começar com validação básica"
@Test
@DisplayName("Deve validar CPF com formato correto")
void deveValidarCpfFormatoCorreto() {
    // Navigator guia estratégia geral
    String cpfValido = "11144477735";
    assertTrue(CpfValidator.isValid(cpfValido));
}
 
// Navigator: "E se o CPF for null?"
@Test
@DisplayName("Deve rejeitar CPF null")
void deveRejeitarCpfNull() {
    assertFalse(CpfValidator.isValid(null));
}

🟢 GREEN Phase - Driver Leading

// Driver implementa minimally:
public class CpfValidator {
    public static boolean isValid(String cpf) {
        if (cpf == null) return false;
        return cpf.equals("11144477735"); // Força passa
    }
}

🔧 REFACTOR Phase - Both Collaborating

// Navigator: "Agora podemos generalizar..."
// Driver implementa com Navigator reviewing:
 
public static boolean isValid(String cpf) {
    if (cpf == null || cpf.length() != 11) {
        return false;
    }
 
    if (!cpf.matches("\\d{11}")) {
        return false;
    }
 
    // Navigator: "Vamos extrair validação de dígitos?"
    return validarDigitosVerificadores(cpf);
}
 
private static boolean validarDigitosVerificadores(String cpf) {
    // Driver implementa com Navigator validando lógica
}

🎯 Benefícios da Combinação:

  • Design emerge através de discussão
  • Edge cases identificados rapidamente
  • Refatoração mais corajosa (duas pessoas validam)
  • Tests mais abrangentes (perspectivas diferentes)

🐛 Live Demo: Debugging Colaborativo

🚀 Vamos Caçar Bugs Juntos!

Bug Intencional no Código:

  • Método com erro sutil de lógica
  • Navigator identifica problema
  • Driver implementa correção
  • Ambos validam solução

Processo Colaborativo:

  1. Ler código juntos linha por linha
  2. Navigator questiona cada decisão
  3. Driver explica intenção vs. implementação
  4. Identificar discrepância em conjunto
  5. Aplicar correção e testar
**Acompanhem o debugging no projetor!**

🏃‍♂️ Exercício Prático 1: TDD em Dupla

📝 Seu Desafio (30 min)

Implementar Calculadora usando TDD em pair:

Historia de Usuário:

“Como usuário, quero uma calculadora para operações básicas, para agilizar meus cálculos matemáticos.”

Acceptance Criteria:

  • ✅ Soma de dois números decimais
  • ✅ Subtração de dois números
  • ✅ Multiplicação com precisão
  • ✅ Divisão com tratamento de zero
  • ✅ Validação de entradas inválidas

🔄 Processo Estruturado:

Rodada 1 (15 min):

  • Navigator A + Driver B: Implementar soma via TDD
  • Alternar a cada teste Red→Green→Refactor

Rodada 2 (15 min):

  • Navigator B + Driver A: Implementar subtração
  • Trocar papéis e aplicar aprendizados

📊 Template Inicial:

public class Calculadora {
    // TODO: implementar via TDD em dupla
}
 
@Test
void deveSomarDoisNumeros() {
    // TODO: escrever teste
}
💡 Dica:
Navigator deve questionar CADA linha antes do Driver digitar

🐞 Exercício Prático 2: Debug Colaborativo

🔍 Identifiquem o Bug em Dupla

public class ContadorVisitas {
    private int visitas = 0;
 
    public void incrementar() {
        visitas++;
    }
 
    public String getStatus() {
        if (visitas = 1) {  // ❓ Algo errado aqui?
            return "Primeira visita";
        }
        return "Visitas: " + visitas;
    }
 
    public void resetar() {
        visitas == 0;  // ❓ E aqui?
    }
 
    public boolean temVisitas() {
        return visitas > 0 && visitas < 100;  // ❓ E aqui?
    }
}

🎯 Processo de Debug:

  • Questionar cada linha suspeita
  • Antecipar comportamento esperado vs. real
  • Sugerir testes para provar o bug

Driver Mission:

  • Implementar testes sugeridos pelo Navigator
  • Aplicar correções propostas
  • Validar com execução real

⏱️ Tempo: 20 minutos

  • 10 min: Identificar todos os bugs
  • 10 min: Implementar correções com testes
Meta: Encontrar pelo menos 3 bugs diferentes colaborativamente

🏢 Quando Usar no Mercado?

🔥 Situações Ideais:

Bug Crítico em Produção

  • Pressão alta → duas mentes reduzem stress
  • Time is money → qualidade imediata é crucial
  • Root cause pode ser sutil → perspectivas múltiplas

Refatoração de Código Legado

  • Complexidade alta → divisão de carga mental
  • Risk management → validação contínua de mudanças
  • Knowledge transfer → compartilhamento de contexto

Onboarding de Desenvolvedores

  • Junior + Senior → mentoring prático
  • Codebase nova → exploração guiada
  • Cultura da empresa → transmissão de práticas

Feature de Alto Impacto

  • Business critical → qualidade não-negociável
  • Multiple stakeholders → decisões precisam ser documentadas
  • Architecture decisions → melhor discutir em tempo real

💰 ROI Comprovado:

MétricaIndividualPair Programming📈 Melhoria
Time to market100%115%-13% initially
Bugs em produção100%15%85% menos
Code review time100%10%90% menos
Knowledge silosAltoBaixoTransferência++
Developer satisfactionVariável96% positivoMuito melhor
⚖️ Trade-off honesto:
15% mais tempo inicial → 60% menos retrabalho posterior

🌟 Benefícios Comprovados

🧠 Para o Desenvolvedor:

Aprendizagem Acelerada:

  • Exposure a diferentes approaches
  • Real-time mentoring de diversos seniors
  • Immediate feedback on coding decisions
  • Soft skills development através de comunicação

Redução de Frustração:

  • Debugging mais eficiente com second pair of eyes
  • Decision paralysis reduzida com discussão
  • Confidence aumentada no código entregue

👥 Para a Equipe:

  • Code style mais consistente
  • Knowledge sharing natural e contínuo
  • Bus factor reduzido drasticamente

🏢 Para a Empresa:

Qualidade Superior:

  • 15% menos bugs reaching production
  • Complexity reduzida através de peer review
  • Maintainability melhorada via design discussions

Time Efficiency:

  • Onboarding 60% mais rápido para novos devs
  • Context switching reduzido - foco conjunto
  • Rework dramaticamente menor

Innovation:

  • Creative solutions emergem from brainstorming
  • Risk taking mais seguro com validation partner
  • Cross-pollination de ideias entre diferentes domains
📈 Empresas que usam:
Spotify, Pivotal, ThoughtWorks, Extreme Programming teams

⚠️ Quando NÃO Fazer Pair Programming?

🚨 Situações Counter-Productive:

📝 Tasks Mecânicas/Repetitivas:

  • CRUD simples sem lógica
  • Configuration files routine
  • Documentation writing (pode ser async)
  • Research individual focused

🧠 Deep Thinking Required:

  • Architecture exploration inicial
  • Algorithm research experimental
  • Proof of concept rápido
  • Learning nova technology sozinho primeiro

👥 Incompatibilidade Pessoal:

  • Communication styles muito diferentes
  • Conflict não resolvido na equipe
  • Experience gap muito grande sem mentoring structure

⚖️ Trade-offs Honestos:

💸 Cost Considerations:

Cenário A: Feature simples (2 story points)
• Solo: 1 dev × 4 horas = 4 horas
• Pair: 2 devs × 2.5 horas = 5 horas
→ 25% overhead sem benefícios significantes

Cenário B: Feature complexa (8 story points)
• Solo: 1 dev × 20 horas + 8 horas debugging = 28 horas
• Pair: 2 devs × 12 horas = 24 horas
→ 14% economia + qualidade superior

🎯 Sweet Spot:

Use pair programming quando:
Cost of bugs > Cost of extra time

⏱️ Remote Considerations:

  • Video call fatigue é real
  • Tool setup pode ser complex (screen sharing, etc.)
  • Time zones podem complicar scheduling

🛠️ Ferramentas para Pair Programming

💻 Presencial:

IDE Colaborativo:

  • VS Code Live Share: real-time collaboration
  • IntelliJ Code With Me: JetBrains solution
  • Atom Teletype: GitHub atom plugin

Setup Físico Ideal:

    [Monitor Grande Compartilhado]
           /              \
    [Teclado A]      [Teclado B]
       |                  |
   [Dev A]            [Dev B]
  • Dual keyboards/mouse para alternância rápida
  • Comfortable seating lado a lado
  • Screen mirroring para ambos verem clearly

🌐 Remoto:

Plataformas All-in-One:

  • Tuple: Dedicated pair programming tool
  • CodeTogether: Cross-IDE collaboration
  • Replit: Browser-based collaborative coding
  • Gitpod: Cloud development environments

Setup Híbrido:

// Code collaboration: VS Code Live Share
// Voice: Discord/Teams
// Screen: OBS for high quality sharing
// Planning: Miro/Figma for whiteboarding

📱 Mobile Pair Programming:

  • Termux + SSH para coding em tablets
  • GitHub Codespaces em mobile browsers
  • iPad Pro com external keyboard viable
⚡ Pro Tip:
Start with simple tools. Complexity overhead pode matar produtividade!

🎯 Consolidação: Pair Programming Eficaz

🔑 Princípios Fundamentais:

1. Comunicação Contínua:

  • Driver explica intenção antes de implementar
  • Navigator pergunta “why” antes de “how”
  • Both discutem trade-offs openly

2. Alternância Regular:

  • Timer de 15-20 minutos visible
  • Natural breakdown entre logical tasks
  • Both should drive AND navigate

3. Foco Compartilhado:

  • One conversation at a time
  • Distractions minimized (phones, slack, etc.)
  • Problem-solving é atividade conjunta

🚀 Técnicas Avançadas:

💡 Strong-Style Pairing:

“For an idea to go from your head into the computer it MUST go through someone else’s hands”

🎯 Driver-Navigator Plus:

  • Driver: Implementation focus
  • Navigator: Strategic + tactical oversight
  • Both: Architecture decisions conjuntas

🔄 Ping Pong Pairing:

  • Person A writes failing test
  • Person B makes test pass + writes next failing test
  • Person A makes test pass + refactors
**Pair Programming é skill que melhora com prática!**

🎯 Próxima Aula 05:

Design Patterns + collaborative design decisions = Architecture emergent


🙋‍♂️ Dúvidas e Discussão

Perguntas sobre Pair Programming?

Vamos compartilhar experiências:

  • Alguém já trabalhou em dupla em projetos pessoais?
  • Qual foi o impacto na qualidade final do código?
  • Como imaginem aplicar pair programming em empresas?
  • Que tools gostariam de experimentar para remote pairing?
💬 Discussão colaborativa:
Compartilhem experiências reais de colaboração técnica

📱 Contato e Recursos

📞 Professor Ricardo Pires

📁 Materiais da Aula

  • Slides: /Aula04/material-pedagogico/
  • Código: /Aula04/projeto-pratico/
  • Exercícios: exercicios-praticos.md
  • Referências: material-apoio.md
Próxima aula:
Design Patterns em Colaboração
Segunda-feira, 06/04/2026
  • Ritmo: Conceito Código Resolução de Problema.
  • Foco: colaboração técnica com qualidade.
  • Meta: reduzir bugs e acelerar aprendizado de time.

🧠 Conceito: como funciona o par

  • Driver: implementa.
  • Navigator: revisa, questiona e antecipa risco.
  • Troca de papéis a cada 15-20 minutos.
[Driver coda] <-> [Navigator valida estratégia]

💻 Live Code: fluxo de tarefa Java

  1. Definir história curta.
  2. Escrever teste JUnit em dupla.
  3. Implementar mínimo viável.
  4. Refatorar juntos.
assertThrows(IllegalArgumentException.class,
    () -> EmailValidator.validarOuFalhar(null));

🧩 Quando usar no mercado

  • Bug crítico em produção.

  • Refatoração de código sensível.

  • Onboarding de júnior.

  • Funcionalidade de alto impacto.

  • Ganho real: menos retrabalho e decisões mais consistentes.


🗣️ Desafio do Código - O Bug de Produção

Dois devs codam sozinhos em módulos acoplados e criam comportamentos incompatíveis.

Sintoma:
- API retorna formato A
- Front espera formato B
- Deploy quebra fluxo de compra
  • Causa: falta de alinhamento técnico durante implementação.

✅ Desafio do Código - A Solução do Sênior

  • Aplicar pair programming na regra crítica.
  • Definir contrato de API antes de codar.
  • Revisar juntos o teste de integração.
Alinhamento antecipado -> menos conflito de integração -> entrega estável

🎯 Checklist final da Aula 4

  1. Houve troca real de papéis?
  2. O Navigator contribuiu com melhoria técnica concreta?
  3. O código final ficou melhor que no modo solo?
  4. As decisões foram registradas no PR?

📝 Atividades práticas em sala (30 min)

Exercício 1: TDD em par

Navigator + Driver: Implementem uma calculadora usando TDD:

  1. Escrever teste para soma
  2. Implementar mínimo para passar
  3. Refatorar
  4. Alternar papéis
  5. Repetir para subtração
// Estrutura inicial
public class Calculadora {
    // TODO: implementar métodos
}
 
@Test
public void deveSomar() {
    // TODO: escrever teste
}

Exercício 2: Debug colaborativo

Em dupla, encontrem e corrijam o bug:

public class ContadorVisitas {
    private int visitas = 0;
 
    public void incrementar() {
        visitas++;
    }
 
    public String getStatus() {
        if (visitas = 1) {
            return "Primeira visita";
        }
        return "Visitas: " + visitas;
    }
}

✅ Gabarito das atividades

Gabarito 1 (TDD):

public class Calculadora {
    public double somar(double a, double b) {
        return a + b;
    }
 
    public double subtrair(double a, double b) {
        return a - b;
    }
}
 
@Test
public void deveSomar() {
    Calculadora calc = new Calculadora();
    assertEquals(5.0, calc.somar(2.0, 3.0));
}
 
@Test
public void deveSubtrair() {
    Calculadora calc = new Calculadora();
    assertEquals(2.0, calc.subtrair(5.0, 3.0));
}

Gabarito 2 (Bug):

// Bug: = em vez de == na condição
public String getStatus() {
    if (visitas == 1) {  // Era: if (visitas = 1)
        return "Primeira visita";
    }
    return "Visitas: " + visitas;
}

Atividade rápida

  • Completar TDD em dupla.
  • Documentar decisões tomadas durante pair programming.