No description
Find a file
2026-08-31 11:17:57 +02:00
.woodpecker chore: migrate CI to .woodpecker/{push,branch}.yml 2026-08-31 11:17:57 +02:00
src fix(031): pedagogical MINOR fixes 2026-08-31 11:17:57 +02:00
tests initial content 2026-08-31 11:17:51 +02:00
.gitignore Initial commit 2026-08-31 09:17:07 +00:00
Cargo.lock initial content 2026-08-31 11:17:51 +02:00
Cargo.toml chore: declare MSRV 1.85 (edition 2024) 2026-08-31 11:17:57 +02:00
LICENSE chore: add AGPL-3.0 license and standard .gitignore 2026-08-31 11:17:57 +02:00
README.md fix(031): pedagogical MINOR fixes 2026-08-31 11:17:57 +02:00

Lição 31: Propagação de Erros (Operador ?)

1. Narrativa

No sistema do mecha Æther, falhas podem ocorrer em cascata — um sensor inativo impede a leitura, que impede a calibragem, que impede a inicialização. O operador ? propaga erros automaticamente pela cadeia de chamadas, permitindo que o piloto escreva código limpo sem tratar cada falha individualmente.

2. Conceito

Propagação de erros com ? e From trait:

  • Operador ?: Desempacota Ok(v) ou retorna Err(e) antecipadamente
  • From trait: Conversão automática entre tipos de erro via impl From<ErrA> for ErrB
  • Encadeamento: Múltiplos ? em sequência — cada um pode falhar
  • map_err: Converte erro manualmente quando From não está implementado
  • Combinação Option/Result: ? funciona em ambos — None propaga como None

3. Requisitos

  • Usar ? para propagar erros em funções que retornam Result
  • Implementar From para conversão automática de erros
  • Encadear múltiplas operações com ?
  • Combinar Option e Result com propagação

4. Design de Dados

graph LR
    A["parse: ErroParse"] -->|"From"| B["ErroSubsistema::DadoCorrompido"]
    C["limite excedido"] --> D["ErroSubsistema::TemperaturaCritica"]
    E["energia baixa"] --> F["ErroSubsistema::EnergiaInsuficiente"]
    G["? operator"] --> H["Propaga ErroSubsistema automaticamente"]

5. Diagrama de Fluxo

flowchart TD
    A[Início] --> B["ler_valor(dado)?"]
    B --> C{Parse OK?}
    C -->|Não| D["Err(DadoCorrompido) ← retorna"]
    C -->|Sim| E["calibrar(valor, limite)?"]
    E --> F{Valor > limite?}
    F -->|Sim| G["Err(TemperaturaCritica) ← retorna"]
    F -->|Não| H["Ok(valor)"]
    H --> I["inicializar_mecha(energia?, temp?, pressao?)"]
    I --> J{Todas OK?}
    J -->|Não| K["Propaga erro via ?"]
    J -->|Sim| L["Ok(Mech operacional)"]

6. Funções

Função Descrição
encontrar_sensor Busca sensor por ID no HashMap → Option
ler_valor_inteiro Parse string com map_err e From
calibrar_sensor Parse + verificação de limite com ?
iniciar_reator Valida temperatura e pressão encadeadas
verificar_piloto Busca piloto por ID → Option
diagnosticar_sistema Diagnóstico motor + escudo com ?
inicializar_mecha Validação completa: energia + temp + pressão

7. Exemplo

fn calibrar_sensor(dado: &str, limite: i32) -> Result<i32, ErroSubsistema> {
    let valor = dado.parse().map_err(ErroSubsistema::from)?;
    if valor > limite {
        Err(ErroSubsistema::TemperaturaCritica)
    } else {
        Ok(valor)
    }
}

8. Missão

  1. Entender o enum ErroSubsistema e a implementação de From<ParseIntError>
  2. Implementar encontrar_sensor e verificar_piloto com Option
  3. Implementar ler_valor_inteiro com map_err + conversão
  4. Implementar calibrar_sensor com ? encadeado
  5. Implementar iniciar_reator com validação múltipla
  6. Implementar diagnosticar_sistema com early returns
  7. Implementar inicializar_mecha com encadeamento completo

Limiares de Validação (contrato)

Os limites abaixo são exigidos pelos testes — memorize-os:

Sistema Limite seguro Limite crítico Erro retornado
Temperatura ≤ 500 > 500 (ex.: 1200) TemperaturaCritica
Pressão ≤ 300 > 300 (ex.: 600) PressaoCritica
Energia ≥ 500 < 500 (ex.: 50) EnergiaInsuficiente
  • calibrar_sensor(dado, limite) retorna TemperaturaCritica se o valor parseado for maior que o limite passado.
  • diagnosticar_sistema(dado_motor, dado_escudo, limite) valida o motor contra o limite (temperatura) e o escudo contra o limiar de energia: um escudo fraco (valor baixo, ex.: "5") retorna EnergiaInsuficiente — o escudo precisa de energia mínima para se manter ativo.

9. Como Executar

cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check

10. Dicas

  • ? só funciona em funções que retornam Result ou Option
  • From<ParseIntError> for ErroSubsistema permite ? converter erros automaticamente
  • Use map_err quando a conversão From não está disponível
  • Early returns com if + return Err(...) são preferíveis a aninhamento profundo