9

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

Introdução9.1

Hoje você vai ver por que entregar um sistema não encerra o trabalho de engenharia de software. Na prática, a entrega apenas muda o tipo de problema que a equipe passa a enfrentar.

Até aqui, estudamos processos, requisitos, modelos, arquitetura, implementação e testes. Todos esses temas aparecem antes da primeira entrega, mas continuam importando depois dela. O motivo é simples: um software útil entra em contato com um ambiente real, e esse ambiente muda. A organização muda suas regras, usuários descobrem novas necessidades, plataformas são atualizadas, defeitos aparecem em produção e outros sistemas passam a exigir integração.

Segundo Sommerville, essa é a razão para tratarmos desenvolvimento e evolução como partes de um 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

Se um sistema acadêmico foi entregue funcionando em 2024, ele continuará adequado em 2026 se mudarem o calendário institucional, as regras de matrícula, a forma de autenticação e a integração com sistemas do governo?

Provavelmente não. Mesmo que o código original estivesse correto, o sistema pode ficar progressivamente menos útil se não acompanhar o ambiente. Essa é a ideia central da evolução de software.

Software útil precisa mudar9.2

Um erro comum é imaginar manutenção como uma atividade menor, feita apenas para corrigir bugs. Isso reduz demais o problema. Em sistemas reais, manutenção também inclui adaptação a novos ambientes, incorporação de novos requisitos, melhoria de estrutura e preparação para mudanças futuras.

Sommerville destaca que sistemas de software são ativos críticos de negócio. Uma organização pode depender deles para vender, atender clientes, controlar estoque, operar infraestrutura ou cumprir obrigações legais. Por isso, preservar o valor desses sistemas costuma consumir uma parte enorme do orçamento de TI.

A Figura 9.1 ajuda a enxergar a ideia de ciclo. O sistema passa por especificação, implementação, validação e operação, mas isso não acontece uma única vez. Depois do primeiro release, novas mudanças alimentam outro ciclo, que produz outro release, e assim por diante.

O ambiente força a evolução9.2.1

A mudança pode vir de muitos lugares:

  1. novas regras de negócio;
  2. mudanças legais ou regulatórias;
  3. defeitos encontrados em operação;
  4. atualização de sistema operacional, banco de dados ou hardware;
  5. integração com outros sistemas;
  6. novas expectativas dos usuários;
  7. pressão competitiva do mercado.

Essa variedade importa porque mostra que a manutenção não é apenas um problema técnico. Ela é também uma resposta a mudanças organizacionais, econômicas e sociais.

Exemplo 1

Imagine um sistema de controle de biblioteca que registra empréstimos, devoluções e multas.

No primeiro ano, ele funciona bem. No segundo ano, a instituição decide aceitar renovação pelo aplicativo. No terceiro, muda a regra de multa. No quarto, a autenticação passa a usar login institucional único. No quinto, a biblioteca precisa exportar relatórios para um sistema nacional.

Nenhuma dessas mudanças significa que o sistema original era inútil. Elas significam que o ambiente continuou se movendo. Se o software não evoluir, ele deixa de sustentar o processo real da organização.

Exemplo 2

Agora pense em um sistema de vendas que depende de uma API de pagamento externa.

A API muda o formato de autenticação e descontinua um endpoint antigo. Mesmo que nenhuma regra interna da loja tenha mudado, o sistema precisa ser alterado para continuar vendendo.

Esse é um caso de evolução provocada pelo ambiente técnico. O software não está isolado. Ele vive dentro de uma rede de dependências.


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ção9.3

Sommerville propõe pensar o software como um processo contínuo. Em vez de separar rigidamente "desenvolvimento" e "manutenção", faz mais sentido enxergar ambos como ciclos de mudança.

Essa mudança de visão é importante porque combate uma ideia perigosa: a de que a equipe pode economizar durante o desenvolvimento e deixar a manutenibilidade para depois. Na prática, depois costuma ser mais caro. Quando o sistema já está em produção, a equipe precisa entender o código existente, avaliar impactos, preservar dados, evitar regressões e negociar mudanças com usuários reais.

Evolução e serviço9.3.1

Rajlich e Bennett, citados por Sommerville, distinguem fases diferentes na vida de um sistema:

  1. desenvolvimento inicial, quando o sistema é criado;
  2. evolução, quando mudanças significativas ainda são feitas;
  3. em serviço, quando apenas mudanças pequenas e essenciais são aceitas;
  4. interrupção gradual, quando o sistema ainda pode ser usado, mas deixa de receber novas mudanças relevantes.

