Ciclo di rilascio strano dell'azienda: vai al controllo del codice sorgente distribuito?


13

Mi dispiace per questo lungo post, ma penso che ne valga la pena.

Ho appena iniziato con un piccolo negozio .NET che funziona in modo leggermente diverso rispetto ad altri posti in cui ho lavorato. A differenza di qualsiasi delle mie precedenti posizioni, il software scritto qui è destinato a più clienti e non tutti i clienti ottengono contemporaneamente l'ultima versione del software. Pertanto, non esiste una "versione di produzione attuale". Quando un cliente riceve un aggiornamento, ottiene anche tutte le funzionalità aggiunte al software dall'ultimo aggiornamento, che potrebbe essere molto tempo fa. Il software è altamente configurabile e le funzionalità possono essere attivate e disattivate: i cosiddetti "toggle di funzionalità". I cicli di rilascio sono molto stretti qui, in realtà non sono in programma: quando una funzionalità è completa, il software viene distribuito al cliente interessato.

Il team solo l'anno scorso è passato da Visual Source Safe a Team Foundation Server. Il problema è che usano ancora TFS come se fosse VSS e impongono i blocchi di Checkout su un singolo ramo di codice. Ogni volta che una correzione di bug viene messa in campo (anche per un singolo cliente), essi semplicemente creano qualsiasi cosa sia in TFS, testano il bug che è stato corretto e lo distribuiscono al cliente! (Provengo da un background software farmaceutico e di dispositivi medici questo è incredibile!). Il risultato è che il codice dev mezzo cotto viene messo in produzione senza essere nemmeno testato. I bug scivolano sempre nelle build di rilascio, ma spesso un cliente che ha appena ricevuto una build non vedrà questi bug se non usano la funzionalità in cui si trova il bug. Il regista sa che questo è un problema poiché la società sta iniziando a crescere tutto all'improvviso con alcuni grandi clienti che salgono a bordo e altri più piccoli.

Mi è stato chiesto di esaminare le opzioni di controllo del codice sorgente al fine di eliminare la distribuzione di codice errato o incompleto, ma di non sacrificare la natura un po 'asincrona delle versioni dei team. Ho usato VSS, TFS, SVN e Bazaar nella mia carriera, ma TFS è dove la maggior parte della mia esperienza è stata.

In precedenza la maggior parte dei team con cui ho lavorato utilizza una soluzione a due o tre rami di Dev-Test-Prod, dove per un mese gli sviluppatori lavorano direttamente in Dev e quindi le modifiche vengono unite a Test e Prod, oppure promosse "al termine" anziché su un ciclo fisso. Sono state usate build automatizzate, usando il controllo della velocità di crociera o il Team Build. Nel mio precedente lavoro Bazaar era utilizzato seduto sopra SVN: gli sviluppatori lavoravano nelle loro piccole filiali e poi spingevano le loro modifiche a SVN (che era legato a TeamCity). È stato bello in quanto era facile isolare i cambiamenti e condividerli con i rami di altre persone.

Con entrambi questi modelli c'era un ramo centrale dev e prod (e talvolta test) attraverso il quale veniva spinto il codice (e le etichette venivano usate per contrassegnare build in prod da cui venivano rilasciate le versioni ... e questi venivano trasformati in branch per correzioni di bug ai rilasci e riuniti in dev). Questo non è proprio adatto al modo di lavorare qui, tuttavia: non c'è alcun ordine a quando verranno rilasciate varie funzionalità, vengono spinte quando sono complete.

Con questo requisito, l'approccio di "integrazione continua" secondo me non funziona. Per ottenere una nuova funzionalità con integrazione continua, questa deve essere spinta tramite dev-test-prod e questo catturerà qualsiasi lavoro incompiuto in dev.

Sto pensando che per ovviare a questo dovremmo scendere a un modello fortemente ramificato di funzioni senza NESSUN ramo di sviluppo dev-test, piuttosto l'origine dovrebbe esistere come una serie di rami di caratteristiche che quando il lavoro di sviluppo è completo sono bloccati, testati, riparati, bloccati , testato e quindi rilasciato. Altri rami delle caratteristiche possono prendere cambiamenti dagli altri rami quando ne hanno bisogno / desideri, quindi alla fine tutti i cambiamenti vengono assorbiti in tutti gli altri. Questo si adatta molto al modello puro di Bazaar rispetto a quello che ho vissuto nel mio ultimo lavoro.

