È buona norma richiedere il commit solo del codice funzionante? [duplicare]

33

A volte sento persone dire qualcosa come "Tutto il codice di commit deve funzionare". In alcuni articoli le persone scrivono anche descrizioni su come creare svn o git hooks che compilano e testano il codice prima del commit.

Nella mia azienda di solito creiamo un ramo per una funzione e un programmatore di solito lavora in questo ramo. Io spesso (1 per 100, penso e penso con una buona ragione) faccio commit non compilabili. Mi sembra che il requisito di "sempre compilabile / stabile" commetta conflitti con l'idea di frequenti commit. Un programmatore preferirebbe eseguire un commit in una settimana piuttosto che testare la stabilità / compilabilità dell'intero progetto dieci volte al giorno. Per il solo codice compilabile utilizzo tag e alcuni rami selezionati (trunk, ecc.)

Vedo questi motivi per il commit di codice non completamente funzionante o non compilabile:

  1. Se sviluppo una nuova funzione, è difficile farlo funzionare scrivendo poche righe di codice.
  2. Se sto modificando una funzione, a volte è difficile mantenere il codice sempre funzionante.
  3. Se cambio il prototipo o l'interfaccia di qualche funzione, farei anche centinaia di modifiche, non di modifiche meccaniche, ma intellettuali. A volte uno di questi potrebbe farmi eseguire centinaia di commit (ma se voglio che tutti i commit siano stabili, dovrei impegnarmi 1 volta anziché 100).

In tutti questi casi per fare commit stabili farei commit con molti e molti cambiamenti e sarà molto, molto, molto difficile scoprire "Cosa è successo in questo commit?".

Un altro aspetto di questo problema è che la compilazione del codice non garantisce il corretto funzionamento.

Quindi è una buona idea richiedere che ogni commit sia stabile / compilabile?

Dipende dal modello di ramificazione o CVS?

Nella tua azienda, è vietato eseguire commit non compilabili? È (e perché) una cattiva idea utilizzare solo rami selezionati (incluso il tronco) e tag per versioni stabili?

    
posta Astronavigator 14.11.2011 - 11:41
fonte

9 risposte

39

D: È consigliabile richiedere il commit solo del codice di lavoro?

A: dipende

Dovresti avere almeno 3 tipi di filiali nel tuo repository (anche se a volte 2 di queste sono uguali).

Produzione: il codice che risiede in un ramo destinato alla produzione dovrebbe sempre funzionare (come in una compilazione e passa tutti i test). L'invio di materiale che non supera i test è un grave reato e devono essere prese misure in modo che non avvengano mai (build giornalieri, orarie, ecc. Con test). Il codice dovrebbe compilare e superare i test .

Ultimo: questo ramo contiene l'ultimo codice stabile. È qui che ogni nuova funzionalità dovrebbe iniziare e terminare. Questo è anche il ramo che contiene il codice che finalmente entrerà nel ramo di produzione. Il codice dovrebbe compilare e superare i test .

Caratteristica: tutto può succedere nei rami delle funzionalità. Potresti essere nel bel mezzo di un grande refactoring o scrivere un sacco di nuovo codice. Non vuoi perdere nessuno di quei lavori, quindi commetti spesso, anche cose che non funzionano. Tuttavia , se stai lavorando su una funzione con più persone potresti voler impostare alcune regole di base come il codice dovrebbe compilare o decidere che dopo un certo punto, il ramo dovrebbe essere stabilizzato e i test dovrebbero passare successivamente. Il codice non deve compilare o superare i test (a meno che non decida dal team che lavora sulla funzione).

Per semplicità, ho usato commit nel mio testo sopra, ma questo vale anche per la combo commit / push dei sistemi di controllo della versione distribuiti.

    
risposta data 15.11.2011 - 05:15
fonte
15

