Saltar para o conteúdo
050 · Open Source Essentials

T16 — 056.1 Ferramentas de desenvolvimento

TópicoT16Objetivo056.1Peso2PáginasLPI Open Source Essentials (050) - Version 1.0

Resumo Conciso

Objetivos do desenvolvimento

ObjetivoDescrição
Robustez e precisãoProduzir programas que funcionem corretamente e de forma confiável
DesempenhoProduzir programas que executam rapidamente
EscalabilidadeProduzir programas fáceis de ampliar
AdaptabilidadeDiferentes utilizadores, dispositivos e ambientes
VelocidadeAcelerar o desenvolvimento e a implantação de novos recursos
Redução de errosDiminuir tarefas tediosas e erros de programação
LegadoSuporte a códigos e dispositivos legados
InteroperabilidadeFuncionar em conjunto com outras ferramentas já utilizadas
ReversãoPermitir reversão fácil em caso de erros ou mudanças de plano

Processos de desenvolvimento

Modelo em cascata

  • Popular nas décadas de 1950–1970; ainda utilizado em grandes organizações
  • Problemas: requisitos difíceis de alterar, compreensão ambígua dos requisitos, processo lento (um lançamento por ano ou menos), detecção tardia de bugs de integração e barreiras entre equipas

CI/CD (Integração Contínua / Entrega Contínua)

ConceitoDescrição
Integração Contínua (CI)Incorporação rápida de pequenas alterações no código; testes automatizados antes de submeter ao repositório principal
Entrega Contínua (CD)Tudo o que acontece após a CI até ao lançamento; testes detalhados e implantação automatizada
PipelineEtapas sequenciais e automatizadas; falha em qualquer etapa interrompe o pipeline e notifica a equipa
Tudo como códigoProcessos e infraestrutura são definidos formalmente no código e versionados
Ambiente de homologaçãoAmbiente intermédio que espelha o de produção para testes antes da implantação
Sistema de desenvolvimento localLaptop ou computador pessoal do programador
Sistema de desenvolvimento remotoSistema compartilhado em nuvem administrado pela organização

Ferramentas de geração de código

Ferramenta/TipoDescrição
CompiladorTransforma código de alto nível em código de máquina (ou bytecode)
GNU Compiler Collection (GCC)Compilador de código aberto para C e C++
LLVMCompilador de código aberto para C e C++
BytecodeCódigo intermédio portátil; compilado por uma máquina virtual (ex.: Java)
InterpretadorConverte e executa código diretamente sem compilação prévia (ex.: Python)
Maven / GradleFerramentas de compilação para Java; gerenciam opções e combinações de arquivos
IA generativaGeração automática de código a partir de descrições em texto simples
RefatoraçãoReestruturação do código para maior lógica e menor duplicação
Engenharia reversaReprodução do funcionamento de outro código; uso de desmontadores (disassemblers)

Depuradores

  • Facilitam a localização de bugs com pontos de interrupção (breakpoints), inspeção de variáveis e execução passo a passo
  • Watchpoint (ponto de observação): monitora quando e como uma variável se altera
  • Depurador GNU (GDB): depurador de código aberto mais conhecido para C e C++

Ferramentas analíticas

TipoDescrição
Análise estáticaExamina o código sem o executar (ex.: linters)
Análise dinâmicaExecuta o programa e verifica problemas durante a execução
LinterDetecta erros como atribuição incorreta de tipos (ex.: float para int)
Ferramentas de segurançaEncontram vulnerabilidades que tornam o programa exposto a ataques

Ambientes de Desenvolvimento Integrados (IDEs)

  • Ferramentas que integram edição, formatação, análise, depuração, compilação e controlo de versão num só ambiente
  • Exemplo de código aberto: Eclipse

Tipos de testes de software

TipoDescrição
Teste unitárioTesta funções individuais; base do desenvolvimento orientado a testes (TDD)
Teste de integraçãoVerifica se o produto como um todo funciona corretamente
Teste de regressãoDeteta quando uma alteração quebra algo que funcionava antes
Smoke testVerifica rapidamente as atividades mais importantes; interrompe se houver erros
Teste de aceitaçãoAvalia o impacto do programa no utilizador (usabilidade e navegação)
Teste de segurançaExecuta ações maliciosas para verificar rejeição sem falha ou fuga de informações
Fuzz testingGera caracteres aleatórios como entrada para revelar vulnerabilidades
Teste de desempenhoVerifica velocidade num ambiente semelhante ao de produção; uso de benchmarks
JUnitFerramenta de código aberto para testes unitários em Java
SeleniumFerramenta para simular interações de utilizador em aplicações web

Ambientes de implantação

  • Ferramentas de CI/CD: constroem pipelines com testes e ramificações
  • Orquestração: verificam falhas em sistemas virtuais e reiniciam automaticamente
  • Jenkins: ferramenta de código aberto mais conhecida para orquestração de pipelines

Exercícios Guiados

