2010-05-14 14 views
8

Ho appena completato un pezzo di codice complesso. Funziona su specifiche, soddisfa i requisiti di prestazione ecc. Ecc., Ma mi sento un po 'ansioso e sto prendendo in considerazione la possibilità di riscriverlo e/o refactarlo. Dovrei farlo (passare del tempo che altrimenti potrebbe essere speso per funzionalità che gli utenti effettivamente noteranno)?Rif. Codice/riscrittura o continua?

Le ragioni mi sento in ansia per il codice sono:

  1. La gerarchia delle classi è complessa e non ovvio
  2. Alcune classi non hanno uno scopo ben definito (che fanno un certo numero di cose non correlate)
  3. Alcune classi utilizzano altri interni (sono dichiarate come classi amico) per ignorare gli strati di astrazione per le prestazioni, ma ritengo che interrompano l'incapsulamento facendo questo
  4. Alcune classi perdono dettagli di implementazione (ad esempio, ho cambiato una mappa in una mappa hash precedente e sono ritrovato a dover modificare il codice in altre sorgenti per far funzionare il cambiamento)
  5. mia gestione della memoria/sistema di pooling è un pò goffo e meno-che trasparente

Sembrano ottime ragioni di refactoring e codice pulito, aiutando la manutenzione e l'estensione future, ma potrebbe richiedere molto tempo. Inoltre, non sarò mai perfettamente soddisfatto di qualsiasi codice che scrivo comunque ...

Quindi, cosa pensa StackOverflow? Pulisci codice o lavora sulle funzionalità?

+0

Grazie a tutti per il consiglio. È molto apprezzato Penso che rifatterò mentre è fresco nella mia mente e mentre posso dedicargli del tempo. Potrei non avere la possibilità di farlo in seguito e il codice è piuttosto difficile da refactoring incrementale così com'è, che non è sicuramente buono. Grazie ancora! – Dan

+0

Un articolo possibilmente rilevante: http://www.joelonsoftware.com/articles/fog0000000069.html –

+0

Grazie per quello. Fortunatamente ci sono ampie sezioni di codice che sono felice e sono in grado di riutilizzare così com'è, quindi non è assolutamente una riscrittura completa. Se fosse "completa riscrittura vs continua", non avrei fatto la domanda e semplicemente continuato. – Dan

risposta

6

Direi che se senti il ​​bisogno di rifattorizzare questo codice, non lo hai ancora "completato".

Penso che sia molto meglio refactoring come si va (supponendo che hai test e stanno seguendo il metodo rosso, verde, refactoring di TDD), ma dato dove sei, non c'è molto senso nel dirti cosa dovresti " aver fatto.

Vorrei consigliarlo a refactoring. Tuttavia, il pragmatico in me darebbe il seguente avvertimento: il codice non viene mai "fatto", quindi timebox il refactoring questa volta (quindi concediti un'ora o due, mantieni il test che passa e quindi definisci "fatto per ora") e quindi ogni volta che tocchi il codice, segui lo boy scout rule e pulisci il codice un po 'ogni volta che lo controlli. Nel tempo, pulisci questo codice e, in futuro, prova a refactoring mentre vai, come parte del processo di sviluppo, piuttosto che un grosso compito da svolgere alla fine dello sviluppo.

+0

Ottimo consiglio in generale, ma a causa dei miei punti 2, 3 e 4, refactoring solo un po 'ora e un po' più tardi è .. difficile - ma penso che sia la mia risposta: devo essere sicuro di poter migliorare in modo incrementale il codice . In questo momento non posso. – Dan

+0

@Dan: "Quando codifichi, quando pensi che mi rifatterò in seguito, possiedi un debito e pagherai uno ad uno" Ottimo consiglio. – nXqd

1

È probabile che altri saranno soggetti agli orrori che hai commesso? Quando ho un codice orribile che sta per essere rilasciato, tendo a ripulirlo, ma se sono l'unico che sarà sottoposto a manutenzione e ad occuparsene, lo lascerò insidiare per un po 'di tempo Funziona abbastanza bene e se mi siedo un po 'su di esso potrei persino trovare una soluzione migliore di quella che avrei avuto se fossi stato ispirato a "sistemarlo" immediatamente.

IMHO, ovviamente.

+0

Sto chiedendo opinioni sulle persone, quindi grazie!:-) Non è probabile che qualcuno vedrà comunque il codice per i prossimi mesi, ma su di esso verrà creato molto codice, quindi sarà molto più difficile risolverlo in seguito. Allo stesso tempo, funziona bene ed è abbastanza veloce e la pulizia può richiedere del tempo che potrebbe essere meglio speso altrove, specialmente se riprogetto per correggere le carenze (come il codice di gestione della memoria) e anche dopo tutto ciò, è improbabile che io ne sarò mai felice al 100%. Ecco perché sto cercando di vedere cosa pensano gli altri. Motivami in un modo o nell'altro. – Dan

