DRY niezwiązany, ale prawie identyczny kod

34

Mam trochę kodu, który jest prawie identyczny, ale używa absolutnie różnych typów, bez dziedziczenia między nimi, na głównej zmiennej. W szczególności piszę analizator z Roslyn dla C # i VB.NET, z następującymi typami:

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

Zastanawiam się, czy, ponieważ kod robi to samo, powinienem zachować jak najbardziej OSUSZANIE, dzieląc jak najmniej na osobne (ale identyczne inne niż typ) metody, czy też całkowicie oddzielić, ponieważ te dwie metody są niezwiązane i przyszłe zmiany mogą zmusić jedną wersję do zmiany, ale nie drugą (chociaż jest to mało prawdopodobne)?

Edycja: Mniej więcej rok później trafiłem na ten sam problem, a zespół Roslyn pomógł mi go rozwiązać: napisz klasę podstawową, która przyjmuje ogólne i ma TAttributeSyntaxparametr, który wykonuje większość pracy. Następnie napisz klasy pochodne z absolutnym minimum danych, które wymagają określonego typu.

Hosch250
źródło
Czy zadziałałoby stworzenie własnego interfejsu AttributeSyntax, który otacza istniejące klasy, ale daje ci dziedzictwo, które koncepcyjnie powinno tam być?
Winston Ewert
7
Przepraszam, jeśli jest to oczywiste, ale istnieją ogólne, więc nie musisz powtarzać się dla kodu, który jest identyczny, ale dla typu. Jeśli nie o to ci chodziło, zignoruj ​​to.
Davislor,
@Lorehead Zazwyczaj zrobiłbym to, ale jest to jedna metoda przekazywana typowi, który zawiera węzeł jako ładunek z metody wewnętrznej, nad którą nie mam kontroli.
Hosch250,
@WinstonEwert Zajmę się tym. Nie jestem jednak pewien, czy chcę to zrobić dla wszystkich typów C # / VB.NET.
Hosch250,
1
Refaktoryzacja narzuca wiele kompromisów, a czasem nawet paradoksonów. Np. Luźne sprzężenie z DRY lub funkcje krótkie, ale wiele z nich, funkcje dłuższe i kilka z nich. W końcu jest to trudna bestia: Twoim celem jest czytelność i łatwość konserwacji. Musisz myśleć jak awatar, który po raz pierwszy widzi Twój kod. A czasem po prostu próbujesz zobaczyć, co jest lepsze. Idealne refaktoryzacja niestety nie jest możliwe.
fresnel

Odpowiedzi:

111

Nie suszysz, ponieważ ktoś napisał to w książce, w której warto to robić, robisz SUCHANIE, ponieważ w rzeczywistości przynosi wymierne korzyści.

W szczególności z tego pytania:

Jeśli się powtórzysz, możesz stworzyć problemy z utrzymaniem. Jeśli wszystkie doStuff1-3 mają kod o podobnej strukturze, a problem został rozwiązany w jednym, łatwo można zapomnieć o rozwiązaniu problemu w innym miejscu. Ponadto, jeśli musisz dodać nowy przypadek do obsługi, możesz po prostu przekazać różne parametry do jednej funkcji zamiast kopiować i wklejać w dowolnym miejscu.

Jednak sprytni programiści często podchodzą do skrajności. Czasami, aby się nie powtarzać, trzeba tworzyć abstrakcje tak tępe, że członkowie drużyny nie mogą ich przestrzegać. Czasami struktura dwóch rzeczy jest tylko nieco podobna, ale wystarczająco inna. Jeśli doStuff1-4 są na tyle różne, że przefakturowanie ich w taki sposób, aby się nie powtarzało, powoduje, że musisz napisać nienaturalny kod lub przejść sprytne kodowanie w tył, co spowoduje, że twój zespół będzie na ciebie patrzył, to może się powtórzyć. Pochyliłem się, żeby nie powtórzyć się kilka razy w nienaturalny sposób i żałowałem produktu końcowego.

Zasadniczo więc nie myśl „och, ten kod jest dość podobny, może powinienem zreformować się, żeby się nie powtarzać”. Pomyśl „czy refaktoryzacja, aby ta podstawa kodu ponownie wykorzystywała wspólne elementy, sprawia, że ​​kod jest łatwiejszy w utrzymaniu, czy mniej ?” Następnie wybierz ten, który sprawia, że ​​jest łatwiejszy w utrzymaniu.


Biorąc to pod uwagę, biorąc pod uwagę SRP i po prostu próbując ogólnie mieć małe, elastyczne klasy, sensowne może być przeanalizowanie kodu z tego powodu , podzielenie fragmentów zachowań, które używają typów ogólnych (mówiłeś, że są one identyczne inne niż typ) na małe klasy. Następnie dowiesz się, że niektóre z tych klas są całkowicie identyczne (nie tylko w większości identyczne), a następnie możesz zbudować zestaw narzędzi na wypadek, gdybyś chciał je dodać Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntax.

durron597
źródło
32
TL; DR - DRY to środek do celu. Skoncentruj się na końcu, a nie na środkach. Gdybym mógł dwukrotnie głosować na Lego Mana, zrobiłbym to.
Jedna ważna uwaga: jeśli zrobić powtarzać sobie, zawsze wspomnieć w komentarzu wszystkie inne miejsca, które mają być wizytowane gdy powtarzające się zmiany kodu. Nie tylko zmniejsza prawdopodobieństwo desynchronizacji, ale działa również jako wskaźnik tego, ile bólu związanego z utrzymaniem powoduje powtórzenie.
Xion