modulo 04 di 24 / Ore 0-20

Moduli 1-8 / Checkpoint 20 ore

Micro-sfida: trova la responsabilità nascosta

Applicare i concetti di responsabilità, coesione, accoppiamento e dipendenze nascoste a un blocco del Registro del laboratorio.

15 min Architettura del software

Micro-sfida: trova la responsabilità nascosta

Questa micro-sfida chiude il modulo su responsabilità, coesione e accoppiamento.

Non devi scrivere molto codice. Devi leggere bene.

Il compito è trovare una responsabilità nascosta: un lavoro importante che una funzione sta facendo senza dichiararlo chiaramente.

Una responsabilità nascosta non è semplicemente “codice brutto”. È una responsabilità reale che il nome della funzione non racconta. Per esempio una funzione chiamata cambiaStatoStrumento potrebbe anche leggere la UI, applicare regole di dominio, salvare su localStorage e mostrare messaggi. Il nome dice una cosa, il corpo ne fa sette.

Obiettivo

Allenarti a riconoscere:

  • funzioni con troppi motivi per cambiare;
  • blocchi poco coesi;
  • dipendenze nascoste;
  • regole finite nella UI;
  • salvataggio mescolato ad altre responsabilità.

Questa abilità viene prima del refactoring. Se non vedi il problema, rischi di spostare codice a caso.

La sfida ha tre risultati:

  • una diagnosi scritta;
  • una proposta di primo refactoring;
  • una verifica da fare dopo la modifica.

Se resta tempo puoi fare il primo refactoring, ma la parte obbligatoria è la diagnosi.

Tempo consigliato

Usa circa 15 minuti:

3 minuti  lettura del codice
5 minuti  elenco responsabilità e dipendenze
4 minuti  scelta della responsabilità nascosta più importante
3 minuti  proposta di refactoring e verifica

Se lavori in coppia, uno studente legge il codice e l’altro compila la scheda. Poi vi scambiate i ruoli.

Codice di partenza

Puoi usare un blocco reale del tuo progetto oppure questo esempio:

function cambiaStatoStrumento() {
  const id = inputStrumentoId.value;
  const nuovoStato = selectNuovoStato.value;
  const strumento = strumenti.find((item) => item.id === id);

  if (!strumento) {
    messaggioElement.textContent = "Strumento non trovato";
    return;
  }

  if (nuovoStato === "in_prestito" && strumento.stato === "guasto") {
    messaggioElement.textContent = "Uno strumento guasto non può andare in prestito";
    return;
  }

  strumento.stato = nuovoStato;
  localStorage.setItem("strumenti", JSON.stringify(strumenti));
  messaggioElement.textContent = "Stato aggiornato";
  mostraStrumenti(strumenti);
}

Il codice sembra gestire un cambio stato. In realtà fa di più.

Prima di correggerlo, devi nominarlo. Questa è la disciplina della micro-sfida: non partire dal “sistemiamo tutto”, ma dal “che cosa sta succedendo qui?”.

Come leggere il codice

Non leggere la funzione solo dall’alto verso il basso. Leggila con queste domande:

1. Quale responsabilità promette il nome della funzione?
2. Quali altre responsabilità compaiono nel corpo?
3. Quali dipendenze non sono nei parametri?
4. Quale regola importante è nascosta?
5. Quale cambiamento futuro sarebbe difficile?
6. Quale piccolo refactoring ridurrebbe il problema?

Esempio di lettura:

Nome: cambiaStatoStrumento
Promessa: cambiare lo stato di uno strumento
Sorpresa: la funzione decide anche se un guasto può andare in prestito
Rischio: la regola è bloccata nella UI

La parola chiave è “sorpresa”. Quando il corpo della funzione fa qualcosa che il nome non prepara a trovare, probabilmente c’è una responsabilità nascosta.

Prodotto da consegnare

Qui “consegnare” significa mostrare al docente o al gruppo un risultato verificabile. In questa micro-sfida la consegna principale è una scheda compilata: breve, concreta, leggibile.

Compila questa scheda:

## Responsabilità nascosta

Funzione analizzata:

Responsabilità dichiarata dal nome:

Responsabilità effettive:

- ...
- ...
- ...

Responsabilità nascosta più importante:

Perché è un problema:

Dipendenze nascoste:

- ...
- ...

Possibile primo refactoring:

Comportamento da verificare dopo:

Non limitarti a dire “fa troppe cose”. Devi nominare le cose.

Esempio di risposta

## Responsabilità nascosta

Funzione analizzata:
  cambiaStatoStrumento

Responsabilità dichiarata dal nome:
  cambiare lo stato di uno strumento

Responsabilità effettive:
  - legge input dalla UI
  - cerca lo strumento
  - applica una regola sul prestito
  - modifica lo stato
  - salva in localStorage
  - mostra un messaggio
  - aggiorna la lista

Responsabilità nascosta più importante:
  contiene una regola di dominio: uno strumento guasto non può andare in prestito.

Perché è un problema:
  la regola resta legata alla UI e non è testabile senza browser.

Dipendenze nascoste:
  - inputStrumentoId
  - selectNuovoStato
  - strumenti
  - localStorage
  - messaggioElement
  - mostraStrumenti

