modulo 08 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

Creare un archivio in memoria

Costruire una persistenza semplice in memoria per separare lettura e salvataggio dai casi d'uso.

25 min Architettura del software

Creare un archivio in memoria

Prima di usare localStorage, database o API, creiamo un archivio in memoria.

L’archivio in memoria e semplice:

  • conserva dati in array;
  • permette di salvare;
  • permette di cercare per id;
  • permette di leggere tutti gli elementi.

Non mantiene i dati dopo il refresh della pagina.

Va bene: in questa fase serve a separare responsabilita.

Obiettivo

Alla fine devi avere:

  • un archivio strumenti in memoria;
  • un archivio prestiti in memoria;
  • funzioni minime coerenti;
  • casi d’uso che usano archivi invece di array globali.

Perche serve un archivio

Nel codice fragile potremmo avere:

const strumenti = [];
const prestiti = [];

Queste variabili globali sono comode, ma creano problemi:

  • tutti possono modificarle;
  • i casi d’uso dipendono da dati globali;
  • i test diventano meno controllabili;
  • cambiare persistenza diventa piu difficile.

Un archivio rende esplicite le operazioni sui dati.

Archivio strumenti

File:

src/infrastructure/archivioStrumentiInMemoria.js

Codice:

export function creaArchivioStrumentiInMemoria(datiIniziali = []) {
  const strumenti = [...datiIniziali];

  return {
    tutti() {
      return [...strumenti];
    },

    trovaPerId(id) {
      return strumenti.find((strumento) => strumento.id === id) ?? null;
    },

    salva(strumento) {
      const indice = strumenti.findIndex((item) => item.id === strumento.id);

      if (indice === -1) {
        strumenti.push(strumento);
      } else {
        strumenti[indice] = strumento;
      }

      return strumento;
    },
  };
}

Questa implementazione fa sia inserimento sia aggiornamento.

Per il laboratorio va bene.

Archivio prestiti

File:

src/infrastructure/archivioPrestitiInMemoria.js

Codice:

export function creaArchivioPrestitiInMemoria(datiIniziali = []) {
  const prestiti = [...datiIniziali];

  return {
    tutti() {
      return [...prestiti];
    },

    trovaPerId(id) {
      return prestiti.find((prestito) => prestito.id === id) ?? null;
    },

    salva(prestito) {
      const indice = prestiti.findIndex((item) => item.id === prestito.id);

      if (indice === -1) {
        prestiti.push(prestito);
      } else {
        prestiti[indice] = prestito;
      }

      return prestito;
    },
  };
}

La forma e simile.

Questa duplicazione per ora e accettabile. Piu avanti potremo riflettere se estrarre una funzione comune.

Perche restituire copie

In tutti() usiamo:

return [...strumenti];

Non:

return strumenti;

Restituire una copia riduce modifiche accidentali dall’esterno.

Non rende i dati completamente immutabili, ma e un buon primo passo didattico.

Usare l’archivio nel caso d’uso

Invece di:

const strumento = strumenti.find((item) => item.id === comando.strumentoId);

usiamo:

const strumento = archivioStrumenti.trovaPerId(comando.strumentoId);

Il caso d’uso non sa se i dati arrivano da:

  • array;
  • localStorage;
  • JSON;
  • database.

Sa solo quali operazioni gli servono.

Limiti dell’archivio in memoria

L’archivio in memoria:

  • perde dati al refresh;
  • non condivide dati tra browser;
  • non gestisce concorrenza;
  • non valida dati salvati;
  • non e adatto alla produzione.

Ma e perfetto per questo checkpoint.

Ci permette di completare la versione essenziale senza introdurre troppa infrastruttura.

Esercizio

Crea due archivi:

const archivioStrumenti = creaArchivioStrumentiInMemoria();
const archivioPrestiti = creaArchivioPrestitiInMemoria();

Poi verifica:

archivioStrumenti.salva({
  id: "s-001",
  nome: "Arduino Uno",
  categoria: "microcontrollori",
  stato: "disponibile",
});

console.log(archivioStrumenti.trovaPerId("s-001"));
console.log(archivioStrumenti.tutti());

