Refactoring di una classe che espone troppo al suo interno

2

Ho un codice legacy (sia nel senso del codice che non ha test, come la definizione fornita in Working Effectively con Legacy Code, e di un codice relativamente vecchio) che devo estendere. C'è questa classe in particolare, che è ampiamente utilizzata attraverso il semplice espediente di accedere direttamente alle sue variabili membro e usando i metodi di detto membro (a volte incatenati ad una profondità di 3 classi). Questo è un incubo con cui lavorare, con mio dispiacere.

Quindi sto cercando di ottenere quella classe sotto test, e arrivare al punto in cui ho un'interfaccia utilizzabile per accedervi. Tuttavia, non vedo un percorso chiaro tra lo stato corrente e il risultato finale.

Dopo aver riflettuto, il mio piano attuale è quello di avvolgere tutti gli usi dei membri (fino alla profondità necessaria) nella classe, che purtroppo lo trasformerà in un po 'di una classe di Dio. Una volta che ogni accesso è stato fatto attraverso un set di funzioni adeguato, spero di ottenere l'intero assembly della classe collegato al framework di test. Dopo di ciò, spero di poter iniziare a estrarre le diverse interfacce o classi nascoste nel pasticcio che sarà stato prodotto dalla fase di wrapping.

Sembra un approccio ragionevole? C'è un altro approccio che potrebbe funzionare meglio in un caso come questo?

    
posta Iker 26.02.2016 - 22:43
fonte

1 risposta

1

Non esiste un proiettile d'argento per un simile problema. Per sua stessa natura, è possibile trovare molte soluzioni e l'idoneità di ciascuna soluzione dipenderà dal modo in cui il resto del codice è strutturato e dalle funzioni che svolge.

Ci sono diversi modi per procedere e ciò che segue è solo una tecnica che ho usato prima di me stesso di fronte a un problema molto simile. Per brevità, farò costantemente riferimento al tuo codice come applicazione ma può anche essere un servizio o una libreria.

Prerequisiti

Prima di procedere assicurati di aver fatto quanto segue:

  1. Scopri cosa deve fare la tua applicazione. Questo va ben oltre la semplice specifica dei requisiti. Più comprendi i punti più sottili del comportamento della tua applicazione, meglio sarà. Inoltre, non temere di sfidare le specifiche (se hai una linea diretta per i tuoi utenti). Potreste scoprire che a volte le persone non si preoccupano veramente di una particolare funzionalità / comportamento che pensavate fosse obbligatoria. A volte potresti persino trovare funzionalità / comportamenti che la gente odia. Ciò si estende non solo agli utenti umani ma anche agli utenti del sistema (ad es. I programmi che usano la tua API). Tuttavia, raccogli consensi prima di procedere con questo approccio.

  2. Inizia a scrivere test deterministici per la tua applicazione. Dovresti mirare a coprire almeno le "specifiche" generali. Una volta che hai scritto questi test, puoi rifattorici facilmente. I test scritti come codice dovrebbero essere preferiti (ad es. Test di integrazione / funzionali). Tuttavia, se non puoi codificare i casi di test, documenta la procedura di test manuale in modo che tu (o anche qualcun altro) possa replicarla in modo esente da errori.

  3. Avvia un registro. Il tuo SCM può aiutarti a tenere traccia delle modifiche e ripristinare una versione precedente. Quindi apporta modifiche in piccoli incrementi e provali. Una volta che tu e un tester indipendente entrambi sono sicuri che i tuoi cambiamenti sono buoni, allora fai il check-in e vai al prossimo bit. Buone descrizioni e note di modifica nel tuo diario di bordo possono aiutarti a seguire le tue tracce nel caso in cui qualcosa di brutto accadesse in futuro. Se altri si uniscono al tuo sforzo, possono studiare le tue note per leggere la tua mente.

Ok, e ora?

Una volta che hai familiarizzato con l'applicazione e hai preparato i casi di test, dovresti provare ad attaccare gli usi del tuo BadClass . Prova a sostituire l'accesso di questa classe con uno schema migliore. Ad esempio, se ai membri della classe viene eseguito l'accesso da un'altra classe, prova a vedere se il chiamato deve avere quel membro disponibile come parametro di un campo o di un parametro di classe. Vedi se invece di rendere visibili questi membri, BadClass può fornire un tratto / funzione da usare --try per vedere se quel tratto deve essere collocato in una classe diversa del tutto. In generale, stai sostituendo l'utilizzo con uno schema migliore invece di provare a correggere BadClass .

Se conosci bene la tua applicazione o il tuo dominio, forse puoi anche capire se l'utilizzo è richiesto o meno (potrebbe essere possibile eliminare semplicemente quella funzionalità o sostituirla con qualcosa di meglio).

Quando si tenta questo approccio, evitare di provare a risolvere troppi problemi contemporaneamente. Mirare prima a piccoli miglioramenti (frutti pendenti bassi). Verifica se questo semplifica il problema fino a un punto in cui puoi introdurre uno schema migliore.

Una volta che il BadClass non viene più referenziato, puoi rimuoverlo.

    
risposta data 27.02.2016 - 12:40
fonte

Leggi altre domande sui tag