Perché Martin Fowler non ha capito il Feature Branching

Traduzione dell’articolo Why does Martin Fowler not understand feature branches

Una nota di aggiornamento: sembra che questo argomento abbia generato un discreto dibattito nella blogosfera e su Twitter. Nel caso tu fossi interessato a sapere cosa ne dicono gli altri e a seguire la discussione, ecco un po’ di link:

Assicurati di leggere i commenti a questi post per conoscere entrambe le posizioni.

Nel mondo dello sviluppo software, e in particolare nella comunità agile, Martin Fowler è quasi universalmente riconosciuto come suprema autorità su praticamente tutto. Non è come Joel Spolsky, che predica messaggi acquietanti farciti di specchietti per le allodole buoni solo per aumentare i link, tipo “inventati il tuo linguaggio di programmazione pur di non usare Ruby“, oppure “i principi SOLID sono troppo burocratici per essere comodi“. Fowler parla con i toni misurati di chi ha anni di esperienza maturati con grandi clienti enterprise. Di solito è tutt’altro che polemico e punta dritto al succo delle questioni. Adotta sempre un punto di vista neutrale. Non è semplicemente un coach agile, un luminare sulle metodologie agili: è uno degli autori stessi dell’Agile Manifesto. Ha scritto svariati libri innovativi sull’ingegneria del software, compreso Refactoring and Patterns of Enterprise Application Architecture. Uno della sua statura fa apparire al suo confronto i migliori di noi come scolaretti coi pantaloni corti.

Così, quando sono incappato nel video dove lui e il suo collega Mike Mason discutono dei rischi dei feature branch sono rimasto atterrito. Sì, atterrito: perché la maggior parte delle cose che sostengono è fuorviante e travisa il significato di branch-per-feature. Sembra il classico FUD anti-branch che mi sarei aspettato di sentire da strapagati rappresentanti di TFS e da venditori di software basato su Subversion, che hanno solo da perdere dai tool di versionamento di nuova generazione con i quali le pratiche di branching e merging sono diventate facili e sicure.

Si noti, prima di tutto, quel che Fowler e Mason sostengono.

  • Affermano che Feature Branching sia incompaibile con la Continuous Integration
  • Non dicono che a fare Feature Branching male ci si possa dare la zappa sui piedi e che si possa essere molto più produttivi a fare Feature Branching correttamente. Affermano che fare Feature Branching sia sbagliato. Punto.
  • Non sostengono che alcuni tool non siano adatti a fare Feature Branching e altri, al contrario, siano più indicati e che se ci si vuole ostinare ad usare i tool inadeguati esiste una tecnica alternativa per sfruttarli al massimo. Dicono che fare Feature Branching sia sbagliato tout-court. Punto

Ora, è possibile che Fowler e Mason controbatteranno che non intendevano dire questo e che io li abbia fraintesi, ma il problema è che è quel che gli allarmisti anti-DVCS capiranno, e com’è vero Dio, sfrutteranno questo fatto finché potranno. Di per certo, il tono dell’intero video nei confronti del Feature Branching è fortemente negativo. E in alcuni punti è fattivamente inaccurato.
Inoltre, l’alternativa che propongo non è migliore.

Il Feature Branching non ha niente a che fare con l’integrazione sporadica.

Fowler pone il Feature Branching in contrasto con la Continuous Integration, come se le due pratiche fossero l’una l’opposta dell’altra. Fowler sostiene che

la ragione fondamentale per la quale io utilizzo la Continuous Integration è perché tutti integrano il proprio codice sul troncone principale almeno una volta al giorno, mentre con il Feature Branching la gente va avanti per giorni e giorni, anche per settimane, fino a che conclude le proprie feature e può finalmente integrare il codice. Ed è proprio la frequenza di integrazione l’elemento chiave che fa la differenza.

No, no, no, no, no, no, no! Il Feature Branching non è affatto questo!