Essa distinção mostra que nem todo sistema em uso está igualmente saudável. Alguns sistemas continuam evoluindo com relativa segurança. Outros ainda são usados, mas já estão tão rígidos ou arriscados que a organização apenas evita mexer neles.

Exemplo 3

Um sistema de folha de pagamento ainda recebe ajustes anuais de regras trabalhistas, relatórios e integrações. Ele está em fase de evolução, porque a organização ainda investe em mudanças significativas.

Já um sistema antigo de consulta histórica, usado apenas para verificar registros de anos anteriores, pode estar em serviço. Ele ainda é necessário, mas ninguém quer adicionar grandes funcionalidades. A prioridade é mantê-lo funcionando até que os dados sejam migrados ou deixem de ser necessários.

Exemplo 4

Considere uma aplicação desktop antiga escrita em uma linguagem pouco usada. Ela controla equipamentos de laboratório e ainda funciona em uma máquina específica.

Se a organização evita qualquer alteração porque ninguém entende bem o código e porque o ambiente de compilação é frágil, esse sistema provavelmente não está mais em evolução saudável. Ele pode estar apenas em serviço, aguardando substituição ou reengenharia.

O processo de evolução9.4

Toda evolução começa com alguma proposta de mudança. Essa proposta pode vir de um bug, de um novo requisito, de uma necessidade operacional ou de uma melhoria sugerida pela equipe. O ponto essencial é que a mudança não deve ser simplesmente implementada sem análise.

A Figura 9.4 mostra um fluxo típico. Uma solicitação de mudança passa por análise de impacto, planejamento de release, implementação e liberação do sistema. Esse processo tenta responder quatro perguntas práticas:

  1. o que precisa mudar?
  2. que partes do sistema serão afetadas?
  3. quanto custará implementar e testar essa mudança?
  4. em qual release ela deve entrar?

Análise de impacto9.4.1

A análise de impacto é a tentativa de 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.

Essa etapa é decisiva porque uma mudança pequena na tela pode esconder uma alteração grande no domínio. Uma mudança aparentemente localizada pode afetar banco de dados, regras de validação, relatórios e APIs externas.

Reflita

Quando um cliente pede "só adicionar um campo obrigatório no cadastro", que partes do sistema podem ser afetadas além da tela de cadastro?

Podem ser afetados o banco de dados, validações, importações, exportações, relatórios, testes automatizados, documentação, integrações, permissões e até regras de negócio que usam aquele cadastro.

Exemplo 5

Solicitação: tornar obrigatório o CPF do responsável financeiro no sistema acadêmico.

A mudança parece pequena, mas a análise de impacto pode revelar vários pontos:

  1. a tabela de responsáveis precisa aceitar e validar CPF;
  2. registros antigos podem não ter esse dado;
  3. a tela de cadastro precisa mudar;
  4. a API precisa rejeitar dados inválidos;
  5. relatórios financeiros podem passar a exibir o CPF;
  6. testes de cadastro e matrícula precisam ser atualizados;
  7. integrações externas podem depender do formato antigo.

O exemplo mostra por que manutenção profissional não é apenas "abrir o código e mexer". Primeiro é preciso entender o alcance da mudança.

Exemplo 6

Solicitação: corrigir cálculo de desconto em um sistema de e-commerce.

Se o desconto aparece no carrinho, no checkout, na nota fiscal, no relatório financeiro e na API de pedidos, corrigir apenas a primeira função encontrada pode deixar o sistema inconsistente.

A análise de impacto deve identificar onde a regra é aplicada, onde é duplicada e quais testes podem revelar regressões.

Correções emergenciais9.4.2

Sommerville também chama atenção para um caso perigoso: a correção emergencial. Às vezes, um defeito grave em produção precisa ser corrigido rapidamente. Nessa situação, a equipe pode pular parte do fluxo formal e aplicar uma solução viável no código.

Isso pode ser necessário, mas tem custo. Se a documentação, os requisitos e os testes não forem realinhados depois, o sistema envelhece mais rápido. A solução emergencial vira uma decisão permanente sem análise adequada.


Uma correção emergencial deve resolver o incidente, mas não deveria encerrar a mudança. Depois da emergência, a equipe precisa revisar a solução, atualizar documentação e reforçar testes.

As leis de Lehman e a dinâmica da evolução9.5

