Riformattazione e controllo della versione


23

La formattazione del codice è importante. Anche il rientro è importante . E la coerenza è più importante dei miglioramenti minori. Ma i progetti di solito non hanno una guida di stile chiara, completa, verificabile e applicata dal primo giorno, e miglioramenti importanti possono arrivare ogni giorno. Forse lo trovi

SELECT id, name, address
FROM persons JOIN addresses ON persons.id = addresses.person_id;

potrebbe essere scritto meglio come / è scritto meglio di

SELECT persons.id,
       persons.name,
       addresses.address
  FROM persons
  JOIN addresses ON persons.id = addresses.person_id;

mentre si lavora sull'aggiunta di più colonne alla query. Forse questa è la più complessa di tutte e quattro le query nel tuo codice o una banale query tra migliaia. Non importa quanto sia difficile la transizione, decidi che ne vale la pena. Ma come si tengono traccia delle modifiche al codice nelle principali modifiche alla formattazione? Potresti semplicemente rinunciare e dire "questo è il punto in cui ricominciamo", oppure potresti riformattare tutte le query nell'intera cronologia del repository.

Se stai usando un sistema di controllo di versione distribuito come Git, puoi tornare al primo commit di sempre e riformattare da lì allo stato attuale. Ma è un sacco di lavoro e tutti gli altri dovrebbero mettere in pausa il lavoro (o essere preparati per la madre di tutte le fusioni) mentre continua. Esiste un modo migliore per cambiare la cronologia che offre il meglio di tutti i risultati:

  • Lo stesso stile in tutti i commit
  • Lavoro di unione minimo

?

Per chiarire, non si tratta delle migliori pratiche all'avvio del progetto, ma piuttosto cosa si dovrebbe fare quando un grande refactoring è stato considerato Good Thing ™ ma si desidera comunque una cronologia rintracciabile? Non riscrivere mai la cronologia è fantastico se è l'unico modo per garantire che le tue versioni funzionino sempre allo stesso modo, ma per quanto riguarda i vantaggi per gli sviluppatori di una riscrittura pulita? Soprattutto se hai modi (test, definizioni di sintassi o un binario identico dopo la compilazione) per assicurarti che la versione riscritta funzioni esattamente allo stesso modo dell'originale?


24
Perché vorresti riscrivere la storia? Sconfigge lo scopo del controllo della versione. Vuoi assicurarti che l'applicazione che hai spedito 3 mesi fa corrisponda alla revisione xxxxxx senza il minimo dubbio. Anche una banale riformattazione è inaccettabile.
Simon Bergot,

5
Mi piace commentare, mi impegno a farlo con l'etichetta "Reformat. Nessun cambiamento funzionale"
Rig,

3
Su un argomento non correlato, sembra che tu stia suggerendo di riscrivere la storia di Git riformattando tutto il codice. Non dare idea alle persone, riscrivere la cronologia di Git è negativo per il 99,9% dei casi. La riformattazione non è il caso limite dello 0,1%.
Andrew T Finnell,

4
In alcune lingue (ti guardo, Python) la riformattazione può cambiare il funzionamento logico del codice. Dovresti essere in grado di analizzare tutte le lingue memorizzate nel tuo VCS per tracciare e ignorare i riformati in modo sicuro.
Joris Timmermans,

3
I riformati sono modifiche al codice e dovrebbero essere impegnati come tali.
David Cowden,

Risposte:


26

Esegui la riformattazione come commit separati. Ciò interferirà minimamente con la cronologia e dovresti essere in grado di vedere a colpo d'occhio quali commit stanno solo riformattando e che cambiano effettivamente il codice. Potrebbe essere distorto git blamee simile, ma se indica un impegno di solo riformattazione, è abbastanza semplice cercare il cambiamento precedente prima di quello.


Ho visto progetti deragliati per settimane perché uno degli sviluppatori ha pensato che fosse una buona idea. Se lo farai, comprendi in anticipo i rischi e decidi esattamente fino a che punto vai con la formattazione. Penso che mjfgates abbia la risposta giusta.
Johntron,

1
Sembra che il team in questione abbia problemi più grandi della formattazione del codice. Ma sì, non consiglio di farlo a meno che tu non debba farlo. Se si desidera apportare modifiche alla riformattazione, direi ancora meglio eseguirle come commit separati piuttosto che mescolati con modifiche funzionali.
Harald,