Il Feature Branching non ha niente a che fare con l’incrementare il tempo tra le intregrazioni: ha a che fare, invece, col diminuire il tempo tra i check-in. Usando il Feature Branching si suddividono comunque le feature da rilasciare in task il più possibile piccoli. Si integra comunque il più possibile, sì, almeno una volta al giorno, dove possibile. La differenza, con il Feature Branching, è che si esegue il check in del codice molte volte all’ora. Perché? Prima di tutto, perché è questo che fornisce i checkpoint utilizzabili per fare roll back non appena si scopre di aver commesso un errore; secondariamente, perché questo rende più semplici da descrivere e da decifrare le riflessioni che si fanno tra le varie attività di sviluppo.

Il motivo per cui la gente pensa che i Feature Branch siano adatti solo agli epic più lunghi è perché la vecchia scuola dei tool di versionamento centralizzati ha insegnato loro a pensare così. La gente si è persuasa che fare branch e merge fosse un’attività difficile per via dell’inefficienza dei tool, degli algoritmi di supporto e delle architetture della vecchia scuola; ha sempre incontrato problemi e così l’intero pattern ha auto-alimentato la propria autorevolezza.

La strategia giusta è quella di rendere branching e merging l’opzione stardard, così che si possa iniziare con merge piccoli e frequenti per arrivare, in modo naturale, a gestire gli epic via via che si acquista dimestichezza.

La dicotomia Feature Branching contro Continuous Integration è una falsa questione. Non è un fatto di “o l’uno o l’altro“: sono tecniche che possono essere applicate contemporaneamente.

I conflitti semantici non sono prerogativa del branching e del merging.

Fowler prosegue spiegando quale sia il problema legato ai conflitti semantici.

E il problema è che, sì, può essere anche possibile eliminare il problema dei conflitti testuali (e certamente gli algoritmi di merge si sono evoluti notevolmente negli ultimi 10 o 20 anni), ma restano i conflitti semantici che sono molto più complessi di quelli testuali; e quelli no, non sono stati risolti, e come risultato c’è ancora un gran timore nel fare merge, ed il timore cresce esponenzialmente più tempo si lascia passare tra le integrazioni.

Così, integrando ancora più frequentemente di quanto lo si stava già facendo, il codice da integrare diviene così poco da rendere trascurabili i problemi di conflitti semantici, e come risultato si può procedere più tranquillamente nel lavoro.

Mi spiace, ma questo è un uomo di paglia. Eh sì, i conflitti semantici sono un problema, ma non sono un problema legato a branching e merging. Qualsiasi tipo di integrazione genera conflitti semantici. Lo sviluppo trunk-based genera conflitti semantici. Un modello lock/edit/unlock come quello di Visual SourceFace, ha conflitti semantici.
Perfino quando tutti editano gli stessi file direttamente sul server, senza usare alcun sistema di versionamento, si generano conflitti semantici. I conflitti semantici sono un fatto della vita, indipendentemente dal modello di integrazione che si stia utilizzando. Facciamocene una ragione.

Inoltre, non sono i conflitti semantici di cui si dovrebbe aver più paura durante le integrazioni.

Perché, in ogni caso, quando ci si trova al momento di dover impazzire a gestire conflitti testuali sparsi ovunque, si avrà l’attenzione ai massimi livelli e si controllerà il codice molto meticolosamente.

I conflitti semantici dei quali ci si dovrebbe preoccupare sono quelli nei quali non si presenta affatto alcun conflitto testuale, tipicamente quando la dimensione delle integrazioni sarà ridotta ai minimi termini grazie alla Continuous Integration. In ogni caso, disponiamo di tool appositi per gestirli. Mi riferisco ai compilatori, alla static analysis, agli unit test. Così come per qualsiasi cosa che sfugga a questi controlli, tutto quel che si può fare è trattare i conflitti semantici alla stregua di qualsiasi altro bug. La questione è, piuttosto: quanti di questi conflitti semantici si traducono in nuovi bug e in regressioni rispetto ai bug introdotti da altre operazioni? È esattamente questo il criterio di interpretazione, quando si ha l’abitudine ad adottare il Feature Branching: né più né meno che come ad altre forme di bug.

