modulo 12 di 24 / Ore 21-40

Moduli 9-16 / Checkpoint 40 ore

Errore applicativo: operazione impossibile nel caso d'uso

Riconoscere e gestire gli errori applicativi nel Registro: operazioni logicamente impossibili nel caso d'uso che non dipendono da input invalidi né da guasti tecnici.

25 min Architettura del software

Errore applicativo: operazione impossibile nel caso d’uso

Questa lezione appartiene al Modulo 12 — Errori, validazione e messaggi.

I quattro tipi di errore nel Registro

Prima di entrare nel dettaglio, è utile avere una mappa completa. Nel Registro del laboratorio esistono quattro tipi di errore distinti:

TipoOrigineEsempio
InputDati mancanti o malformati dall’utenteNome strumento vuoto, ID non fornito
DominioRegola del laboratorio violataStrumento guasto non prestabile
ApplicativoOperazione logicamente impossibile nel caso d’usoStrumento non trovato nell’archivio
InfrastrutturaleSalvataggio o lettura fallitalocalStorage non disponibile

Questa lezione riguarda gli errori applicativi.

Cos’è un errore applicativo

Un errore applicativo nasce nel caso d’uso quando un’operazione non può essere completata per un motivo logico, ma non perché l’utente abbia sbagliato l’input e non perché una regola del dominio sia stata violata.

Il caso tipico nel Registro: il caso d’uso cerca uno strumento nell’archivio — e non lo trova.

function creaRegistraPrestito({ archivioStrumenti, archivioPrestiti }) {
  return async function registraPrestito(comando) {
    const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);

    // ← Errore applicativo: lo strumento non esiste nell'archivio.
    // Non è colpa dell'input (l'ID era valido), non è una regola del dominio.
    // È una condizione del sistema: l'oggetto non c'è.
    if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");

    // ...resto del caso d'uso
  };
}

Perché non è un errore di input

L’input era corretto: l’utente ha fornito un strumentoId nel formato giusto. Il problema è che quell’ID non corrisponde a nessun strumento nell’archivio. La validazione dell’input non può rilevare questo — lo sa solo chi ha accesso all’archivio.

Perché non è un errore di dominio

Una regola di dominio è una regola del laboratorio, indipendente da come i dati sono organizzati: “uno strumento guasto non si presta”, “un prestito chiuso non si richiude”. L’assenza di un oggetto nell’archivio non è una regola del laboratorio — è una condizione del sistema.

Dove nasce e dove va gestito

