Come mantieni il codice di sviluppo e il codice di produzione?

Quali sono le migliori pratiche e le regole pratiche da seguire per mantenere il codice? È buona norma avere solo il codice di produzione pronto nel ramo di sviluppo, o l’ultimo codice non testato dovrebbe essere disponibile nel ramo di sviluppo?

Come mantenete il vostro codice di sviluppo e il codice di produzione?

Modifica – Domanda supplementare – Il tuo team di sviluppo segue il protocollo “commit-as-soon-come-possible-e-spesso-anche-se-il-codice-contiene-minori-o-è-incompleto” o “commit- Protocollo “ONLY-perfect-code” durante l’inserimento del codice nel ramo DEVELOPMENT?

Tutto dipende dalla natura sequenziale della gestione del rilascio

Innanzitutto, è tutto nel tuo baule davvero per la prossima versione ? Potresti scoprire che alcune delle funzioni attualmente sviluppate sono:

  • troppo complicato e deve ancora essere raffinato
  • non pronto in tempo
  • interessante ma non per questa prossima release

In questo caso, trunk dovrebbe contenere qualsiasi sforzo di sviluppo corrente, ma un ramo di release definito prima che il prossimo rilascio possa servire come ramo di consolidamento in cui viene unito solo il codice appropriato (convalidato per la prossima release), quindi risolto durante la fase di omologazione, e infine congelato mentre entra in produzione.

Quando si tratta di codice di produzione, è necessario gestire anche i rami delle patch , tenendo presente che:

  • la prima serie di patch potrebbe effettivamente iniziare prima di essere rilasciata in produzione (nel senso che sai che entrerai in produzione con alcuni bug che non puoi aggiustare in tempo, ma puoi iniziare a lavorare per quei bug in un ramo separato)
  • le altre filiali di patch avranno il lusso di iniziare da un’etichetta di produzione ben definita

Quando si tratta di dev branch, puoi avere un trunk, a meno che tu non abbia altri sforzi di sviluppo che devi fare in parallelo come:

  • enorme refactoring
  • test di una nuova libreria tecnica che potrebbe cambiare il modo di chiamare le cose in altre classi
  • inizio di un nuovo ciclo di rilascio in cui è necessario incorporare importanti cambiamenti architettonici.

Ora, se il tuo ciclo di sviluppo-rilascio è molto sequenziale, puoi semplicemente andare come suggeriscono le altre risposte: un tronco e diversi rami di rilascio. Questo funziona per piccoli progetti in cui tutto lo sviluppo è sicuro di andare alla prossima versione, e può essere solo congelato e servire come punto di partenza per il ramo di rilascio, dove possono avvenire le patch. Questo è il processo nominale, ma non appena hai un progetto più complesso … non è più sufficiente.


Per rispondere al commento di Ville M.:

  • tieni presente che dev branch non significa ‘un ramo per sviluppatore’ (che innescherebbe ‘fusione follia’, in quanto ogni sviluppatore dovrebbe unire il lavoro di altri per vedere / ottenere il proprio lavoro), ma un ramo dev per sviluppo sforzo.
  • Quando questi sforzi devono essere riuniti nel tronco (o in qualsiasi altro ramo “principale” o di rilascio definito), questo è il lavoro dello sviluppatore, non – ripeto, NON – il manager SC (che non saprebbe come risolvere qualsiasi unione conflittuale). Il capo progetto può supervisionare l’unione, cioè assicurarsi che inizi / termini in tempo.
  • chiunque tu scelga per fare l’unione, il più importante è:
    • per avere unit test e / o ambienti di assemblaggio in cui è ansible distribuire / testare il risultato dell’unione.
    • avere definito un tag prima dell’inizio dell’unione per poter tornare allo stato precedente se tale unione si rivela troppo complessa o piuttosto lunga da risolvere.

Noi usiamo:

  • ramo di sviluppo in esclusiva

fino a quando il progetto è quasi terminato, o stiamo creando una versione milestone (ad esempio demo del prodotto, versione di presentazione), quindi (regolarmente) dirammo il nostro attuale ramo di sviluppo in:

  • ramo di rilascio

Nessuna nuova funzionalità entra nel ramo di rilascio. Nel ramo di rilascio vengono risolti solo bug importanti e il codice per correggere questi bug viene reintegrato nel ramo di sviluppo.