Per quel che può contare, i conflitti semantici sono stato argomento di studi accademici, per esempio in questa ricerca, una lettura che può risultare interessante a tutti quelli che si interessano di conflitti semantici, della loro diffusione, dei rischi che espongono e di quelli che non espongono e anche delle strategie per mitigarne gli effetti. Ma sarebbe ingenuo ed errato essere troppo paranoici nei confronti del feature branching solo per via dei conflitti semantici, perché, come ho detto, si presentano anche nello sviluppo trunk-based.

Anche il Feature Toggle ha dei problemi, del resto.

Anzi, problemi ben più grandi e gravi. Il Feature Toggle è un sistema per evitare branching e merging: Joel Spolsky lo descrive come un “workaroud derivato dal fatto che il sistema di versionamento che hai adottato non fa quel che dovrebbe essere progettato per fare“. Anche il Branch by Abstraction è sostanzialmente la stessa cosa, tranne per il fatto che utilizza un container di Inversion of Control. Mike Mason lo descrive così:

Il Feature Toggle è un meccanismo per mezzo del quale si può implementare una nuova feaure ma, semplicemente, la si spegne, di solito tramite un’impostazione in configurazione. Nella maggior parte dei sistemi è facile prioprio come non includere una funzionalità nell’interfaccia grafica, per cui la funzionalità risulta implementata dietro le quinte, è presente nel codice sorgente ma semplicemente non è abilitata, così nessuno la vede.

Riesci a vedere il problema? E, credimi, è un grosso problema: si sta rilasciando in produzione del codice che si sa di per certo essere bacato, non testato, incompleto e probabilmente incompatibile con i dati di produzione.
Gli if del tuo codice e le impostazioni di configurazione sono essi stessi a tutti gli effetti codice soggetto a bug; è codice che può essere collaudato appropriatamente solo in produzione, che richiede molto sforzo di manutenzione e che è altamente esposto ad accidentali errori di digitazione. La possibilità di esposizione accidentale è un enorme rischio che può condurre troppo facilmente a vulnerabilità della sicurezza, corruzione di dati e perfino perdita di segreti aziendali. Le funzionalità del software possono essere molto meno isolate tra loro di quanto non si pensi e in più c’è il rischio che si possano rilasciare in produzione dei bug. E non sto parlando da un punto di vista teorico: è una cosa che ho sperimentato personalmente.

A meno che i feature toggle siamo veramente ben incapsulati e si disponga di un processo e di un’infrastruttura molto maturi atti a gestirli, si stanno cercando rogne. Di sicuro, le mie personali esperienze sull’argomento sono state sistematicamente negative.

Ma aspetta! Fowler prosegue dicendo di conoscere bene questi dubbi, ma utilizza dei termini molto più annacquati e indorati rispetto al deciso FUD che profonde contro i feature branch:

Il dubbio classico che questo approccio fa sorgere è: si sta rilasciando una feature incompleta nel codebase e, OK, non è visibile dalla UI; ma se si dovesse fare qualche modifica, si potrebbe rompere qualcosa? La risposta corretta è che si dovrebbe aver fiducia del proprio sistema di test automatico: è un componente che dovrebbe essere sempre presente per garantire che anche con delle feature parzialmente sviluppate e nascoste tramite Feature toggle non si rompa nulla.

Bene. Così, dove non averci dato la benché minima indicazione su come usare i feature branch efficacemente e responsabilmente, Fowler e Mason proseguono istruendoci su come usare responsabilmente, quando si concretizzerà, quello che è a tutti gli effetti un hack pesante da manuterere e ad altissimo rischio.

Se questa non è una visione di parte dell’argomento, allora cos’è?
Infatti, Fowler e Mason vanno avanti a parlare del caso di un cliente che aveva talmente tanti feature toggle che fu necessario eseguire una compilazione custom del kernel di Linux per gestirli.

Ma, abbastanza stranamente, non traducono questo fatto nella considerazione che “i feature toggle devono essere considerati dannosi, così come fanno per i feature branch.

Per quel che può contare, questo evidenzia un problema relativo all’idea stessa della Continuous Integration.

La Continuous Integration è essa stessa un workaround.

