modulo 17 di 24 / Ore 41-60
Moduli 17-24 / Checkpoint 60 ore
Scegliere una variante: database, API o mock server
Confrontare le tre alternative infrastrutturali per il Registro — database leggero, API REST e mock server — e scegliere quella giusta per il proprio contesto.
Scegliere una variante: database, API o mock server
Questa lezione appartiene al Modulo 17 — Variante database o API.
Le tre varianti a confronto
Il Registro del laboratorio usa localStorage per default. Esistono tre alternative più avanzate, ognuna adatta a contesti diversi.
Variante 1: database leggero (SQLite / JSON file)
Un database leggero come SQLite gira senza un server separato — il file del database è nella stessa cartella del progetto. In Node.js si usa con librerie come better-sqlite3.
// infrastructure/archivioStrumentiSQLite.js
import Database from "better-sqlite3";
const db = new Database("registro.db");
db.exec(`
CREATE TABLE IF NOT EXISTS strumenti (
id TEXT PRIMARY KEY,
nome TEXT NOT NULL,
categoria TEXT NOT NULL,
stato TEXT NOT NULL DEFAULT 'disponibile'
)
`);
function creaArchivioStrumentiSQLite() {
function leggiTutti() {
return db.prepare("SELECT * FROM strumenti").all();
}
function trovaPerId(id) {
return db.prepare("SELECT * FROM strumenti WHERE id = ?").get(id) ?? null;
}
function salva(strumento) {
db.prepare(`
INSERT INTO strumenti (id, nome, categoria, stato)
VALUES (@id, @nome, @categoria, @stato)
ON CONFLICT(id) DO UPDATE SET nome=@nome, categoria=@categoria, stato=@stato
`).run(strumento);
}
return { leggiTutti, trovaPerId, salva };
}
Quando scegliere: vuoi dati persistenti, transazioni atomiche, e il progetto gira su Node.js. Non serve un server separato.
Limite: non funziona nel browser — richiede Node.js o un backend.
Variante 2: API REST
Il Registro parla con un server che espone endpoint HTTP. Il frontend chiama fetch("/api/strumenti") e il server gestisce il database.
// infrastructure/archivioStrumentiAPI.js
function creaArchivioStrumentiAPI(baseUrl = "/api") {
async function leggiTutti() {
const risposta = await fetch(`${baseUrl}/strumenti`);
if (!risposta.ok) throw new Error("ARCHIVIO_NON_DISPONIBILE");
return risposta.json();
}
async function trovaPerId(id) {
const risposta = await fetch(`${baseUrl}/strumenti/${id}`);
if (risposta.status === 404) return null;
if (!risposta.ok) throw new Error("ARCHIVIO_NON_DISPONIBILE");
return risposta.json();
}
async function salva(strumento) {
const risposta = await fetch(`${baseUrl}/strumenti`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(strumento)
});
if (!risposta.ok) throw new Error("ARCHIVIO_NON_DISPONIBILE");
}
return { leggiTutti, trovaPerId, salva };
}
Quando scegliere: vuoi dati condivisi tra più utenti, o hai già un backend disponibile.
Limite: richiede un server reale. Durante lo sviluppo, serve un mock server per non dipendere dal backend.
Variante 3: mock server
Un mock server simula un’API reale restituendo risposte predefinite, senza un vero backend. Strumenti come json-server o msw (Mock Service Worker) lo permettono in pochi minuti.
Con json-server:
# Installa e avvia
npm install -g json-server
json-server --watch db.json --port 3001
// db.json
{
"strumenti": [
{ "id": "s1", "nome": "Trapano", "categoria": "Elettrico", "stato": "disponibile" }
],
"prestiti": []
}
Il mock server espone automaticamente:
GET /strumenti→ lista tuttiGET /strumenti/:id→ trova per IDPOST /strumenti→ salvaPUT /strumenti/:id→ aggiornaDELETE /strumenti/:id→ elimina
Il tuo adapter API (creaArchivioStrumentiAPI) funziona senza modifiche puntando a http://localhost:3001.
Quando scegliere: stai sviluppando il frontend e il backend non è ancora pronto, oppure vuoi testare il comportamento con un’API reale senza scrivere un server.
Limite: i dati in db.json si resettano se il file viene sovrascritto. Non è per la produzione.
Tabella di confronto
| Caratteristica | localStorage | Database SQLite | API REST | Mock server |
|---|---|---|---|---|
| Setup | Zero | Libreria NPM | Server backend | json-server |
| Funziona nel browser | ✓ | ✗ | ✓ (via fetch) | ✓ (via fetch) |
| Dati condivisi | ✗ | Parziale | ✓ | ✓ |
| Transazioni | ✗ | ✓ | Dipende | ✗ |
| Adatto per sviluppo | ✓ | ✓ | Con mock | ✓ |
| Adatto per produzione | ✗ | Sì (app desktop) | ✓ | ✗ |
Cosa cambia nel codice del Registro
Niente, se l’architettura è corretta. Il caso d’uso registraPrestito riceve l’archivio come dipendenza — non sa quale variante viene usata.
// main.js — l'unico punto che cambia
// Variante localStorage:
const archivioStrumenti = creaArchivioStrumentiLocalStorage();
// Variante SQLite (Node.js):
// const archivioStrumenti = creaArchivioStrumentiSQLite();
// Variante API:
// const archivioStrumenti = creaArchivioStrumentiAPI("http://localhost:3001");
const registraPrestito = creaRegistraPrestito({ archivioStrumenti, archivioPrestiti });
Una riga cambia. Il resto del sistema rimane invariato.
Come scegliere per il tuo contesto
Stai sviluppando nel browser senza server → localStorage o mock server
Stai sviluppando con Node.js e vuoi persistenza reale → SQLite
Il progetto ha già un backend → API REST
Vuoi testare il comportamento con fetch senza un server reale → mock server
Stai preparando la presentazione finale → localStorage (il più semplice)
Procedura guidata
- Scegli la variante più adatta al tuo contesto tra le quattro.
- Crea il nuovo adapter in
infrastructure/che rispetta il contratto (leggiTutti,trovaPerId,salva). - Sostituisci l’archivio in
main.js— solo quella riga. - Verifica che il Registro funzioni identicamente con la nuova variante.
- Documenta la scelta nel README con motivazione.
Attività in classe
## Scelta della variante infrastrutturale
Variante scelta:
Motivo della scelta:
Setup necessario:
Adapter creato (file):
- metodi implementati: leggiTutti, trovaPerId, salva
Riga in main.js modificata:
Verifica funzionamento:
Limite noto della variante scelta:
Spiegazione guidata per studiare
Le tre varianti (database, API, mock server) risolvono problemi diversi. La scelta dipende dal contesto — non esiste la variante “migliore” in assoluto. Un mock server è perfetto durante lo sviluppo ma inutile in produzione. SQLite è eccellente per un’app desktop ma non serve in un laboratorio scolastico con browser.
Il punto centrale è: la scelta dell’infrastruttura non cambia il dominio né i casi d’uso. Questa è la prova concreta che la separazione dei livelli funziona. Se cambiare variante richiede di modificare registraPrestito.js, c’è una dipendenza nascosta da correggere prima.
Il rischio tipico è scegliere la variante più complicata disponibile invece della più semplice che risolve il problema. Per un laboratorio scolastico, localStorage è spesso sufficiente. La complessità aggiuntiva va giustificata con un problema reale.
Passo per passo nel progetto
- Descrivi il problema che vuoi risolvere passando a una nuova variante.
- Scegli la variante minima che risolve quel problema.
- Scrivi il nuovo adapter — rispetta esattamente il contratto
{ leggiTutti, trovaPerId, salva }. - Sostituisci in
main.js— una riga. - Verifica: registra uno strumento, apri un prestito, cerca per categoria. Tutto funziona?
Esempio da leggere lentamente
// I tre adapter rispettano lo stesso contratto —
// il caso d'uso non sa quale sta usando
// localStorage
const archivio = creaArchivioStrumentiLocalStorage();
// → leggiTutti() restituisce JSON.parse(localStorage...)
// → salva() chiama localStorage.setItem(...)
// mock server
const archivio = creaArchivioStrumentiAPI("http://localhost:3001");
// → leggiTutti() chiama fetch("http://localhost:3001/strumenti")
// → salva() chiama fetch("http://localhost:3001/strumenti", { method: "POST" })
// SQLite (Node.js)
const archivio = creaArchivioStrumentiSQLite();
// → leggiTutti() esegue SELECT * FROM strumenti
// → salva() esegue INSERT OR REPLACE INTO strumenti
// Il caso d'uso:
const registraPrestito = creaRegistraPrestito({ archivioStrumenti: archivio, ... });
// → non sa quale archivio ha ricevuto — non gli interessa
Prova di comprensione
- Qual è la differenza tra un mock server e un’API REST reale?
- Se scegli la variante API, quali file del Registro devi modificare?
- Quale variante sceglieresti se volessi condividere i dati tra tre computer nell’aula?
Errori da evitare
- scegliere la variante più complessa perché “è più professionale”;
- implementare il nuovo adapter ma dimenticare di aggiornare
main.js; - testare la nuova variante senza verificare tutti gli scenari (non solo il caso felice);
- non documentare perché hai scelto quella variante.
Prodotto da consegnare
Può essere:
- il nuovo adapter implementato con i tre metodi del contratto;
- la modifica a
main.jscon la nuova variante attiva; - una nota nel README che spiega la variante scelta e i motivi.
Checklist di chiusura
- Ho scelto una variante e motivato la scelta
- Il nuovo adapter ha
leggiTutti,trovaPerId,salvacon le stesse firme - Ho modificato solo
main.jsper attivare la nuova variante - Il Registro funziona identicamente con la nuova variante
- Ho documentato la scelta nel README
Domande per la revisione
- Hai dovuto modificare file fuori da
infrastructure/emain.js? Se sì, c’era una dipendenza nascosta. - La variante scelta risolve il problema per cui l’hai scelta?
- Qual è il limite principale della variante scelta?
Risultato atteso
Alla fine lo studente deve saper dire:
Ho scelto la variante [X] perché [motivo concreto].
Ho implementato l'adapter in [file].
Ho modificato solo main.js per attivarlo.
Il Registro funziona identicamente — ho verificato con [scenario].
Il limite principale della variante è [limite].
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.