قراءة الكود من أجل معدلات النمو
مراجعة الكود من أجل الصحة مقابل مراجعة الكود من أجل التعقيد
مراجعة الكود من أجل الصحة يكتشف أخطاء المنطق: الشرطات الخاطئة، والفواتح بمسافة واحدة، والتفادي من النقاط الخالية. مراجعة الكود المعرفية بالتعقيد يكتشف فئة مختلفة من الخلل: الكود الذي يعمل بشكل صحيح عند N = 100 ولكن ينمو بشكل كارثي عند N = 100,000.
يتصل هذا الدرس بتحقيق أكثر عمقًا في الدورة غير هامينغ: [الفصل المفقود: التعقيد الخوارزمي](/ar/un/unhamming_algorithmic_complexity) يغطي Big O في سياق الأخطاء المنتجة، و[MOAD-0001: الخلل الجيري](/ar/un/unhamming_moad_sedimentary) يرسم النمط عبر أكثر من 60 بيئة برمجية.
اثنين من استراتيجيات المراجعة
الدوائر الموجودة داخل الدوائر تضاعف التعقيد. الدوائر الموجودة داخل الدوائر داخل N العناصر تنتج O(N²). ثلاثة تنتج O(N³). عند المراجعة: احسب عمق طبقات الدوائر أولاً.
الكمية داخل الدائرة الساخنة. أي .contains(), .includes(), .find(), أو في قائمة التحقق داخل دائرة تكلفتها O(N) لكل تحقق. فوق N التكرار: O(N²) الإجمالي. يظهر هذا النمط في كود الأنظمة الإنتاجية في عشرات البيئات البرمجية - معالج Haskell GHC، Python pip، Apache Maven، Rust Cargo، TypeScript، Godot. نفس الخطأ، مختلف الكودات.
مراجعة: إيجاد التكرارات
قم بمراجعة الدالة التالية من حيث التعقيد:
def find_duplicates(items):
seen = []
duplicates = []
for item in items:
if item in seen:
duplicates.append(item)
else:
seen.append(item)
return duplicates
MOAD-0001: العارض الجيري
نفس العارض، ستة بيئات
يظهر نمط if x not in list: list.append(x) داخل حلقة - وقد ظهر- في كود الإنتاج عبر عدة عشرات من بيئات برمجية:
- GHC (معالج هاسكل): معالج التبعيات، O(N²) عند N = 50,000 حزم، وقت بناء يبلغ 17 دقيقة
- Python pip: حل النزاعات حول التبعيات
- Apache Maven: تكرار مسار الكلاسز
- Rust Cargo: توحيد الميزات
- TypeScript compiler: حلول الموديول
- Godot / Redot محرك الألعاب: التنقل في الرسم البياني للنود
لم يرتكب أي من هذه الفرق خطأً. كتبوا كود صحيح في الحالات الصغيرة. نمت N. كتب الكود. كان النمط يحمل اسم: MOAD-0001، العارض الجيري. الجير: كود صحيح، آمن في طبقات رقيقة. مع الوقت، تجمع الطبقات وتحول إلى صخر.
الحل
في كل حالة: استبدل الحاوية التتابعية بالحاوية المخزنة. سطر واحد. لا تغيير سلوكي في المدخلات الصحيحة. تزداد سرعة 100-1000× عند N الواقعي.
يعمل الحل لأن هناك عملية تحتاج إلى أن تبقى سريعة:
1. تحقق العضوية: هل تم رؤية هذا العنصر من قبل؟
2. الإخراج المرتب: عودة العناصر في ترتيب ظهورها (في بعض الأحيان مطلوب، وفي بعض الأحيان ليس مطلوبًا).
تتعامل المجموعة مع (1) في O(1). إذا كان (2) مهمًا أيضًا، احتفظ بمجموعة منقطة لخروج المرتبة وتحقق العضوية في المجموعة. اثنان من الهيكلات البيانية، كل منها يقوم بعمله.
رد على مراجعة
طلب استدعاء يقوم بحل MOAD-0001 في دالة تطفو في مشروع الرسم البياني. يقدم المراجع:
> "Sets don't preserve insertion order — this changes behavior."
نمط تحليل المقابلة
التنسيق المتوقع
تحليل معقدية الالغوريثم يظهر في المقابلات في مجال هندسة البرمجيات. يجب أن يتبع الجواب نمطًا يتألف من أربعة أجزاء:
1. وضح التعقيد الحالي - O(?) بالنسبة للزمن، O(?) بالنسبة للمساحة.
2. شرح السبب - تحديد البناء المعين المسؤول (الخوارزمية المكررة، الفحص الخطي داخل الدائرة، الفرعيات التكرارية).
3. اقتراح تحسين - تسمية التغيير والبنية أو الخوارزمية التي تقدمه.
4. وضح التعقيد الجديد - بعد الصياغة، ما التعقيد الزمني والمساحة؟
مثال:
الكود: [دالة تحقق العضوية في قائمة داخل دائرة تكرارية]
الحالي: O(N²) - `item in seen_list` هو O(N) لكل فحص × N تكرار
التحسين: استبدال seen_list بـ seen_set (مجموعة هاشية)
بعد: O(N) - فحص العضوية في المجموعة هو O(1)
يتحول هذا المهارة خارج المقابلات: مراجعة الكود مع وعي بالمعقدية، تصميم المعمارية، فحص الأداء، الفحوصات الأمنية. أي نظام يعالج مدخلات مختلفة بحجمه يفيد من ذلك.
يتصل هذا الدرس ببعض المحتوى المقدم في دورة unhamming، التي تطبق هذا النمط الدقيق لتحسين الأخطاء في التحقيقات الإنتاجية عبر 60+ مشروع مفتوح المصدر.
مقابلة: تحليل has_common_element
تطبيقات هذا النمط الأربعة في الدالة التالية:
def has_common_element(list_a, list_b):
for item in list_a:
for other in list_b:
if item == other:
return True
return False