Ho modificato una firma del metodo e ora ho oltre 25.000 errori. E adesso?

166

Ho recentemente iniziato un nuovo lavoro dove sto lavorando su un'applicazione molto grande (15M loc). Nel mio precedente lavoro avevamo un'applicazione altrettanto grande ma (nel bene o nel male) usavamo OSGi, il che significava che l'applicazione era suddivisa in molti microservizi che potevano essere modificati, compilati e distribuiti in modo indipendente. La nuova applicazione è solo una grande base di codice, con forse un paio di .dll.

Quindi ho bisogno di cambiare l'interfaccia di questa classe, perché è quello che il mio capo mi ha chiesto di fare. Inizialmente lo hanno scritto con alcune supposizioni che non si generalizzano troppo bene, e per un po 'hanno evitato il problema del refactoring perché è così strettamente accoppiato. Ho cambiato l'interfaccia e ora ci sono oltre 25000 errori. Alcuni degli errori sono presenti nelle classi con nomi importanti come "XYZPriceCalculator" che in pratica non dovrebbero interrompere. Ma non posso avviare l'applicazione per verificare se funziona fino a quando tutti gli errori sono stati risolti. E molti dei test unitari fanno riferimento direttamente a quell'interfaccia, o sono accoppiati a classi base che fanno riferimento a quell'interfaccia, quindi il solo aggiustamento di questi è un compito piuttosto enorme in sé. Inoltre, non so davvero come tutti questi pezzi combacino, quindi anche se potessi farlo iniziare, non so davvero come sarebbe se le cose fossero rotte.

Non ho mai affrontato un problema del genere nel mio ultimo lavoro. Cosa devo fare?

    
posta user788497 04.11.2016 - 03:01
fonte

9 risposte

349

25000 errori significa fondamentalmente "non toccarlo". Cambialo indietro Crea una nuova classe con l'interfaccia desiderata e sposta lentamente i consumatori della classe su quella nuova. A seconda della lingua, puoi contrassegnare la vecchia classe come deprecata, che potrebbe causare tutti i tipi di avvertimenti del compilatore, ma in realtà non distruggerà la tua build.

Sfortunatamente queste cose accadono nelle vecchie basi di codice. Non c'è molto che puoi fare se non lentamente migliorare le cose. Quando crei le nuove classi, assicurati di testarle correttamente e crearle utilizzando i principi SOLID, in modo che possano essere più facili da modificare in futuro.

    
risposta data 04.11.2016 - 03:35
fonte
80

Dividi e vinci con i refactoring

Spesso, la suddivisione delle modifiche che è necessario eseguire in passaggi più piccoli può essere d'aiuto in quanto è possibile eseguire la maggior parte dei passaggi più piccoli in un modo che non interrompa affatto il software. Gli strumenti di refactoring aiutano molto con tali compiti.

Divide

Innanzitutto, identifica le modifiche più piccole possibili (in termini di modifiche logiche, non in termini di LoC modificato) che riassumono il cambiamento che desideri ottenere. Soprattutto cerca di isolare i passaggi che sono puramente refactoring e può essere eseguito da strumenti.

Conquer

Per casi complicati come il tuo, può essere logico eseguire un piccolo refactoring alla volta e quindi lasciare che il problema si riposi, in modo che tutti i sistemi di integrazione continui possano verificare il cambiamento, e forse anche il team di test ha dato un'occhiata. Questo convalida i passaggi che fai.

Per eseguire un particolare refactoring, è assolutamente necessario il supporto degli strumenti per un caso in cui si hanno 25.000 siti di chiamata del metodo che si desidera modificare. Forse anche i lavori di ricerca e sostituzione, ma per un caso così critico, sarei spaventato da quello.

Esempio

In C #, ad esempio, è possibile utilizzare Resharper a modifica della firma di un metodo. Se la modifica è abbastanza semplice, ad es. aggiungendo un nuovo parametro, , puoi specificare quale valore deve essere usato nei siti di chiamata che altrimenti avrebbero un errore di compilazione.

Sei immediatamente in una code base priva di errori e puoi eseguire tutti i test unitari, che passeranno, perché era solo un refactoring.