Il processo in due parti con un ramo di sviluppo e uno stabile (rilascio) rende la vita molto più facile per noi, e non credo che potremmo migliorarne una parte introducendo più rami. Ogni ramo ha anche il proprio processo di compilazione, ovvero ogni paio di minuti viene generato un nuovo processo di generazione e quindi, dopo un controllo del codice, abbiamo un nuovo eseguibile di tutte le versioni di build e rami entro circa mezz’ora.

Occasionalmente abbiamo anche filiali per un singolo sviluppatore che lavora su una tecnologia nuova e non provata, o che crea una dimostrazione del concetto. Ma generalmente è fatto solo se le modifiche riguardano molte parti della base di codice. Ciò accade in media ogni 3-4 mesi e tale ramo viene generalmente reintegrato (o rottamato) entro un mese o due.

Generalmente non mi piace l’idea di ogni sviluppatore che lavora nel suo stesso ramo, perché tu “salti e vai direttamente all’integrale dell’integrazione”. Vorrei fortemente sconsigliarlo. Se hai una base di codice comune, dovresti lavorare tutti insieme. Ciò rende gli sviluppatori più cauti sui loro check-in, e con esperienza ogni codificatore sa quali cambiamenti sono potenzialmente in grado di distruggere la build e quindi il testing è più rigoroso in questi casi.

Alla prima domanda del check-in:

Se richiedi solo il CODICE PERFETTO per il check-in, in realtà nulla dovrebbe essere archiviato. Nessun codice è perfetto, e per il controllo qualità per verificarlo e testarlo, deve essere nel ramo di sviluppo in modo da poter build un nuovo eseguibile.

Per noi ciò significa che una volta che una funzionalità è completa e testata dallo sviluppatore è stata archiviata. Potrebbe anche essere archiviata se ci sono noti bug (non fatali), ma in tal caso le persone che potrebbero essere interessate dal bug sono di solito informato. È anche ansible verificare il codice incompleto e in corso di lavorazione, ma solo se non causa ovvi effetti negativi, come arresti anomali o interruzioni della funzionalità esistente.

Ogni tanto un inevitabile controllo combinato di codice e dati renderà il programma inutilizzabile fino a quando il nuovo codice non sarà stato creato. Il minimo che facciamo è aggiungere un “WAIT FOR BUILD” nel commento del check-in e / o inviare una e-mail.

Per quello che vale, è così che lo facciamo.

La maggior parte dello sviluppo viene eseguita in trunk, anche se le funzionalità sperimentali o le cose che potrebbero rompere il sistema tendono in modo significativo a ottenere il proprio ramo. Questo funziona abbastanza bene in quanto significa che ogni sviluppatore ha sempre la versione più recente di tutto nella loro copia di lavoro.

Significa che è importante mantenere il tronco vagamente funzionante, poiché è perfettamente ansible romperlo completamente. In pratica ciò non accade spesso ed è raramente un problema significativo.

Per una versione di produzione, suddividiamo il trunk, interrompiamo l’aggiunta di nuove funzionalità e lavoriamo sulla correzione di bug e sul testing del ramo (che si fonde regolarmente nel trunk) finché non è pronto per il rilascio. A quel punto facciamo un’ultima fusione nel bagagliaio per assicurarci che tutto sia lì dentro, quindi rilasciare.

La manutenzione può quindi essere eseguita sul ramo di rilascio secondo necessità, e tali correzioni possono essere facilmente rimesse nel bagagliaio.

Non ritengo che questo sia un sistema perfetto (e ha ancora dei buchi – non penso che la nostra gestione delle release sia ancora abbastanza complicata), ma funziona abbastanza bene.

Perché nessuno lo menziona ancora? Un modello di branching Git di successo .

È per me l’ultimo modello di ramificazione!

Se il tuo progetto è di piccole dimensioni, non utilizzare sempre tutte le diverse diramazioni (forse potresti saltare i rami delle funzionalità per le piccole funzionalità). Ma in caso contrario, è il modo per farlo!

modello di ramificazione

Codice di sviluppo sulle filiali, codice in tempo reale taggato sul tronco.

Non c’è bisogno di essere una regola del “commit only perfect code” – tutto ciò che manca allo sviluppatore dovrebbe essere rilevato in quattro punti: la revisione del codice, test delle filiali, test di regressione, test finali del QA.

