کد تکراری

کد تکراری یک اصطلاح برنامه‌نویسی برای بخشی از کد منبع است که بیش از یک بار می‌آید، چه در درون یک برنامه و چه در برنامه‌های مختلفی که توسط یک موجودیت نگه‌داری می‌شود. به صورت کلی، کد تکراری به دلایلی نامطلوب به حساب می‌آید. معمولاً حداقل مقدار خط کدی نیاز است تا آن را به جای آنکه تشابه تصادفی دو قسمت بدانیم، تکراری در نظر بگیریم. به این بخش‌های تکراری کد، کد کلون یا کلون گفته می‌شود و به فرایند خودکار پیدا کردن تکرارها در کد پیدا کردن کلون می‌گویند.

دو بخش از کد ممکن است تکراری باشند بدون اینکه همه کاراکترهای آن‌ها برابر باشد، مثلاً ممکن است وقتی فاصله‌ها و کامنت‌ها در نظر گرفته نشوند با هم برابر باشند یا اگر آن‌ها را تحلیل واژگانی کنیم برابر شوند یا واژه به واژه معادل باشند و در بخش‌هایی تنوع داشته باشند. حتی بخش‌هایی از کد که کارکرد یکسان دارند می‌توانند به عنوان کد تکراری در نظر گرفته شوند.

 پدیداری 
برخی از راه‌های تولید کد تکراری عبارت است از:
 برنامه‌نویسی با کپی و الصاق، که ممکن است به خاطر دستبرد فکری به سایر کد انجام شده باشد.
 برداشتن یک قطعه از کد و کپی کردن آن به خاطر آنکه کار می‌کند. در اکثر موارد این کار نیاز به تغییر جزئی در کد کپی‌شده دارد مثل تغییر نام متغیرها با اضافه/کم کردن کد. زبان‌های برنامه‌نویسی تقریباً در همهٔ موارد این امکان را می‌دهند که یک کپی از کد از مکان‌های مختلفی فراخوانی شوند تا بتواند به اهداف متفاوتی پاسخ دهد و در عین حال نیازی به به وجود آوردن یک کپی دیگر از کد نباشد اما با این حال برنامه‌نویس به دلایل زیر ممکن است کد را کپی کند:
 با امکانات زبان به اندازهٔ کافی آشنا نباشند.
 به اندازهٔ کافی زمان برای کد زدن خوب نداشته باشند.
 به افزایش خراب شدن فعال نرم‌افزار اهمیتی ندهند.

همچنین ممکن است عملکردی که برنامه‌نویس می‌خواهد پیاده‌سازی کند بسیار مشابه با عملکرد تکه‌ای از کد باشد که به صورت مستقل در جای دیگری از کد وجود دارد. مطالعات نشان می‌دهد که این قسمت‌های مستقل کد که دوباره نوشته می‌شوند معمولاً از نظر دستوری مشابه هم نیستند.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 در مطالعه‌ای که توسط واگنر، عبدالخالق و کایا انجام شده، به این نتیجه رسیدند که اگرچه باید کار بیشتری برای همگام سازی نسخه‌ها انجام شود، با این حال اگر برنامه نویسان مربوطه از کد تکراری آگاه باشند، به‌طور قابل توجهی خطاها نسبت به کد بدون تکرار کاهش می‌یابد. 

 تشخیص کد تکراری 
الگوریتم‌های مختلفی برای کشف کد تکراری پیشنهاد شده‌است. برای مثال:
 الگوریتم بیکر.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).
 حساس بودن به محل
 ضد اتحادBulychev, Peter, and Marius Minea. "Duplicate code detection using anti-unification." Proceedings of the Spring/Summer Young Researchers’ Colloquium on Software Engineering. No. 2. Федеральное государственное бюджетное учреждение науки Институт системного программирования Российской академии наук, 2008.

 مثال کد تکراری 
قطعه کد زیر را که میانگین آرایهای از اعداد صحیح را محاسبه می‌کند، در نظر بگیرید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; دو حلقه را می‌توان در قالب یک تابع، به صورت زیر بازنویسی کرد: 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); توجه داشته باشید که در این مورد بدیهی، کامپایلر ممکن است هر دو فراخوانی را به صورت گسترش در خط ترجمه کند، در این صورت کد ماشین به دست‌آمده از ترجمه، برای هر دو مثال با تکرار و بدون تکرار کد، یکسان خواهد بود. اگر به صورت گسترش در خط ترجمه نشده باشد، احتمالاً سربار اضافی فراخوانی تابع منجر به زمان اجرای بیشتری (در حدود ۱۰ دستورالعمل پردازنده برای اکثر زبان‌ها با کارایی بالا) خواهد شد. از لحاظ تئوری، این زمان اضافی برای اجرا می‌تواند مهم باشد.
بندانگشتی| نمونه ای از رفع کد تکراری با استفاده از جایگزینی کد با تابع

 جستارهای وابسته 
 اصل انتزاع (برنامه‌نویسی)
 ضد الگوی
 اختصاص داده‌ها
 خودت را تکرار نکن (DRY)
 لیست ابزارهای تجزیه و تحلیل کد ایستا
 کد اضافی
 قانون سه (برنامه‌نویسی رایانه)

 منابع 

 جستارهای وابسته 
 دانشگاه آلاباما در بیرمنگام: ادبیات کد کلون
 یافتن کد تکراری در C # ، VB. خالص ، ASPX ، روبی ، پایتون ، جاوا ، C , C ++ ، ActionScript یا XAML

رده:ضدالگوها
رده:کد منبع
رده:معیارهای نرم‌افزارسنجی
رده:مقاله‌های دارای کد نمونه به زبان سی