cat swift/perche-swift-pensa-in-modo-diverso.md

Lezione 01 25 min

Perché Swift pensa in modo diverso

La prima lezione del modulo Fondamenta mentali: Swift come linguaggio di sicurezza, valori ed espressività, non come semplice sintassi Apple.

Swift non nasce per essere soltanto “il linguaggio per fare app iOS”. Nasce con un’ambizione più precisa: permettere di scrivere codice espressivo, vicino al modo in cui ragioniamo sui problemi, ma con molte protezioni integrate nel linguaggio.

Questa è la prima differenza importante: Swift non vuole che tu scriva codice che “parte e poi si vedrà”. Swift prova a farti modellare meglio il problema prima che il programma venga eseguito.

Un corso su Swift, quindi, non dovrebbe iniziare chiedendo di memorizzare var, let, if, for, func. Quelle cose servono, ma non sono il cuore. Il cuore è capire perché Swift ti spinge continuamente a rispondere a domande come:

  • questo dato può mancare?
  • questo valore deve cambiare o no?
  • questa cosa è uno stato possibile oppure un errore di modellazione?
  • questa funzione può fallire?
  • questo oggetto deve essere condiviso oppure copiato?

Sono domande di progetto, non di sintassi.

Swift è un linguaggio di vincoli utili

Molti principianti vivono il compilatore come un ostacolo. In Swift conviene cambiare prospettiva: il compilatore è un collaboratore severo che ti costringe a chiarire le intenzioni.

Prendiamo un esempio volutamente semplice:

let prezzo = 29.90
let quantita = 2
let totale = prezzo * quantita

Questo codice sembra innocuo, ma Swift non lo accetta: prezzo è un Double, quantita è un Int. Il linguaggio non converte automaticamente tra tipi numerici diversi.

Potrebbe sembrare fastidioso, ma è una scelta importante. Swift ti chiede di decidere:

let prezzo = 29.90
let quantita = 2
let totale = prezzo * Double(quantita)

Il punto non è scrivere una riga in più. Il punto è evitare che il linguaggio faccia conversioni implicite in punti dove il significato potrebbe non essere ovvio.

Valori espliciti invece di comportamenti impliciti

Swift tende a preferire l’esplicito quando l’implicito potrebbe produrre ambiguità. Questo si vede soprattutto con gli optionals.

In molti linguaggi, una variabile che dovrebbe contenere un nome può contenere anche null, spesso senza che il tipo lo dica chiaramente. In Swift, invece, c’è una differenza netta:

let nome: String = "Ada"
let soprannome: String? = nil

String significa: qui c’è sempre una stringa.

String? significa: qui potrebbe esserci una stringa, oppure potrebbe non esserci nulla.

Questa piccola differenza cambia il modo in cui progetti il codice. Non stai solo imparando un simbolo; stai imparando a rappresentare l’assenza come informazione.

Sintassi dentro problemi reali

In questo modulo useremo un piccolo dominio: un carrello con utenti, prodotti e ordini.

Non scriveremo esempi come:

let nome = "Mario"
let eta = 30

Li useremo solo se servono a modellare qualcosa:

struct Prodotto {
  let nome: String
  let prezzoInCent: Int
  let categoria: Categoria
}

Già qui compaiono alcune scelte mentali:

  • Prodotto è una struct perché rappresenta un valore.
  • nome e let perché il nome di quel prodotto non dovrebbe cambiare dopo la creazione.
  • prezzoInCent è un Int per evitare errori di arrotondamento con i decimali.
  • categoria non è una String, ma un tipo dedicato.

Swift diventa interessante quando inizi a usare i tipi per impedire stati confusi.

Un primo modello ingenuo

Ecco un modo molto fragile di rappresentare un prodotto:

let prodottoNome = "Tastiera"
let prodottoPrezzo = 4990
let prodottoCategoria = "accessori"

Funziona, ma il significato è disperso in tre variabili separate. Nulla impedisce di scrivere:

let prodottoCategoria = "ACCESSORII"

Oppure:

let prodottoPrezzo = -4990

Swift non può aiutarti se tu non gli dai un modello.

Un primo modello Swift

Possiamo fare meglio:

enum Categoria {
  case libri
  case elettronica
  case accessori
}

struct Prodotto {
  let nome: String
  let prezzoInCent: Int
  let categoria: Categoria
}

let tastiera = Prodotto(
  nome: "Tastiera",
  prezzoInCent: 4990,
  categoria: .accessori
)

Non abbiamo ancora risolto tutto. Il prezzo può ancora essere negativo. Ma abbiamo già migliorato due cose:

  • un prodotto ora è un concetto unico;
  • la categoria non può essere scritta male, perché non è più testo libero.

Questo è il tipo di ragionamento che guiderà il modulo.

Cosa portare via

Swift ti premia quando usi il sistema di tipi come strumento di progettazione. Il codice migliore non è quello con meno righe, ma quello in cui gli stati validi sono facili da rappresentare e gli stati sbagliati diventano difficili.

Quando impari una nuova sintassi, chiediti sempre:

  • quale incertezza elimina?
  • quale errore rende più difficile?
  • quale intenzione rende più chiara?

Esercizio

Modella un prodotto in tre modi:

  1. con variabili separate;
  2. con una struct;
  3. con una struct e una enum per la categoria.

Poi rispondi per iscritto:

  • quale versione rende più chiaro il dominio?
  • quale versione impedisce più errori?
  • cosa rimane ancora non protetto dal tipo?