代码重复

代码重复（英文：duplicate code，也叫代码克隆）在程序设计中表示一段源代码在一个程序，或者一个团体所维护的不同程序中重复出现，是不希望出现的现象。为避免巧合，只有一定数量的代码完全相同才能判定为代码重复。重複代碼的段落有時被稱為代碼克隆，自动检测代码重复的过程叫做克隆检测。

 产生 
产生代码重复可能有以下几个原因：

 因为某段代码能用就复制粘贴过来。多数情况下代码会有少许不同，如变量名称改变或代码增删。
 因为要实现与已有功能类似的功能，开发者独立写出与别处相似的代码。研究表明独立撰写的代码在语法上不一定相似。Code similarities beyond copy & paste  by Elmar Juergens, Florian Deissenboeck, Benjamin Hummel.
 抄袭，即不经允许复制代码，且未列出版权归属。
 代码系自动生成。这时可能需要重复代码以提高性能或方便开发。注：这里代码重复是指代码生成器自动生成的代码，而非生成器本身的代码。

 成本與效益 
不恰当的代码重复表明程序设计不良，例如缺少抽象。这会导致程序过长，错误更多，进而难以维护，因为需要人工寻找并修改重复的部分。然而由于种种原因，适当的代码重复难以避免，例如给与已有设备相似的新设备写驱动程序时，复制代码能使开发更便捷。Kapser, C.; Godfrey, M.W., ""Cloning Considered Harmful" Considered Harmful ," 13th Working Conference on Reverse Engineering (WCRE), pp. 19-28, Oct. 2006

當複製具有軟件漏洞的代碼時，如果開發人員不知道這樣的副本，則複製的代碼中可能會繼續存在漏洞。代码重构可以改善許多軟件的度量衡標準，例如源代碼行數，循環複雜度和耦合度。這可能會縮短編譯時間，降低認知負載，減少人為錯誤，減少被遺忘或被忽視的代碼。

但並不是所有的代碼重複都可以被重構。如果編程語言提供不充分或過於複雜的抽象，克隆或許是具有速度效益上的解決方式，特別是修改代碼使用的編輯器如有支持區塊(行)編輯的功能。而且，重構時破壞代碼的風險可能會超過維護的效益。重複的代碼似乎不會比不重複的代碼更容易出錯。使用開源方式共享代碼組件，而不是在软件配置管理的倉儲庫之間複製它們，也可以減少複製。

 检测 
检测代码重复的手段有：

 Baker算法Brenda S. Baker. A Program for Identifying Duplicated Code. Computing Science and Statistics,24:49–57, 1992.

 利用抽象语法树Ira D. Baxter, et al. Clone Detection Using Abstract Syntax Trees 
 可视化检测器Visual Detection of Duplicated Code  by Matthias Rieger, Stephane Ducasse.
 矩阵计数检测Yuan, Y. and Guo, Y.  CMCD: Count Matrix Based Code
Clone Detection, in 2011 18th Asia-Pacific Software Engineering Conference. IEEE, Dec. 2011, pp. 250–257.Chen, X., Wang, A. Y., & Tempero, E. D. (2014). A Replication and Reproduction of Code Clone Detection Studies . In ACSC (pp. 105-114).

 例子 
以计算整数数组的平均值的代码片段为例

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

int sum1 = 0;
int sum2 = 0;
int average1 = 0;
int average2 = 0;

for (int i = 0; i < 4; i++)
{
   sum1 += array1[i];
}
average1 = sum1/4;

for (int i = 0; i < 4; i++)
{
   sum2 += array2[i];
}
average2 = sum2/4;

这两个循环可以改写为一个函数：
int calcAverage (int* Array_of_4)
{
   int sum = 0;
   for (int i = 0; i < 4; i++)
   {
       sum += Array_of_4[i];
   }
   return sum/4;
}
利用以上函数可以写出无重复的源代码
extern int array1[];
extern int array2[];

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


 参见 
 代码异味
 一次且仅一次
 抽象化 (计算机科学)

 參考資料 

分類:計算機編程