+0

OK, "un sacco di codice verrà costruito sopra di esso" sono informazioni precedentemente non divulgate che modificano totalmente l'equazione. Sicuramente refactoring l'interfaccia che il codice client utilizzerà, in modo tale da rendere quell'interfaccia di supporto una "buona implementazione" è una priorità elevata. –

+0

Sono abbastanza soddisfatto dell'interfaccia. Potrebbero esserci alcuni piccoli miglioramenti che potrei fare, ma nel complesso è buono. Immagino che gli interni siano un po 'complessi nel mantenere stabile l'interfaccia, quindi potrebbe valere la pena di rivalutarlo e vedere come posso semplificare il modo in cui tutto si connette, specialmente ora che il codice inizia effettivamente ad usare l'interfaccia. – Dan

1

"Alcune classi fuoriescono dettagli di implementazione (per esempio, ho cambiato una mappa per una mappa di hash in precedenza e sono ritrovato a dover modificare il codice in altre sorgenti per fare il lavoro di modifica)"

Questa è una ragione sufficiente per renderlo degno dello sforzo imo. Per definizione è qualcosa che gli utenti noteranno effettivamente.

Alcune altre cose importanti da considerare:

  • Maintainability - Come sarà facile per correggere eventuali bug inevitabile che emergono?
  • Testability - Lavorare il codice in una forma più testabile è un ottimo modo per effettuare il refactoring. Aggiungere test unitari significa quindi che puoi cambiarlo e sapere esattamente quali sono le interruzioni.
  • Espandibilità - Pensi che avrai mai bisogno di aggiungere nuove funzionalità?

In realtà, l'unica volta in cui non si desidera prendere in considerazione la possibilità di migliorare il codice è se si sa per certo che non sarà più necessario toccarlo di nuovo (cioè QUASI mai).

+0

Grazie per quello. Grandi punti. L'espandibilità è coperta, quindi questo non è un problema, ma vale la pena considerare la manutenibilità e la testabilità. Ho appena realizzato che potrebbe essere un incubo trattare con quelli a causa del mio terzo punto. Immagino di aver sentito quello che hai detto, ma di avere quel fastidioso "lavoro su qualcosa che ti porta benefici ORA", che immagino sia probabilmente la cosa sbagliata da fare. Grazie per il consiglio! – Dan

0

Direi sempre il refattore. Ogni riga di codice in più e tutti quei piccoli trucchi fastidiosi torneranno e ti morderanno nel culo.

In futuro si potrebbe persino refactoring mentre si va - il tempo non è mai in vita - anche se lo butti via hai ancora imparato a fare qualcosa di meglio.

2

Da quello che posso dire che sei un po 'perfezionista e vuoi rendere il tuo codice il più pulito possibile, un tratto meritevole, ma nel business devi considerare l'analisi costi-benefici di quello che stai facendo. Se il codice è conforme alle specifiche e ci sono funzioni più importanti su cui lavorare, prendi nota che vorresti rifattorizzare il codice e andare avanti. Se hai mai del tempo libero, puoi tornare ad esso.

1

"Ho appena completato ..."

suona come si sta attivamente scrivendo codice legacy, che non è una buona cosa. Hai evidenziato molte ragioni per cui potresti voler refactoring il tuo codice, ma come dici tu funziona correttamente, quindi non ci sono costi per mantenerlo così com'è.

Sul lato positivo, il modo in cui funziona il codice (e dovrebbe funzionare) è probabilmente nuovo nella tua mente, quindi il refactoring ora rischia di essere più economico rispetto al refactoring successivo; d'altra parte il refactoring più tardi con una reale richiesta di modifica in mente aumenterà la probabilità di refactoring nella giusta direzione.

