---
title: "التكرار بدلاً من الاستخراج"
type: "ai-smell"
slug: "duplication-instead-of-extraction"
url: "http://localhost:3000/ar/ai-smells/duplication-instead-of-extraction.md"
category: "البنية"
description: "يميل مساعدو الذكاء الاصطناعي إلى لصق نسخة جديدة معدلة قليلاً من المنطق البرمجي الحالي بدلاً من إعادة استخدام دالة مشتركة أو استخراجها، مما يؤدي إلى تضخيم الكود المكرر مع اختفاء إعادة الهيكلة بصمت."
---
# التكرار بدلاً من الاستخراج

> يميل مساعدو الذكاء الاصطناعي إلى لصق نسخة جديدة معدلة قليلاً من المنطق البرمجي الحالي بدلاً من إعادة استخدام دالة مشتركة أو استخراجها، مما يؤدي إلى تضخيم الكود المكرر مع اختفاء إعادة الهيكلة بصمت.

## Signs and Symptoms

يتعرف المراجع على هذه الرائحة عندما يضيف ملف الفروقات (diff) المولد بواسطة الذكاء الاصطناعي كتلة برمجية موجودة بالفعل في مكان ما في المستودع بعد تعديل طفيف على اسمها، بدلاً من استدعاء الدالة المتوفرة بالفعل. النمط المميز هو وجود متنين أو أكثر شبه متطابقين يختلفان فقط في اسم الكيان (مثل `user`/`order`)، أو نقطة نهاية، أو قيمة ثابتة — وهو نوع النسخ الذي كان المطور البشري ليستخرجه في دالة مشتركة.

العلامات الشائعة:

* معالجات أو خدمات جديدة تكرر نفس عمليات التحقق، أو إعادة المحاولة، أو تحويل الأخطاء، أو الكود الجاهز لعمليات جلب البيانات حرفياً.
* إعادة كتابة السلاسل النصية السحرية والثوابت البرمجية في كل كتلة جديدة بدلاً من الإشارة إليها من مكان واحد.
* كل محادثة مع الوكيل البرمجي تعيد تطبيق منطق كتبته المحادثة السابقة بالفعل (ليس لدى الوكيل ذاكرة بوجود دالة مساعدة).
* تُظهر سجلات `git log` التزامات متتالية للذكاء الاصطناعي تضيف سطوراً جديدة دون وجود سطور "منقولة" أو معاد تسميتها تقريباً — إضافات دون دمج أو تنظيم.

```ts
// أضاف الذكاء الاصطناعي هذا للمسار الجديد — لكن getUser موجود بالفعل قبل 30 سطراً
async function getOrder(id: string) {
  const res = await fetch(`${API}/orders/${id}`, { headers: authHeaders() });
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  const json = await res.json();
  if (!json?.data) throw new Error("Malformed response");
  return json.data;
}

async function getUser(id: string) {                 // <-- متن متطابق بنسبة 95%
  const res = await fetch(`${API}/users/${id}`, { headers: authHeaders() });
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  const json = await res.json();
  if (!json?.data) throw new Error("Malformed response");
  return json.data;
}

```

