Domanda

La nostra politica nel fornire una nuova versione è quella di creare una filiale nel nostro VCS e gestirla nel nostro team di controllo qualità. Quando quest'ultimo dà il via libera, contrassegniamo e rilasciamo il nostro prodotto. Il ramo è tenuto a ricevere (solo) correzioni di bug in modo da poter creare rilasci tecnici. Tali correzioni di errori vengono successivamente unite sul trunk.

Durante questo periodo, il trunk vede il principale lavoro di sviluppo ed è potenzialmente soggetto a modifiche di refactoring.

Il problema è che c'è una tensione tra la necessità di avere un trunk stabile (in modo che l'unione delle correzioni di bug abbia successo - di solito non è possibile se il codice è stato ad esempio estratto in un altro metodo o spostato in un altro classe) e la necessità di riformattarla quando si introducono nuove funzionalità.

La nostra politica è di non effettuare alcun refactoring prima che sia trascorso abbastanza tempo e che la filiale sia abbastanza stabile. In questo caso, si può iniziare a eseguire modifiche di refactoring sul trunk e le correzioni di bug devono essere impegnate manualmente sia sul trunk che sul ramo.

Ma questo significa che gli sviluppatori devono attendere un po 'di tempo prima di eseguire qualsiasi modifica di refactoring sul trunk, poiché ciò potrebbe interrompere la successiva unione dal ramo al trunk. E dover portare manualmente i bug dal ramo al tronco è doloroso. Mi sembra che questo ostacoli lo sviluppo ...

Come gestite questa tensione?

Grazie.

È stato utile?

Soluzione

Questo è un vero problema pratico. Peggiora se hai diverse versioni che devi supportare e hai ramificato per ognuna. Ancora peggio se hai anche un vero ramo R & amp; D.

La mia preferenza era quella di consentire al trunk principale di procedere alla sua velocità normale e di non resistere perché in un ambiente in cui i tempi di rilascio erano importanti commercialmente non avrei mai potuto sostenere il caso in cui dovremmo consentire al codice di stabilizzarsi (" what , vuoi dire che l'hai rilasciato in uno stato instabile? ").

La chiave era assicurarsi che i test unitari che erano stati creati per le correzioni dei bug fossero passati attraverso quando il bug veniva migrato nel ramo principale. Se le tue nuove modifiche al codice sono veramente solo il factoring, i vecchi test dovrebbero funzionare altrettanto bene. Se le modifiche sono tali da non essere più valide, non puoi semplicemente eseguire il porting della correzione in ogni caso e dovrai far riflettere qualcuno sulla correzione nel nuovo flusso di codice.

Dopo alcuni anni nella gestione di questo tipo di problema, ho concluso che probabilmente hai bisogno di almeno 4 stream di codice per fornire supporto e copertura adeguati e una raccolta di processi piuttosto rigorosi per gestire il codice attraverso di essi. È un po 'come il problema di poter disegnare qualsiasi mappa in 4 colori.

Non ho mai trovato letteratura davvero valida su questo argomento. Sarà inevitabilmente collegato alla tua strategia di rilascio e agli SLA che firmi con i tuoi clienti.

Addendum: dovrei anche menzionare che era necessario scrivere il ramo unendolo come pietre miliari specifiche nel programma di rilascio del ramo principale. Non sottovalutare la quantità di lavoro che potrebbe comportare per riunire le tue filiali se hai una raccolta di sviluppatori che lavorano duramente per svolgere le loro funzioni di implementazione del lavoro.

Altri suggerimenti