Una volta che la firma del metodo sembra buona, puoi andare e sostituire i valori che Resharper ha aggiunto come argomenti al parametro appena introdotto. Questo è non un refactoring più, ma hai una base di codice priva di errori e puoi eseguire i test dopo ogni riga che cambi.

A volte non funziona

Questo è un approccio molto utile per casi come il tuo, in cui hai molti siti di chiamata. E ora hai un software funzionante, quindi potrebbe essere possibile eseguire piccoli passaggi di refactoring per modificare la firma solo un po ', quindi fare un altro.

Purtroppo non funzionerà se la modifica della firma è troppo complessa e non può essere suddivisa in modifiche più piccole. Ma questo è raro; suddividere il problema in problemi più piccoli di solito mostra che è possibile.

    
risposta data 04.11.2016 - 08:37
fonte
36

Chiarifica il tuo compito con il tuo capo per aiutarlo a capire il problema e le tue esigenze come sviluppatore di software professionale.

Se fai parte di una squadra, cerca lo sviluppatore principale e chiedigli un consiglio.

Buona fortuna.

    
risposta data 04.11.2016 - 08:53
fonte
28

Non toccarlo. Non commettere nulla.

Invece, siediti sulla tua sedia e urla "Heeeeelp !!!!!" più strong che puoi.

Bene, non esattamente così, ma chiedi consiglio ai tuoi colleghi senior. Se hai 25.000 errori, non aggiusti gli errori, correggi ciò che ha causato gli errori. E un collega anziano dovrebbe essere in grado di consigliarti come fare il cambiamento che il tuo capo vuole senza i 25.000 errori coinvolti. Ci sono vari modi per farlo, ma ciò che è un buon modo dipende dalla tua situazione specifica.

E potrebbe essere il capo ha detto ai tuoi colleghi più anziani di fare lo stesso cambiamento, e hanno detto "no". Perché sapevano cosa sarebbe successo. Ecco perché ti è stato dato il lavoro.

    
risposta data 04.11.2016 - 10:02
fonte
22

Le API trincerate non possono essere semplicemente cambiate. Se veramente è necessario cambiarli, anootarli e / o documentarli come deprecati (con qualsiasi mezzo consentito dalla lingua) e documentare quale API dovrebbe invece essere usata. La vecchia API può essere gradualmente eliminata lentamente ... forse molto lentamente a seconda del budget di tempo per il refactoring.

    
risposta data 04.11.2016 - 03:29
fonte
10

Valutare

Valuta se questo cambiamento è necessario o se puoi aggiungere un nuovo metodo e deprecare l'altro.

Avanti

Se il cambiamento è necessario; quindi è necessario un piano di migrazione.

Il primo passo è quello di introdurre il nuovo metodo e fare in modo che il vecchio metodo massaggi i suoi argomenti in modo che possa chiamare quello nuovo. Ciò potrebbe richiedere l'hard-coding di alcune cose; va bene.

Questo è un punto di commit: controlla che tutti i test superino, confermino, spingano.

migrazione

Il lavoro intenso è la migrazione di tutti i chiamanti del vecchio metodo a quello nuovo. Per fortuna può essere fatto gradualmente grazie allo spedizioniere.

Quindi vai avanti; non esitare a utilizzare gli strumenti per aiutare ( sed è il più semplice, ce ne sono altri).

Contrassegna il vecchio metodo come deprecato (con un accenno al passaggio al nuovo metodo); ti aiuterà a individuare se hai dimenticato qualcosa e ti aiuterà se un collega ti presenta una chiamata al vecchio metodo mentre stai lavorando su questo.

Questo è un punto di commit (o forse più punti di commit): controlla che tutti i test passino, confermino, spingano.

Rimuovi

Dopo che è trascorso un po 'di tempo (forse un minimo di un giorno), rimuovi semplicemente il vecchio metodo.

    
risposta data 04.11.2016 - 10:46
fonte
8

Se la modifica alla firma del metodo è semplicemente una modifica del nome, la soluzione più semplice consiste nell'utilizzare strumenti per automatizzare la modifica delle 25.000 classi che fanno riferimento al metodo in questione.

