중복 코드

중복 코드는 동일한 실체가 소유하거나 유지 보수하고 있는 하나의 프로그램 내에서 또는 각기 다른 프로그램 내에서 한 번 이상 발생하는 일련의 소스 코드를 가리키는 컴퓨터 프로그래밍 용어이다. 중복 코드는 보통 바람직하지 않는데 여기에는 수많은 이유가 있다. 중복 코드의 최소한의 요건은 동시다발적 유사성 보다는 연속적으로 중복되는 것으로 보이는 코드의 양에 적용된다. 중복 코드의 연속은 코드 클론(code clone), 간단히 클론(clone)이라고도 하며 소스 코드 내에서 중복을 찾는 자동화된 과정은 클론 감지(clone detection)라고 한다.

중복을 일으키는 원리 
중복 코드가 발생하는 이유들 중에는 복사해서 붙여넣기 프로그래밍을 포함하는데, 여기에서 학문적인 문맥에서 표절, 징발의 일부로 간주될 수도 있으며 그저 동작하기 때문에 코드의 부분이 복사되는 것이다. 대부분의 경우 이러한 작업에는 변수 이름 변경이나 코드 추가/삭제와 같은 복제된 코드 내의 사소한 수정이 수반된다. 언어적인 측면에서는 코드의 한 복사본을 여러 목적으로 다룰 수 있게 하는 기능을 거의 늘 제공하지만 프로그래머가 적절하게 이를 처리할 시간이 부족해서가 아니라, 또 소프트웨어 부후증의 증가를 고려해서가 아닌, 해당 언어를 잘 알지 못해서 복사본이 만들어진다.

프로그램의 다른 일부분과 매우 비슷한 기능을 포함하는 경우도 있으며 개발자가 독립적으로 다른 곳에 존재하는 것과 매우 비슷한 코드를 작성할 수 있다. 여러 연구에 따르면 이렇게 독립적으로 작성된 코드는 일반적으로 문법적으로 유사하지 않다.

개발 속도나 용이성을 증가하기 위해 복제 코드의 생성을 필요로 하는 자동으로 생성되는 코드는 중복의 또다른 이유이기도 하다. 실제 생성기에는 소스 코드에 중복을 포함하지 않고 만들어내는 출력에만 영향을 미친다.

비용과 이점 
소프트웨어 취약점이 있는 코드가 복사될 때 개발자가 이러한 사본을 알지 못하는 경우 취약점은 계속해서 복사된 코드에 남아있게 된다. 코드 중복을 사용하면 컴파일 시간의 단축, 인지 부하의 감소, 인적 오류의 감소, 코드를 잊거나 간과하는 일의 감소를 달성할 수 있다. 그러나 모든 코드 중복이 리팩터링이 될 수 있는 것은 아니다. 프로그래밍 언어가 특히 동시 편집과 같은 사용자 인터페이스 기법과 함께 지원되는 경우 부적절하거나 과도하게 복잡한 추상화를 제공한다면 복제 자체가 가장 효율적인 해결책이 될 수 있다. 게다가, 리팩토링을 할 때 코드를 분리하는 것이 어떠한 유지보수적 이익 보다 더 중요할 수 있다. 중복 코드는 중복되지 않은 코드 보다 상당히 더 오류가 있는 경향이 있는 것으로 보이지는 않는다.

중복 코드의 감지 
중복 코드를 찾기 위해 수많은 여러 알고리즘들이 제안되었다. 이를테면 다음과 같다:
 베이커 알고리즘.
 라빈-카프 문자열 검색 알고리즘.
 추상 구문 트리를 사용.
 시각적 클론 감지(Visual clone detection).
 카운트 매트릭스 클론 감지(Count Matrix Clone Detection).
 Locality-sensitive hashing

기능적 중복 코드의 예 
정수의 배열의 평균을 셈하는 다음의 코드 스니펫이 있다고 하자.

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;

2개의 루프를 하나의 함수로 재작성할 수 있다:
int calc_average_of_four(int* array) {
   int sum = 0;
   for (int i = 0; i < 4; i++)
       sum += array[i];

   return sum / 4;
}

위의 함수를 사용하면 루프 중복이 없는 소스 코드를 제공한다:
extern int array1[];
extern int array2[];

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

이 사소한 경우에서 컴파일러는 해당 함수로 향하는 두 호출에 대한 인라인을 선택할 수 있으며 위의 예처럼 기계 코드가 중복되거나 중복되지 않을 수 있다. 함수가 인라인 처리되지 않으면 추가적인 함수 호출의 부하가 발생하여 실행에 시간이 더 소요될 수 있다. 이론적으로 실행 시 추가 시간은 문제가 될 수 있다.

같이 보기 
 안티패턴
 중복배제

각주

외부 링크 
 The University of Alabama at Birmingham: Code Clones Literature
 Finding duplicate code in C#, VB.Net, ASPX, Ruby, Python, Java, C, C++, ActionScript, or XAML

안티패턴
소스 코드