Sembra che tutto il FUD intorno al Feature branching ruoti intorno a un singolo assunto: ci si dovrebbe ricondurre allo sviluppo trunk-based perché la Continuous Integraion è il Solo Modo Corretto di gestire la configurazione. Ma permettetemi di fare giusto un passo indietro per chiedere: innanzi tutto, per quale motivo si fa Continuous Integration? Soprattutto perché si fa sviluppo trunk-based. Se si fa un check-in di codice che rompe la compilazione e poi si va a casa e qualcun altro fa check out, questo qualcun altro non può proseguire il lavoro finché chi ha provocato il danno non torna e non ripara il codice. Con lo sviluppo trunk-based si ha costantemente bisogno di una versione del codice pronta per il rilascio, nel caso di vulnerabilità sulla sicurezza. Anche se questo non completa il quadro ed esistono certamente molti altri argomenti a favore della Continuous Integration, è indubbiamente vero almeno in parte che questo sia un trucco che serve ad aggirare le limitazioni provocate dallo sviluppo trunk-based. La vaghezza della “regola del pollice” enunciata da Martin Fowler, cioè che si dovrebbe fare check in almeno una volta al giorno, lo testimonia.
Persuadere le persone a praticare il Cargo culting programming con suggerimenti di questo tipo conduce a fare il check in di codice incompleto, pieno di bug o persino clamorosamente rotto, e costringe alla necessità di trucchi costosi da manutenere come il Feature Toggle per compensarne i problemi.

È solo un trucco pensato per aggirare le limitazioni di un altro workaround, pensato a sua volta per superare le limitazioni dei propri tool. E tutto questo viene declamato ai quattro venti come una best practice. A che punto siamo arrivati?

Eppure, queste restrizioni non si applicano ai tool basati sui Directed acyclic graph, con i quali ci si può affidare tranquillamente alle più recenti tecniche di versionamento.
Sì, durante il branching e il merging possono capitare dei conflitti; sì, è anche possibile tirarsi la zappa sui piedi se non si procede con cautela; sì, si può anche arrivare al momento del Grande Spaventoso Merge, ma con una buona comunicazione e una buona pianificazione tra gli sviluppatori molti team possono (e riescono) a gestire con facilità e confidenza branch sorprendentemente lunghi con pochi o nessun problema. E sì, è anche possibile mantenere le unità di lavoro piccole quanto si desidera, così che possano essere integrate il più frequentemente possibile. Sì, il feature branching può essere usato impropriamente.

Ma la corretta risposta all’uso improprio non è l’invito all’abbandono, ma l’invito all’uso proprio e corretto.

Il fattore più pericoloso di tutta questa faccenda, comunque, è la reputazione di cui Martin Fowler gode. Molti agilisti lo vedono come un personaggio infallibile che parla ex cathedra di argomenti riguardanti metodologie e architetture; da parte sua, un discorso che promuove un punto di vista come questo è un invito a nozze per la lobby anti-DVCS, un argomento facile servito su un piatto d’argento.

Se ciò dovesse portare a un rifiuto radicale del Feature Branching e dei sistemi di versionamento distribuiti, si tratterebbe di un un passo indietro di anni per l’intero movimento agile; e questo sarebbe molto triste.

Quel che è realmente necessario, invece, è una revisione olistica ed imparziale sia del Feature Branching che della Continuous Integration, per comprendere come sia possibile utilizzare il Feature Branching responsabilmente e, allo stesso momento, per capire come la Continuous Integration e la Continuous Delivery possano essere sfruttati di conseguenza.

Insistere a suggerire di restare ancorati alle vecchie istituzioni, ignorando nuove e migliori tecnologie e Cargo Cult Programming, e questo non è certamente agile.

About these ads

One thought on “Perché Martin Fowler non ha capito il Feature Branching

  1. Grazie per la traduzione, come dicevo sulla ML XP-it il fatto di fare un branch per implementare una caratteristica non vuol dire necessariamente che debbano passare settimane o mesi prima che si faccia il merge nel ramo di sviluppo principale, o che il branch non possa essere aggiornato periodicamente o che i membri del team non debbano comunicare tra di loro.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s