Sì, molti problemi: PI vuole solo avvertire i nuovi sviluppatori che non è semplice come sembra. Gli strumenti di riformattazione in blocco sono rischiosi (specialmente se lo costruisci tu stesso con regex - almeno usi AST), e se ti preoccupi della revisione del codice e del tracciamento dei bug, può davvero rovinare il tuo processo. Personalmente, scrivo il mio codice per essere coerente con lo stile di ogni file, anche se non mi dispiace rivedere il codice quando alcune funzioni vengono riformattate. Molti sviluppatori rimangono
bloccati

In programmazione, niente è così semplice come sembra :)
harald

13

Non riscrivere la storia di VCS: è contro i principi di VCS.

Non tentare di automatizzare la correzione della formattazione: tratta i sintomi, non il vero problema (= gli sviluppatori non seguono gli standard di codifica).

Definire lo standard di codifica e le migliori pratiche di formattazione in un documento comune e far concordare tutti gli sviluppatori.

Hai citato Git, il che è fantastico, perché è distribuito. Con un DVCS è molto semplice applicare le migliori pratiche attraverso il flusso di lavoro del gatekeeper . I gatekeeper rifiutano le proposte di unione (= richieste pull in Git) che non sono conformi alle linee guida comuni. E intendo rifiutare , in grassetto, altrimenti il ​​programmatore in violazione non si preoccuperà di seguire le regole e continuerà a ripetere gli stessi errori.

Questa tecnica funziona bene per me. I programmatori vogliono che il loro lavoro sia unito, quindi dopo alcuni errori all'inizio iniziano a seguire le regole.

Per quanto riguarda la correzione della base di codice esistente ... ti consiglio di farlo gradualmente, forse modulo per modulo, o come ha senso per il tuo progetto. Prova attentamente ad ogni passaggio. Può sembrare stupido, ma si verificano errori anche con cambiamenti banali come solo la formattazione, quindi preparatevi per alcuni piccoli dossi sulla strada.


1
Sottovalutato, perché l'autore afferma chiaramente che questo è nel contesto di progetti che non sono iniziati con "... una guida di stile chiara, completa, verificabile e applicata dal primo giorno". Non può trattare il vero problema, perché è già successo. Sono d'accordo con te però :)
Johntron,

2
rifiutare significa che ci sarà una lotta tra gli umani e il robot. Stato lì. Prima o poi, il robot richiederà una parte di codice davvero complessa per essere formattato in modo illeggibile. Esempi: una stringa Java è in realtà un'istruzione SQL, ma il robot non lo sa; gli spazi bianchi prima della chiusura delle parentesi possono contenere informazioni sulla struttura del codice per l'uomo, ma non per il robot; i parametri delle funzioni vengono suddivisi su più righe nel modo più insignificante ...
18446744073709551615

9

La risposta alla tua vera domanda è "Non lo fai". Non conosco nessuno strumento SCM corrente in grado di tracciare le modifiche nella logica dal codice formattato in un modo, attraverso una modifica sostanziale della formattazione e attraverso ulteriori modifiche dopo che il codice è stato formattato nel nuovo modo. E, lo sai, perdere la cronologia su un pezzo di codice non è buono.

Di conseguenza, contraddirò un po 'la tua prima frase. Codice di formattazione non importa che molto. Pretty è carino, ma non è per questo che siamo qui. Capisco bene quanto a chiunque il fatto di essere scaricato nel vecchio e strano infernale codice variante K&R di qualcuno con i rientri a due spazi fa schifo (1), ma ... la formattazione non è in realtà un ostacolo per capire cosa sta succedendo, a meno che non sia qualcosa di eccezionalmente patologico. E in tal caso, avrai comunque problemi a cambiare il codice e non dovresti disturbarlo.

Pertanto, non vale la pena apportare modifiche rigorosamente al codice stabilito per riformattarlo. Cambiando i nomi delle variabili, spezzando le lunghe funzioni, tutte quelle cose buone di refactoring che cambiano il contenuto, sì, ma non SOLO riformattazione.