Per quanto possa sembrare flessibile, sembra strano non avere un tronco di sviluppo o un ramo prod da qualche parte, e sono preoccupato per i rami che non desiderano mai reintegrarsi, o per i piccoli cambiamenti in ritardo che non vengono mai trasferiti ad altri rami e gli sviluppatori si lamentano unisci disastri ...

Quali sono i pensieri delle persone su questo?

Una seconda domanda finale: sono un po 'confuso circa la definizione esatta del controllo del codice sorgente distribuito: alcune persone sembrano suggerire che si tratta solo di non avere un repository centrale come TFS o SVN, altri dicono che si tratta di essere disconnesso (SVN è disconnesso al 90% e TFS ha una modalità offline perfettamente funzionante) e altri dicono che si tratta di Feature Branching e facilità di fusione tra rami senza relazione genitore-figlio (TFS ha anche una fusione priva di fondamento!). Forse questa è una seconda domanda!


Risposte:


5

Cosa definisce un DVCS?

Le distribuite in DVCS significa che ogni clone di un repository ha tutte le informazioni necessarie per impegnarsi, aggiornamento, ramo, unione o la ricerca di una revisione in quel repository, senza mai toccare un server . L'unica cosa che puoi fare offline svnè in realtà modificare i file - hai bisogno dell'accesso al server per quasi tutti i svncomandi, incluso fare qualcosa di semplice come un grepping svn loge quindi è più vicino allo 0% che al 90%!

Qualsiasi repository centrale autorevole che è possibile impostare in un flusso di lavoro DVCS è solo un altro clone e l'unica volta in cui è necessario interagire con esso è quando si eliminano gli aggiornamenti di altre persone o quando si spingono i propri cambiamenti in modo che altre persone possano vederli , praticamente tutto il resto può essere fatto off-line.

Quale modello di diramazione è appropriato?

Sono stato nella situazione in cui ti trovi adesso. Tali sistemi possono essere una vera sofferenza, ma devi capire le ragioni pragmatiche che sono diventate così e rendersi conto che non sono al di là della redenzione . Sono stati sviluppati molti strumenti che possono aiutare a gestire questo tipo di complessità .

Prima di tutto, qualunque cosa tu faccia, non mostrare alle persone il modello di ramificazione git di successo , li confonderà e li spegnerà. Invece, sviluppa il tuo modello che rifletta il tuo flusso di lavoro esistente , ma risolva i problemi con il tuo flusso di lavoro esistente .

Alcune risorse che potresti prendere in considerazione includono elementi come i sottomoduli git che permetteranno alle diverse versioni dei clienti di specificare diverse combinazioni di configurazione del cliente, moduli applicativi e librerie. Un'altra opzione sarebbe l'uso di un sistema di gestione delle patch per applicare code di patch specifiche per cliente / prodotto.

Entrambe queste opzioni forniranno maggiore flessibilità, trasparenza e sicurezza rispetto al tuo attuale flusso di lavoro e potrebbero essere più facili da usare rispetto a una strategia ancora più complessa. Vorrei certamente avere accesso a questi strumenti quando ero nella tua situazione.

Per ulteriori informazioni su queste opzioni, vedere le mie risposte a Strategia per utilizzare il controllo versione su un sistema modulare , Come utilizzare il repository Subversion all'interno del repository Git? e controllo sorgente / versione per l'applicazione utilizzata da più società .

In definitiva, questo è davvero qualcosa che dovrai sviluppare con il resto della squadra. Se hai la visione di proporre qualcosa che funzioni meglio di quello che hai già e puoi ottenere il buy-in dei tuoi colleghi sviluppatori, avrai un tempo molto più facile.

La cosa più importante è mostrare ai tuoi colleghi come ciò che proponi faciliterà la loro vita . Una volta che sono convinti, hai molte più possibilità di convincere il management a buttare via i loro investimenti in TFS e iniziare a utilizzare un modello più adeguato ai tuoi metodi di lavoro.


1
+1 per trovare il modello di ramificazione git adatto a te
jcmeloni

1
+1 per "rendere la vita più facile". Questo è il principale motivatore.

5

In primo luogo, DVCS è un'aringa rossa per i problemi che hai: lo strumento di controllo della versione in uso non è la radice dei problemi che devono essere risolti. Può darsi che ci siano aspetti delle soluzioni DVCS che sono "migliori" di TFS ma non è ciò che deve essere risolto a questo punto.