Scrivi cosa ti aspetti prima di eseguire.

Cosa produrre

Alla fine della lezione devi avere:

  • archivioStrumentiInMemoria;
  • archivioPrestitiInMemoria;
  • metodi tutti, trovaPerId, salva;
  • almeno un caso d’uso collegato all’archivio;
  • nessun array globale usato direttamente dal caso d’uso.

Spiegazione guidata per studiare

Questa lezione va studiata su due piani. Il primo è il comportamento visibile del Registro del laboratorio: che cosa vede o fa l’utente quando registra uno strumento, cerca un dispositivo, apre un prestito o segnala un guasto. Il secondo è il confine architetturale: dove deve stare il codice che rende possibile quel comportamento.

Per creare un archivio in memoria, il punto centrale è questo: L’infrastruttura è il bordo tecnico: salva, legge, chiama API, usa localStorage o file JSON. È importante, ma deve restare sostituibile.

Il rischio tipico è far entrare il formato salvato dentro il dominio. Un oggetto comodo per localStorage non è automaticamente il modello con cui ragiona il progetto. Per evitarlo, non partire dal file che hai già aperto nell’editor. Parti dalla domanda: “quale responsabilità sto modificando?”. Se la risposta riguarda una regola del laboratorio, guarda il dominio. Se riguarda una sequenza di operazioni, guarda i casi d’uso. Se riguarda salvataggio, file, localStorage, API o database, guarda l’infrastruttura. Se riguarda input, pulsanti, form e messaggi, guarda la Presentation.

Il tempo è sufficiente per alternare spiegazione, modifica guidata e revisione. Alla fine della lezione lo studente non deve ricordare una definizione a memoria: deve saper indicare un punto del progetto, spiegare perché quel codice sta lì e mostrare una verifica del comportamento.

Passo per passo nel progetto

  1. Rileggi il titolo della lezione e riscrivilo come domanda pratica. Per esempio: “dove deve stare questa regola?”, “chi deve salvare questo dato?”, “come verifico questo errore?”.
  2. Apri solo i file necessari. Se devi toccare più di tre file, fermati e scrivi prima una mini-mappa.
  3. Distingui modello di dominio e formato salvato.
  4. Crea una funzione di mapping leggibile.
  5. Gestisci dati mancanti o non validi.
  6. Verifica che i casi d’uso non cambino quando cambi archivio.
  7. Aggiorna una nota breve nel README o negli appunti se hai cambiato un confine del progetto.

Esempio da leggere lentamente

Questo esempio serve a ragionare, non a incollare codice senza capire:

function strumentoToDTO(strumento) {
  return {
    id: strumento.id,
    name: strumento.nome,
    category: strumento.categoria,
    status: strumento.stato
  };
}

Leggilo chiedendoti che cosa cambierebbe se domani sostituissimo la pagina web con una CLI, oppure localStorage con un’API. Se l’esempio continua ad avere senso senza riscrivere tutto, il confine è probabilmente buono. Se invece un dettaglio tecnico si propaga in molti file, il progetto sta tornando fragile.

Prova di comprensione

Prima di chiudere la lezione, rispondi per iscritto a queste domande:

  • Qual è la responsabilità principale trattata in questa lezione?
  • In quale livello del progetto dovrebbe stare?
  • Quale errore faresti se cercassi la soluzione più veloce?
  • Quale piccolo test, controllo manuale o esempio dimostra che hai capito?
  • Che cosa deve restare facile da cambiare dopo questa lezione?

Una risposta accettabile non deve essere lunga. Deve però usare parole concrete del Registro: strumento, prestito, stato, archivio, caso d’uso, messaggio, test.

Controllo finale

La lezione e completata quando puoi rispondere si:

  • so creare un archivio in memoria;
  • so salvare un elemento;
  • so aggiornarlo;
  • so trovarlo per id;
  • il caso d’uso usa l’archivio;
  • so spiegare perche questo archivio non e ancora persistenza definitiva.

Nella prossima lezione colleghiamo la UI ai casi d’uso.