modulo 22 di 24 / Ore 41-60
Moduli 17-24 / Checkpoint 60 ore
Rendere più chiari i confini tra livelli
Identificare e correggere i punti del Registro dove i confini tra Domain, Application, Infrastructure e Presentation sono sfumati o violati, un confine alla volta.
Rendere più chiari i confini tra livelli
Questa lezione appartiene al Modulo 22 — Refactoring avanzato e varianti.
Il problema: confini che si sfumano
Con il tempo, i confini tra livelli tendono a degradarsi. Non per cattiveria — per fretta, per convenienza, per un “metto qui per ora e poi sistemo”. Il problema è che il “poi” non arriva mai, e ogni confine sfumato rende il passo successivo più difficile.
Segnali che un confine è sfumato:
✗ domain/ importa qualcosa da infrastructure/
✗ application/ chiama document.getElementById
✗ presentation/ ha condizioni if (stato === "guasto")
✗ infrastructure/ contiene regole di business
✗ main.js ha decine di righe di logica applicativa
Come si riconosce un confine sfumato
Test pratico per ogni file: apri il file e poniti questa domanda per ogni import e ogni dipendenza esterna:
"Se spostassi questo file in un progetto diverso senza localStorage, senza browser,
senza UI — il file funzionerebbe ancora?"
domain/strumento.js→ deve rispondere “sì” (nessuna dipendenza esterna)application/registraPrestito.js→ deve rispondere “sì” (riceve tutto come parametro)infrastructure/archivioLocalStorage.js→ “no” (usa localStorage — è corretto)presentation/ui.js→ “no” (usa document — è corretto)
Se domain/ risponde “no” → confine sfumato da correggere.
Tre confini sfumati frequenti nel Registro
Confine 1: dominio che conosce localStorage
// ❌ domain/strumento.js — confine sfumato
function creaStrumento({ id, nome, categoria }) {
const strumento = { id, nome, categoria, stato: "disponibile" };
localStorage.setItem(`str-${id}`, JSON.stringify(strumento)); // ← Infrastructure nel Domain
return strumento;
}
// ✅ domain/strumento.js — confine chiaro
function creaStrumento({ id, nome, categoria }) {
if (!id) throw new Error("ID_MANCANTE");
if (!nome || nome.trim().length < 2) throw new Error("NOME_NON_VALIDO");
return { id, nome: nome.trim(), categoria, stato: "disponibile" };
// Il salvataggio avviene nell'archivio, chiamato dal caso d'uso
}
Correzione: sposta il salvataggio nel caso d’uso o nell’adapter. Il dominio crea e valida, non salva.
Confine 2: caso d’uso che accede al DOM
// ❌ application/registraPrestito.js — confine sfumato
async function registraPrestito(comando) {
const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
if (!strumento) {
document.getElementById("messaggio").textContent = "Non trovato"; // ← Presentation nell'Application
return;
}
// ...
}
// ✅ application/registraPrestito.js — confine chiaro
async function registraPrestito(comando) {
const strumento = await archivioStrumenti.trovaPerId(comando.strumentoId);
if (!strumento) throw new Error("STRUMENTO_NON_TROVATO"); // ← lancia, non mostra
// La Presentation cattura e mostra il messaggio
}
Correzione: il caso d’uso lancia errori, non mostra messaggi. La Presentation cattura e traduce.
Confine 3: presentation con regole di dominio
// ❌ presentation/ui.js — confine sfumato
function renderStrumento(strumento) {
const prestabile = strumento.stato === "disponibile"; // ← regola del dominio nella UI
return `<li class="${prestabile ? "ok" : "no"}">${strumento.nome}</li>`;
}
// ✅ presentation/ui.js — confine chiaro
function renderStrumento(strumento) {
return `<li class="strumento--${strumento.stato}">${strumento.nome}</li>`;
// La classe CSS riflette lo stato — la regola di prestabilità è nel dominio
}
Correzione: la UI mostra lo stato, il dominio decide le regole.
Il processo di chiarimento di un confine
Non si correggono tutti i confini insieme — uno alla volta:
1. Scegli un confine sfumato (es. domain/ con localStorage)
2. Scrivi una verifica del comportamento attuale
3. Sposta il codice nel livello corretto
4. Aggiorna i chiamanti
5. Verifica che il comportamento sia identico
6. Documenta la modifica
Regola: se tocchi più di tre file in un solo passo, il passo è troppo grande. Fermati e dividi.
Come trovare tutti i confini sfumati nel tuo progetto
Cerca in domain/: localStorage, fetch, document, alert, import "../infrastructure"
Cerca in application/: document, alert, innerHTML, import "../presentation"
Cerca in presentation/: archivioStrumenti.trovaPerId(), JSON.parse(localStorage...)
Cerca in infrastructure/: regole di business (if stato === "guasto"), casi d'uso
Crea una lista di tutti i problemi trovati. Poi ordina per priorità: prima i confini che rendono impossibile il test.
Procedura guidata
- Apri ogni cartella (
domain/,application/,infrastructure/,presentation/). - Per ogni file: lista le dipendenze esterne che usa.
- Per ogni dipendenza: è del livello giusto?
- Scegli il problema più critico (quello che rende impossibile il test).
- Correggi un confine alla volta con verifica intermedia.
Attività in classe
## Confini sfumati trovati nel Registro
Ricerca sistematica completata (sì/no):
Problemi trovati:
- [file]: usa [dipendenza] che appartiene a [livello diverso]
- [file]: usa [dipendenza] che appartiene a [livello diverso]
Confine scelto da correggere:
- File:
- Dipendenza da spostare:
- Livello corretto:
Verifica prima della correzione:
Correzione applicata:
Verifica dopo la correzione:
Prossimo confine da correggere (sessione futura):
Spiegazione guidata per studiare
I confini tra livelli non si violano in modo drammatico — si sfumano gradualmente. Una chiamata a localStorage nel posto sbagliato, una condizione if nella UI che dovrebbe stare nel dominio. Ognuna sembra innocua da sola. Insieme rendono il progetto difficile da modificare.
Il punto centrale è: un confine chiaro si riconosce da una proprietà semplice — il codice di un livello non sa nulla dei dettagli degli altri livelli. Il dominio non sa di localStorage. L’Application non sa del DOM. La Presentation non sa delle regole del laboratorio.
Il rischio tipico è correggere tutti i confini in una sessione. Non funziona — si introducono errori e si perde il filo. Un confine alla volta, con verifica, è l’unico modo disciplinato.
Passo per passo nel progetto
- Apri
domain/strumento.js— importa qualcosa dainfrastructure/o usalocalStorage? Se sì, è il primo confine da correggere. - Apri
application/registraPrestito.js— hadocumentoalert? Se sì, è il secondo. - Apri
presentation/ui.js— halocalStorage.getItemdiretto o condizionistato ===? Se sì, terzo. - Scegli uno solo — correggi, verifica, documenta.
Esempio da leggere lentamente
// Audit di domain/strumento.js — cosa importa?
// ❌ Versione con confine sfumato
import { archivioGlobale } from "../infrastructure/archivioGlobale.js"; // ← sbagliato
function creaStrumento({ id, nome, categoria }) {
const strumento = { id, nome, categoria, stato: "disponibile" };
archivioGlobale.salva(strumento); // ← il dominio salva = confine sfumato
return strumento;
}
// ✅ Versione con confine chiaro
// Nessun import — il dominio non dipende da nulla di esterno
function creaStrumento({ id, nome, categoria }) {
if (!id || !nome) throw new Error("DATI_INSUFFICIENTI");
return { id, nome: nome.trim(), categoria, stato: "disponibile" };
// Il salvataggio è responsabilità di chi chiama questa funzione
}
Prova di comprensione
- Hai trovato almeno un confine sfumato nel tuo progetto?
- Dopo la correzione, il file modificato può girare senza localStorage?
- Quanti file hai toccato per correggere il confine? Erano meno di tre?
Errori da evitare
- correggere tutti i confini insieme senza verifica intermedia;
- spostare codice nel livello “più vicino” invece che nel livello corretto;
- lasciare la dipendenza sbagliata e aggiungerne una corretta — duplicazione;
- non documentare il confine corretto dopo la modifica (rischia di tornare sfumato).
Prodotto da consegnare
Può essere:
- una modifica che sposta una dipendenza nel livello corretto, con verifica;
- una lista di tutti i confini sfumati trovati nel progetto con priorità;
- un commento o nota nel README che descrive qual è il confine corretto tra due livelli.
Checklist di chiusura
- Ho cercato sistematicamente dipendenze fuori posto nei quattro livelli
- Ho scelto un confine da correggere — uno solo
- Ho verificato il comportamento prima della correzione
- Ho corretto il confine e aggiornato i chiamanti
- Il comportamento è identico dopo la correzione
- Ho documentato quale confine era sfumato e come è stato corretto
Domande per la revisione
- Quanti confini sfumati hai trovato in totale? Quale era il più critico?
- Dopo la correzione,
domain/dipende ancora da qualcosa di esterno? - Quale confine lasci per la prossima sessione? Perché?
Risultato atteso
Alla fine lo studente deve saper dire:
Ho trovato questi confini sfumati nel Registro: [lista].
Ho corretto: [confine specifico] in [file].
Il file ora non dipende da [dipendenza esterna].
Ho verificato con [metodo] che il comportamento è invariato.
Se questa spiegazione non è possibile, la lezione non è ancora davvero conclusa.