Powielony kod - Duplicate code

Zduplikowany kod to termin programowania komputerowego oznaczający sekwencję kodu źródłowego, która występuje więcej niż raz, w ramach programu lub w różnych programach należących do tej samej jednostki lub przez nią utrzymywanych. Powielony kod jest ogólnie uważany za niepożądany z wielu powodów. Minimalny wymóg jest zwykle stosowany do ilości kodu, który musi pojawić się w sekwencji, aby można go było uznać za duplikat, a nie przypadkowo podobny. Sekwencje zduplikowanego kodu są czasami nazywane klonami kodu lub po prostu klonami, zautomatyzowany proces znajdowania duplikatów w kodzie źródłowym nazywa się wykrywaniem klonów.

Dwie sekwencje kodu mogą być duplikatami siebie nawzajem bez identyczności znak po znaku, na przykład będąc identycznymi znak za znak tylko wtedy, gdy znaki odstępu i komentarze są ignorowane lub będąc identycznym tokenem za token lub tokenem -dla-symboliczne identyczne ze sporadycznymi zmianami. Nawet sekwencje kodu, które są tylko funkcjonalnie identyczne, można uznać za zduplikowany kod.

Powstanie

Oto niektóre sposoby, w jakie można utworzyć zduplikowany kod:

  • scrounging, w którym fragment kodu jest kopiowany „ponieważ działa”. W większości przypadków operacja ta obejmuje niewielkie modyfikacje sklonowanego kodu, takie jak zmiana nazw zmiennych lub wstawianie / usuwanie kodu. Język prawie zawsze pozwala na wywołanie jednej kopii kodu z różnych miejsc, aby mogła służyć wielu celom, ale zamiast tego programista tworzy drugą kopię, być może dlatego, że

Może się również zdarzyć, że wymagana jest funkcjonalność bardzo podobna do tej w innej części programu, a programista niezależnie pisze kod bardzo podobny do tego, który istnieje gdzie indziej. Badania sugerują, że taki niezależnie przepisany kod zazwyczaj nie jest podobny pod względem składniowym.

Automatycznie generowany kod, w przypadku którego zduplikowany kod może być pożądany w celu zwiększenia szybkości lub łatwości programowania, to kolejny powód duplikacji. Zauważ, że rzeczywisty generator nie będzie zawierał duplikatów w swoim kodzie źródłowym, a jedynie dane wyjściowe, które generuje.

Ustalenie

Powielony kod jest najczęściej naprawiany poprzez przeniesienie kodu do jego własnej jednostki (funkcji lub modułu) i wywołanie tej jednostki ze wszystkich miejsc, w których był pierwotnie używany. Korzystanie z bardziej otwartego stylu programowania, w którym komponenty znajdują się w scentralizowanych lokalizacjach, może również pomóc w powielaniu.

Koszty i korzyści

Kod, który zawiera zduplikowaną funkcjonalność, jest trudniejszy w obsłudze,

  • po prostu dlatego, że jest dłuższy i
  • ponieważ jeśli wymaga aktualizacji, istnieje niebezpieczeństwo, że jedna kopia kodu zostanie zaktualizowana bez dalszego sprawdzania obecności innych wystąpień tego samego kodu.

Z drugiej strony, jeśli jedna kopia kodu jest używana do różnych celów i nie jest odpowiednio udokumentowana, istnieje niebezpieczeństwo, że zostanie zaktualizowana w jednym celu, ale ta aktualizacja nie będzie wymagana ani odpowiednia dla innego. cele.

Te rozważania nie dotyczą automatycznie generowanego kodu, jeśli w kodzie źródłowym jest tylko jedna kopia funkcji.

W przeszłości, gdy miejsce w pamięci było bardziej ograniczone, zduplikowany kod miał dodatkową wadę polegającą na tym, że zajmował więcej miejsca, ale obecnie jest mało prawdopodobne, aby był to problem.

W przypadku kopiowania kodu z luką w zabezpieczeniach oprogramowania luka może nadal istnieć w kopiowanym kodzie, jeśli programista nie jest świadomy istnienia takich kopii. Refaktoryzacja zduplikowanego kodu może poprawić wiele metryk oprogramowania, takich jak wiersze kodu , cykliczna złożoność i sprzężenie . Może to prowadzić do krótszych czasów kompilacji, mniejszego obciążenia poznawczego , mniej błędów ludzkich i mniej zapomnianych lub przeoczonych fragmentów kodu. Jednak nie wszystkie powielenia kodu można refaktoryzować. Klony mogą być najskuteczniejszym rozwiązaniem, jeśli język programowania zapewnia nieadekwatne lub zbyt złożone abstrakcje, szczególnie jeśli są obsługiwane przez techniki interfejsu użytkownika, takie jak jednoczesna edycja . Ponadto ryzyko złamania kodu podczas refaktoryzacji może przeważyć nad korzyściami związanymi z konserwacją. Badanie przeprowadzone przez Wagnera, Abdulkhaleqa i Kaya wykazało, że chociaż należy wykonać dodatkową pracę, aby zachować synchronizację duplikatów, jeśli zaangażowani programiści są świadomi duplikatu kodu, nie było znacznie więcej błędów niż w kodzie nie powielonym.

Wykrywanie zduplikowanego kodu

Zaproponowano szereg różnych algorytmów do wykrywania duplikatów kodu. Na przykład:

Przykład funkcjonalnie zduplikowanego kodu

Rozważmy następujący fragment kodu do obliczania średnio o tablicę z liczb całkowitych

extern int array_a[];
extern int array_b[];
 
int sum_a = 0;

for (int i = 0; i < 4; i++)
   sum_a += array_a[i];

int average_a = sum_a / 4;
 
int sum_b = 0;

for (int i = 0; i < 4; i++)
   sum_b += array_b[i];

int average_b = sum_b / 4;

Dwie pętle można przepisać jako jedną funkcję:

int calc_average_of_four(int* array) {
   int sum = 0;
   for (int i = 0; i < 4; i++)
       sum += array[i];

   return sum / 4;
}

lub, zwykle korzystnie, poprzez parametryzację liczby elementów w tablicy.

Użycie powyższej funkcji da kod źródłowy, który nie ma powielania pętli:

extern int array1[];
extern int array2[];

int average1 = calc_average_of_four(array1);
int average2 = calc_average_of_four(array2);

Zauważ, że w tym trywialnym przypadku kompilator może zdecydować się na wstawienie obu wywołań funkcji w taki sposób, że wynikowy kod maszynowy jest identyczny zarówno dla zduplikowanych, jak i nie powielonych przykładów powyżej. Jeśli funkcja nie jest wbudowana, to dodatkowe obciążenie wywołań funkcji prawdopodobnie potrwa dłużej (w kolejności 10 instrukcji procesora dla większości języków o wysokiej wydajności). Teoretycznie ten dodatkowy czas na bieg może mieć znaczenie.

Przykład poprawki zduplikowanego kodu poprzez zastąpienie kodu metodą

Zobacz też

Bibliografia

Linki zewnętrzne