Exercício Guiado 1 — Verificação de segurança de um programa

Enunciado: Cite algumas maneiras de verificar a segurança de um programa.

Solução: Especialistas humanos podem examinar o código. Muitas ferramentas de análise estática e dinâmica existem para detetar práticas de programação inadequadas que expõem um programa a ameaças de segurança. Outras ferramentas enviam informações maliciosas para programas em execução e verificam as suas reações.

Exercício Guiado 2 — Testes unitários para uma função

Enunciado: Por que escrever vários testes unitários para uma única função de um programa?

Solução: Uma função de programa geralmente precisa ser executada em muitas variedades de entrada, e cada variedade merece o seu próprio teste. Por exemplo, a função pode lidar com um valor de entrada zero de uma maneira específica. Também é necessário antecipar as entradas inválidas e escrever testes para mostrar que a função lida com elas adequadamente.

Exercício Guiado 3 — Diferença entre cascade e CI/CD

Enunciado: Quais são as principais diferenças entre o modelo em cascata e o modelo CI/CD?

Solução: O modelo em cascata é um processo linear e lento em que os requisitos são definidos no início e os testes ocorrem pouco antes do lançamento, o que torna as alterações complicadas e dispendiosas. O CI/CD, por outro lado, baseia-se em comunicação estreita entre a equipa, implementação rápida de correções e novos recursos, testes rigorosos e contínuos, e automação máxima de etapas desde a escrita do código até à implantação.

Exercício Guiado 4 — Ambientes de teste e produção

Enunciado: Por que os testes devem ser realizados em sistemas diferentes dos sistemas de produção?

Solução: Uma falha catastrófica não só pode derrubar um sistema de produção, como também corromper dados. Além disso, os testes competem pelo tempo do sistema e prejudicam o desempenho da máquina. Portanto, é recomendável configurar um ambiente de homologação que espelhe o ambiente de produção, com hardware e software semelhantes, para executar os testes sem riscos para os utilizadores.

Exercícios Exploratórios

Exercício Exploratório 1 — Melhoria de aplicativos legados

Enunciado: Sua equipa herdou um aplicativo antigo que roda lentamente e ao qual é difícil adicionar recursos. Cite algumas maneiras de melhorar o aplicativo sem descartá-lo e escrever um novo do zero.

Primeiro, verifique se o projeto está sob controlo de versão, se ainda não for o caso. Depois de adicionar um novo recurso, execute testes de regressão para determinar onde o programa falha e designe programadores para descobrir quais funções são responsáveis por isso. Essas funções podem ser substituídas seletivamente. Os testes de desempenho podem identificar as funções específicas mais lentas, sendo mais fácil concentrar os esforços em corrigir ou substituir o código mais ineficiente. Se o código estiver numa linguagem que não é mais popular, considere adicionar recursos numa linguagem preferida pela equipa, garantindo que as funções na nova linguagem possam ser integradas às funções antigas.

Exercício Exploratório 2 — Colaboração inter-equipas (InnerSource)

Enunciado: Em projetos grandes, frequentemente, a Equipa A deseja que um recurso seja implementado numa parte do sistema mantida pela Equipa B, mas a Equipa B não vê o recurso como prioridade. Como a Equipa A pode codificar o recurso como parte do projeto da Equipa B?

A Equipa B pode permitir que a Equipa A crie uma nova ramificação, escreva o código do recurso e envie a ramificação para a Equipa B para incluir no seu projeto. A Equipa A, no entanto, não deve ter poderes para fazer o que quiser. A Equipa B deve fornecer documentação e ajuda para a Equipa A seguir os padrões do projeto. Um membro da Equipa B também deve rever o envio da Equipa A e executar todas as formas usuais de testes de integração. Essa forma de colaboração às vezes é chamada de InnerSource, porque se assemelha ao código aberto, mas ocorre dentro de uma única organização.

Exercício Exploratório 3 — TDD vs. testes tradicionais

Enunciado: O que é o desenvolvimento orientado a testes (TDD) e quais são as suas principais vantagens?

No desenvolvimento orientado a testes (TDD), os programadores escrevem testes antes de escrever o código que desejam testar. Os defensores do TDD afirmam que ele preenche lacunas nos testes e ajuda a garantir que o código faça o que o programador deseja. Ao escrever primeiro o teste, o programador define claramente o comportamento esperado, o que orienta a implementação e facilita a deteção precoce de erros.

Exercício Exploratório 4 — Fuzz testing

Enunciado: O que é o fuzz testing e por que pode ser eficaz na deteção de vulnerabilidades?

O fuzz testing (ou fuzz testing) consiste em gerar sequências de caracteres aleatórios e enviá-los como entrada para um programa. Embora possa parecer perda de tempo, essa abordagem frequentemente revela vulnerabilidades que os testes comuns não detetam, uma vez que os caracteres aleatórios podem desencadear comportamentos inesperados no programa, como falhas de memória, erros de tratamento de entrada ou vulnerabilidades de segurança.