Engenharia de Software

Evolução, Manutenção e Refatoração de Software

Professor: Gabriel Soares Baptista

Por que essa aula importa?

Entregar um sistema não encerra o trabalho de engenharia de software.

Depois da entrega, o sistema entra em contato com usuários, dados, regras e integrações reais.
O problema muda: agora a equipe precisa manter o software útil apesar das mudanças no ambiente.

Ideia central do Sommerville

Segundo Sommerville, desenvolvimento e evolução fazem parte do mesmo ciclo de vida.

Um sistema profissional raramente é construído, entregue e abandonado.
Ele continua sendo modificado enquanto ainda tiver valor para a organização.

Reflita

Reflita

Se um sistema acadêmico foi entregue funcionando em 2024, ele continuará adequado em 2026 se mudarem calendário, regras de matrícula, autenticação e integrações externas?

Provavelmente não. Mesmo correto, o sistema pode ficar progressivamente menos útil se não acompanhar o ambiente.

Software útil precisa mudar

Manutenção não é apenas correção de bugs.

Em sistemas reais, manutenção inclui adaptação a novos ambientes, novos requisitos, melhoria de estrutura e preparação para mudanças futuras.
Como sistemas de software são ativos críticos, preservar seu valor consome grande parte do orçamento de TI.

Evolução em espiral

O sistema passa por especificação, implementação, validação e operação várias vezes, release após release.

O ambiente força a evolução

A mudança pode vir de:

  • novas regras de negócio
  • mudanças legais ou regulatórias
  • defeitos encontrados em operação
  • atualização de sistema operacional, banco ou hardware
  • integração com outros sistemas
  • novas expectativas dos usuários
  • pressão competitiva do mercado

Exemplos de ambiente mudando

Sistema de biblioteca:

  • renovação pelo aplicativo
  • nova regra de multa
  • login institucional único
  • relatório para sistema nacional

Sistema de vendas:

  • API de pagamento muda autenticação, endpoint ou contrato de resposta
O sistema original não era inútil. O ambiente continuou se movendo.

Cuidado importante


Um sistema pode ficar obsoleto sem ter um único bug novo. Basta que o mundo ao redor dele mude e ele não acompanhe essa mudança.

Do desenvolvimento para a evolução

Separar rigidamente desenvolvimento e manutenção pode esconder o custo real da vida do sistema.

Economizar na manutenibilidade durante o desenvolvimento costuma cobrar juros depois.
Em produção, a equipe precisa entender código existente, avaliar impactos, preservar dados reais, evitar regressões e negociar mudanças com usuários reais.

Evolução, serviço e fim gradual

Fase Ideia
Desenvolvimento inicial O sistema é criado.
Evolução Mudanças significativas ainda são feitas.
Em serviço Apenas mudanças pequenas e essenciais são aceitas.
Interrupção gradual O sistema ainda pode ser usado, mas deixa de receber mudanças relevantes.
Uso contínuo não significa evolução saudável.

Exemplo: evolução ou serviço?

Folha de pagamento:

  • recebe ajustes anuais de regras, relatórios e integrações
  • ainda está em evolução

Consulta histórica:

  • ainda é necessária
  • quase ninguém quer adicionar funcionalidade
  • provavelmente está apenas em serviço

Processo de evolução

Toda evolução começa com uma proposta de mudança.

Ela pode vir de bug, novo requisito, necessidade operacional ou melhoria sugerida pela equipe.

Perguntas antes de mudar

Antes de implementar, a equipe deve perguntar:

  1. o que precisa mudar?
  2. que partes do sistema serão afetadas?
  3. quanto custará implementar e testar?
  4. em qual release a mudança deve entrar?
Mudança profissional começa por análise, não por edição apressada do código.

Análise de impacto

Análise de impacto é entender as consequências de uma mudança antes de implementá-la.

Ela exige examinar código, requisitos, arquitetura, testes, dados, interfaces e integrações.
Uma mudança pequena na tela pode afetar banco, validações, relatórios, APIs e permissões.

Exemplos de análise de impacto

CPF obrigatório no responsável financeiro:

  • tabela de responsáveis
  • registros antigos sem CPF
  • tela de cadastro
  • validação na API
  • relatórios financeiros
  • testes e integrações externas

Correção de desconto no e-commerce:

  • pode afetar carrinho, checkout, nota fiscal, relatório financeiro e API de pedidos

Correções emergenciais