Application (caso d'uso)   →  lancia l'errore applicativo
Presentation (UI)          →  cattura, traduce in messaggio per l'utente
Infrastructure (log)       →  registra il dettaglio tecnico

Il caso d’uso non mostra messaggi all’utente — lancia un errore con un codice chiaro. La UI cattura e traduce.

// Presentation
try {
  await registraPrestito(comando);
} catch (errore) {
  if (errore.message === "STRUMENTO_NON_TROVATO") {
    mostraMessaggio("Strumento non trovato. Verifica l'ID e riprova.");
  } else {
    mostraMessaggio("Operazione non riuscita. Riprova tra poco.");
    console.error("Errore non gestito:", errore);
  }
}

Altri errori applicativi nel Registro

Oltre a STRUMENTO_NON_TROVATO, il Registro può generare questi errori applicativi:

  • PRESTITO_NON_TROVATO — si prova a chiudere un prestito che non esiste
  • NESSUN_PRESTITO_APERTO — si cerca il prestito aperto di uno strumento, ma non ce n’è
  • ASSEGNATARIO_NON_AUTORIZZATO — (in varianti avanzate) l’utente non ha i permessi per questa operazione

Tutti nascono nel caso d’uso, non nel dominio né nell’infrastruttura.

Differenza pratica in codice

// Errore di dominio — la regola sta nel dominio
function puoEsserePrestato(strumento) {
  if (strumento.stato !== "disponibile") throw new Error("STRUMENTO_NON_DISPONIBILE");
}

// Errore applicativo — la condizione si verifica nel caso d'uso
async function registraPrestito(comando) {
  const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
  if (!strumento) throw new Error("STRUMENTO_NON_TROVATO"); // ← applicativo

  puoEsserePrestato(strumento); // ← qui potrebbe lanciare un errore di dominio
}

Il codice d’errore (STRUMENTO_NON_TROVATO) usa lettere maiuscole e underscore — convenzione che il corso adotta per distinguerli dai messaggi utente.

Procedura guidata

  1. Apri i tuoi casi d’uso (application/).
  2. Identifica ogni punto in cui viene cercato un oggetto nell’archivio.
  3. Aggiungi un controllo if (!oggetto) throw new Error("OGGETTO_NON_TROVATO") dove manca.
  4. Verifica che la UI catturi questo errore e mostri un messaggio comprensibile.
  5. Scrivi un test che verifica il comportamento: il caso d’uso lancia l’errore corretto quando l’oggetto non c’è.

Attività in classe

## Errore applicativo nel mio Registro

Caso d'uso analizzato:

Condizione che genera l'errore applicativo:

Codice errore scelto:

Messaggio utente corrispondente:

Test o verifica manuale eseguita:

Spiegazione guidata per studiare

Gli errori applicativi sono quelli che nascono nel caso d’uso quando il sistema non riesce a completare l’operazione per un motivo logico: un oggetto non trovato, una condizione non soddisfatta che non dipende dall’input dell’utente né dalle regole del dominio.

Il punto centrale è: ogni tipo di errore ha un’origine diversa e deve essere gestito nel livello corretto. Un errore applicativo non deve essere catturato e gestito nel dominio (che non sa dell’archivio) né nell’infrastruttura (che non sa della logica). Lo gestisce il caso d’uso che lo genera, e lo traduce la Presentation.

Il rischio tipico è confondere un errore applicativo con un errore di dominio. La domanda da porsi: “questa condizione dipende da una regola del laboratorio, o dalla presenza/assenza di dati nell’archivio?”. Se dipende dall’archivio, è applicativo.

Passo per passo nel progetto

  1. Cerca tutte le chiamate trovaPerId o trovaPer* nei casi d’uso.
  2. Ogni chiamata ha un controllo if (!risultato)? Aggiungilo dove manca.
  3. Il codice errore è chiaro e univoco? (STRUMENTO_NON_TROVATO, non ERRORE_GENERICO)
  4. La UI traduce questo codice in un messaggio comprensibile?
  5. C’è un test che verifica che il caso d’uso lanci l’errore corretto?

Esempio da leggere lentamente

// application/cercaStrumento.js
function creaCercaStrumento({ archivioStrumenti }) {
  return async function cercaStrumento({ strumentoId }) {
    const strumento = await archivioStrumenti.trovaPerId(strumentoId);

    // Errore applicativo: l'oggetto non esiste nell'archivio
    if (!strumento) throw new Error("STRUMENTO_NON_TROVATO");

    return strumento;
  };
}
// presentation/gestoreUI.js
try {
  const strumento = await cercaStrumento({ strumentoId: "str-99" });
  mostraStrumento(strumento);
} catch (errore) {
  if (errore.message === "STRUMENTO_NON_TROVATO") {
    mostraAvviso("Strumento non trovato. Controlla l'ID e riprova.");
  }
}

Prova di comprensione

  • Qual è la differenza tra un errore applicativo e un errore di dominio? Fai un esempio per ciascuno.
  • Perché il caso d’uso non deve tradurre l’errore in un messaggio per l’utente?
  • Dove nel tuo progetto potrebbe comparire un errore STRUMENTO_NON_TROVATO?

Errori da evitare

  • usare un codice errore generico (ERRORE, FALLITO) invece di uno specifico;
  • catturare l’errore applicativo nel dominio — il dominio non sa dell’archivio;
  • mostrare il codice errore grezzo all’utente nella UI;
  • non scrivere mai il controllo if (!oggetto) assumendo che l’archivio abbia sempre i dati.

Prodotto da consegnare

Può essere:

  • un controllo if (!strumento) aggiunto al caso d’uso con codice errore chiaro;
  • un test che verifica che il caso d’uso lanci STRUMENTO_NON_TROVATO quando appropriato;
  • una tabella che mappa codici errore applicativi ai messaggi utente corrispondenti.

Checklist di chiusura

  • I casi d’uso controllano se l’oggetto cercato esiste nell’archivio
  • I codici errore applicativi sono chiari e specifici
  • La UI traduce i codici in messaggi comprensibili
  • C’è almeno un test che verifica il comportamento in caso di oggetto non trovato
  • Il dominio non gestisce errori applicativi

Domande per la revisione

  • Hai trovato casi d’uso che non gestiscono la condizione “oggetto non trovato”?
  • I tuoi codici errore sono abbastanza specifici da capire dove è sorto il problema?
  • Come distingueresti un errore applicativo da uno infrastrutturale nel tuo progetto?

Risultato atteso

Alla fine lo studente deve saper dire:

Nel mio Registro, il caso d'uso [X] genera un errore applicativo quando [condizione].
Il codice errore è [Y].
La UI mostra il messaggio: [Z].
Ho verificato questo comportamento con [test / scenario manuale].

Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.