modulo 09 di 24 / Ore 21-40

Moduli 9-16 / Checkpoint 40 ore

Composizione nel punto di avvio dell'applicazione

Usare il file di avvio per creare archivi, casi d'uso e UI, lasciando ai moduli interni responsabilità più pulite.

30 min Architettura del software

Composizione nel punto di avvio dell’applicazione

Qualcuno deve creare gli oggetti concreti.

Qualcuno deve decidere:

  • quale archivio usare;
  • quali casi d’uso creare;
  • come collegare la UI;
  • quali dipendenze passare.

Questo posto si chiama punto di composizione.

Nel nostro progetto puo essere:

src/main.js

Obiettivo

Alla fine devi avere un punto di avvio che:

  • crea archivi concreti;
  • crea casi d’uso passando dipendenze;
  • avvia la UI passando i casi d’uso;
  • non contiene regole di dominio;
  • non contiene logica applicativa estesa.

Prima: tutto sparso

Situazione fragile:

// uiRegistro.js
const archivioStrumenti = creaArchivioStrumentiInMemoria();
const registraStrumento = creaRegistraStrumento({ archivioStrumenti });

form.addEventListener("submit", () => {
  // ...
});

Oppure:

// registraPrestito.js
const archivioPrestiti = creaArchivioPrestitiInMemoria();

Le dipendenze sono create in posti diversi.

Diventa difficile capire come l’applicazione e collegata.

Dopo: un punto chiaro

Esempio:

import { creaArchivioStrumentiInMemoria } from "./infrastructure/archivioStrumentiInMemoria.js";
import { creaArchivioPrestitiInMemoria } from "./infrastructure/archivioPrestitiInMemoria.js";
import { creaRegistraStrumento } from "./application/registraStrumento.js";
import { creaCercaStrumenti } from "./application/cercaStrumenti.js";
import { creaRegistraPrestito } from "./application/registraPrestito.js";
import { creaChiudiPrestito } from "./application/chiudiPrestito.js";
import { avviaUIRegistro } from "./presentation/uiRegistro.js";

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

const casiUso = {
  registraStrumento: creaRegistraStrumento({ archivioStrumenti }),
  cercaStrumenti: creaCercaStrumenti({ archivioStrumenti }),
  registraPrestito: creaRegistraPrestito({
    archivioStrumenti,
    archivioPrestiti,
  }),
  chiudiPrestito: creaChiudiPrestito({
    archivioStrumenti,
    archivioPrestiti,
  }),
};

avviaUIRegistro(casiUso);

Ora la composizione e leggibile.

Che cosa puo stare in main.js

In main.js possono stare:

  • import dei moduli;
  • creazione archivi concreti;
  • creazione casi d’uso;
  • avvio UI;
  • dati iniziali di esempio, se dichiarati.

Non dovrebbero stare:

  • regole di dominio;
  • funzioni lunghe di validazione;
  • dettagli di rendering;
  • implementazione degli archivi;
  • logica completa dei casi d’uso.

Dati iniziali

Per facilitare la demo, puoi creare dati iniziali:

const strumentiIniziali = [
  {
    id: "s-001",
    nome: "Arduino Uno",
    categoria: "microcontrollori",
    stato: "disponibile",
  },
];

const archivioStrumenti = creaArchivioStrumentiInMemoria(strumentiIniziali);

Va bene, ma dichiaralo come dati demo.

Non confondere dati iniziali con regole del sistema.

Cambiare archivio dal punto di composizione

Questa e la prova:

const archivioStrumenti = creaArchivioStrumentiInMemoria();

puo diventare:

const archivioStrumenti = creaArchivioStrumentiLocalStorage();

Se i casi d’uso non cambiano, il lavoro del modulo sta funzionando.

UI che riceve casi d’uso

La UI puo essere avviata cosi:

avviaUIRegistro({
  registraStrumento,
  cercaStrumenti,
  registraPrestito,
  chiudiPrestito,
});

La UI non deve creare gli archivi.

La UI deve ricevere le operazioni disponibili.

Questo rende piu chiaro cosa puo fare l’interfaccia.

Test e composizione

Nei test puoi creare una composizione diversa:

const archivioStrumenti = creaArchivioStrumentiInMemoria([
  { id: "s-001", nome: "Arduino Uno", stato: "disponibile" },
]);

const registraPrestito = creaRegistraPrestito({
  archivioStrumenti,
  archivioPrestiti: creaArchivioPrestitiInMemoria(),
});

Il test non avvia la UI.

Compone solo cio che serve.

Esercizio

Apri il tuo main.js o file di avvio.

Compila:

# Punto di composizione

Archivi creati:
- ...

Casi d'uso creati:
- ...

UI avviata:
- ...

Regole che non dovrebbero stare qui:
- ...

Dettagli di rendering che non dovrebbero stare qui:
- ...

Poi sposta almeno una creazione di archivio o caso d’uso nel punto di composizione.

Cosa produrre

Alla fine della lezione devi avere:

  • file di avvio leggibile;
  • archivi concreti creati in un punto chiaro;
  • casi d’uso creati con dipendenze esplicite;
  • UI avviata con casi d’uso gia pronti;
  • nota su come cambiare archivio in futuro.

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 composizione nel punto di avvio dell’applicazione, il punto centrale è questo: Un caso d’uso coordina un’operazione completa: riceve un comando, legge ciò che serve, applica regole, salva il risultato e restituisce un esito.

Il rischio tipico è far diventare il caso d’uso una seconda UI o un secondo database. Deve coordinare, non mostrare HTML e non conoscere dettagli tecnici di salvataggio. 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. Definisci input e output del caso d’uso.
  4. Leggi i dati attraverso un archivio o una dipendenza esplicita.
  5. Chiama le regole del dominio.
  6. Salva il risultato senza sapere come funziona la persistenza concreta.
  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 registraPrestito(comando, archivioStrumenti, archivioPrestiti) {
  const strumento = archivioStrumenti.trovaPerId(comando.strumentoId);
  verificaStrumentoPrestabile(strumento);
  const prestito = apriPrestito(strumento.id, comando.nomePersona);
  archivioPrestiti.salva(prestito);
  archivioStrumenti.salva({ ...strumento, stato: "in_prestito" });
  return prestito;
}

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 dove vengono create le implementazioni concrete;
  • main.js compone, non contiene tutto;
  • i casi d’uso ricevono dipendenze;
  • la UI riceve casi d’uso;
  • posso indicare quale riga cambierei per usare un archivio diverso.

Nella prossima lezione facciamo l’esercizio finale: sostituire archivio senza toccare RegistraPrestito.