A volte la duplicazione del codice è il risultato di un "gioco di parole": due cose sembrano uguali, ma non lo sono.
È possibile che un eccesso di astrazione possa rompere la vera modularità del sistema. Sotto il regime della modularità, devi decidere "cosa è probabile che cambi?" e "cosa è stabile?". Qualunque cosa sia stabile viene inserita nell'interfaccia, mentre tutto ciò che è instabile viene incapsulato nell'implementazione del modulo. Quindi, quando le cose cambiano, la modifica che devi apportare è isolata per quel modulo.
Il refactoring è necessario quando ciò che pensavi fosse stabile (ad esempio, questa chiamata API avrà sempre due argomenti) deve essere modificato.
Quindi, per questi due frammenti di codice duplicati, vorrei chiedere: Una modifica richiesta per uno significa necessariamente che anche l'altro deve essere modificato?
Il modo in cui rispondi a questa domanda potrebbe fornirti una visione migliore di ciò che potrebbe essere una buona astrazione.
I modelli di progettazione sono anche strumenti utili. Forse il tuo codice duplicato sta eseguendo un attraversamento di qualche forma e dovrebbe essere applicato il pattern iteratore.
Se il tuo codice duplicato ha più valori di ritorno (ed è per questo che non puoi eseguire un semplice metodo di estrazione), forse dovresti creare una classe che contenga i valori restituiti. La classe potrebbe chiamare un metodo astratto per ogni punto che varia tra i due frammenti di codice. Dovresti quindi realizzare due concreti implementazioni della classe: una per ogni frammento. [Questo è effettivamente il modello di progettazione del metodo Template, da non confondere con il concetto di template in C ++. In alternativa, ciò che stai guardando potrebbe essere risolto meglio con il modello di strategia.]
Un altro modo naturale e utile per pensarci è con le funzioni di ordine superiore. Ad esempio, creando lambda o usando classi interne anonime affinché il codice passi all'astrazione. In generale, puoi rimuovere la duplicazione, ma a meno che non ci sia una relazione tra loro [se uno cambia, così anche l'altro], potresti danneggiare la modularità, non aiutarla.