Lehman e Belady estudaram a evolução de sistemas de software de grande porte e propuseram leis que descrevem padrões observados ao longo do tempo. A ideia mais importante para esta aula é que sistemas usados no mundo real não ficam parados.

Sommerville destaca algumas leis particularmente úteis para raciocinar sobre manutenção:

Lei Ideia central
Mudança contínua Um programa usado em ambiente real precisa mudar ou se torna menos útil.
Aumento da complexidade Ao mudar, a estrutura tende a ficar mais complexa se não houver cuidado preventivo.
Conservação da familiaridade Mudanças incrementais tendem a permanecer limitadas para que a equipe consiga entender o sistema.
Crescimento contínuo A funcionalidade precisa crescer para manter a satisfação dos usuários.
Declínio de qualidade A qualidade cai se o sistema não for adaptado ao ambiente operacional.

Essas leis não devem ser lidas como fórmulas matemáticas rígidas. Elas funcionam melhor como alertas gerenciais e técnicos. Se uma equipe adiciona funcionalidade continuamente sem refatorar, testar e reorganizar, a complexidade tende a crescer.

Exemplo 7

Um sistema de atendimento começa simples. Depois recebe chat, histórico de contato, integração com WhatsApp, relatórios, automações e permissões especiais por setor.

Se cada mudança for adicionada no lugar mais rápido, sem reorganização, o sistema passa a ter regras duplicadas, condicionais espalhadas e dependências difíceis de entender. A funcionalidade cresceu, mas a manutenibilidade caiu.

Exemplo 8

Uma empresa decide lançar uma grande versão com muitas funcionalidades novas em um único release. Logo depois, aparecem vários defeitos, porque as mudanças interagiram de formas difíceis de prever.

Esse caso conversa com a ideia de que grandes incrementos aumentam risco. Muitas vezes, um release grande precisa ser seguido por releases menores focados em correção e estabilização.

Tipos de manutenção de software9.6

Sommerville organiza a manutenção em três tipos principais. A distinção é útil, mesmo que na prática os casos se misturem.

Tipo de manutenção Quando acontece Exemplo
Correção de defeitos Quando o sistema precisa ser alterado para corrigir erros encontrados em operação. Corrigir um cálculo de desconto que gera total incorreto no pedido.
Adaptação ao ambiente Quando o ambiente técnico muda e o sistema precisa continuar funcionando nele. Ajustar o sistema para uma nova versão do banco de dados, sistema operacional, biblioteca ou API externa.
Adição ou modificação de funcionalidade Quando os requisitos mudam por causa de novas necessidades do negócio ou dos usuários. Incluir renovação on-line em um sistema de biblioteca ou mudar regras de matrícula em um sistema acadêmico.

A manutenção não é apenas correção de bugs. No capítulo, Sommerville destaca que uma parte muito grande do esforço de manutenção vem de adaptar o sistema e adicionar ou modificar funcionalidades depois que ele já está em uso.

A Figura 9.7 é especialmente importante para desfazer um mito. A maior parte do esforço de manutenção não costuma estar na correção de defeitos. No exemplo apresentado por Sommerville, a maior fatia está na adição ou modificação de funcionalidade.

Por que manutenção custa caro9.6.1

Adicionar uma funcionalidade depois que o sistema está em operação costuma ser mais caro do que adicioná-la durante o desenvolvimento inicial. Isso acontece por vários motivos:

  1. a equipe original pode ter sido desmobilizada;
  2. a nova equipe precisa entender decisões antigas;
  3. a documentação pode estar incompleta ou desatualizada;
  4. o sistema pode ter estrutura degradada;
  5. os testes precisam proteger funcionalidades já existentes;
  6. dados reais precisam ser preservados;
  7. integrações externas podem ser afetadas.

Sommerville também destaca um problema organizacional: contratos de desenvolvimento e manutenção muitas vezes são separados. Isso reduz o incentivo para a equipe inicial investir em manutenibilidade, porque o custo da má estrutura será pago por outra equipe ou por outro orçamento.

Exemplo 9

Durante o desenvolvimento inicial, uma equipe copia a mesma regra de cálculo de mensalidade em três módulos para entregar mais rápido.

Meses depois, a regra muda. A equipe de manutenção precisa descobrir todas as cópias, alterar cada uma, testar cada fluxo e torcer para não ter esquecido nenhuma variação.

O custo não veio apenas da regra nova. Ele veio da estrutura anterior, que dificultou a mudança.

Exemplo 10