Direi che dipende dal ramo in cui viene effettuato il commit. Un ramo di funzionalità potrebbe contenere errori commessi, ma tutto ciò che è stato eseguito o unito a un master oa un ramo di manutenzione deve compilare e passare la suite di test (se ce n'è uno).

    
risposta data 14.11.2011 - 11:47
fonte
8

Sometimes I hear people saying something like "All committed code must be working".

Questa è una regola valida, ma dovrebbe essere applicata con un po 'di buon senso. Le regole per ciò che è accettabile per il commit dovrebbero dipendere da dove stai accettando il codice.

È normale utilizzare una strategia di ramificazione che include alcuni o tutti i seguenti elementi:

  • rami specifici dello sviluppatore
  • rami specifici dell'attività
  • un ramo di sviluppo principale
  • rilascia i rami candidati
  • testing branches
  • un ramo di produzione
  • rami di versione
  • rami di patch

Diverse persone hanno idee diverse su quale tipo di regole dovrebbero governare i commit, e in ogni caso le regole per una determinata organizzazione dovrebbero essere specificate nell'SDLC dell'organizzazione. Tuttavia, sembra abbastanza chiaro che le regole dovrebbero essere sempre più restrittive mentre ti sposti dalla cima della lista alla fine. Quindi, ad esempio, gli sviluppatori potrebbero non essere autorizzati a commettere nulla sui tipi sotto il ramo di sviluppo principale della lista sopra. Certamente, tutto ciò che è impegnato nel ramo di sviluppo principale non dovrebbe essere solo compilato, ma funzionare (cioè passare tutti i test).

Ma per quanto riguarda lo sviluppatore e le filiali delle attività? Sembra ovvio che il codice impegnato in un ramo specifico dell'attività non debba necessariamente superare tutti i test. L'intero punto di un ramo specifico dell'attività consiste nel fornire il controllo della versione mentre l'attività viene completata; se si riuscisse a controllare solo il codice "funzionante", è possibile eseguire il commit solo su un ramo specifico dell'attività una volta, al termine dell'attività. Pertanto, potresti creare una regola per la compilazione del codice impegnato nei rami attività, ma non necessariamente per passare tutti i test.

I rami specifici dello sviluppatore dovrebbero essere ancora meno restrittivi. Le filiali degli sviluppatori dovrebbero essere come aree di lavoro private in cui puoi provare le cose. Essere in grado di impegnare il codice in un ramo di sviluppatori offre agli sviluppatori la libertà di provare le cose senza preoccuparsi di perdere il lavoro. Elimina la maggior parte del rischio associato a provare un'idea senza sapere prima che funzioni.

In some articles people even write descriptions how to create svn or git hooks that compile and test code before commit.

Anche in questo caso, tali hook possono essere utili per monitorare i commit al ramo di sviluppo principale, al ramo di produzione, ecc., ma non dovrebbero essere applicati ai rami degli sviluppatori. Un gancio del genere potrebbe essere utilizzato per indicare automaticamente se una determinata attività supera tutti i test, ma non dovrebbe impedire un commit.

    
risposta data 15.11.2011 - 06:01
fonte
7

Chiediti cosa succederebbe se ti fossi impegnato a metà di un grande sforzo di refactoring, poi venissi investito da un autobus. Cosa farebbero le altre persone della tua squadra? Potresti essere interessato a Git; con Git, puoi eseguire commit a livello locale, quindi inviare tali commit in blocco al server. Anche se il tuo server non usa Git, puoi usarlo per mettere in scena i commit localmente prima di spingere a qualcosa come CVS o SVN.

    
risposta data 14.11.2011 - 11:47
fonte
6

Diamo un'occhiata in questo modo.

Ti prendi una settimana di lavoro e quando torni ottieni l'ultimo codice dal repository di controllo della versione.

Esegui alcune modifiche che richiedono circa un'ora e poi le metti a provarlo. Il codice inizialmente non viene compilato, quindi trascorri un giorno a lavorare sulla rimozione degli errori nel codice che non hai nemmeno toccato, in modo che venga compilato.

Quindi scopri che non passa nessuna delle routine di test impostate per il tuo progetto e così trascorri un altro giorno a correggerlo e assicurandoti che tutti i test passino.

Impegni il codice e scopri che ci sono molti conflitti nel codice che hai scritto rispetto a ciò che si trova nel repository. Passi un altro giorno a risolvere i conflitti solo per scoprire che non passa nessuna delle routine di test eseguite un giorno fa.

Questo mi sembra una grande perdita di tempo. Nella mia esperienza, il codice non compilabile non ha valore e quindi non dovrebbe essere impegnato.

In effetti direi che su progetti che hanno routine di test automatizzate, il codice che non supera i test non dovrebbe essere impegnato neanche.

modifica

Vedo che hai modificato la tua domanda alla luce di tutte queste risposte.

Non hai mai affermato che stavi lavorando su un ramo separato (che di per sé può causare problemi se le fusioni sono troppo poche e lontane tra loro), ma rimarrebbe comunque il fatto che il codice non compilabile non debba essere eseguito .

Anche se il tuo codice non funziona, almeno se compila le persone possono unirlo, costruirlo, testarlo e dimostrare che non funziona.

Inoltre, non credo onestamente che tu faccia molte centinaia di modifiche al tuo codice e non lo compili mai.

Ovviamente ci sono molte strategie di sviluppo del software e alcune funzionano meglio di altre. Dalla mia esperienza, i test automatizzati (e anche lo sviluppo guidato dai test) sono una necessità, tanto più che i progetti diventano più grandi. Il bello è che tutti sanno che il codice funziona prima che venga eseguito il commit, che si tratti di un ramo o del trunk principale. Esistono molti strumenti che consentono di costruire e test automatici, ad es. regolazione automatica della velocità.

Ma la tua domanda iniziale non era la domanda su SDLC o strategie o anche se il codice impegnato dovesse funzionare, ma solo se il codice non compilabile dovesse essere eseguito.

    
risposta data 14.11.2011 - 11:56
fonte
4

Sembra che tu stia parlando di due cose distinte:

  • Il codice deve essere compilabile.
  • Il codice deve funzionare.

Per prima cosa, direi che tutto il codice impegnato dovrebbe essere compilabile prima del commit. Anche questo è abbastanza semplice da fare, come immagino che compilerai il tuo codice mentre apporti le modifiche. Alcuni IDE (ad esempio Eclipse) verranno compilati anche durante il salvataggio. Se stai facendo lo sviluppo attivo, compilare il tuo codice dovrebbe far parte del tuo flusso di lavoro, quindi questo requisito dovrebbe essere banale.

Il vantaggio di questo è che chiunque può entrare in qualsiasi momento e controllare il capo della propria filiale e iniziare a lavorare ulteriormente senza dover prima risolvere i problemi di compilazione. Quella persona potrebbe davvero essere te, dopo una pausa.

Il secondo è una questione più complessa e ha più flessibilità in quanto "lavorare" è una cosa molto soggettiva. Se stai creando una nuova funzione, spesso non funzionerà "per un certo periodo". Suggerirei di guardarlo in un modo leggermente diverso: cioè assicurandoti di non eseguire il commit del codice che interrompe qualsiasi altra cosa. Le rotture sono più facili da misurare.

Come sopra, questo è utile per chiunque (incluso te stesso) essere in grado di saltare direttamente nel ramo e avere un codice non rotto. Detto questo, dico spesso ai colleghi junior che possono andare avanti e trattare i propri rami di sviluppo personale come dominio proprio e commettere codice spezzato (ma ancora compilabile) se lo trovano utile.

Riguardo al tuo commento sull'impegno di molti file e sull'essere incapace di capire cosa è cambiato, il mio modo di lavorare è che io commetterò il codice in una singola "unità logica". Che si tratti di una modifica in un singolo file o di un refactoring su più file. Lavorando in questo modo, so esattamente cosa è cambiato per commit.

Un tema comune sopra è come i tuoi commit influenzano le altre persone e la loro capacità di lavorare. Lo sviluppo del software è uno sforzo collaborativo ed è importante riflettere e capire in che modo lo stato del codice influenza i colleghi.

    
risposta data 14.11.2011 - 21:42
fonte
4

Esegui il codice non funzionante? Sì. Premi codice non funzionante? No. Dovresti impegnarti presto e spesso nel tuo ramo privato. Ecco a cosa serve lo strumento, per tenere traccia delle modifiche. Quando il codice funziona e viene testato, puoi inviarlo ad altri.

Ovviamente, questo consiglio funziona solo con uno strumento SCM che fornisce sia un flusso di lavoro commit che push / pull. Se si utilizza un sistema centralizzato, non si deve assolutamente impegnare il codice sul server centralizzato a meno che non compili almeno una semplice regressione.

Se il tuo strumento non rende banale la creazione delle tue filiali private, scegli uno strumento migliore se possibile. Basta non andare a spingere / commettere il codice che altri possono usare a meno che non si sia ragionevolmente certi che non causi regressioni.

    
risposta data 15.11.2011 - 04:42
fonte
0

Per determinare se il codice funziona o no sono necessari test automatizzati. Se non li hai, avere la compilazione del codice è un minimo da inviare al ramo principale. Nel tuo ramo privato immagino che tu possa avere un codice che non viene compilato, ma probabilmente non è una buona idea; la ragione per inviare spesso è fare fusioni e evitare di perdere dati in caso di errore del disco. Se hai davvero tanta paura di perdere tutto il lavoro che ancora non compila, vuol dire che avrai un lavoro da far tornare a lavorare, non è proprio una bella idea. Se vuoi fare una fusione, probabilmente dovresti modificare il tuo modello di ramificazione, o provare a lavorare con meno dipendenze.

    
risposta data 14.11.2011 - 11:54
fonte
-1

Non sono d'accordo con il principio: "Impegnati spesso (ogni sera) per non perdere il lavoro." Un sistema di controllo della versione è lì per memorizzare revisioni significative del codice, non come una funzione di backup. È possibile utilizzare i backup (zip / copia / rsync) per salvare tutte le modifiche correnti.

Penso che dovresti solo convertire il codice che compila. Per questo: aggiorna / unisci lo stato corrente del repository, compila localmente, commetti. Il tempo impiegato per rimuovere i conflitti localmente è il tempo che altrimenti verranno spesi da diversi membri del tuo team quando recuperano le tue modifiche. Non forzare gli altri a correggere i tuoi errori, se possibile.

Dovresti anche provare a impegnare le funzionalità complete, poiché è più difficile tenere traccia delle modifiche che sono state commesse in fasi diverse. Se stai lavorando su funzionalità molto complesse, considera di lavorare in un ramo e quindi unire tutto al ramo principale in un solo passaggio.

    
risposta data 15.11.2011 - 07:38
fonte

Leggi altre domande sui tag