◇ OpenCyber Academy
Engenharia · Capítulo 9 · Português

Capítulo 9 — Programação II

Ensino gratuito e aberto para quem deseja proteger pessoas e tecnologias. Não é preciso criar uma conta para estudar ou consultar as respostas.

Capítulo 9 — Programação II

Mapa da aula

Aula 09 publicada. Mapa, exemplo, EX025.

flowchart TD
  N0["9.1 De scripts a programas"]
  N1["9.2 Estruturas de dados"]
  N2["9.4 Testes unitários"]
  N3["9.5 Casos-limite"]
  N4["9.6 Desempenho"]
  N5["9.7 Revisões"]
  N6["Registro de log dentro das ferramentas"]
  N7["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Exemplo resolvido"]
  EX --> Q["Exercício EX025"]

Desenho lógico

flowchart LR
  N0["9.1 De scripts a programas"]
  N1["9.2 Estruturas de dados"]
  N2["9.4 Testes unitários"]
  N3["9.5 Casos-limite"]
  N4["9.6 Desempenho"]
  N5["9.7 Revisões"]
  N6["Registro de log dentro das ferramentas"]
  N7["Síntese"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX025"]
[9.1 De scripts a programas]
    |
    v
[9.2 Estruturas de dados]
    |
    v
[9.4 Testes unitários]
    |
    v
[9.5 Casos-limite]
    |
    v
[9.6 Desempenho]
    |
    v
[9.7 Revisões]
    |
    v
[Registro de log dentro das ferramentas]
    |
    v
[Síntese]
    |
    v
[Exemplo resolvido] --> [Exercício EX025]

Objetivos de aprendizagem

Você vai (1) estruturar programas maiores em módulos; (2) usar estruturas de dados para buscas eficientes; (3) tratar erros e casos-limite de forma deliberada; (4) escrever testes unitários para a lógica de detecção.

9.1 De scripts a programas

À medida que as ferramentas de Amara crescem, ela separa a análise sintática, a lógica e a saída em módulos. Cada um pode ser testado e substituído sem mexer nos outros. Um único script longo mistura responsabilidades: mudar o formato de saída arrisca quebrar o analisador. Módulos com fronteiras claras permitem a Amara trocar o analisador por um novo formato de log enquanto a lógica de contagem permanece intocada e testada. A estrutura também permite a Paolo revisar um módulo de cada vez, o que mantém as revisões curtas e focadas. Cada módulo tem seus próprios testes, e um pequeno programa principal os une.

9.2 Estruturas de dados

Dicionários dão buscas rápidas — por exemplo, mapear um nome de usuário à sua contagem de falhas. Conjuntos respondem rapidamente a perguntas de pertinência. Escolher a estrutura certa transforma minutos em segundos em logs grandes. Procurar um nome de usuário numa lista significa percorrer cada entrada até aparecer uma correspondência; com um milhão de entradas, isso fica lento quando se repete para cada linha de log. Um dicionário salta para a entrada quase diretamente. Os conjuntos fazem o mesmo para perguntas do tipo "já vi isto antes?", que a lógica de detecção faz o tempo todo, como saber se um endereço já está numa lista de observação.

9.3 Erros

Os programas encontram campos ausentes, codificações estranhas e linhas enormes. O tratamento deliberado — capturar erros específicos, contá-los e continuar — mantém as análises completas e honestas. Capturar todos os erros com um único tratador amplo esconde defeitos reais, como um nome de variável digitado errado. Capturar erros específicos, como um valor que não pode ser lido como horário, trata os problemas esperados e deixa os inesperados aparecerem. A contagem de erros tratados vai para a saída, para que os leitores saibam quantos registros foram deixados de lado. O silêncio é pior.

9.4 Testes unitários

O módulo unittest do Python permite a Amara escrever testes como "cinco falhas para usuários distintos numa rede devem disparar; quatro não". Os testes rodam automaticamente antes de cada mudança ser incorporada. Um par de testes, um de cada lado do limiar, fixa exatamente onde o comportamento da regra muda. Rodar os testes automaticamente antes da incorporação faz com que uma mudança posterior que desloque o limiar por acidente falhe de imediato, em vez de ser descoberta quando um ataque real passar despercebido. Os testes também servem de documentação do que a regra deve fazer.

9.5 Casos-limite

Valores de fronteira (exatamente o limiar), entrada vazia e eventos duplicados são onde o código de detecção costuma quebrar. Os testes miram neles primeiro. Uma regra que dispara com "mais de cinco" e uma que dispara com "cinco ou mais" diferem apenas em exatamente cinco, e é aí que os defeitos se escondem. Testes com entrada vazia verificam se o código não relata nada em vez de travar. Eventos duplicados, comuns quando um encaminhador de logs tenta de novo, verificam se a mesma falha não é contada duas vezes. Amara lista esses casos antes de escrever a regra, e não depois que aparece um defeito.

9.6 Desempenho

Para um dia de logs do portal (2 milhões de linhas), ler linha a linha usa pouca memória; carregar tudo numa lista pode esgotá-la. Dois milhões de linhas de algumas centenas de bytes cada podem ocupar muito mais memória quando cada linha vira um objeto Python separado. Ler uma linha de cada vez e atualizar contadores mantém o uso de memória estável. Amara mede as duas abordagens num dia de amostra e registra o pico de memória de cada uma, o que justifica o desenho em fluxo na revisão.

9.7 Revisões

Paolo revisa o código quanto à correção e à clareza; um segundo par de olhos pega deslizes de lógica que os testes deixaram passar. Os testes verificam aquilo que o autor pensou em testar; um revisor pergunta pelo que não foi considerado. Paolo percebe que o código de Amara trata os nomes de usuário diferenciando maiúsculas de minúsculas, enquanto o portal não faz isso, de modo que "U5" e "u5" eram contados separadamente. Acrescenta-se um teste para esse caso, e as notas de revisão viram uma lista de verificação para futuros códigos de detecção. As revisões são registradas com o nome do revisor, para que leitores posteriores saibam que alguém conferiu o código antes de ele entrar em produção.

Registro de log dentro das ferramentas

As ferramentas de Amara registram as próprias ações: arquivo de entrada, seu hash, registros lidos, registros pulados e saída gravada. Quando um resultado é questionado semanas depois, o log da ferramenta mostra exatamente o que ela processou. Esse autorregistro custa algumas linhas de código e poupa horas de dúvida.

Exemplo resolvido

O teste de Amara para "exatamente 5 falhas" falha: o código dela usa "> 5", enquanto o documento de projeto diz "pelo menos 5". Ela pergunta a Paolo qual é a intenção; eles escolhem "≥ 5", atualizam juntos o documento de projeto e o código e mantêm o teste.

Caso sintético. Os testes e os dados são sintéticos.

Erros e limites

Os testes codificam o entendimento do momento em que foram escritos; se a ameaça mudar, eles podem impor uma lógica desatualizada.

Exercícios

Síntese

Código estruturado, estruturas de dados adequadas e testes de casos-limite tornam confiável a lógica de detecção.

Continue estudando — capítulo 09 de 50

← Capítulo 08 (rascunho) · Índice de capítulos do curso · Capítulo 10 (rascunho) →