Suppongo che tu abbia semplicemente modificato il codice manualmente, il che ha dato origine a tutti gli errori. Presumo anche che tu abbia familiarità con Java (vedendo il tuo riferimento a OSGi), quindi ad esempio in Eclipse (non so quale ambiente di programmazione usi, ma altri ambienti hanno strumenti di refactoring simili) puoi usare "Refactoring - > Rinomina "per aggiornare tutti i riferimenti al metodo, che dovrebbero lasciare senza errori.

Se stai apportando altre modifiche alla firma del metodo rispetto alla semplice rinomina (modificando il numero o i tipi di parametri), puoi utilizzare "Refactoring - > Cambia firma del metodo". Tuttavia, è probabile che dovrai essere più attento come suggeriscono le altre risposte. Inoltre, indipendentemente dal tipo di modifica, potrebbe comunque essere un'attività abbastanza impegnativa impegnare tutte quelle modifiche in una base di codice occupata.

    
risposta data 04.11.2016 - 10:16
fonte
6

Ecco il mio contributo.

I started a new job recently where I am working on a very large application (15M lines of code).

Probabilmente non hai familiarità con il progetto e le sue "caratteristiche". Prima di digitare una singola riga di codice, è importante avere familiarità con il progetto. Quindi esegui il rollback delle modifiche e inizia analizzando il codice . (Almeno quello interessato)

Capire la soluzione esistente ti offre una prospettiva migliore su dove ti stai avvicinando. Contestualizzare la soluzione e la sua importanza.

Come sottolineato da @Greg, dovresti essere in grado di testare il codice esistente per avere un riferimento valido da confrontare con (test di regressione). La tua soluzione dovrebbe essere in grado di generare gli stessi risultati di quella esistente. in questo momento non ti interessa se i risultati sono corretti o meno . Il primo obiettivo è quello di refactoring, non di correggere bug. Se la soluzione esistente dice "2 + 2 = 42", anche la soluzione dovrebbe. Se non genera eccezioni, la tua non dovrebbe neanche. Se restituisce valori nulli, il tuo dovrebbe restituire anche i valori null. E così via. Altrimenti, comprometterai 25k linee di codice.

Questo è per motivi di compatibilità retroattiva

Perché? Perché in questo momento, è la tua unica garanzia di un refactoring di successo.

And many of the unit tests either directly reference that interface, or are coupled to base classes which reference that interface.

Un modo per garantire la retro-compatibilità è urgentemente necessario per te Quindi ecco la tua prima sfida. Isolare il componente per il test dell'unità.

Tieni presente che quelle 25k linee di codice sono state create assumendo i possibili risultati del codice esistente. Se non rompi questa parte del contratto, allora sei a metà strada verso la soluzione finale. Se lo fai, bene: può la forza essere con te

Una volta che hai progettato e implementato il nuovo "contratto", sostituisci il vecchio. Deprecarlo o tirarlo fuori.

Ho suggerito di lasciare i bug da soli a causa del refactoring e la correzione dei bug sono compiti diversi. Se provi a portarli avanti, potresti fallire in entrambi. Potresti pensare di aver trovato bug, tuttavia potrebbero essere "funzionalità". Quindi lasciali soli (per un minuto).

25k righe di codice mi sembrano abbastanza problemi da farmi concentrare su un solo compito.

Una volta terminato il tuo primo compito. Esporre questi bug / funzionalità al tuo capo.

Infine, come @Stephen ha detto:

There's not much you can do about it except slowly make things better. When you create the new classes, make sure you properly test them and create them using SOLID principles so they will be easier to change in the future

    
risposta data 05.11.2016 - 17:22
fonte
5

Provalo.

Tutti gli altri raccomandano come refactoring quindi c'è poco impatto. Ma con questo numero di errori, anche se riesci a refactoring con un minimo di 10 righe di codice (probabilmente lo puoi fare), hai avuto un impatto su 25.000 code flows , anche se non hai avuto bisogno di riscrivere loro.

Quindi, la prossima cosa da fare è assicurarsi che la tua suite di test di regressione passi con i colori volanti. E se non ne hai uno, allora creane uno che lo farà. Aggiungere una suite di test di regressione completa al tuo progetto monolitico sembra noioso, ma è un buon modo per aumentare la fiducia nei candidati al rilascio, oltre a renderli più veloci se la suite è automatizzata bene.

    
risposta data 04.11.2016 - 22:17
fonte

Leggi altre domande sui tag