Um sistema legado foi escrito para uma versão antiga de banco de dados. A organização precisa atualizar o servidor por razões de segurança.

Mesmo sem novos requisitos de negócio, a equipe precisa adaptar queries, drivers, scripts de implantação e testes. Esse é um caso típico de manutenção por adaptação ambiental.

Previsão de manutenção9.7

Gerentes tentam prever manutenção porque mudanças inesperadas podem consumir orçamento e atrasar entregas. A previsão envolve estimar quais partes do sistema provavelmente mudarão, quais serão caras de manter e quanto esforço será necessário em determinado período.

Sommerville sugere observar tanto o ambiente quanto o próprio sistema. Partes mais expostas a mudança tendem a ter mais interfaces, requisitos voláteis ou forte dependência de processos de negócio instáveis.

Algumas métricas úteis são:

  1. número de solicitações de manutenção corretiva;
  2. tempo médio de análise de impacto;
  3. tempo médio para implementar uma solicitação de mudança;
  4. número de solicitações de mudança pendentes;
  5. complexidade de componentes críticos.

Métrica não substitui julgamento técnico. Ela ajuda a enxergar tendência. Se o tempo médio de análise de impacto aumenta, talvez o sistema esteja ficando mais acoplado e difícil de compreender.

Exemplo 11

Uma equipe percebe que mudanças simples no módulo financeiro levavam dois dias no ano passado e agora levam duas semanas.

Ao investigar, descobre que o módulo acumulou regras especiais, integrações sem testes e dependências diretas com relatórios. A métrica não explicou tudo sozinha, mas apontou que a manutenibilidade estava piorando.

Exemplo 12

Outro sistema recebe poucas solicitações de mudança, mas cada solicitação afeta muitas telas e serviços.

Nesse caso, o problema não é volume de demandas. O problema pode ser acoplamento. Uma mudança pequena no domínio se espalha porque as responsabilidades estão mal separadas.

Reengenharia de software9.8

Quando um sistema legado ainda tem valor, mas se tornou difícil de entender e modificar, uma opção é aplicar reengenharia. O objetivo é melhorar sua estrutura, documentação e inteligibilidade sem mudar sua funcionalidade essencial.

A Figura 9.10 apresenta um processo geral de reengenharia. Ele pode envolver tradução de código-fonte, engenharia reversa, melhoria da estrutura do programa, modularização e reengenharia de dados.

Reengenharia não é reescrita total9.8.1

Reengenharia e substituição completa são decisões diferentes. 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, pode repetir erros de especificação e pode atrasar a entrega do novo sistema.

Sommerville destaca dois benefícios da reengenharia em relação à substituição:

  1. risco reduzido, porque o sistema existente já incorpora conhecimento operacional;
  2. custo reduzido, porque melhorar o sistema pode ser mais barato do que reconstruí-lo completamente.

Mas há limites. Reengenharia não transforma magicamente um sistema antigo em um sistema moderno perfeito. Grandes mudanças arquiteturais e reorganizações profundas de dados continuam sendo caras e difíceis.

Exemplo 13

Uma empresa tem um sistema COBOL que calcula benefícios com regras acumuladas por décadas.

Reescrever tudo em uma linguagem moderna pode parecer o caminho ideal, mas o risco é enorme se as regras reais não estiverem completamente documentadas. Uma estratégia de reengenharia pode começar pela engenharia reversa, documentação das regras, criação de testes de regressão e modularização gradual.

Exemplo 14

Um sistema antigo usa vários arquivos duplicados para armazenar dados de clientes. Antes de criar novas integrações, a equipe decide fazer reengenharia de dados.

Ela identifica duplicidades, corrige inconsistências, define um modelo de dados mais claro e cria scripts de migração. A funcionalidade visível pode mudar pouco, mas a capacidade de evolução aumenta.

Refatoração como manutenção preventiva9.9

Refatoração é o processo de melhorar a estrutura interna do código sem alterar seu comportamento observável. Ela não adiciona funcionalidade. Ela torna o código mais claro, menos duplicado, menos acoplado ou mais fácil de modificar.

Sommerville apresenta a refatoração como uma forma de manutenção preventiva. A ideia é simples: se a estrutura degrada com mudanças sucessivas, então a equipe precisa investir continuamente em pequenas melhorias estruturais para evitar que o custo futuro exploda.

Essa ideia conversa diretamente com a aula de testes. Refatorar com segurança depende de testes de regressão. Se os testes antes passavam e continuam passando depois da refatoração, a equipe ganha confiança de que melhorou a estrutura sem mudar o comportamento.

