Spring Boot: lo standard degli sviluppatori coreani e l’inversione del controllo

📖 15min read

La Corea del Sud è una “repubblica Spring”?

Se vuoi trovare lavoro come sviluppatore backend in Corea, c’è una domanda da cui è difficile scappare: “Sai usare Spring?”

Basta aprire un sito di annunci di lavoro: nove offerte su dieci indicano esplicitamente “esperienza con Spring Boot” tra i requisiti. Non a caso si parla perfino di “repubblica Spring”. Quando ero all’università, pensavo che fosse semplicemente una moda.

“Ma non basta scriverlo direttamente in Java? Perché usare proprio Spring, che è così pesante?” “Node.js o Python (Django) non sono più semplici?”

Ma entrando nel lavoro reale e passando attraverso progetti di grandi dimensioni, ho capito il motivo. Spring non era una semplice tendenza, ma un banco da lavoro standard affinato da tantissimi sviluppatori senior per costruire sistemi enterprise enormi e complessi in modo sicuro e veloce.

Questa serie parla proprio di come costruire, su quel banco da lavoro standard, un castello che non crolla: un Monolith.

Framework: perché non puoi fare tutto a modo tuo

Prima di entrare davvero nel discorso tecnico, c’è una cosa da chiarire. Che cos’è esattamente un framework? E in cosa si differenzia da una libreria?

L’avevo già accennato nella serie Re: Booting, ma la differenza decisiva tra i due sta in una sola domanda: chi ha il controllo?

Spring è un framework. Usare Spring, quindi, è quasi come firmare una promessa: “metterò un po’ da parte il mio stile personale e lavorerò come Spring mi chiede”. Il cuore di quel “fare come Spring vuole” è proprio il tema di oggi: la Inversion of Control (IoC).

“Per favore, smettetela di usare sempre new

La prima regola di quella promessa mi colpì parecchio. In pratica diceva: non usare new, uno degli operatori più fondamentali di Java.

All’università, se avevo bisogno di un oggetto, scrivere MemberService service = new MemberService(); era la cosa più naturale del mondo. Se mi serve qualcosa, la creo io stesso e la uso. Cosa ci poteva essere di più normale?

Ma una volta entrato in azienda e aperto un progetto Spring Boot, non trovavo da nessuna parte la parola chiave new. Al suo posto vedevo annotazioni insolite come @Autowired o @RequiredArgsConstructor.

“Aspetta un attimo: se nessuno crea l’oggetto, allora come fa a essere chiamato il metodo? Questa cosa funziona davvero?”

Quando lo chiesi a uno sviluppatore senior, la risposta suonò frustrantemente vaga: “Ci pensa Spring Container a iniettarlo, quindi non dobbiamo crearlo noi. Anzi, se usi direttamente new, poi il codice diventa molto più difficile da mantenere.”

Non riuscivo ad accettarlo. Ero io il proprietario del codice che scrivevo, quindi perché non potevo nemmeno creare liberamente un oggetto? Mi sembrava quasi una dittatura di Spring.

Lo costruisco io oppure uso qualcosa che qualcun altro ha preparato per me?

Lo chef e il responsabile degli ingredienti (IoC & DI)

Per capire perché questa regola apparentemente autoritaria sia necessaria, cambiamo metafora e spostiamoci nella cucina di un ristorante.

1. Il modo tradizionale (comando io)

Io sono uno chef, cioè una Class. Per cucinare mi serve un coltello, cioè una Dependency.

2. Il modo di Spring (comanda Spring)

Io sono sempre lo chef. Ma questa volta c’è un responsabile degli ingredienti e degli strumenti: lo Spring Container.

In altre parole, invece di gestire direttamente le risorse di cui ho bisogno, c’è qualcuno all’esterno che le gestisce e me le consegna. Questa è la Inversion of Control (IoC: Inversion of Control), e la tecnica concreta con cui si realizza è la Dependency Injection (DI).