Às vezes, um defeito grave em produção exige correção rápida.

Isso pode ser necessário, mas se documentação, requisitos e testes não forem realinhados depois, a solução emergencial vira decisão permanente sem análise adequada.

Uma correção emergencial deve resolver o incidente, mas não deveria encerrar a mudança.

Leis de Lehman

Lehman e Belady estudaram a evolução de sistemas de grande porte.

A ideia central: sistemas usados no mundo real não ficam parados.
Lei Ideia central
Mudança contínua O sistema precisa mudar ou se torna menos útil.
Aumento da complexidade A estrutura tende a ficar mais complexa sem cuidado.
Crescimento contínuo A funcionalidade precisa crescer para manter usuários satisfeitos.
Declínio de qualidade A qualidade cai se o sistema não acompanhar o ambiente.

O alerta das leis

As leis não são fórmulas matemáticas rígidas.

Elas funcionam como alertas gerenciais e técnicos.
Se a equipe adiciona funcionalidade continuamente sem refatorar, testar e reorganizar, a complexidade cresce.

Exemplos das leis em ação

Sistema de atendimento que cresce:

  • chat, WhatsApp, relatórios, automações e permissões especiais
  • se tudo entra no lugar mais rápido, surgem regras duplicadas e condicionais espalhadas

Release grande:

  • muitas funcionalidades novas interagem de formas inesperadas
  • frequentemente precisa ser seguido por releases de correção e estabilização

Tipos de manutenção

Tipo Quando acontece Exemplo
Correção de defeitos Corrigir erros em operação. Desconto incorreto.
Adaptação ao ambiente Ajustar a mudanças técnicas externas. Nova versão de banco ou API.
Adição ou modificação de funcionalidade Atender novas necessidades do negócio. Renovação on-line em biblioteca.
Na prática, esses tipos podem se misturar.

Mito sobre manutenção


Manutenção não é apenas correção de bugs. Uma parte grande do esforço vem de adaptar o sistema e adicionar ou modificar funcionalidades depois que ele já está em uso.

Por que manutenção custa caro?

Adicionar funcionalidade depois que o sistema está em operação costuma ser mais caro porque a equipe precisa:

  • entender decisões antigas
  • lidar com documentação incompleta
  • trabalhar sobre estrutura possivelmente degradada
  • preservar dados reais
  • proteger funcionalidades existentes com testes
  • evitar quebrar integrações externas

Problema organizacional

Contratos de desenvolvimento e manutenção muitas vezes são separados.

Isso reduz o incentivo para investir em manutenibilidade no início.
O custo da má estrutura pode ser pago por outra equipe, outro orçamento ou pelos usuários.

Exemplos de custo de manutenção

Regra duplicada:

  • mensalidade copiada em três módulos para entregar rápido
  • depois, a manutenção precisa encontrar, alterar e testar todas as cópias

Banco antigo:

  • atualização por segurança exige adaptar queries, drivers, scripts e testes
  • mesmo sem novo requisito de negócio

Previsão de manutenção

Gerentes tentam prever manutenção para evitar surpresas de orçamento e prazo.

Partes mais expostas a mudança tendem a ter muitas interfaces, requisitos voláteis ou dependência de processos instáveis.

Métricas úteis:

  • solicitações corretivas
  • tempo médio de análise de impacto
  • tempo médio para implementar mudança
  • solicitações pendentes
  • complexidade de componentes críticos

Métrica ajuda, mas não decide sozinha


Métrica não substitui julgamento técnico. Ela ajuda a enxergar tendência.

Exemplo: mudanças simples no módulo financeiro levavam dois dias e agora levam duas semanas.
A investigação pode revelar regras acumuladas, integrações sem testes e dependências diretas com relatórios.

Reengenharia de software

Quando um sistema legado ainda tem valor, mas se tornou difícil de mudar, uma opção é aplicar reengenharia.

Objetivo: melhorar estrutura, documentação e inteligibilidade sem mudar a funcionalidade essencial.

O que pode entrar na reengenharia?

  • tradução de código-fonte
  • engenharia reversa
  • melhoria da estrutura do programa
  • modularização
  • reengenharia de dados
Nem todo projeto usa todas as etapas.

Reengenharia não é reescrita total

Reescrever um sistema crítico do zero pode parecer atraente, mas envolve alto risco.

A equipe pode não entender todas as regras implícitas do sistema antigo.

Benefícios destacados por Sommerville:

  • risco reduzido
  • custo reduzido
