Fundamentos de Manutenção de Software
1 Introdução 🔗
Programmers are constantly in maintenance mode. ― David Thomas and Andrew Hunt (The Pragmatic Programmer, 1999)
Este capítulo começa com uma apresentação sobre a importância do tema do livro (Seção 1.1) e então descrevemos os principais tipos de Manutenção de Software (Seção 1.2). Em seguida, enfatizamos a relevância da área de Compreensão de Código, já que todo programa precisa ser devidamente entendido antes de ser mantido (Seção 1.3). Na sequência, apresentamos um breve histórico da área, abordando tópicos como as Leis de Evolução de Software ou Leis de Lehman (Seção 1.4). Depois, definimos o conceito de manutenibilidade e destacamos sua importância (Seção 1.5). Ainda neste primeiro capítulo, discutimos o papel de Modelos de Linguagem (LLMs) em tarefas de Compreensão, Manutenção e Evolução de Software (Seção 1.6). Por fim, apresentamos o conteúdo dos capítulos seguintes (Seção 1.7), para que o leitor tenha uma visão geral do que será estudado.
1.1 Motivação 🔗
A Computação possui diversas áreas, como Engenharia de Software, Bancos de Dados, Inteligência Artificial, Computação Gráfica, entre outras. Por sua vez, essas áreas contam com subáreas. No caso específico de Engenharia de Software, existe um documento chamado Software Engineering Body of Knowledge (SWEBOK, link) que define suas principais subáreas. Esse documento é elaborado por cientistas e profissionais convidados por uma organização científica chamada IEEE Computer Society. A versão mais recente do SWEBOK foi lançada em 2024 e, sem surpresa, Manutenção de Software aparece como uma das subáreas da Engenharia de Software, ao lado de Processos, Requisitos, Design, Arquitetura, Testes, entre outras.
Na verdade, a importância de Manutenção de Software não é uma surpresa, pois uma parte cada vez maior do mundo moderno é digital — ou seja, movida por software. Isso inclui serviços bancários, comércio, entretenimento, mídia, notícias, jogos, agendamento de transportes e hotéis, pedidos de comida, educação, livros, mapas, entre outros. Por exemplo, em seu celular, você certamente possui aplicativos que oferecem esses serviços. No entanto, o que queremos destacar neste momento é o seguinte: há uma quantidade crescente de software impulsionando empresas e organizações no mundo inteiro, e esse software precisa ser desenvolvido, mas também compreendido, mantido e evoluído.
Assim, se você for um desenvolvedor de software, é provável que passe a maior parte do seu dia entendendo, modificando, corrigindo, adaptando e evoluindo sistemas que já estão em funcionamento e que foram implementados por outras pessoas, conforme sugerido também pela observação de David Thomas e Andrew Hunt, com a qual abrimos o capítulo.
1.2 Tipos de Manutenção 🔗
Existem cinco tipos de manutenção de software:
Manutenção Corretiva: ocorre quando é necessário corrigir um bug em um sistema reportado por seus usuários. Esse é o tipo de manutenção mais comum, e mesmo alunos de cursos de Introdução a Programação já tiveram esse tipo de experiência.
Manutenção Preventiva: este tipo de manutenção é realizado quando se busca por bugs latentes, ou seja, que ainda não foram reportados por usuários e, portanto, não causaram falhas ou danos. Trata-se de uma manutenção análoga àquela feita por alguém que leva o carro à oficina mesmo que ele não tenha ainda apresentado problemas.
Manutenção Adaptativa: ocorre quando é necessário adaptar um sistema a uma nova regra de negócio ou tecnologia. Por exemplo, se você trabalha em um banco, pode ficar responsável, em algum momento, por adaptar um sistema a uma nova norma do Banco Central. Como um outro exemplo de manutenção adaptativa, você pode integrar um time encarregado de migrar a linguagem de programação usada no aplicativo do banco. Por exemplo, o aplicativo é implementado em Java, mas o banco pretende migrar para Kotlin.
Refatoração: ocorre quando você percebe que determinada parte do código não está implementada da melhor forma. Mais especificamente, trata-se de um código com algum problema que vai dificultar manutenções futuras. Por exemplo, uma função pode ser muito complexa, com centenas de linhas. Então, dizemos que ela deve ser refatorada, o que implica dividi-la em funções menores e mais fáceis de compreender. No entanto, neste livro, não vamos incluir um capítulo sobre refatoração porque, apesar de ser uma manutenção muito importante, ela já foi tratada em nosso livro anterior (Engenharia de Software Moderna).
Manutenção Evolutiva: ocorre quando implementamos novas funções e recursos em um sistema existente, ou seja, quando evoluímos seu conjunto de funcionalidades. Por exemplo, um banco está sempre procurando oferecer novos serviços para seus clientes, como PIX, investimentos em criptomoedas, “caixinhas” para guardar dinheiro, etc. O sistema desse banco não nasceu com tais serviços. Na verdade, ele passou por manutenções evolutivas, realizadas para implementar funcionalidades que vão manter o banco competitivo no mercado.
Nota: A classificação e os tipos de manutenção podem variar conforme o autor. Por exemplo, uma classificação amplamente utilizada no passado foi proposta por Lientz & Swanson, em 1978 (link). No entanto, por ser mais antiga, ela não inclui refatorações — um tipo de manutenção que hoje é essencial para garantir a longevidade de sistemas de software.
Uma diferença fundamental entre produtos físicos e produtos digitais — como software — é que, nestes últimos, é mais fácil realizar manutenções evolutivas. Imagine, por exemplo, um computador. É sempre possível realizar alguma manutenção evolutiva nele, como acrescentar mais memória ou trocar a CPU por uma mais potente. Porém, existe um limite para isso e, na prática, somos forçados a trocar de computador após alguns anos. Por outro lado, sistemas de software costumam durar muito mais tempo do que produtos de hardware. Para dar alguns exemplos, o sistema operacional Linux foi criado em 1991, a primeira versão do Excel para Windows foi lançada em 1987 e até hoje usamos sistemas bancários cujo desenvolvimento teve início na década de 1980. Esses sistemas, no entanto, não ficaram congelados no tempo; ao contrário, eles foram sendo continuamente evoluídos e passaram a incorporar diversas novas funcionalidades.
1.3 Compreensão de Código 🔗
Para realizar qualquer manutenção com sucesso, você precisa antes compreender o código que será modificado. Costuma-se dizer que o código é escrito uma vez, mas lido centenas de vezes pelos diferentes desenvolvedores que irão mantê-lo no futuro, realizando os tipos de manutenção mencionados anteriormente. Por isso, é fundamental escrever código que possa ser facilmente lido e entendido por outros desenvolvedores. Compreensão de Código é o nome dado ao conjunto de práticas e convenções usadas para escrever código que possa ser facilmente lido, entendido e modificado.
Literatura Científica: Em 2017, pesquisadores de universidades de quatro países publicaram um estudo que mediu o percentual de tempo que desenvolvedores dedicam a atividades de compreensão de código (link). Para isso, utilizaram uma ferramenta que coleta todas as interações de um desenvolvedor com IDEs e outras aplicações durante seu dia de trabalho. A ferramenta foi instalada nas máquinas de 78 desenvolvedores que atuavam em sete projetos de duas empresas chinesas. Os pesquisadores concluíram que, em média, os desenvolvedores passaram 58% do tempo efetivo de trabalho em atividades de compreensão de código. Portanto, esses resultados reforçam nosso argumento principal nesta seção: para que atividades de manutenção sejam realizadas de forma produtiva, o código precisa primeiro ser lido e entendido.
1.4 Um Pouco de História 🔗
Manutenção, especialmente a corretiva, sempre foi uma preocupação dos desenvolvedores de software. Por exemplo, uma das primeiras pessoas a usar o termo bug como sinônimo de defeito também na área de software foi a cientista da computação Grace Hopper. Em 1947, enquanto trabalhava na Universidade de Harvard, ela observou que os programas executados por um dos grandes computadores da época não estavam funcionando corretamente. Ao investigar, ela descobriu que o motivo era uma mariposa que havia entrado em um dos relés eletromecânicos do computador. Conforme pode ser conferido na próxima figura, Hopper fez então uma anotação bem-humorada no diário de sua equipe: primeiro caso real de um bug encontrado em um dos nossos computadores.
Desde então, diversos bugs ficaram famosos por causarem grandes prejuízos e, por isso mesmo, foram estudados em detalhes. Em 1996, um foguete francês, chamado Ariane 5, explodiu devido a um overflow na conversão de um valor do tipo float para um valor inteiro. Esse bug resultou na explosão do foguete e em um prejuízo de centenas de milhões de dólares. Em meados da década de 1980, uma máquina de radioterapia chamada Therac-25 foi lançada com bugs de concorrência, que fizeram com que pacientes recebessem doses excessivas de radiação. Infelizmente, esses bugs levaram à morte de seis pacientes.
Mais recentemente, em julho de 2024, um bug em um sistema de segurança da empresa CrowdStrike causou uma pane em oito milhões de máquinas Windows, paralisando aeroportos, serviços bancários, empresas de mídia, etc. O bug ocorreu na função do programa que faz a leitura dos arquivos com as regras de segurança monitoradas pelo sistema. Curiosamente, o código do sistema era distribuído de forma gradual para as máquinas clientes, permitindo uma rápida reversão para a versão anterior em caso de bugs críticos. Porém, o arquivo de configuração — que não faz parte do código executável — era disponibilizado de uma só vez para todas as máquinas clientes da CrowdStrike. Por esse motivo, o bug rapidamente causou uma “tela azul” em milhões de máquinas.
Um exemplo conhecido de manutenção preventiva ocorreu na virada do último milênio, de 1999 para 2000. Na época, diversos sistemas armazenavam os valores de datas com dois dígitos, ou seja, no formato DD-MM-AA. Muitas empresas ficaram receosas de que, na virada do milênio, certas operações com datas pudessem retornar valores incorretos. Por exemplo, uma subtração 00 - 99 poderia gerar um resultado inesperado. Diante disso, formaram grupos de trabalho para realizar manutenções preventivas e converter todas as datas para o formato DD-MM-AAAA. Assim, os possíveis bugs foram prevenidos, e pouquíssimos sistemas apresentaram problemas na virada do milênio.
1.4.1 Leis de Lehman 🔗
Meir Lehman foi um pesquisador da IBM e também professor do Imperial College na Inglaterra. Nas décadas de 1970 e 1980, ele investigou diversos desafios inerentes à evolução de sistemas de software, tendo publicado vários artigos nos quais propôs, discutiu e deu exemplos do que ficou conhecido como Leis da Evolução de Software ou, simplesmente, Leis de Lehman.
Em essência, as Leis de Lehman enunciam propriedades que, embora hoje sejam amplamente conhecidas, eram menos óbvias na época. No seu conjunto, elas recomendam que sistemas de software devem sempre passar por manutenções adaptativas e evolutivas, de forma que continuem satisfazendo seus usuários. Por outro lado, essas manutenções têm um custo, pois aumentam a complexidade dos sistemas, que crescem de forma contínua e, paralelamente, sofrem um declínio na sua qualidade interna. Ou seja, com o passar dos anos, a compreensão do código e a realização de novas manutenções tornam-se mais difíceis.
De forma interessante, na década de 1990, a prática de refatoração foi proposta exatamente para mitigar o declínio na qualidade do código de um sistema, que ocorre quando ele é modificado ao longo dos anos por desenvolvedores diferentes. O conceito surgiu em uma tese de doutorado, defendida por William Opdyke em 1992, na Universidade de Illinois, EUA (link). Em seguida, em 1999, refatoração foi incluída entre as práticas de programação preconizadas por Extreme Programming (XP). Em 2000, Martin Fowler publicou seu livro sobre o assunto, o que ajudou também a popularizar a adoção da prática. Como afirmamos, a ideia de refatoração é simples: periodicamente, precisamos reorganizar o código de um sistema, tornando-o mais legível e também melhorando sua estrutura. Porém, após uma refatoração, o comportamento do sistema deve ser preservado; ou seja, não podemos implementar novas funcionalidades e nem mesmo corrigir bugs.
1.5 Manutenibilidade 🔗
Sistemas de software podem levar um ou dois anos para serem construídos, mas depois podem ser mantidos por décadas. Por esse motivo, os custos de manutenção frequentemente representam até 90% do custo total de um sistema ao longo de sua vida útil. Consequentemente, toda empresa que desenvolve ou contrata o desenvolvimento de um software deve se preocupar com sua manutenibilidade, isto é, com a facilidade de compreender e manter o código de um sistema.
Manutenibilidade é um requisito não-funcional, assim como desempenho, escalabilidade, usabilidade, segurança, privacidade, confiabilidade, portabilidade, entre outros. Existe uma norma ISO, chamada ISO/IEC 25010, que define atributos de qualidade para produtos de software. Você pode pensar nessa norma como uma espécie de ISO 9001 voltada para a qualidade de software. Sem surpresas, manutenibilidade é uma das características que devem ser consideradas para avaliar a qualidade de um produto de software, segundo a ISO 25010. A norma também define algumas subcaracterísticas que tornam a manutenção de um sistema mais fácil, incluindo:
Modularidade: O sistema possui módulos bem definidos que se comunicam apenas por meio de interfaces ou APIs?
Reusabilidade: É fácil reutilizar as funções e classes do sistema?
Analisabilidade: É fácil compreender as funções e classes do sistema?
Facilidade de mudanças: É fácil modificar as funções e classes do sistema?
Testabilidade: É fácil testar as funções e classes do sistema?
Essas características deixam claro que manutenibilidade abrange
aspectos variados, incluindo não apenas a compreensão e modificação do
código, mas também elementos de design, arquitetura e testes. Por
exemplo, se o design e a arquitetura de um sistema forem uma big ball
of mud
, sua manutenção será difícil, mesmo quando as mudanças
requeridas são simples. Já a ausência de testes aumenta os riscos de
regressões e, portanto, torna as manutenções menos seguras.
1.6 Papel dos Modelos de Linguagens 🔗
As pesquisas sobre o uso de Inteligência Artificial (IA) em tarefas de Compreensão, Manutenção e Evolução de Software não são uma novidade. Desde a década de 1990 (ou até mesmo antes) são realizadas pesquisas sobre recomendação de refatorações, remodularização automática de sistemas, detecção de code smells e correção de bugs, dentre outras.
Porém, a partir de 2020, surgiu uma inovação relevante na área de IA, representada por Modelos de Linguagem de Grande Escala (LLM). Esses modelos surpreenderam a todos por apresentarem uma capacidade de resolução de problemas muito superior às ferramentas de IA que existiam até então. Para tanto, beneficiaram-se de avanços em algoritmos de IA e de uma fase de treinamento utilizando uma enorme quantidade de documentos disponíveis na Web, incluindo código.
Uma das principais aplicações de modelos de linguagem está na área de Engenharia de Software. Por exemplo, esses modelos apresentam resultados muito bons quando usados para gerar código. Logo, não é surpresa que tenham surgido versões customizadas de LLMs para a implementação de sistemas, por exemplo, na forma de agentes.
Modelos de linguagem também são úteis em atividades de Compreensão, Manutenção e Evolução de Software. Por exemplo, podem ser usados para correção de bugs, recomendação de refatorações, revisão de código, geração de documentação, etc.
No entanto, quaisquer resultados produzidos por modelos de linguagem precisam ser revisados por humanos, pois são sujeitos a erros e também a alucinações, isto é, muitas vezes esses modelos tomam caminhos errados e geram respostas sem nexo.
Portanto, resumindo, nossa visão sobre o uso de IA em Engenharia de Software é a seguinte:
Modelos de Linguagem, de fato, aumentam a produtividade dos desenvolvedores, principalmente em atividades de codificação.
No entanto, as decisões principais de um projeto de software continuam sendo de responsabilidade humana, pois esses modelos, por natureza, são sujeitos a erros. Por exemplo, se um bug em um sistema de cartões de crédito causar um prejuízo de bilhões, a
culpa
não será do modelo, mas daqueles responsáveis pelo seu uso.Por isso, domínio dos fundamentos de Engenharia de Software continua sendo importante, incluindo aqueles relacionados com Compreensão, Manutenção e Evolução de Software.
Consequentemente, as práticas para escrita de código limpo, bem documentado, flexível a mudanças e com dívida técnica controlada, tal como vamos estudar nos próximos capítulos, permanecem importantes, por dois motivos principais:
Existe uma grande chance de que código gerado por LLMs, em algum momento, terá que ser lido e entendido por humanos. Por exemplo, quando uma LLM não conseguir corrigir um bug. Logo, é importante que esse código não seja um grande monolito implementado de forma totalmente cifrada.
Existem evidências de que LLMs funcionam melhor em código de qualidade. Ou seja, é mais fácil também para uma LLM corrigir um bug em uma função com 20 linhas do que em uma função com 10 KLOC (inclusive porque essa última requer um contexto maior; e tamanho do contexto é uma variável chave para o desempenho de LLMs).
1.7 O que Vamos Estudar? 🔗
O restante deste livro possui oito capítulos:
No Capítulo 2, vamos estudar algumas práticas e recomendações para escrita de código legível. Por exemplo, vamos comentar sobre guias de estilo e de nomes, sobre o uso de linters e formatadores e sobre a importância de investir tempo na escolha de nomes legíveis e consistentes ao longo de todo o código. Em seguida, vamos abordar a importância de escrever funções de fácil entendimento, as quais devem ser coesas e possuir baixo acoplamento. Terminamos o capítulo recomendando boas práticas para tratamento de exceções.
No entanto, como código é uma notação operacional e de baixo nível, nem todo código é auto-explicativo, principalmente para aqueles que não participaram da sua escrita. Por isso, no Capítulo 3, vamos estudar boas práticas para a escrita de comentários de código. Vamos começar tratando de ferramentas para geração de documentação a partir de comentários, como a ferramenta Javadoc. Em seguida, apresentaremos dois tipos de comentários: comentários públicos e comentários privados. Comentários públicos fazem parte da documentação de referência de uma biblioteca ou subsistema e, portanto, documentam elementos de código que serão usados por terceiros. Já comentários privados explicam partes internas de um módulo e, logo, serão lidos por desenvolvedores que vão manter esse módulo no futuro. Ainda no Capítulo 3, tratamos de anti-padrões de comentários, isto é, tipos de comentários que devem ser evitados. E terminamos com uma seção sobre documentação de APIs Web, especificamente de APIs REST.
Software possui esse nome porque é mais fácil de modificar, quando comparado a hardware e a outros produtos físicos. Por isso, desenvolvedores de software devem se acostumar com mudanças. No Capítulo 4, apresentamos boas práticas para escrever código flexível a mudanças. Iniciamos discutindo uma propriedade central em projeto de software: ocultamento de informação (information hiding). A ideia é que cada módulo de software deve ocultar os detalhes de sua implementação que são sujeitos a mudanças, isto é, não deve expô-los em sua interface. Em seguida, tratamos de um evento indesejado, mas que acontece: breaking changes. São mudanças na interface de um módulo que quebram seus clientes, exigindo que eles sejam modificados e adaptados. Então, discutimos boas práticas para lidar com breaking changes, como depreciação, versionamento semântico e documentação. Para encerrar o capítulo, apresentamos práticas para escrever código aberto a customizações, das mais simples, como o uso de parâmetros de funções, às mais elaboradas, como injeção e inversão de dependências.
No Capítulo 5, começaremos a tratar de manutenção corretiva. Nele, comentaremos que não podemos assumir que sistemas de software serão perfeitos; ou seja, bugs vão ocorrer, mesmo que a gente procure minimizá-los. Após uma Introdução, vamos tratar dos principais tipos de bugs, como bugs de memória, de concorrência, de segurança e de entendimento de requisitos. Em seguida, vamos comentar sobre ferramentas de detecção de bugs, com ênfase em ferramentas de análise estática, que são bastante populares atualmente entre desenvolvedores. Depois, vamos tratar dos sistemas de rastreamento de bugs, tais como Jira, Bugzilla e os oferecidos por plataformas como GitHub e GitLab. Vamos então apresentar boas práticas para o preenchimento de relatórios de bugs. Por fim, vamos falar do ciclo de vida dos bugs, cujo entendimento nos ajuda a adotar um fluxo de trabalho mais padronizado e produtivo para correção de bugs.
Após estudar sobre diversos aspectos de bugs, vamos avançar e, no
Capítulo 6, trataremos de como corrigi-los. Em
manutenção de software, chamamos de depuração as atividades realizadas
com o objetivo de reproduzir, localizar, identificar as causas e
corrigir bugs. Vamos estudar sobre cada uma dessas atividades, bem como
descrever os objetivos e desafios inerentes a cada uma delas. Por outro
lado, depuração também possui um aspecto psicológico, que vamos comentar
neste capítulo. Por exemplo, todos já devemos ter ficado horas depurando
um bug, sem sucesso. Então, após uma pausa ou mesmo depois de uma noite
bem dormida, conseguimos achar o bug em minutos. Na sequência do
capítulo, vamos descrever os principais recursos, vantagens e
desvantagens de depuradores. Embora não sejam ferramentas obrigatórias,
eles podem contribuir de forma relevante para o sucesso de atividades de
depuração. Para concluir o capítulo, trataremos de dois temas: o emprego
de comandos assert também em código de produção e, por fim,
o uso de logging. Em relação a logging, faremos uma discussão mais
detalhada, incluindo tópicos como níveis de logging e recomendações de
boas práticas.
No Capítulo 7 vamos tratar de um conceito que se
tornou muito popular: dívida técnica. A ideia do conceito é criar uma
metáfora para representar um dilema frequente em organizações que
desenvolvem software: como combinar qualidade do código com velocidade e
pressão por entregas. A solução
então é a seguinte: podemos
privilegiar entregas, se for necessário, mas ao custo de uma dívida
técnica que mais cedo ou mais tarde vai cobrar juros
, na forma de
um código mais difícil de manter, mais sujeito a bugs, regressões, etc.
Após apresentar a metáfora, vamos descrever os principais tipos de
dívida técnica: design e arquitetura, requisitos, implementação, testes
e implantação. Em seguida, vamos lembrar que dívida técnica pode ser
tanto intencional quanto não planejada. Depois, discutiremos formas de
documentar, gerenciar e priorizar essa dívida. Por fim, abordaremos duas
outras metáforas que também já foram adaptadas para o contexto de
manutenção de software: a Teoria das Janelas Quebradas e a Regra dos
Escoteiros.
No Capítulo 8, mudamos o foco para sistemas legados, isto é, sistemas antigos que continuam em operação e apoiando processos críticos de diversas organizações. Inicialmente, discutimos as principais características desses sistemas, destacando que, embora usem tecnologias antigas, eles incluem conhecimento importante sobre o domínio do negócio e, por isso, não podem simplesmente ser descartados. Em seguida, apresentamos um conjunto de técnicas que auxiliam na manutenção de sistemas legados. Entre elas estão a melhoria de documentação, limpeza e organização do código, criação de testes automatizados e o uso de estratégias que permitem evoluir o sistema com segurança, como sprouts, wrappers, branch by abstraction, dark launch e execução paralela. Na sequência, discutimos estratégias para descontinuação gradual de sistemas legados. Em vez de uma substituição abrupta, mostramos que a abordagem mais recomendada consiste em migrar funcionalidades aos poucos para novos serviços, seguindo um padrão conhecido como Strangler Fig. Por fim, analisamos um conjunto de decisões arquiteturais importantes ao extrair serviços de um legado, incluindo quando reescrever ou reutilizar código existente, como delimitar o serviço a ser extraído, quais refatorações podem ser necessárias para preparar o legado, quais modelos de comunicação distribuída podem ser adotados e quais estratégias podem ser usadas para migrar os dados entre o sistema antigo e o novo serviço.
(demais capítulos em breve)
Bibliografia 🔗
Marco Tulio Valente. Engenharia de Software Moderna: Princípios e Práticas para Desenvolvimento de Software com Produtividade, 2020.
Meir M. Lehman, Juan F. Ramil, Paul Wernick, Dewayne E. Perry, Wladyslaw M. Turski: Metrics and Laws of Software Evolution — The Nineties View. 4th IEEE International Software Metrics Symposium (METRICS), 1997.
International Organization for Standardization, ISO/IEC 25002:2024 — Systems and software engineering — Systems and Software Quality Requirements and Evaluation (SQuaRE) — Quality model overview and usage, 2024.
Exercícios 🔗
1. Pensando em um prédio, o que seria uma manutenção: (a) evolutiva; (b) adaptativa; (c) corretiva; (d) preventiva; (e) e uma refatoração.
2. Como você classificaria uma manutenção para melhorar o desempenho em tempo de execução de uma certa funcionalidade de um sistema? E para eliminar uma falha de segurança?
3. Seja a seguinte classe de um sistema Python, de um banco hipotético.
class ContaBancaria:
def __init__(self, saldo):
self.saldo = saldo
def sacar(self, valor):
self.saldo = self.saldo - valor
def depositar(self, valor):
self.saldo = self.saldo + valor
Classifique as seguintes mudanças segundo os tipos de manutenção estudados:
- Verificar se a conta possui saldo antes de um saque.
- Implementar um novo método para realizar transferências entre
contas.
- Migrar o sistema para uma outra linguagem de programação.
4. Suponha que você trabalhe mantendo uma Calculadora para Android. Descreva uma possível manutenção adaptativa neste aplicativo. E também uma manutenção evolutiva.
5. Existem sistemas de software importantes e grandes que sofrem pouquíssima manutenção e que continuam sendo usados? Se sim, dê exemplos.
6. Uma das Leis de Lehman afirma que “à medida que um sistema sofre manutenções, sua complexidade interna aumenta e a qualidade de sua estrutura interna deteriora-se, a não ser que um trabalho seja realizado para estabilizar ou evitar tal fenômeno.” Qual o nome que se dá atualmente para esse trabalho realizado para evitar a degradação da qualidade interna de um sistema?
7. Suponha um artigo científico com o seguinte título: Um Catálogo
de Refatorações para Garantir Conformidade com a Lei Geral de Proteção
de Dados Pessoais (LGPD)
. Por que o uso de refatoração nesse
contexto não está correto?
8. Pesquise sobre o significado desses dois termos: projetos greenfield e projetos brownfield. Este livro pretende te ajudar a atuar, principalmente, em qual tipo de projeto?