Possibile primo refactoring:
  estrarre una funzione puoCambiareStato(strumento, nuovoStato).

Comportamento da verificare dopo:
  se lo strumento è guasto e il nuovo stato è in_prestito, il prestito deve essere bloccato.

Questa risposta è buona perché non si ferma a una critica generica. Dice:

  • quale funzione è stata analizzata;
  • che cosa promette il nome;
  • che cosa succede davvero;
  • qual è la responsabilità più importante da separare;
  • quale rischio produce;
  • quale primo passo si può fare.

Vincoli

Durante la sfida:

  • non riscrivere tutta la funzione;
  • non creare cartelle nuove;
  • non introdurre pattern;
  • non cambiare comportamento;
  • se fai una modifica, deve essere un solo piccolo refactoring.

La cosa importante è la diagnosi.

Un refactoring accettabile in questa sfida è piccolo, per esempio:

function puoCambiareStato(strumento, nuovoStato) {
  if (nuovoStato === "in_prestito" && strumento.stato === "guasto") {
    return false;
  }

  return true;
}

Uso nella funzione:

if (!puoCambiareStato(strumento, nuovoStato)) {
  messaggioElement.textContent = "Uno strumento guasto non può andare in prestito";
  return;
}

Non è ancora il dominio perfetto. Però la regola ha un nome e può essere provata separatamente.

Livelli di riuscita

Usa questa griglia per capire se la consegna è sufficiente:

| Livello | Descrizione |
| --- | --- |
| Da rivedere | Dice solo "la funzione fa troppe cose" senza dettagli |
| Base | Elenca almeno tre responsabilità effettive |
| Buono | Individua una regola o una dipendenza nascosta importante |
| Avanzato | Propone un refactoring piccolo e indica cosa verificare dopo |

Una consegna breve può essere avanzata se è precisa. Una consegna lunga può essere debole se resta generica.

Variante in coppia

Uno studente sceglie una funzione e la passa a un compagno.

Il compagno deve:

  1. elencare responsabilità;
  2. trovare dipendenze nascoste;
  3. proporre un primo refactoring;
  4. spiegare quale comportamento va verificato dopo la modifica.

Poi si confrontano le risposte.

Se le risposte sono diverse, non è un problema. L’importante è argomentare.

Domande per il confronto:

  • Abbiamo individuato la stessa responsabilità nascosta?
  • Quale dipendenza ci sembra più pericolosa?
  • Quale refactoring è più piccolo?
  • Che cosa rischiamo di rompere?
  • Quale prova manuale basta per controllare?

Variante con codice reale

Se hai già un Registro funzionante, non usare l’esempio. Scegli una funzione reale tra:

  • registraStrumento;
  • cercaStrumenti;
  • registraPrestito;
  • chiudiPrestito;
  • apriSegnalazioneGuasto;
  • cambiaStatoStrumento;
  • una funzione di render che contiene anche logica.

Scegli una funzione che abbia almeno 12 righe o che usi almeno due dipendenze nascoste. Se scegli una funzione troppo semplice, la sfida diventa finta.

Mini-refactoring facoltativo

Se il docente chiede anche una modifica, fai solo questa:

  1. estrai la responsabilità nascosta in una funzione;
  2. dai alla funzione un nome chiaro;
  3. sostituisci il blocco originale con la chiamata alla funzione;
  4. verifica un caso valido e un caso bloccato.

Esempio:

function puoCambiareStato(strumento, nuovoStato) {
  if (nuovoStato === "in_prestito" && strumento.stato === "guasto") {
    return false;
  }

  return true;
}

Poi annota:

Ho estratto la regola sul cambio stato in `puoCambiareStato`.
La funzione principale resta ancora legata alla UI e al salvataggio.
Il comportamento da verificare è il blocco del passaggio da guasto a in_prestito.

Questa nota è importante: mostra che non stai fingendo di aver risolto tutto.

Domande di riflessione

Rispondi per iscritto:

  • Quale responsabilità era dichiarata dal nome della funzione?
  • Quale responsabilità hai trovato nascosta?
  • Perché quella responsabilità dovrebbe stare altrove?
  • Quale dipendenza nascosta rende la funzione difficile da testare?
  • Quale comportamento devi verificare se fai il refactoring?

Risultato atteso

Alla fine devi avere:

  • una scheda compilata;
  • una responsabilità nascosta individuata;
  • almeno tre dipendenze nascoste;
  • una proposta di primo refactoring;
  • una verifica da fare dopo il refactoring.

Controllo finale

La micro-sfida è completata quando puoi dire sì a queste domande:

  • ho analizzato una funzione reale o realistica;
  • ho trovato responsabilità effettive, non solo quella dichiarata dal nome;
  • ho individuato almeno una regola nascosta;
  • ho individuato dipendenze nascoste;
  • ho proposto un refactoring piccolo;
  • so quale comportamento controllare dopo la modifica.

Hai completato il Modulo 4. Ora hai strumenti pratici per leggere il codice fragile: responsabilità, coesione, accoppiamento e dipendenze. Nel prossimo modulo useremo questi strumenti per chiarire requisiti, utenti e linguaggio del problema.