Limite: grandes mudanças arquiteturais e reorganizações profundas de dados continuam caras.

Exemplos de reengenharia

Sistema COBOL com regras acumuladas:

  • exige engenharia reversa, documentação de regras, testes e modularização gradual

Sistema com dados duplicados:

  • pode exigir limpeza, modelo de dados claro e scripts de migração
A funcionalidade visível pode mudar pouco, mas a capacidade de evolução aumenta.

Refatoração como manutenção preventiva

Refatoração é melhorar a estrutura interna do código sem alterar o comportamento observável.

Ela não adiciona funcionalidade.
Ela reduz complexidade, duplicação, acoplamento e custo mental de mudança.

Refatoração depende de testes

Refatoração conversa diretamente com a aula de testes.

Testes de regressão ajudam a verificar se o comportamento antes e depois continua o mesmo.

Refatoração sem testes aumenta risco. Você pode mudar a estrutura e introduzir defeitos sem perceber.

Refatoração x reengenharia

Refatoração Reengenharia
Processo contínuo e incremental. Processo mais amplo, comum em legados.
Atua em melhorias localizadas. Pode envolver código, dados, documentação e arquitetura.
Acontece durante desenvolvimento e evolução. Acontece quando manutenção ficou cara ou arriscada.
Depende de testes de regressão. Pode exigir engenharia reversa e migração.

Maus cheiros de código

Fowler, citado por Sommerville, chama de maus cheiros os sinais de que o código pode precisar de refatoração.

Exemplos:

  • código duplicado
  • métodos longos
  • condicionais complexas ou repetidas
  • grupos de dados repetidos
  • generalidade especulativa

Exemplo: código duplicado

Antes:

def calcular_total_carrinho(valor):
    frete = 0 if valor >= 200 else 15
    return valor + frete

def simular_pagamento(valor):
    frete = 0 if valor >= 200 else 15
    return {"total": valor + frete}

Depois:

def calcular_frete(valor):
    return 0 if valor >= 200 else 15

Exemplo: método longo

Antes, uma função pode misturar validação, cálculo e montagem de resposta.

Depois, a refatoração separa responsabilidades:

def validar_pedido(cliente, itens):
    if cliente is None or len(itens) == 0:
        raise ValueError("pedido invalido")

def calcular_subtotal(itens):
    return sum(item["preco"] * item["quantidade"] for item in itens)

def calcular_frete(total):
    return 0 if total >= 200 else 15
Refatorar não é enfeitar. É reduzir o custo mental de entender e alterar o sistema.

Sistemas legados

Sistemas legados são sistemas antigos que continuam importantes para a organização.

O problema não é simplesmente a idade.
O problema aparece quando há alto valor de negócio, baixa qualidade técnica, dependências obsoletas ou manutenção cara.

Avaliação de sistemas legados

Sommerville propõe avaliar legados por duas perspectivas:

  1. valor de negócio
  2. qualidade do sistema

Matriz de decisão

Situação Estratégia provável
Baixo valor e baixa qualidade Descartar.
Alto valor e baixa qualidade Reestruturar, fazer reengenharia ou substituir.
Baixo valor e alta qualidade Manter apenas se o custo for baixo.
Alto valor e alta qualidade Continuar manutenção normal.

O que avaliar?

Valor de negócio:

  • uso em momentos críticos, apoio a processos centrais, importância das saídas e impacto de falhas

Qualidade técnica:

  • inteligibilidade, documentação, dados, desempenho, ferramentas, configuração, testes e conhecimento da equipe

Exemplos de decisão em legados

Sistema antigo de boletos:

  • usado diariamente, falha afeta o caixa, código difícil e biblioteca sem suporte
  • alto valor e baixa qualidade: reengenharia ou substituição gradual

Sistema antigo de relatórios:

  • funciona bem, mas quase ninguém usa
  • baixo valor: manter só se o custo for mínimo ou planejar descarte

Responsabilidade profissional

Engenheiros de software têm responsabilidade profissional de produzir código que possa ser mantido e alterado.

Mesmo quando isso não aparece explicitamente como requisito do cliente.
Decisões internas afetam custos futuros, riscos operacionais, trabalho de outras equipes e experiência dos usuários.

Ideia final


Manutenção não é a fase menos nobre da engenharia de software. Ela é a prova de que o software entrou no mundo real e precisa continuar útil apesar da mudança.

Próximos passos

Avaliação!