In futuro, prenderei seriamente in considerazione la possibilità di rallentare e pensare in anticipo mentre si scrive codice. Refactoring (o factoring!) Mentre si va è molto più semplice e non si ha la pressione "ma funziona" per mantenere le cose come sono.

Orologio. Se noti che una classe sembra guadagnare più responsabilità, fermati e pensa se è necessario separare le responsabilità in classi separate.

Se si nota che si desidera raggiungere l'interno di una classe, fermarsi e capire quale deve essere l'interfaccia tra le classi in modo che non sia necessario conoscere e utilizzare un interno di classe concreta.

+0

"Prenderò seriamente in considerazione il rallentamento e il futuro" - l'ho fatto e il codice è abbastanza solido e potrei farla franca lasciando che sia senza troppe conseguenze per il codice futuro (ovvero, nel suo insieme, il codice è in modo autonomo -contained). Ma non puoi mai prevedere cosa accadrà e potrebbe essere molto più costoso cambiare le cose in seguito. Il motivo per cui ho fatto questa domanda non è quello di immergermi e pulire il codice è che ho già passato molto tempo su questo e se lo pulisco adesso, spendo di nuovo di più. Certo, potrebbe essere la cosa migliore da fare in questa fase. – Dan

+0

Se hai rallentato e pensato in anticipo e hai ancora finito con le classi che si tuffavano l'una sull'altra negli interni e accumulando più responsabilità, allora è probabile che sia un segno che non hai ancora ottenuto il giusto design. Questo non è inaspettato, in quanto ottenere il massimo dal semplice design della classe al primo tentativo è estremamente difficile. Devi rallentare _even more_. Solo una volta che stai andando ad un ritmo in cui puoi individuare e correggere il tuo progetto prima di completare ogni lezione, arriverai sul palco che il tuo codice non ha bisogno di refactoring non appena lo hai completato. –

2

Se questo codice ha già superato il QA, allora forse dovresti rilasciarlo così com'è e accettare il debito del codice. Se c'è tempo da dedicare a questo, selezionerei i pezzi di ciò che è più eclatante e cercherò di ridefinirli, ad esempio completando l'implementazione di hashtable. Altrimenti, fai una lista di cose da migliorare e fai i miglioramenti con le tue future richieste di cambiamento.

È bello sapere di te che non ti sentirai mai contento del codice. Ricorda che così non devi permettere al tuo perfezionismo di intralciare le versioni regolari.

3

Refactor ora.

Dato che si sta prendendo in considerazione anche il refactoring, sembra che si possa dedicare il tempo a questo. Se lo lasci per dopo, è probabile che ti darai da fare con altre cose e perderai questa opportunità. Quando gli orari diventano rigidi, i clienti possono capire se hai bisogno di un po 'di tempo in più per terminare una nuova funzione. Sono molto meno comprensivi quando dici loro che hai bisogno di più tempo per riscrivere qualcosa che sta già funzionando.

+0

Buon punto, grazie – Dan

0

Se si dispone di una serie di test per verificare che il codice funzioni ora e dopo il refactoring, direi, se si ha tempo, risolverlo, poiché ti costerà più tempo dopo. Ma, se il tempo stringe, allora è perfettamente accettabile metterlo giù come debito di codice e tornare ad esso in un momento migliore. Se il codice funziona, puoi tagliare una versione perfettamente valida con esso ora e tornare più tardi quando hai più tempo e meno pressione.

1

Lavora sugli aspetti che porteranno a bug in seguito. Non placchetta d'oro.

2

In uno dei tuoi commenti hai detto "molto codice verrà costruito sopra di esso". Dici che funziona correttamente, ma se è sciatto e funziona su principi di progettazione sbagliati, diventerà sempre più difficile cambiare qualcosa con il passare del tempo. In generale, più importante è un pezzo di codice, migliore dovrebbe essere. Prendi il disegno giusto prima di aggiungere le cose su di esso (entro limiti ragionevoli).

Inoltre, uno degli obiettivi principali della scrittura del software (secondo me) è la gestione della complessità. Se hai funzionato, hai fatto la metà del lavoro. L'altra metà MOLTO importante del lavoro è rendere le cose ragionevolmente facili da capire e cambiare. Senza di ciò, si crea un software che non risponde bene ai cambiamenti. E il software deve cambiare. Spesso.

