I feature branch hanno una notevole popolarità anche grazie alla diffusione di git e gitflow. Sono diventati uno standard al punto che ci sentiamo in dovere di utilizzarli. Sono assunti come preconcetti. Cerchiamo di capirne il perché.
Cosa sono i feature branch?
Potremmo discutere per ore sul significato di feature nell’ambito dello sviluppo software ma accordiamoci su questa semplice definizione: “Una funzionalità del nostro software”. Una funzionalità potrebbe essere qualcosa come “Creare un nuovo post”, “Aggiungere una immagine a una bozza”, “Cancellare un post”.
Questa imprecisa definizione non è realmente importante per il contesto. Dovremmo invece essere tutti d’accordo sul seguente assunto: qualunque sia la definizione formale di feature, più piccola è, meglio è:
- Da un punto di vista del business, più una funzionalità è piccola e più velocemente è implementata e quindi rilasciata sul mercato, iniziando a generare introiti prima
- Per il progetto, una funzionalità piccola vuol dire anticipare il feedback del cliente, permettendo maggiore reattività per correggere il tiro e rimanere profittevoli
- Per lo sviluppatore, una funzionalità piccola significa meno conflitti e meno mal di testa in fase di merge, oltre a un minore sforzo mentale per lo sviluppo in sé
Proviamo ora a dare una definizione di feature branch. Un feature branch altro non è un branch che contiene una feature.
Ogni qualvolta abbiamo a che fare con i feature branch, nella nostra testa si rinforza però la corrispondenza uno a uno tra le feature e i feature branch, al punto da creare dei vincoli mentali talmente radicati da sentirci a disagio anche solo a pensare di fare diversamente:
- committare parte di una feature direttamente sul branch develop (o qualunque sia il branch di sviluppo principale)
- mergiare il feature branch prima che la feature sia completata
- committare una piccola feature direttamente su develop, senza nessun altro branch
- usare lo stesso branch per due feature
- … qualsiasi altra azione che vada contro i nostri feature branch
Il razionale dei feature branch
Quali sono i vantaggi dei feature branch?
“Facilitano le code review tramite le merge request” potremmo dire, ma questo non è specifico dei feature branch dato che può essere fatto anche con un branch non-feature.
“Sono utili perché permettono di generare automaticamente il changelog per le release basandosi sui commenti dei commit di merge”, ma dubito che questa sia la ragione per cui decidiamo di adottare i feature branch.
Se il cliente decidesse, mentre una feature viene sviluppata, che quella feature non è più richiesta, se quella feature fosse interamente contenuta in un branch si potrebbe abortirne lo sviluppo con un semplice comando.
Ditemi, sinceramente, quante volte è capitato.
Penso sia assurdo decidere di adottare una tecnica solamente perché facilita un’operazione che potremmo dover eseguire una manciata di volte al massimo nella nostra vita quando poi abbiamo altre attività manuali e lente che eseguiamo quotidianamente: test, pulizia dello stile del codice, build, deploy…Oltretutto rimuovere una piccola feature incompleta dovrebbe essere sufficientemente semplice da poter esser fatto manualmente, tramite il revert
di alcuni commit.
Non usassimo i feature branch, ad un certo punto avremmo una feature incompleta presente su develop che potrebbe essere deployata in produzione prima che sia completa! Nessun cliente lo accetterebbe!
Questa è effettivamente una buona ragione per usare un feature branch, anche se non è l’unica possibile soluzione.
Il problema di una feature incompleta non è tanto che la feature sia in produzione quanto che sia disponibile per l’utente il quale, usando la feature non interamente funzionante, probabilmente penserà ad un baco e sarà frustrato nel provare ad utilizzarla. Esistono vari modi per far arrivare una feature incompleta in produzione senza indispettire l’utente:
- usare un feature toggle, ovvero una configurazione per abilitare o disabilitare interamente una funzionalità. In questo caso committeremmo la feature incompleta, nascosta dietro a un feature toggle disabilitato
- committare codice non ancora utilizzato: invece di iniziare l’implementazione partendo dalla UI, potremmo partire dal codice della logica di business che, non essendo ancora eseguito da nessuna parte dell’interfaccia utente, può essere deployata in produzione senza creare problemi
- iniziare ad aggiungere un nuovo endpoint api, non ancora documentato
- aggiungere una nuova versione di un endpoint già esistente, qualora si usasse il versionamento delle nostre api
- nascondere la UI che utilizza la nuova feature: senza usare un feature toggle, potremmo ad esempio applicare lo stile
display: none
al pulsante che cancella il post
Questi trucchetti non sono necessariamente sempre applicabili e sviluppare software in questo modo potrebbe essere rischioso con poca esperienza e senza prestare la massima attenzione ma dimostrano che il feature branch non è l’unica possibilità.
Siete un po’ più convinti che il feature branch sia uno dei tanti strumenti da poter adottare per risolvere alcuni problemi? Ovviamente con i suoi pro e contro.
Contro?
Certamente, e sono gli stessi dell’utilizzare branch normali, con l’aggravante che probabilmente un feature branch durerà più a lungo: ritardano l’integrazione, il che porta a un feedback tardivo, che porta a risposte più lente, oltre a merge più difficili. Nel caso migliore una feature sarà sufficientemente piccola da essere completata in uno o due giorni, il che vuol dire uno o due giorni prima che si possa mergiare e arrivi feedback.
Quando usare un branch?
A questo punto spero che la corrispondenza uno a uno inizi a sembrare sospetta e restrittiva.
Immagina di essere nel mezzo dello sviluppo di una feature e di fare un refactoring utile anche per la feature che sta sviluppando un collega. Una possibilità semplice per rendere il refactoring disponibile a chi serve è mergiare il branch su develop in modo che ognuno possa integrarlo nei propri sviluppi.
Ma così facendo sto mergiando un feature branch prima che la funzionalità sia completata!
Ok, prova però a dimenticare per un attimo la parola feature. Ho sviluppato un refactoring in un branch che ora viene mergiato. È così male?
Ma quel branch conteneva anche parte di una feature!
Se quella feature incompleta non esponesse all’utente un comportamento non funzionante ciò non dovrebbe creare problemi, giusto?
Dimenticare la connotazione di feature branch pone tutto sotto una luce differente.
Devo implementare una piccola feature, poche righe al massimo, solo un commit. Dovrei usare un feature branch? Perchè dovrei farlo? Che benefici otterrei?
Sto implementando una feature complessa in un branch. Temo si stia scrivendo molto codice e vorrei farne una review col team e iniziare a mergiare questa parte che è testata, funzionante e che non espone un comportamento errato all’utente. Posso mergiare? E perché no? Avrò feedback prima e gli altri sviluppatori potranno iniziare ad integrare il codice che stanno scrivendo con le mie modifiche, probabilmente evitando conflitti totalmente.
La prossima domanda che sorge spontanea è: quando allora dovrei usare un branch? Dovrei usare i branch?
Ci sono poche situazioni dove un branch è necessario. Mi vengono in mente le seguenti:
- sono le 18, sono nel mezzo di una feature ma la build è rotta e i test non passano ancora. Invece di lasciare queste modifiche solo in locale sul mio computer, potrei committarle su un branch remoto in modo che siano al sicuro sul server, senza rompere la build a nessuno
- Sto facendo pair da remoto, vogliamo cambiare ruolo ma il controllo remoto non funziona molto bene. Possiamo usare un branch per condividere il codice e continuare a fare pair. Ovviamente potremmo usare anche develop ma dipende da build, test, feature toggle, …
- Vengo interrotto e devo cambiare argomento urgentemente, voglio quindi salvare sul server la mia feature incompleta, senza test, che espone comportamenti non funzionanti. Uso un branch
- Voglio fare una review della feature che ho implementato, che è suddivisa in vari commit sparpagliati. In questo caso potrebbe essere più semplice fare la review a partire da un branch per vedere le modifiche tutte assieme.
In questi e molti altri casi un branch è uno degli strumenti che può essere usato per risolvere un problema.
Conclusioni
I branch sono uno strumento potente a nostra disposizione. Limitarli con la connotazione di feature branch solo perché qualcuno ha detto che è la best practice non ha senso. Piuttosto riflettiamo bene per scegliere il giusto strumento per il lavoro da fare!
Ringraziamenti
Vorrei ringraziare il Milano eXtreme Programming User Group the ha discusso con me circa il trunk based development, stimolando e ispirando quello che poi ho scritto in questo articolo.
Vorrei anche ringraziare molti colleghi che mi hanno ascoltato mentre li ammorbavo con le mie teorie sui branch.