Hai identificato che hai bisogno di una struttura di ramificazione praticabile che si adatti alla tua organizzazione: penso che scoprirai che hai ancora un trunk, quando una funzionalità è completa viene riunita nuovamente nel trunk e chiusa. Ci sono alcuni pensieri positivi su come implementare anche le dipendenze comuni.

È inoltre necessario far funzionare l'integrazione continua (nessun motivo per non avere una build automatizzata per ogni ramo attivo per darti la sicurezza di poter costruire quel ramo e che supera i test pertinenti). Sono a disagio quando un commit (o almeno una "spinta") non fa scattare una build per me.

E devi iniziare i test automatici a tutti i livelli, ma in particolare i test unitari e i test di integrazione per iniziare a ridurre le possibilità che nuovi bug sfuggano allo stato selvatico. Quest'ultimo è enorme e qualcosa con cui sto ancora lottando, ma è chiaro che una volta che sai che puoi costruire le cose, questo avrà il massimo valore.

È necessario combinare questo per assicurarsi che i pacchetti di distribuzione provengano dal server di compilazione e che la distribuzione sia automatizzata per quanto possibile (si dovrebbe essere in grado di passare dall'artefatto del server di generazione al codice distribuito in tempo reale con il minimo sforzo e il minimo stress).

Hmm, ho ipotizzato che ci sia una buona configurazione di tracciamento dei problemi ben ordinata ... ne hai bisogno anche tu ed essere sicuro che sia usato correttamente. Idealmente, vuoi che le tue applicazioni live trasmettano automaticamente errori a questo sistema (o per il triage).

Infine, non cercare di risolvere tutti i tuoi problemi in una volta - costruire e test mi sembrerebbe essere il luogo su cui concentrarti per primo.


C'è una parte di me che concorda sul fatto che DVCS potrebbe essere anche un'aringa rossa: sono certamente d'accordo sul fatto che il problema riguarda il processo più di ogni altra cosa. Penso che l'integrazione continua possa essere un tratto qui e i test unitari non accadranno perché saranno visti come troppo lavoro. La base di codice non è comunque testabile in quanto è un sistema monolitico strettamente accoppiato e tutto si basa su tipi conici: nessuna interfaccia.
MrLane,

@MrLane - So che sarà difficile spiegarlo alle persone, ma da quando ho iniziato a sviluppare in modo TDD , sono sempre più convinto di non avere il tempo di non scrivere test.
Mark Booth,

1

La seconda domanda è più semplice e più breve, quindi proverò a partire da essa

Il DVCS è un sistema, in cui nessuna fonte di codice "autorevole" (tranne "di comune accordo", se utilizzato) e lo scambio di dati P2P è possibile senza livelli aggiuntivi (definizione personale, non canonica)

Sull'argomento la prima domanda

Temo che le aziende debbano ricostruire il flusso di lavoro e ripensare allo stile per ottenere "codice in qualche modo gestito e prevedibile". Non posso dire di TFS (tranne l'opinione personale e il sentimento, che è un sistema debole nella parte Controllo versione / unione senza base è male /), ma per qualsiasi VCS nella tua situazione ("Prodotto" è un insieme di "Moduli" indipendenti, ogni "Cliente" ottiene diversi "Prodotti" - questo presupposto è corretto?) Preferirò dividere lo sviluppo di moduli in rami separati, avere Prodotto come "Supermodule" (anche ramo?), lì ogni modulo è legato alla revisione specifica del modulo- branch, lo sviluppo del modulo utilizza il paradigma branch-per-task (e il branch del modulo è costituito solo da unioni).

In questo modo puoi sempre sapere, quale "Collezione" (ovvero un insieme di moduli e le relative revisioni) forma ogni "Prodotto", avere la possibilità di fare CI (per rami delle attività finiti e uniti ), Unit test e Build


1

Domanda principale dell'annuncio: credo che ciò di cui stai parlando sia esattamente ciò di cui git ha successo il modello di ramificazione (e lo strumento helper git flow per supportarlo). Avere un ramo principale, che è sempre nello stato distribuibile e fare tutto il lavoro sui rami delle caratteristiche.

Puoi anche usare il processo usato da git stesso, che deriva dallo stesso principio di base. Nello sviluppo di git-core, tutto il lavoro avviene sui rami delle caratteristiche. I rami delle funzionalità vengono inviati all'integratore, che esegue uno script per unirli tutti per creare un ramo denominato pu(aggiornamenti proposti). Diverse persone prendono questo ramo e lavorano con esso per testarlo.

Invece di integratore, è possibile fare in modo che il server di integrazione continua esegua questa unione all'inizio di una build. In questo modo ogni volta che qualcuno del team invia modifiche al repository centrale come ramo di funzionalità (probabilmente usando una convenzione di denominazione per dire quali rami dovrebbero essere selezionati).

In git al ramo della funzione che procede a next, mastero mainta seconda di quale rilasciarlo che sia indirizzato ad (maint è per i fix dei bug release corrente, master per versione corrente in preparazione e il prossimo per quello dopo), ma non avranno che molti.

Mentre le funzioni sono pu("cottura" nella terminologia di git maintainer), vengono riavvolte e il puramo viene scartato e creato di nuovo ogni volta, il che rende più facile la revisione, ma non adatto per basare altri lavori. Quando il ramo della funzione viene unito in una delle linee principali, viene chiuso per i riavvolgimenti e ulteriori correzioni vengono eseguite come nuovi commit.

Personalmente consiglierei il gitmeglio. Inizialmente è un po 'più difficile da imparare, perché cresce più organicamente, ma alla fine sembra più flessibile. Ma uno qualsiasi dei tre sistemi distribuiti, git, mercurial e bazaar ti servirà bene (e spesso puoi anche mescolarli, ad esempio mercurial può tirare e spingere verso / dal repository git e credo che così possa bazar).

Seconda domanda annuncio: mi è stato insegnato che "distribuito", in generale, significa che puoi spostare gli oggetti e mantenere la loro identità. Il che è esattamente ciò che fa il controllo della versione distribuita: clonate il repository e contiene gli stessi commit e consente di fare le stesse cose con loro. La facilità di diramazione e l'operazione di disconnessione sono le principali caratteristiche a livello di utente che seguono il principio dello spostamento dei commit e il layout grafico diretto che lo consente.


1

Sfortunatamente, non esiste una soluzione nota ai bug nel codice :)

Quindi stai solo cercando di impedire che i check-in incompiuti vengano catturati nella versione principale e l'unica risposta a ciò è la fusione tra filiali e lavoro per ogni sviluppatore. L'ho fatto in un'azienda precedente usando Clearcase, ha funzionato abbastanza bene (anche se dovevamo avere una dozzina di amministratori Clearcase).

Ora, presumo anche che tu esegua la correzione dei bug sulla versione del prodotto che ogni cliente attualmente ha ... quindi hai un problema di unione che porta correzioni di bug dalla versione A fino alla versione Z. Non c'è modo semplice di gestire questo, ma dovrai avere una filiale per ogni versione spedita. Il modo migliore per gestirlo è mantenere i rami delle funzionalità solo sull'ultima versione e fare in modo che i clienti si aggiornino per ottenere le nuove funzionalità, allo stesso tempo, eseguano la correzione di bug direttamente sul ramo di rilascio e unirli verso l'alto con tutti gli altri rami di rilascio quando completo.

Non troppo bello, ma può funzionare molto bene. Mantieni il codice organizzato e ben separato. È anche facile da capire per gli altri sviluppatori: piccole correzioni direttamente sul "codice", qualcosa di più di un paio di righe viene fatto su un ramo dedicato dove possono impiegare il tempo che vogliono per completarlo. (dovrai risolvere i problemi di unione e rassicurarli che è ok se 2 sviluppatori lavorano su 2 funzionalità contemporaneamente !!)

Dopo un po 'è possibile introdurre anche rami di funzionalità sui rami di rilascio, in cui i bug vengono corretti e poi uniti, ma IMHO in genere è più sforzo del necessario. Se è necessario aggiungere funzionalità alle versioni precedenti, è necessario seguire questo approccio: ramo di un ramo di rilascio, quindi unire nuovamente il codice in quella versione e unire la modifica anche alle versioni successive. Ciò renderà il tuo team di test molto infelice poiché le versioni saranno fortemente ritardate a causa della necessità di testare più versioni ripetutamente e il team di sviluppo non è soddisfatto poiché dovranno fare molta fusione prima di poter iniziare con un nuovo codice (nella mia azienda attuale questo accade, principalmente a causa della quantità di lavoro che abbiamo che deve sempre essere completa al più presto).

DVCS:

fondamentalmente un DVCS è dove ognuno ha la propria copia del repository server. Presenta alcuni vantaggi (specialmente nei team distribuiti con comunicazione limitata), ma presenta anche alcuni svantaggi, quindi verificali prima di passare a un DVCS. Se sei un negozio di Windows, probabilmente scoprirai che Mercurial è il DVCS migliore per te.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.