هذه هي رائحة [الكود المكرر (Duplicate Code)](https://refactoring.guru/smells/duplicate-code) الكلاسيكية، ولكنها تُنتج بشكل منهجي ومبرمج بدلاً من أن تحدث بالصدفة.

## Reasons for the Problem

**لماذا تنتجها النماذج؟**

* **محلية الرمز التالي (Next-token locality).** يكمل نموذج اللغة الكبيرة المقطع _الحالي_ بناءً على النص الأكثر تشابهاً في نافذة السياق الخاصة به. إن إعادة إنتاج كتلة قريبة معروفة بصحتها هو التكملة الأكثر احتمالاً إحصائياً؛ أما إيقاف الكتابة والذهاب لتعريف دالة مساعدة ثم استدعائها فهو مسار أطول وأقل احتمالاً يتطلب التنقل بين ملفات متعددة.
* **غياب نموذج على مستوى المستودع بأكمله.** نادراً ما يعرف المساعد بوجود دالة مساعدة مناسبة خارج سياقه. وبدون استرجاع للمعلومات (retrieval)، لا يمكنه إعادة استخدام ما لا يستطيع رؤيته، لذا يقوم بإعادة توليده. يصف الممارسون الوكلاء البرمجيين بأنهم "يعيدون إنشاء منطق مماثل من الصفر لكل مهمة جديدة"، ويصيغ إينو رييس (من Factory) جودة الكود نفسها كأهم متنبئ بما إذا كان الذكاء الاصطناعي سيساعد قاعدة الكود أم سيضرها.
* **فقدان الذاكرة بين المحادثات + نطاق الأمر الموجه.** يتم التعامل مع كل طلب كوحدة قائمة بذاتها ("اجعل _هذا_ يعمل")، وبالتالي يفرط الوكيل البرمجي في تخصيص حل ضيق أحادي الاستخدام بدلاً من التعميم. تطلق Ox Security على هذا **الإفراط في التخصيص** (يحدث في 80-90% من أكواد الذكاء الاصطناعي) و**تجنب إعادة الهيكلة** (80-90%): حيث يصدر النموذج كوداً يعمل للمهمة الحالية ولكنه لا يدمجه مع الباقي أبداً.
* **التملق / المسار الأقل مقاومة.** تعمل النماذج على تحسين المخرجات لتلبي الطلب بشكل مرئي دون لمس الملفات غير ذات الصلة. التكرار عملية "آمنة" ومحلية؛ بينما تهدد إعادة الهيكلة بكسر شيء لا يستطيع النموذج رؤيته، لذا يتجنبها.
* **الأدوات تجعل التكرار رخيصاً.** كما تشير GitClear، فإن الإكمال التلقائي بضغطة زر يجعل إدراج كتلة برمجية جديدة مجانياً تقريباً، مما يزيل المقاومة التي كانت تدفع المطورين سابقاً نحو إعادة الاستخدام.

**لماذا يسبب ضرراً؟**

* **تآكل الجودة المقاس.** وجد تحليل GitClear لعام 2025 (211 مليون سطر متغير، من 2020 إلى 2024) أن السطور المنسوخة/الملصقة ارتفعت من 8.3% إلى 12.3% بينما انخفضت السطور "المنقولة" (المعاد هيكلتها) من \~24% إلى 9.5% — وكان عام 2024 هو العام الأول الذي _تجاوزت_ فيه السطور المنسوخة السطور المنقولة، كما قفزت كتل التكرار المكونة من 5 سطور أو أكثر بمعدل \~8 أضعاف.
* **دين الصحة — "أخطاء مكررة مألوفة (Bugs Déjà-Vu)".** وجدت Ox Security هذا في 70-80% من أكواد الذكاء الاصطناعي: الخطأ الذي يتم إصلاحه في نسخة مستنسخة يظل حياً وصامتاً في كل النسخ الأخرى، مما يؤدي إلى تكرار نفس العيوب وحاجة كل منها إلى إصلاح منفصل. التكرار يحول الخطأ الواحد إلى عدة أخطاء.
* **قابليته الصيانة وعبء المراجعة.** يجب العثور على كل تعديل سلوكي وتعديله في أماكن متعددة؛ وتتضخم الفروقات (diffs) بكتل شبه متطابقة يتعين على المراجعين فحصها سطراً بسطر للتأكد من أنها متطابقة _بالفعل_ (وليس بينها اختلافات طفيفة وخطيرة).
* **مساحة التعرض الأمني.** ينتشر النمط البرمجي الضعيف (مثل غياب فحص الصلاحيات، أو عدم تنقية المدخلات) في كل نسخة، وقد يغفل إصلاح أمني لاحق بعض النسخ المكررة — فالتكرار يضاعف المساحة المطلوب ترقيعها أمنياً.

## Treatment

**تكتيكات المراجعة وصياغة الأوامر**

* أخبر النموذج بمكان البحث أولاً: _"قبل كتابة كود جديد، ابحث في المستودع عن دالة مساعدة حالية تقوم بهذا وأعد استخدامها؛ لا تكرر الكود"_. ألصق الوحدة البرمجية ذات الصلة بحيث تكون في سياق النموذج.
* اطلب الدمج بوضوح: _"إذا كانت كتلتان تختلفان فقط في المعاملات، فاستخرج دالة واحدة ذات معاملات (Extract Function) واستدعها في كلا المكانين"_.
* أجبره على تشغيل الأدوات: _"شغّل أداة الفحص / jscpd / فحص التكرار وحل أي استنساخ يبلغ عنه قبل إرجاع الفروقات (diff)"_. يصحح الوكلاء البرمجيون أنفسهم بشكل ممتاز عندما يُمنحون إشارة حتمية.
* في المراجعة، تعامل مع الكتل التي تبدو منسوخة كدافع للبحث (grep): ابحث عن سطر مميز واحد؛ وإذا كان موجوداً بالفعل، فأعد الكود للوكيل لاستخراجه.

**إعادة الهيكلة — استخراج الدالة (Extract Function) + جعلها ذات معاملات**

```ts
// بعد: مصدر واحد للحقيقة، يتم استدعاؤه من الطرفين
async function getResource<T>(path: string): Promise<T> {
  const res = await fetch(`${API}/${path}`, { headers: authHeaders() });
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  const json = await res.json();
  if (!json?.data) throw new Error("Malformed response");
  return json.data as T;
}

const getOrder = (id: string) => getResource<Order>(`orders/${id}`);
const getUser  = (id: string) => getResource<User>(`users/${id}`);

```

الآن، أي إصلاح لمعالجة الأخطاء أو تحليل الاستجابة يستقر في مكان واحد فقط. وحين تختلف النسخ المكررة في خطوات المعالجة بدلاً من القيم، يفضل استخدام [نمط طريقة القالب (Form Template Method)](https://refactoring.guru/design-patterns/template-method) أو تمرير الخطوة المتغيرة كدالة استدعاء (callback). الحركات المعتمدة هنا هي **استخراج الدالة (Extract Function)**، و**استخراج المتغير/الثابت (Extract Variable/Constant)** (للقيم الحرفية المعاد كتابتها)، و**رفع المنهج (Pull Up Method)** عندما تعيش النسخ المستنسخة في كلاسات شقيقة — وكلها علاجات قياسية لـ [الكود المكرر (Duplicate Code)](https://refactoring.guru/smells/duplicate-code).

**حاجز حماية، وليس مجرد تنظيف:** اربط مكتشف استنساخ الكود في خادم التكامل المستمر (CI) بحد منخفض بحيث يفشل بناء الكود عند توليد الذكاء الاصطناعي للتكرار التالي بدلاً من دمجه. اربطه بقاعدة منزلية مكونة من سطر واحد في `CLAUDE.md`/`AGENTS.md` ("أعد استخدام الدوال المساعدة الحالية؛ ولا تلصق كوداً شبه مكرر أبداً") لكي ترافق هذه القيود سياق النموذج في كل دورة محادثة.

## Detected by

- **jscpd** `copy/paste duplication (configurable min-tokens / min-lines threshold; supports --threshold gate in CI)` — تكرار النسخ/اللصق (حد أدنى قابل للتعديل للرموز/السطور؛ يدعم بوابة التقييم --threshold في CI) (https://github.com/kucherenko/jscpd)
- **PMD** `CPD (Copy/Paste Detector) — token-based clone detection across 30+ languages` — CPD (مكتشف النسخ/اللصق) — كشف الاستنساخ المبني على الرموز عبر أكثر من 30 لغة (https://pmd.github.io/pmd/pmd_userdocs_cpd.html)
- **SonarQube / SonarSource** `S4144 — Methods should not have identical implementations` — S4144 — يجب ألا تمتلك الأساليب تطبيقات متطابقة (https://rules.sonarsource.com/javascript/RSPEC-4144/)
- **SonarQube / SonarSource** `S1192 — String literals should not be duplicated` — S1192 — يجب ألا تتكرر السلاسل النصية الحرفية (https://rules.sonarsource.com/javascript/RSPEC-1192/)
- **SonarQube** `Duplicated blocks / duplicated_lines_density metric (built-in clone engine, fails quality gate over threshold)` — الكتل المكررة / مقياس كثافة السطور المكررة (محرك استنساخ مدمج، يفشل بوابة الجودة عند تخطي الحد المسموح به) (https://docs.sonarsource.com/sonarqube-server/latest/user-guide/code-metrics/metrics-definition/)
- **eslint-plugin-sonarjs** `sonarjs/no-identical-functions` — sonarjs/no-identical-functions (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-identical-functions.md)
- **eslint-plugin-sonarjs** `sonarjs/no-duplicate-string` — sonarjs/no-duplicate-string (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-duplicate-string.md)
