DRY codice non correlato, ma quasi identico


34

Ho un codice che è quasi identico, ma usa tipi assolutamente diversi, senza ereditarietà tra loro, sulla variabile principale. In particolare, sto scrivendo un analizzatore con Roslyn per C # e VB.NET, con i seguenti tipi:

Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax

Mi chiedo se, poiché il codice sta facendo la stessa cosa, dovrei tenerlo il più SECCO possibile, suddividendolo il meno possibile in metodi separati (ma identici oltre al tipo), o separarlo completamente perché i due metodi sono cambiamenti non correlati e futuri potrebbero costringere una versione a cambiare, ma non l'altra (anche se questo è improbabile)?

Modifica: circa un anno dopo, ho riscontrato lo stesso problema e il team di Roslyn mi ha aiutato a risolverlo: scrivere una classe di base che prende generici e ha un TAttributeSyntaxparametro che fa la maggior parte del lavoro. Quindi, scrivere le classi derivate con il minimo indispensabile di dati che richiedono un tipo specifico.


Funzionerebbe per creare la tua interfaccia AttributeSyntax che avvolge le classi esistenti ma ti dia l'eredità che concettualmente dovrebbe essere lì?
Winston Ewert,

7
Scusate se questo è ovvio, ma i generici esistono quindi non è necessario ripetere se stessi per il codice identico ma per il tipo. Se non è quello che intendevi, ti preghiamo di ignorare.
Davislor,

@Lorehead In genere lo farei, ma questo è un singolo metodo a cui viene passato un tipo che contiene il nodo come payload da un metodo interno su cui non ho alcun controllo.
Hosch250,

@WinstonEwert Lo esaminerò. Non sono sicuro di volerlo fare per tutti i tipi C # / VB.NET.
Hosch250,

1
Il refactoring impone molti compromessi e talvolta persino paradossi. Ad esempio, accoppiamento libero rispetto a DRY, o funzioni brevi, ma molte di esse, rispetto a funzioni più lunghe, e poche di esse. Alla fine, è una bestia difficile: il tuo obiettivo è la leggibilità e la manutenibilità. Devi pensare come un avatar che vede il tuo codice per la prima volta. E a volte provi solo a vedere cosa c'è di meglio. Purtroppo il refactoring perfetto non è possibile.
phresnel,

Risposte:


111

Non fai il SECCO perché qualcuno lo ha scritto in un libro da qualche parte che è buono da fare, fai il SECCO perché in realtà ha benefici tangibili.

In particolare da quella domanda:

Se ti ripeti, puoi creare problemi di manutenibilità. Se doStuff1-3 ha tutti un codice strutturato in modo simile e risolvi un problema in uno, potresti facilmente dimenticare di risolvere il problema in altri luoghi. Inoltre, se devi aggiungere un nuovo caso da gestire, puoi semplicemente passare parametri diversi in una funzione piuttosto che incollare dappertutto.

Tuttavia, DRY è spesso portato all'estremo da programmatori intelligenti. A volte per non ripetere te stesso devi creare astrazioni così ottuse che i tuoi compagni di squadra non possono seguirle. A volte la struttura di due cose è solo vagamente simile ma abbastanza diversa. Se doStuff1-4 è abbastanza diverso da non poter essere ripetuto, il refactoring non ti costringe a scrivere codice innaturale o a subire backflip di codifica intelligenti che faranno sì che il tuo team ti guardi, quindi potrebbe essere giusto ripeterti. Mi sono chinato all'indietro per non ripetermi un paio di volte in modi innaturali e mi sono pentito del prodotto finale.

Quindi, fondamentalmente, non pensare "oh amico, questo codice è abbastanza simile, forse dovrei refactor per non ripetermi". Pensa "il refactoring per rendere questo codice base riutilizzare elementi comuni rende il codice più gestibile o meno gestibile ?" Quindi, scegli quello che lo rende più gestibile.


Detto questo, dato SRP e solo cercando di avere classi piccole e flessibili in generale, potrebbe avere senso analizzare il tuo codice per quel motivo , dividere frammenti di comportamento che usano tipi generici (hai detto che sono identici oltre al tipo) in piccole classi. Quindi scoprirai che alcune di queste classi sono in realtà totalmente identiche (non solo per lo più identiche) e quindi puoi costruire un toolkit nel caso tu voglia aggiungerlo Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntax.


32
TL; DR - DRY è un mezzo per raggiungere un fine. Concentrati sull'estremità, non sui mezzi. Se potessi votare due volte Lego Man, lo farei.

Una nota importante: se si fa ripetere se stessi, occorre citare sempre nel commento tutti gli altri luoghi che devono essere visitati quando le modifiche al codice ripetuti. Non solo riduce la probabilità di una desincronizzazione, ma funge anche da indicatore di quanto dolore di mantenimento ti sta causando la ripetizione.
Xion,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.