La mia azienda ha un software che è stato costruito in modo molto sciatto nella sua infanzia, e ogni piccola modifica aggiunta negli anni è stata leggermente inchiodata sulla base già sciatta. Ora è al punto in cui le persone chiedono cose semplici (come il supporto della rotellina del mouse per lo scorrimento), e lo sviluppatore principale risponde con "Non sai quanto dovrei cambiare per farlo." Tuttavia, se il codice è stato pulito mentre veniva scritto (o poco dopo), non avremmo questo problema.

Se hai un codice sciatto e mal progettato ora, ti morderà nel sedere più tardi. Soprattutto se un sacco di altro codice sarà scritto sopra di esso.

0

Se si dispone di una serie di test automatici che verificano il corretto funzionamento del codice, è meraviglioso: procedere e rifattorizzarlo; ora è il momento migliore, mentre è fresco nella tua mente. Se non lo fai, usa questa volta, mentre è fresco nella tua mente, per scrivere i test. Se hai tempo solo per i test o per il refactoring: scrivi i test in modo che sia più facile (alcuni direbbero possibile) al refactoring più avanti.

Il ciclo TDD è RED-GREEN-REFACTOR, e si dice che non stai "completato" fino a quando il design è buono - vale a dire, fino a che non ha bisogno di refactoring più.

1

In realtà non è così complicato. Basta seguire questa regola:

Codice del refactore spesso. Refactor ogni volta che è possibile.

Quindi, se pensi di poter refactoring il tuo codice, dovresti farlo ora prima che diventi molto complicato in seguito, quando tutti i codici sono così serrati insieme.

1

Ora avete la vostra implementazione di riferimento. Se ti senti motivato, prova a refactoring.Non aver paura di buttar via e andare avanti o ricominciare.

Forse ripetere l'API/interfaccia in base al codice utente e guidare il refactoring verso il basso.

Non si dovrebbe essere disturbati dall'avere membri di dati pubblici. Le persone scrivono troppi accessor che finiscono per scrivere per divertimento e francamente la fonte di bug davvero stupidi e frustranti (l'unico codice senza bug è il codice che non è mai stato scritto). È irritante. Solo incapsulare per proteggere gli stati fragili (quando lo stato dei dati membro è accoppiato).

+0

Per quanto riguarda i dati pubblici, non ti preoccupare, non sono un fan degli accessor e ritengo che gli oggetti debbano operare sui propri dati e non cercare in altri oggetti i dati ove possibile. – Dan

1

Quindi, cosa pensa StackOverflow? Pulire codice o lavorare sulle funzionalità?

La domanda che vedo qui è quale prezzo si dovrà pagare se si refactoring vs quale prezzo si paga se non lo fai.

Se lo lasci così com'è, ti costerà per qualsiasi manutenzione (tempo extra, maggiore possibilità di aggiungere nuovi difetti ad ogni cambio) e reputazione come sviluppatore (qualsiasi altro coder che lo guarda potrebbe probabilmente imprecare:)).

Se puoi garantire che nessuno toccherà mai più quel codice (non perché sia ​​troppo orribile;)) puoi tranquillamente lasciarlo così com'è. (In oltre 10 anni come sviluppatore non ho mai trovato una situazione in cui potessi garantirlo).

In tutti gli altri casi, è meglio refactoring.

Sembrano ottimi motivi per refactoring e codice pulito, favoreggiamento futuro manutenzione e ampliamento, ma potrebbe richiedere molto tempo.

Non è necessario rendere il codice perfetto. Di fatto, dovresti prenderne una alla volta e rifattorici nelle iterazioni, e se lo fai correttamente non avrà effetto su nessun altro codice.

Questo significa che dovresti essere in grado di effettuare il refact in base al tuo tempo disponibile, non viceversa.

Ad esempio, se si interrompe solo una delle classi multiuso in tre o quattro classi separate e si aggiorna il codice utilizzando tale, il resto del codice funzionerà come prima. Se sei fuori tempo quando hai finito questo cambiamento, puoi lasciarlo così com'è (solo un po 'più chiaro, in una sola area).

Se si dispone di più tempo, è possibile effettuare il successivo refactoring e ripetere.

Inoltre, se si utilizza un sistema di controllo del codice sorgente si può anche lavorare in parallelo per il refactoring e l'aggiunta di nuove funzionalità con costi aggiuntivi relativamente ridotti (e continuare il refactoring a mano a mano che si ha più tempo).

Problemi correlati