cat swift/linting-formattazione-coerenza.md

Lezione 44 35 min

Linting, formattazione e coerenza

Uno stile coerente riduce attrito: formattazione, linting e convenzioni devono aiutare il team, non sostituire il giudizio.

Il codice professionale non deve solo funzionare. Deve essere leggibile in modo coerente da più persone nel tempo.

Formattazione e linting servono a ridurre discussioni inutili:

  • spaziatura;
  • ordinamento;
  • lunghezza;
  • pattern rischiosi;
  • convenzioni di naming;
  • import inutili.

Non sostituiscono il design. Liberano attenzione per il design.

Formattazione

La formattazione risponde a domande come:

  • dove vanno gli a capo?
  • come indentiamo closure lunghe?
  • come allineiamo parametri?
  • come ordiniamo import?

Uno strumento di formattazione rende queste scelte automatiche.

Nel mondo Swift puoi incontrare strumenti come swift-format o strumenti adottati dal team. L’importante è non formattare a mano in modo incoerente.

Un esempio pratico:

let risultato = prodotti.filter { $0.disponibile }.map { $0.nome }.sorted()

Un formatter può trasformarlo in una forma più leggibile quando la pipeline cresce:

let risultato = prodotti
  .filter { $0.disponibile }
  .map { $0.nome }
  .sorted()

Non cambia il comportamento. Riduce il carico visivo.

Linting

Un linter segnala pattern indesiderati.

Esempi:

  • force unwrap non giustificato;
  • funzioni troppo lunghe;
  • nomi non coerenti;
  • try!;
  • codice non usato;
  • complessità eccessiva.

Non ogni warning è una verità assoluta. Ma ogni warning merita una decisione.

Regole locali

Un corso o team dovrebbe avere poche regole chiare:

  • evitare ! salvo casi motivati;
  • preferire let;
  • niente Task.detached senza commento;
  • no @unchecked Sendable senza giustificazione;
  • nomi di dominio in italiano o inglese, ma non misti senza motivo;
  • test per errori di dominio.

Le regole migliori proteggono il progetto, non il gusto personale.

Configurazione minima

Una policy utile sta nel repository, non nella memoria del team.

Esempio di sezione README:

## Style

- Prefer `let` unless mutation is required.
- Avoid force unwrap except in test fixtures or after explicit validation.
- Do not use `Task.detached` without documenting why structured concurrency is not enough.
- Run `swift format lint --recursive Sources Tests` before opening a PR.

Anche se il progetto non usa ancora un file di configurazione, rendere esplicite le regole evita discussioni ricorrenti.

Formattare in CI

Il controllo deve essere riproducibile.

Esempio concettuale:

swift format lint --recursive Sources Tests

Oppure:

swiftlint lint

Il comando concreto dipende dagli strumenti scelti dal progetto.

Evitare churn

Non riformattare tutto il repository mentre stai cambiando una funzione. Genera diff enormi e rende difficile fare review.

Strategia:

  • introdurre formattazione una volta;
  • poi applicarla automaticamente;
  • evitare modifiche di stile fuori scope.

Per una codebase già esistente, fai una PR solo di formattazione. Dopo quella PR, ogni modifica futura deve rispettare lo stile. Mischiare refactor logico e riformattazione di massa rende quasi impossibile capire cosa è cambiato davvero.

Eccezioni motivate

Ogni regola deve prevedere eccezioni rare.

let prezzo = Price(100)!

In un test, un force unwrap su una fixture controllata può essere accettabile. In codice di produzione su dati esterni, quasi mai.

L’obiettivo non è eliminare ogni simbolo !. È sapere perché esiste.

Stile e API design

Il lint non può decidere se un nome è buono nel dominio.

Questo passa il lint:

func process(_ item: Item) -> Item

Ma può essere pessimo.

Questo è più utile:

func applica(_ coupon: Coupon, a carrello: Carrello) throws -> Carrello

La coerenza meccanica è solo il pavimento.

Checklist

Per un setup sano:

  • formatter scelto è documentato;
  • linter scelto è documentato;
  • comandi eseguibili da terminale;
  • CI controlla build, test e stile;
  • regole non troppo rumorose;
  • eccezioni motivate;
  • niente riformattazioni casuali fuori scope.

Esempio di policy breve

Build: swift build
Test: swift test
Format check: swift format lint --recursive Sources Tests
Regole manuali: niente DTO nel dominio, niente rete nei test unitari, niente singleton nascosti nei use case.

Questa policy collega stile meccanico e architettura. Il formatter sistema gli spazi; il team protegge i confini.

Esercizio

Definisci una mini policy per CouponKit:

  • quando è ammesso !;
  • come gestire Task.detached;
  • come nominare funzioni di dominio;
  • quale comando usare per formattare;
  • quale comando usare in CI.

Poi prendi una lezione precedente e individua tre punti in cui uno stile automatico aiuterebbe.