Reengenharia e refatoração não são a mesma coisa9.9.1

Refatoração Reengenharia
Processo contínuo e incremental. Processo mais amplo, geralmente aplicado a sistemas legados.
Atua em pequenas melhorias de estrutura. Pode envolver código, dados, documentação, linguagem e arquitetura.
Normalmente ocorre durante desenvolvimento e evolução. Normalmente ocorre quando a manutenção já ficou cara ou arriscada.
Depende fortemente de testes de regressão. Pode exigir engenharia reversa, migração e ferramentas especializadas.
Pergunta típica Exemplo
"Como deixo este código mais fácil de mudar sem alterar comportamento?" Refatoração.
"Como modernizo este sistema legado para que ele volte a ser mantível?" Reengenharia.

Maus cheiros de código9.9.2

Fowler, citado por Sommerville, usa a expressão maus cheiros para indicar sinais de que o código pode precisar de refatoração. Alguns exemplos são:

  1. código duplicado;
  2. métodos longos;
  3. condicionais complexas ou repetidas;
  4. grupos de dados que aparecem juntos em vários lugares;
  5. generalidade especulativa, quando a equipe cria abstrações para um futuro que talvez nunca chegue.
Exemplo 15

Antes da refatoração, duas funções duplicam a mesma regra de frete.

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


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

Depois da refatoração, a regra fica em um único lugar.

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


def calcular_total_carrinho(valor):
    return valor + calcular_frete(valor)


def simular_pagamento(valor):
    return {"total": valor + calcular_frete(valor)}

O comportamento esperado permanece o mesmo. O ganho está na manutenção futura. Se a regra mudar, há um lugar principal para alterar.

Exemplo 16

Antes da refatoração, um método acumula validação, cálculo e montagem de resposta.

def fechar_pedido(cliente, itens):
    if cliente is None:
        raise ValueError("cliente obrigatorio")
    if len(itens) == 0:
        raise ValueError("pedido vazio")

    total = 0
    for item in itens:
        total += item["preco"] * item["quantidade"]

    if total >= 200:
        frete = 0
    else:
        frete = 15

    return {
        "cliente": cliente["nome"],
        "total": total + frete,
        "frete": frete,
    }

Depois, a estrutura separa responsabilidades.

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


def calcular_subtotal(itens):
    total = 0
    for item in itens:
        total += item["preco"] * item["quantidade"]
    return total


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


def fechar_pedido(cliente, itens):
    validar_pedido(cliente, itens)
    subtotal = calcular_subtotal(itens)
    frete = calcular_frete(subtotal)

    return {
        "cliente": cliente["nome"],
        "total": subtotal + frete,
        "frete": frete,
    }

Esse exemplo mostra um ponto importante. Refatorar não é "embelezar" código. É reduzir o custo mental de entender e alterar o sistema.


Refatoração sem testes aumenta risco. Se você não consegue verificar o comportamento antes e depois, pode estar mudando a estrutura e introduzindo defeitos sem perceber.

Sistemas legados e decisões estratégicas9.10

Sistemas legados são sistemas antigos que continuam importantes para a organização. O problema não é simplesmente a idade. Um sistema antigo pode ser estável, bem documentado e barato de manter. O problema aparece quando ele tem alto valor de negócio, mas baixa qualidade técnica, dependências obsoletas ou manutenção cara.

Sommerville propõe avaliar sistemas legados por duas perspectivas:

  1. valor de negócio, que indica quanto o sistema contribui para processos importantes;
  2. qualidade do sistema, que inclui qualidade da aplicação e do ambiente técnico.

A Figura 9.12 organiza a decisão em uma matriz. O cruzamento entre valor de negócio e qualidade técnica ajuda a escolher a estratégia.

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

O que avaliar em um legado9.10.1

Para avaliar o valor de negócio, algumas perguntas são fundamentais:

  1. o sistema é usado por muitas pessoas ou em momentos críticos?
  2. ele apoia processos centrais do negócio?
  3. suas saídas são importantes para decisões ou operações?
  4. falhas nele afetam clientes, receita, segurança ou obrigações legais?

Para avaliar a qualidade técnica, observe fatores como:

  1. inteligibilidade do código;
  2. documentação disponível;
  3. qualidade e consistência dos dados;
  4. desempenho;
  5. linguagem de programação e ferramentas disponíveis;
  6. gerenciamento de configuração;
  7. dados de teste e testes de regressão;
  8. disponibilidade de pessoas com conhecimento no sistema.
