Tecniche per ridimensionare la spazzatura e mantenere la sanità mentale? [duplicare]

38

Quindi mi siedo in una bella ciotola di spaghetti c #, e ho bisogno di aggiungere qualcosa o rimuovere qualcosa ... ma ho sfide ovunque dalle funzioni che passano argomenti che non hanno senso, qualcuno che non capisce strutture dati che abusano stringhe, variabili ridondanti, alcuni commenti sono red-hearings, l'internazionalizzazione è su un livello per ogni uscita, SQL non usa alcun tipo di DBAL, le connessioni al database sono lasciate aperte ovunque ...

Ci sono strumenti o tecniche che posso usare per tenere traccia almeno della "integrità funzionale" del codice (che significa che i miei "miglioramenti" non lo infrangono), o una risorsa online con "schemi cattivi" comuni che spiega un buon modo per il codice di transizione? Sto fondamentalmente cercando una guida su come trasformare la paglia in oro.

Ecco alcuni esempi della stessa funzione di 500 righe:

protected void DoSave(bool cIsPostBack) {
  //ALWAYS  a cPostBack
  cIsPostBack = true;
  SetPostBack("1");
  string inCreate ="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
  parseValues = new string []{"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""};


  if (!cIsPostBack) { //.......
  //....
  //....
  if (!cIsPostBack) {

  } else {

  }
  //....  
  //....
  strHPhone = StringFormat(s1.Trim());
  s1 = parseValues[18].Replace(encStr," ");
  strWPhone = StringFormat(s1.Trim());
  s1 = parseValues[11].Replace(encStr," ");
  strWExt = StringFormat(s1.Trim());
  s1 = parseValues[21].Replace(encStr," ");
  strMPhone = StringFormat(s1.Trim());
  s1 = parseValues[19].Replace(encStr," ");
  //(hundreds of lines of this)
  //....
  //....
  SQL = "...... lots of SQL .... ";

  SqlCommand curCommand;

  curCommand = new SqlCommand();
  curCommand.Connection = conn1;

  curCommand.CommandText = SQL;
  try {
    curCommand.ExecuteNonQuery(); 
  } catch {}
  //....
}

Non ho mai dovuto refactoring qualcosa di simile prima, e voglio sapere se c'è qualcosa come una guida o una knowledgebase su come fare questo genere di cose, trovare modelli comuni e offrire le migliori soluzioni per ripararle. Non voglio solo rubacchiarlo dall'orbita,

    
posta Incognito 08.04.2011 - 15:54
fonte

11 risposte

30

Ci sono tre libri che consiglierei:

Tutti questi libri hanno lo scopo di porre un "nido di sicurezza" prima di impegnarsi nel refactoring quando possibile. Questo significa avere test che assicurano di non rompere l'intento originale del codice che stai rifattando.

E fai sempre un refactoring alla volta .

    
risposta data 08.04.2011 - 16:09
fonte
11

Questo è esattamente ciò di cui parla Martin Fowler nel suo libro Refactoring .

Riepilogo di base:

  • Test unitari! Per prima cosa devi stabilire test per il codice esistente. Capire quali sono gli input e gli output attesi e testarli. Non testare il codice. Verifica le specifiche: non vuoi riprodurre bug.
  • Refactor bit alla volta, mantenendo i test che passano mentre procedi.
  • Tieni presente che se non hai alcun test o per grandi porzioni di codice, una riscrittura potrebbe effettivamente essere la scelta più efficace.

Questo colloquio con Martin Fowler sugli argomenti del libro mette molta luce sull'argomento (su unit test, payoff, individuazione bug tramite refactoring, refactoring vs. riscrittura).

Tieni presente che i modelli errati sono negativi per una ragione: è una soluzione scadente al problema. Ciò significa che anche se hai visto lo stesso tipo di codice errato, non significa che il problema sia lo stesso e che la soluzione migliore sia probabilmente diversa per ogni caso.

    
risposta data 08.04.2011 - 16:06
fonte
6

Nella mia esperienza passata, definire in modo iterativo le aree di funzionalità ed estrarre il codice pertinente in metodi / funzioni sarà il modo più rapido per iniziare. È quindi possibile estrarre il codice, inserire tale codice in una funzione e quindi eseguire un test per confermare che non si è verificato alcun errore. Risciacquare e ripetere fino al termine o fino a quando non è necessario aggiungere nuove funzionalità. Refactoring iterativamente fornirà maggiore flessibilità consentendo di prendere pause occasionali dal refactoring, specialmente se è ancora necessario / vuoi aggiungere un nuovo codice. Psicologicamente, un approccio iterativo ti darà la soddisfazione di vedere la tua base di codice diventare più ordinata, il che renderà più facile per te completare questa attività di refactoring.

    
risposta data 15.12.2011 - 17:40
fonte
4

Sembra che quello che vuoi sia avere dei test unitari. Aggiungi i casi di test che coprono il comportamento esistente, quindi quando fai il refactoring puoi fare affidamento sui tuoi test per avvisarti di eventuali guasti. Fai questo anche su un nuovo ramo nel tuo controllo del codice sorgente, in modo che eventuali incidenti non diventino catastrofici.

    
risposta data 08.04.2011 - 15:57
fonte
4

Vorrei fare qualcosa di simile al seguente:

  • Avvolgi il maggior numero possibile di codice nelle classi, raggruppandolo per funzionalità, ma lasciandolo per il momento invariato. Questo ti permetterà di triage il tuo codice.
  • Crea un livello database usando PDO.
  • Converti il tuo codice nel pattern MVC, facendo particolare attenzione a eliminare qualsiasi codice PHP che genera inutilmente HTML e trasferendolo alla vista. I tuoi controllori dovrebbero determinare quale modello e quale vista caricare, e i tuoi modelli dovrebbero contenere tutto il resto.
  • Rifattora le tue restanti classi, una per una. Affronta prima le classi più pervasive. Cerca le classi che fanno più cose e dividerle. Sbarazzarsi del codice ripetuto. Crea metodi di responsabilità unica.
  • Aggiungi test unitari mentre vai avanti. Ciò renderà il tuo codice più stabile nel lungo periodo. Se hai bisogno di rifattorizzarlo di nuovo in futuro, avrai un contratto che specifica come deve essere eseguito il codice. PHPUnit è un framework di test che puoi utilizzare, ma ce ne sono anche altri.
risposta data 15.12.2011 - 18:02
fonte
3

Ingegneria inversa testata

Scrivi test unitari per "prima".

refactoring.

Assicurati che i test vengano eseguiti dopo.

Scegli i piccoli pezzi che possono essere chiaramente identificati come appartenenti a un singolo scopo o componente concettuale.

    
risposta data 08.04.2011 - 16:07
fonte
3

Vorrei iniziare coprendo il più possibile il tuo codice con test automatici. Potrebbe essere noioso e noioso, ma ti consente di catturare il comportamento corrente del tuo sistema. Quindi, mentre pulisci in modo iterativo le cose e riscrivi / rifatti le parti della tua base di codice, puoi sentirti più sicuro di non introdurre una tonnellata di regressioni. Spererete anche che possiate introdurre test a grana più fine che potreste fare prima. Questo mi ha sempre aiutato in passato.

    
risposta data 15.12.2011 - 18:05
fonte
1

Yous dovrebbe sicuramente iniziare con la scrittura dei test unitari, come altri hanno menzionato. Sfortunatamente, questo codice ha chiaramente bisogno di essere cancellato dall'esistenza. Ora, se funziona bene così com'è, forse non ne hai bisogno, ma qualsiasi maintina diventerà rapidamente molto costosa. Questo codice sembra essere la definizione di non modificabile. Ma hey, con un design migliore, puoi probabilmente passare attraverso una riscrittura molto più veloce della persona che vi è inciampata (so che i cowboys possono essere dei programmatori veloci, ma questo programmatore non era cowboy ... Penso che potrebbe essere letteralmente una mucca) .

    
risposta data 08.04.2011 - 16:39
fonte
1

Se si tratta di un'app Web, puoi testare "l'output" con un po 'di creatività - usa qualcosa come il selenio sul lato del browser per assicurarti che i bit dell'interfaccia utente funzionino ancora e quindi controlla il database sul retro per conferma che il tuo aggiornamento è andato a buon fine. La tua scatola nera è grande, ma puoi almeno controllare le modifiche automaticamente e ripetutamente.

    
risposta data 08.04.2011 - 16:43
fonte
1

Come altri hanno già detto che la tua arma principale sono i test unitari. Indipendentemente da ciò che mai farai avrai bisogno di questi.

Per quanto riguarda gli strumenti per aiutare il refactoring, esistono, ma non faranno un aggiustamento su larga scala per te. Cose come Resharper ti aiuteranno a spostare i metodi, rinominare le variabili, estrarre interfacce, ecc, ma sospetto che dovrai fare un anche molto refactoring manuale.

    
risposta data 08.04.2011 - 18:39
fonte
1

Questo non è ciò che è il refactoring. Il refactoring consiste nel suddividere un pezzo di codice nelle sue parti componenti (fattori) in modo da migliorare il riutilizzo e la leggibilità del codice.

Per migliorare il codice terribile è riscrivere . Quindi la domanda è: come si fa a riscrivere un'intera applicazione di codice errato. La risposta è che inizi da zero. La riscrittura frammentaria è molto più difficile e, a lungo termine, impiegherà più tempo a farlo correttamente.

    
risposta data 15.12.2011 - 17:41
fonte

Leggi altre domande sui tag