Ricevere qualcosa tramite injection significa lasciare a qualcun altro il problema di scegliere e preparare gli strumenti.

[Code Verification] Perché new è pericoloso?

A parole è difficile percepirlo davvero. Mettiamolo a confronto direttamente nel codice. Immaginiamo di costruire un sistema di pagamento con carta.

1. Cattivo esempio: creazione diretta (accoppiamento forte)

public class PaymentService {
    // Ho scelto e creato io stesso una Samsung Card (con new)
    private final SamsungCard card = new SamsungCard();

    public void pay() {
        card.payment(); // Pagamento possibile solo con Samsung Card
    }
}

Il problema: un giorno il capo dice: “Passiamo a Hyundai Card, ha commissioni più basse!” A quel punto dovrei aprire il codice di PaymentService e sostituire ovunque SamsungCard con HyundaiCard. E se quel codice fosse sparso in cento punti diversi? Straordinari assicurati.

2. Buon esempio: dependency injection (accoppiamento debole)

public class PaymentService {
    private final Card card; // Non specificare un emittente concreto (usa linterfaccia)

    // Iniezione da costruttore: ti fidi che qualcuno dallesterno ti passi la carta
    public PaymentService(Card card) {
        this.card = card;
    }

    public void pay() {
        card.payment();
    }
}

Ora a PaymentService non importa più quale implementazione concreta della carta riceva.

    Questo è il cuore di ciò che nel lavoro reale si definisce “codice facile da mantenere”, o principio OCP. Ed è proprio questa flessibilità il vero motivo per cui si usa Spring Boot.

    Spring Container: un hotel per gli oggetti

    Allora chi è questo “responsabile” che crea gli oggetti e li distribuisce? È proprio lo Spring Container.

    Nel momento in cui avviamo il server Spring Boot con run, all’interno succedono moltissime cose.

    Il nostro compito è semplicemente attaccare sulla classe un’etichetta che dica “gestisci questo”, per esempio con @Service. Per tutto il resto ci pensa Spring, come l’enorme direttore di un hotel che tiene in ordine tutti i suoi ospiti.

    Consiglio pratico: usa l’iniezione tramite costruttore

    Spring offre vari modi per iniettare le dipendenze: field injection con @Autowired, setter injection e constructor injection. Ma nei progetti reali si raccomanda quasi sempre la constructor injection. È il pattern che di solito si usa insieme a @RequiredArgsConstructor di Lombok.

    @Service
    @RequiredArgsConstructor // Questo genera automaticamente liniezione da costruttore.
    public class OrderService {
        // si puo usare final, quindi e sicuro
        private final PaymentService paymentService;
    }
    
    

    Perché?

    In chiusura: non un mago, ma un direttore d’orchestra

    All’inizio Spring mi respingeva, perché avevo l’impressione che facesse del mio codice ciò che voleva. Adesso la vedo diversamente. Spring non è un dittatore che mi tormenta, ma un direttore d’orchestra capace che mette ordine in relazioni complesse tra oggetti.

    Grazie a questo, passo meno tempo a chiedermi “quale oggetto devo creare?” e posso concentrarmi di più su “come costruire la logica di business con questo oggetto?”. Probabilmente è proprio per questo che così tanti sviluppatori in Corea continuano ad amare Spring.

    Ora abbiamo affidato a Spring la gestione degli oggetti. Il server è pronto per partire. Ma un’applicazione web non gira da sola: deve parlare con il frontend. Ai tempi di PHP era comodo, perché HTML e codice vivevano nello stesso file. Allora perché oggi si separa il frontend, con Vue o React, dal backend? E perché compare un errore rosso di CORS non appena si cerca di collegare le due parti?

    Nella prossima puntata vedremo il cambiamento dell’architettura web, SSR vs CSR, e la vera identità di CORS, il muro che si alza in mezzo ai due.

    Lascia un commento