Exemplo 17

Um sistema antigo de emissão de boletos é usado diariamente e qualquer falha afeta diretamente o caixa da empresa. Porém, o código é difícil de entender e depende de uma biblioteca sem suporte.

Esse sistema tem alto valor de negócio e baixa qualidade técnica. A decisão provável é investir em reestruturação, reengenharia ou substituição gradual, não simplesmente descartá-lo.

Exemplo 18

Um sistema antigo de relatórios gerenciais ainda funciona bem, mas quase ninguém usa seus relatórios porque a empresa adotou uma plataforma de BI.

Mesmo com boa qualidade técnica, seu valor de negócio pode ser baixo. Nesse caso, talvez a melhor decisão seja manter apenas enquanto o custo for mínimo ou planejar descarte.

O papel profissional da manutenibilidade9.11

O capítulo termina com uma provocação ética importante. 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.

Essa responsabilidade existe porque decisões internas de projeto afetam custos futuros, riscos operacionais e a capacidade da organização de responder a mudanças. Código difícil de manter pode funcionar hoje, mas criar uma dívida que outra equipe, outro orçamento ou os próprios usuários pagarão depois.


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.

Questões9.12

1. Explique por que um sistema usado em ambiente real precisa mudar ao longo do tempo, mesmo que tenha sido entregue corretamente.

2. Diferencie correção de defeitos, adaptação ambiental e adição de funcionalidade. Dê um exemplo para cada tipo.

3. Uma equipe recebeu a solicitação "adicionar CPF obrigatório ao cadastro de responsável financeiro". Liste pelo menos cinco impactos possíveis que deveriam ser analisados antes da implementação.

4. Assinale a alternativa correta sobre refatoração.

  • A) Refatoração adiciona novas funcionalidades ao sistema.
  • B) Refatoração melhora a estrutura interna sem mudar o comportamento observável.
  • C) Refatoração substitui completamente a necessidade de testes.
  • D) Refatoração só pode ser feita em sistemas orientados a objetos.

5. Explique a diferença entre refatoração e reengenharia de software.

6. Um sistema legado tem alto valor de negócio, mas baixa qualidade técnica. Qual estratégia tende a ser mais adequada segundo a matriz discutida na aula? Justifique.

7. Por que uma correção emergencial pode aumentar o custo de manutenção no futuro?

8. Observe o código abaixo e indique um mau cheiro de código. Em seguida, proponha uma refatoração simples.

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


def resumo_compra(valor):
    if valor >= 200:
        frete = 0
    else:
        frete = 15
    return f"Total: {valor + frete}"
Gabarito

1. Porque o ambiente muda. Regras de negócio, usuários, plataformas, integrações, leis e defeitos encontrados em operação podem exigir mudanças. Se o sistema não acompanha essas mudanças, torna-se progressivamente menos útil.

2. Correção de defeitos corrige erros, como cálculo incorreto de desconto. Adaptação ambiental ajusta o sistema a mudanças de plataforma, como nova versão do banco de dados. Adição de funcionalidade incorpora ou modifica requisitos, como permitir renovação de empréstimo pelo aplicativo.

3. Banco de dados, validações, telas, API, relatórios, dados antigos, permissões, integrações externas, testes automatizados e documentação.

4. B.

5. Refatoração é melhoria contínua e geralmente localizada da estrutura interna do código sem alterar comportamento. Reengenharia é um processo mais amplo aplicado com frequência a sistemas legados, podendo envolver documentação, engenharia reversa, modularização, dados, linguagem e arquitetura.

6. A estratégia tende a ser reestruturar, aplicar reengenharia ou substituir gradualmente se houver alternativa viável. Como o valor de negócio é alto, descartar diretamente seria arriscado. Como a qualidade técnica é baixa, manter sem intervenção tende a aumentar custos e riscos.

7. Porque a solução rápida pode não ser a melhor estrutura, pode deixar documentação e requisitos inconsistentes e pode criar código difícil de entender. Se a mudança não for revisada depois, futuras alterações ficam mais caras.

8. O mau cheiro é código duplicado. Uma refatoração simples é extrair a regra de frete para uma função única.

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


def total_compra(valor):
    return valor + calcular_frete(valor)


def resumo_compra(valor):
    return f"Total: {valor + calcular_frete(valor)}"

Próximos passos9.13


Ainda não há próxima aula cadastrada nesta sequência.