Come usare (e non usare) le Migration in Laravel

1
2416

Da stamattina ho in testa di scrivere un articolo che parli di uno strumento che ritengo molto importante: le migration in Laravel, uno tool potentissimo che troppo spesso viene usato male.

Durante questo periodo di feste, infatti, ne ho lette di tutti i colori su gruppi, forum e così via. Ho deciso, quindi, di buttare giù qualche considerazione e darvi qualche consiglio che avrei voluto ricevere io, la prima volta che le ho studiate.

Prima di tutto, cosa sono?

Come la documentazione a riguardo ci suggerisce, le migration sono una sorta di sistema di versioning per il nostro database. Nelle migration c’è la storia del nostro database e viene spiegato il modo in cui questo è evoluto nel tempo. 

Grazie a questo strumento possiamo capire in che momento della storia della nostra app abbiamo avuto bisogno di memorizzare determinati dati, o magari quando invece abbiamo deciso di non usarli più. Ogni migration è un file che contiene due metodi:

  • up, che effettua la modifica di cui abbiamo bisogno;
  • down, che annulla tale modifica;

Questo è il primo aspetto importante da tenere a mente: grazie alle migration, infatti, possiamo spostarci nella storia del database in avanti e all’indietro.

Inoltre, usare le migration è fondamentale se lavoriamo con altre persone: è comodissimo poter avere una struttura del database unica e standard per tutti gli sviluppatori sullo stesso progetto. Le migration automatizzano un processo, ed ogni processo che automatizziamo riduce gli errori umani. E gli errori umani fanno schifo.

Primo consiglio: “up” e “down” devono essere SPECULARI!

Mi rendo conto che non è semplice applicare questo consiglio in alcune situazioni ma è il punto su cui batto di più: i metodi up e down di ogni migrazione devono essere speculari! In poche parole, down deve annullare SEMPRE il lavoro di up in ogni singola migration. Qualche esempio:

  • se in up creo una tabella, in down devo eliminarla;
  • se in up aggiungo delle colonne, in down devo eliminarle;
  • se in up aggiungo degli indici, in down devo eliminarli;
  • se in up elimino una colonna, in down devo ricrearla (e magari avere il modo di assegnare come minimo un valore di default);

Mi rendo conto che in casi come l’ultimo può essere davvero difficile essere fedeli a questo principio, ma vi prego: provate il più possibile ad applicare questa regola. In tanti, tantissimi non lo fanno. Ecco due possibili vantaggi:

  • in un ambiente locale, sarà semplicissimo costruire e ricostruire il database visto che sarà sufficiente eseguire un comando artisan;
  • in un ambiente di produzione, sarà possibile effettuare un rollback in caso di deploy andato male / bug o chissà cosa;

Non mi sembra poco…

Basta con phpMyadmin!

Fino a qualche anno fa usavo spesso phpMyAdmin oppure Adminer. Sono ottimi tool, senza dubbio, ma per cortesia smettiamo di usarli come default per effettuare operazioni sui nostri dati o, ancora peggio, sulla struttura dei nostri database.

Devo ammettere che l’idea per questo articolo mi è venuta guardando un post in cui qualcuno consigliava a qualcun altro di “fare la modifica al volo” con Adminer. Brrr.

Il motivo dovrebbe essere scontato: fare operazioni non automatizzate sui dati e sulla struttura aumenta la possibilità di errori, di inconsistenze e di problemi in generale, soprattutto quando si lavora in più persone sullo stesso codice.

Davvero, è letteralmente questione di un attimo sentire due colleghi che dicono “come mai hai quella tabella? Io da me non ce l’ho”.

Troppe migration? Squash!

Una delle obiezioni che mi fanno più spesso sulle migration, che francamente non ho neanche troppo capito (però va bene così), è che troppe migration porterebbero ad avere confusione nella codebase.

Ripeto, non capisco come: ho lavorato con repository da 100, 200 migration senza problemi. Sono la storia del database e, a voler essere precisi, qualche volta mi è stato utile poter spulciare in giro per risolvere un bug.

Perché la migration non ti dice solo COSA è successo, ma anche QUANDO. Se si usa Git, inoltre, è possibile sapere anche CHI. Sia chiaro: non per organizzare un’esecuzione in pubblica piazza…

In ogni caso, se rimanete fermi nella vostra convinzione che troppe migration sono il male… beh, ho una notizia per voi: adesso c’è il comando di dump.

Con un semplice php artisan schema:dump –prune, tutte le migration vengono “schiacciate” in un unico dump pronto all’uso, che viene messo nella cartella database/schema. Se viene specificata l’opzione –prune, inoltre, le migration esistenti vengono cancellate.

Lavoro con un database pre-esistente, cosa faccio?

Uno scenario che vedo sempre più spesso, ultimamente, è quello di un’app Laravel da realizzare sul famigerato database pre-esistente.

Niente sorrisini, tanto capita pure a voi prima o poi. Ed in quei casi meglio arrivare pronti. Quando succede a me, in genere, cerco di seguire una di queste tre strade possibili:

  • posso scappare via? Se sì, scappo. Altrimenti…
  • il database è stato creato da molto e contiene molti dati? Se la risposta è no, come primo tentativo cerco di riscrivermi le migration necessarie per replicare la stessa struttura. A volte riesco anche a sistemare qualche stranezza che mi evita grane in un secondo momento. Meglio qualche giorno in più di ragionamenti all’inizio se posso salvarne a decine dopo. Se la risposta, invece, è sì…
  • uso il comando di dump descritto poco più in alto per replicare una prima struttura del database, dopodiché uso le migration da quel punto in avanti;

Protip: se non usate una versione di Laravel che possiede il comando di dump, no problem. Nelle migration è possibile usare DB::statement per eseguire codice SQL. Quindi, non dovete fare altro che fare un backup della struttura del database esistente ed usare

per ogni tabella da ricostruire. Da quel punto in avanti… migration!

Concludendo…

… per ora queste sono le cose più importanti che mi vengono in mente quando si parla di migration e del loro uso in Laravel. Onestamente penso siano dei consigli che, in generale, si possono applicare anche ad altre tecnologie: il concetto di migration non è esclusivo di questo framework.

Nelle prossime settimane scriverò qualcosa riguardo i Seeder, molto spesso lasciati in secondo piano ma molto, molto interessanti.

EDIT: l’articolo sui seeder è pronto, leggilo qui!

Ogni suggerimento e commento, come al solito, è ben accetto se volete condividere qualche esperienza particolarmente interessante. Alla prossima!