cat swift/perche-swift-pensa-in-modo-diverso.md
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è unastructperché rappresenta un valore.nomeeletperché il nome di quel prodotto non dovrebbe cambiare dopo la creazione.prezzoInCentè unIntper evitare errori di arrotondamento con i decimali.categorianon è unaString, 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:
- con variabili separate;
- con una
struct; - con una
structe unaenumper 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?