Czasami duplikacja kodu jest wynikiem „pun”: dwie rzeczy wyglądają tak samo, ale nie są.
Możliwe jest, że nadmierna abstrakcja może złamać prawdziwą modułowość twojego systemu. Zgodnie z reżimem modułowości musisz zdecydować „co może się zmienić?” i „co jest stabilne?”. Wszystko, co jest stabilne, zostaje umieszczone w interfejsie, a to, co jest niestabilne, zostaje zawarte w implementacji modułu. Następnie, gdy rzeczy się zmieniają, zmiana, którą musisz wprowadzić, jest izolowana dla tego modułu.
Refaktoryzacja jest konieczna, gdy to, co uważasz za stabilne (np. To wywołanie API zawsze przyjmuje dwa argumenty), musi się zmienić.
Tak więc w przypadku tych dwóch zduplikowanych fragmentów kodu zapytam: Czy wymagana zmiana jednego z nich oznacza koniecznie również zmianę drugiego?
To, jak odpowiesz na to pytanie, może dać ci lepszy wgląd w to, czym może być dobra abstrakcja.
Wzory projektowe są również przydatnymi narzędziami. Być może zduplikowany kod wykonuje przejście w jakiejś formie i należy zastosować wzorzec iteratora.
Jeśli zduplikowany kod ma wiele zwracanych wartości (i dlatego nie możesz wykonać prostej metody wyodrębniania), być może powinieneś utworzyć klasę, która przechowuje zwracane wartości. Klasa może wywołać metodę abstrakcyjną dla każdego punktu, który różni się między dwoma fragmentami kodu. Wykonałbyś wtedy dwie konkretne implementacje klasy: po jednej dla każdego fragmentu. [Jest to faktycznie wzorzec projektowy metody szablonów, którego nie należy mylić z koncepcją szablonów w C ++. Alternatywnie to, na co patrzysz, może być lepiej rozwiązane za pomocą wzorca strategii.]
Innym naturalnym i użytecznym sposobem myślenia o tym są funkcje wyższego rzędu. Na przykład tworzenie lambdas lub korzystanie z anonimowych klas wewnętrznych, aby kod mógł przejść do abstrakcji. Ogólnie rzecz biorąc, możesz usunąć duplikację, ale chyba że naprawdę istnieje między nimi relacja [jeśli jedna się zmieni, a także druga], możesz zranić modułowość, nie pomagając.
Osobiście to ignoruję i idę dalej. Są szanse, że jeśli to dziwny przypadek, lepiej jest go zduplikować, możesz poświęcić całe wieki na refaktoryzację, a następny twórca spojrzy i cofnie twoją zmianę!
źródło
Bez próbki kodu trudno jest powiedzieć, dlaczego w kodzie nie ma łatwo rozpoznawalnej abstrakcji. Z tym zastrzeżeniem, oto kilka pomysłów:
Największą trudnością w tym ćwiczeniu jest to, że twoja funkcja prawdopodobnie zawiera zbyt wiele niepowiązanych zachowań na danym poziomie abstrakcji i musisz poradzić sobie z niektórymi z nich na niższych poziomach. Prawidłowo przypuszczasz, że przejrzystość jest kluczem do utrzymania kodu, ale wyraźne zachowanie kodu (jego aktualny stan) różni się bardzo od wyjaśnienia intencji kodu.
Uczyń streszczenie mniejszych fragmentów kodu abstrakcyjnymi, dzięki ich sygnaturom funkcji identyfikującym co, a większe fragmenty powinny być łatwiejsze do sklasyfikowania.
źródło