1) - Ho posseduto una volta il Visualizzatore degli Appunti di Windows per un po '. Il tutto era uno, 150k, modulo C. Ho trovato un posto in cui diverse persone avevano usato, credo, cinque diversi stili di controvento a trenta righe l'una dall'altra. Ma quella sezione di cose ha funzionato. Ho portato in giro una stampa di quel pezzo di codice per dieci anni, ma non l'ho colpito perché la storia contava e quel codice era in almeno tre alberi di origine (Windows 3.x, NT, futuro 95) che vivevano tutti in diversi edifici.


In passato, usando hg, ho scoperto che l'unione per parti è uno strumento prezioso per far fronte alle grandi e complesse fusioni di ri-fattori . In genere ciò che farei è unire i commit prima del grande re-factor, quindi unire il grande re-factor stesso e infine unire i commit dal re-factor. Ognuna di queste tre fusioni da sola è molto più semplice quindi cercare di districare il disordine che deriva dal fare tutte le fusioni in una volta sola.
Mark Booth,

Sono totalmente d'accordo! Inoltre, ho visto molti sviluppatori esagerare (inclusa una versione più giovane di me stesso) sulla riformattazione e sullo stile del codice e finiscono per introdurre difetti. Una virgola / punto e virgola mancanti qui, le dichiarazioni delle variabili spostate in cima alle funzioni, i for-loop cambiati in for-each - possono tutti introdurre bug sottili. Ci vuole una quantità ingannevole di abilità per apportare questi cambiamenti in sicurezza.
Johntron,

4

Ma come si tengono traccia delle modifiche al codice nelle principali modifiche alla formattazione?

Le modifiche alla formattazione sono modifiche al codice; trattali come faresti con qualsiasi altra modifica al tuo codice. Chiunque abbia lavorato a un progetto significativo avrà probabilmente visto bug e altri problemi creati quando qualcuno ha deciso di "semplicemente" riformattare un codice.

Ma è un sacco di lavoro e tutti gli altri dovrebbero mettere in pausa il lavoro (o essere preparati per la madre di tutte le fusioni) mentre continua.

Perché devi riformattare tutto allo stesso tempo? Soprattutto se la riformattazione non modifica il significato del codice, dovresti essere in grado di riformattare i file singolarmente e archiviarli man mano che procedi. Meglio, fai in modo che tutti nel tuo team siano d'accordo su uno stile (altrimenti non ha senso riformattare comunque) e fai in modo che tutti si occupino della riformattazione nel corso del loro altro lavoro. Dopo un po ', avrai coperto la maggior parte del codice senza interrompere il resto del progetto.


1

Ci sono due possibili approcci che ho visto per questo.

1. Riformattare il codice su commit-hook

Anche se inizialmente è necessario cambiare il codice dopo averlo inviato, se la tua procedura di riformattazione (es. Astyle ) non danneggia il codice, allora è un'operazione sicura. Nel tempo, tutto il team apprezzerà che tutto il codice alla fine avrà lo stesso aspetto. Chiaramente, avere test unitari / automatizzati completi garantirà che nulla si rompa.

2. Formattazione una tantum di tutto il codice

Questo è più pericoloso nella mia esperienza e rende difficili i problemi di tracciamento nel big bang, ma è possibile. Eseguire tutti i test in seguito è essenziale. Per lo stile di codifica, la maggior parte delle differenze ruota attorno all'uso dello spazio bianco - rientro o newline. Uno strumento di unione decente dovrebbe essere in grado di dire di ignorare tutte le differenze di spazi bianchi, quindi questo aiuterà con le fusioni.


1
L'opzione 1 quando attivata su ripple nella maggior parte della base di codice si tradurrebbe rapidamente nello stesso big bang di avere ogni cambio di file?
Firma il

@Sign: Esattamente il mio punto - Quando l'hook del commit cambia, la tua storia potrebbe deteriorarsi in qualcosa di quasi inutile. La formattazione che non modifica la funzionalità non dovrebbe essere un commit, ma dovrebbe essere trapiantata in tutta la cronologia del codice.
l0b0,

1
Se l'IDE lo supporta, allora c'è anche 3) avere l'IDE formattazione automatica al salvataggio. Quindi utilizza le stesse impostazioni ovunque: questo è più semplice se utilizzi l'impostazione predefinita con l'IDE.

Ho fatto entrambi questi approcci. Il primo approccio è molto invadente perché ci saranno un sacco di modifiche ogni volta che viene eseguito il commit di un nuovo file per la prima volta. Il secondo approccio è migliore per il team, come strappare un cerotto veloce.
Druska,
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.