Ecco una spiegazione passo-passo più dettagliata:

  1. Fai tutto lo sviluppo su un ramo, impegnandoti regolarmente mentre vai.
  2. Codice indipendente Revisione delle modifiche una volta completato lo sviluppo.
  3. Quindi passare il ramo a Test.
  4. Una volta completato il test delle filiali, unire il codice nel ramo Release Candidate.
  5. Release Il ramo candidato viene sottoposto a regressione dopo ogni singola unione.
  6. Test finali di QA e UA eseguiti su RC dopo che tutte le filiali di sviluppo si sono fuse.
  7. Una volta passati QA e UAT, unire il ramo di rilascio nel ramo MAIN / TRUNK.
  8. Infine, tagga il trunk in quel punto e distribuisci quel tag su Live.

dev va in trunk (stile svn) e rilascia (codice di produzione) ottiene i propri rami

È il “modello di scopo Branch-by” (figura 3 in L’importanza dei modelli di ramificazione /! \ Pdf)

Risolviamo questo problema separando completamente il codice di produzione (il tronco principale) dal codice di sviluppo (in cui ogni sviluppatore ha il proprio ramo).

Nessun codice è consentito nel codice di produzione prima che sia stato accuratamente controllato (dal QA e dai revisori del codice).

In questo modo non c’è confusione su quale codice funzioni, è sempre il ramo principale.

Oh sì, un’altra cosa: manteniamo il codice di non produzione (cioè quello che non sarà MAI rilasciato – es. Script di strumenti, test di utilità) in HEAD cvs. Di solito deve essere chiaramente contrassegnato in modo che nessuno “accidentalmente” lo rilasci.

Sviluppiamo su un tronco che viene poi ramificato ogni due settimane e messo in produzione. Solo gli errori critici sono corretti nella filiale, il resto può aspettare altre due settimane.

Per trunk l’unica regola è che un commit non dovrebbe rompere nulla. Per gestire il codice wip e il codice non testato, aggiungiamo le statiche appropriate per semplificare l’triggerszione e la distriggerszione.

Fondamentalmente potrebbe essere ansible diramare il tronco in qualsiasi momento e metterlo in produzione.

Io uso git e ho 2 rami: master e maint

  • master – codice di sviluppo
  • maint – codice di produzione

quando rilascio il codice in produzione, lo taggato e unisco il master al ramo maint . Mi schiero sempre dalla maint branch. Patch dal ramo di sviluppo I cherry-pick loro di ramo maint e distribuire patch.

Abbiamo un ramo “release” che contiene ciò che è attualmente in produzione o verrà implementato a breve (già superato la maggior parte del QA)

Ogni progetto, o in alcuni casi un’altra unità, ha una propria filiale che è derivata dalla pubblicazione.

Le modifiche vengono commesse, dagli sviluppatori sul progetto, nella propria filiale del progetto. Periodicamente, il rilascio viene reimmesso in un ramo di sviluppo.

Una volta che i pacchetti di lavoro sul ramo sono tutti QA (test unitario, test di sistema, revisione del codice, revisione del QA, ecc.), Il ramo viene unito al ramo di rilascio. Le nuove build sono costruite dal ramo di rilascio e la validazione finale avviene su quella versione.

Il processo è fondamentalmente OK fino a quando non viene scoperto un problema dopo che è stata eseguita un’unione. Se un WP si “blocca” dopo che è stato unito, mantiene tutto dopo di esso fino a quando non viene corretto (non possiamo fare altro rilascio finché non viene rilasciato quello bloccato).


È anche un po ‘flessibile: un cambiamento molto banale potrebbe accadere direttamente sul ramo di rilascio se fosse rilasciato su una scala temporale molto breve (circa 1-2 giorni).

Se per qualche motivo un cambiamento è stato messo direttamente in produzione (un problema di produzione che incide sul cliente e che ha richiesto una modifica immediata del codice da correggere), tali modifiche verrebbero reinserite in BRANCH_RELEASE. Ciò accade quasi mai.

Dipende dal progetto. Il nostro codice web è controllato in modo abbastanza coerente, mentre il nostro codice applicazione viene controllato solo se viene compilato. Ho notato che questo è molto simile a come rilasciamo le cose. Le cose sul Web aumentano quando ansible mentre le applicazioni raggiungono una scadenza difficile. Non ho visto una perdita di qualità in entrambi i metodi però.