Dove lavoro, creiamo filiali di lavoro temporanee, di breve durata (meno di un giorno - alcune settimane) per ogni cambiamento non banale (aggiunta di funzionalità o correzione di bug). Il trunk è stabile e (idealmente) potenzialmente rilasciabile in ogni momento; solo gli elementi completati vengono uniti in esso. Ogni cosa impegnata dal tronco viene unita ogni giorno nei rami di lavoro; questo può essere ampiamente automatizzato (usiamo Hudson, Ant e Subversion). (Quest'ultimo punto perché di solito è meglio risolvere eventuali conflitti prima che dopo, ovviamente.)

Il modello attuale che utilizziamo è stato ampiamente influenzato da un eccellente articolo ( che ho inserito prima ) di Henrik Kniberg: Controllo versione per più squadre agili .

(Nel nostro caso, abbiamo due team di scrum che lavorano su una base di codice, ma sono arrivato a pensare che questo modello possa essere utile anche con una squadra.)

C'è qualche sovraccarico riguardo alla ramificazione e alla fusione extra, ma in realtà non troppo, una volta che ci si abitua e ci si migliora con gli strumenti (ad esempio svn merge --reintegrate è utile) . E no, non creo sempre un ramo temporaneo, ad es. per refactoring più piccoli ea basso rischio (non correlati ai principali elementi attualmente in fase di lavorazione) che possono essere facilmente completati con un commit su trunk.

Manteniamo anche un ramo di rilascio precedente in cui i bug critici vengono corretti di volta in volta. Certo, potrebbe esserci un lavoro di fusione manuale (a volte noioso) se una parte particolare del codice si è evoluta in modo significativo rispetto al ramo. (Si spera che questo diventi un problema minore quando ci muoviamo verso il rilascio continuo di incrementi dal trunk (internamente) e lasciando che il marketing e la gestione del prodotto decidano quando vogliono fare una versione esterna.

Non sono sicuro se questo risponda direttamente alla tua domanda, o se puoi applicarlo nel tuo ambiente (con il team di QA separato e tutti) - ma almeno posso dire che la tensione che descrivi non esiste per noi e siamo liberi di rifattorizzare ogni volta. Buona fortuna!

Penso che la tensione possa essere gestita aggiungendo i seguenti ingredienti al tuo processo di sviluppo:

  1. Integrazione continua
  2. Test funzionali automatizzati (suppongo che contiate già con i test unitari)
  3. Consegna automatizzata

Con l'integrazione continua, ogni commit implica una build in cui tutti i test unitari vengono eseguiti e sei allarmato se qualcosa va storto. Inizi a lavorare di più con head e sei meno incline a ramificare la base di codice.

Con i test funzionali automatizzati, puoi testare la tua applicazione con un clic sul pulsante. In genere, poiché questi test richiedono più tempo, vengono eseguiti di notte. Con questo, il ruolo classico del controllo delle versioni inizia a perdere importanza. Non prendi la tua decisione su quando rilasciare in base alla versione e alla sua maturità, è più una decisione aziendale. Se hai implementato test unitari e funzionali e il tuo team sta inviando codice testato, head dovrebbe sempre dichiarare che può essere rilasciato. I bug vengono continuamente scoperti, corretti e rilasciati, ma questo non è più un processo ciclico, è continuo.

Probabilmente avrai due tipi di detrattori, poiché ciò implica cambiare alcune pratiche radicate da lungo tempo. Innanzitutto, il cambio di paradigma della consegna continua sembra controintuitivo per i manager. "Non stiamo rischiando di inviare un grosso bug?" Se dai un'occhiata alle distro Linux o Windows, è esattamente quello che stanno facendo: spingere i rilasci verso i clienti. E poiché conta con una serie di test automatizzati, i pericoli vengono ulteriormente ridotti.

Successivamente, team o dipartimento QA. (Alcuni sosterrebbero che il problema è la loro esistenza in sé!) Saranno generalmente avversi all'automazione dei test. Significa imparare uno strumento nuovo e talvolta complicato. Qui, il meglio è predicare facendolo. Il nostro team di sviluppo ha iniziato a lavorare su integrazioni continue e nello stesso tempo ha scritto la suite di test funzionali con Selenium . Quando il team addetto al controllo qualità ha visto lo strumento in azione, è stato difficile opporsi alla sua implementazione.

Infine, il punto è che il processo che ho descritto non è semplice come aggiungere 3 componenti al processo di sviluppo. Implica un profondo cambiamento nel modo in cui sviluppi il software.

Forse Git (o altri DVCS) sono più bravi a gestire le fusioni con il codice aggiornato grazie al fatto che gestiscono (davvero) le modifiche piuttosto che confrontare i file ... Come Joel afferma :

  

Con il controllo della versione distribuita, le fusioni sono facili e funzionano bene. Quindi puoi effettivamente avere un ramo stabile e un ramo di sviluppo o creare rami di lunga durata per il tuo team di QA in cui testano le cose prima dell'implementazione, oppure puoi creare rami di breve durata per provare nuove idee e vedere come funzionano.

Non ancora provato, però ...

Dove lavoro, continuiamo con il refactoring nel ramo principale. Se le fusioni diventano complicate, devono solo essere trattate su una base ad hoc, sono tutte fattibili, ma a volte impiegano un po 'di tempo.

Forse il nostro problema deriva dal fatto che abbiamo filiali che devono avere una vita abbastanza lunga (fino a 18 mesi) e ci sono molte correzioni che devono essere fatte contro di loro.

Assicurarci di derivare solo da un codice estremamente stabile sarebbe probabilmente d'aiuto, ma non sarà così facile ... :(

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top