تنقيح برمجي

التنقيح أو تشخيص الأخطاء  أو علاج الأخطاء أو تصحيح الأخطاء هو عملية منهجية لإيجاد وتقليل عدد الخطأ البرمجي، أو العيوب، في برنامج (حاسوب) أو قطعة من عتاد الحاسوب الإلكترونية، وبالتالي، جعلها تعمل بالطريقة المتوقعة منها. ويميل تصحيح الأخطاء إلي أن يكون أصعب عندما يتم الربط بين أنظمة فرعية متعددة بشكل كبير، بحيث ربما تؤدي التغييرات في أحد الأنظمة إلي ظهور أخطاء برمجية في الآخر. وقد تم تأليف العديد من الكتب حول تصحيح الخطأ (انظر بأسفل: لمزيد من القراءة)، وذلك لأنه يشمل العديد من الجوانب، بما في ذلك تصحيح الأخطاء التفاعلي، التحكم في التدفق، اختبار الترابط، ملفات تسجيل البيانات، المراقبة (التطبيق، والنظام)[، ]طبع محتوى الذاكرة، تحليل البرنامج، مراقبة العملية الإحصائية، وتكتيكات التصميم الخاص من أجل تحسين الاكتشاف مع تبسيط التغييرات.

الأصل

هناك جدل حول أصل مصطلح " تصحيح الخطأ"/التنقيح.
ينسب مصطلحي " خطأ " و" تصحيح الخطأ " إلي العميد البحري جريس هوبر في الأربعينات. وبينما كانت تعمل على جهاز حاسوب من موديل النسخة الثانية بجامعة هارفارد، اكتشف زملائها فراشة ملصقة بمحرك مؤازر وبالتالي تعوق التشغيل، ومن ثم علقت بأنهم كانوا " يزيلون الخطأ (الحشرة) " من النظام". ومع هذا، فالمصطلح في معنى الخطأ الفني يرجع إلي عام 1878 على الأقل وتوماس إديسون (انظر أيضا خطأ برمجي للمناقشة الكاملة)، يبدو أن " تصحيح الخطأ " قد تم استخدامه في علم الطيران قبل دخوله عالم الكمبيوتر. وبالفعل، في مقابلة علقت جريس هوبر أنها لم تكن تبتكر المصطلح. فالفراشة قد ناسبت المصطلح الموجود بالفعل، وبالتالي تم تخزينه.
وتدوين قاموس أوكسفورد الإنجليزي لمصطلح " يصحح الخطأ " ينقل مصطلح " تصحيح الخطأ" debugging المستخدم في اختبار محرك الطائرة في مقال عام 1945 بمجلة جمعية الطيران الملكي، ووجد أن خطأ برمجي bug التي قالتها هوبر قد وجدت في التاسع من سبتمبر علم 1947. ولم يستخدم مبرمجو الحاسوب هذا المصطلح حتى أوائل الخمسينات. والمقال الرائد للعالم Gill في عام 1951 هو المناقشة المتعمقة الأولى لأخطاء البرمجة، إلا أنه لا يستخدم مصطلح " خطأ برمجي" أو " تصحيح الخطأ ". وفي المكتبة الرقمية رابطة مكائن الحوسبة، كان الاستخدام الأول لمصطلح " تصحيح الخطأ " في ثلاث مقالات من الاجتماعات المحلية لرابطة مكائن الحوسبة. اثنان من الثلاثة يستخدم المصطلح بين قوسين. وفي عام 1963، كان مصطلح " تصحيح الخطأ " شائعا بدرجة كافية ليتم ذكره والمرور عليه بدون تفسير على الصفحة رقم 1 من دليل نظام المشاركة الزمنية المتوافقة CTSS.
ومقال Kidwell " Stalking the Elusive Computer Bug" يناقش أصل مصطلح " bug" و" debug " بتفصيل أكبر.

النطاق

ولأن الأنظمة البرمجية والإلكترونية قد أصبحت معقدة بشكل عام، فقد توسعت أساليب تصحيح الخطأ الشائعة مع وجود المزيد من الوسائل لاكتشاف الأخطاء، وتقييم التأثير، ووضع جدول زمني لتصليح الأخطاء في البرامج أو التحديثات الكاملة للنظام. ويمكن استخدام كلمة شذوذ anomaly أو كلمة تباين discrepancy، على أنهما مصطلحات أكثر حيادية، من أجل تجنب كلمات مثل " خطأ error وعيب defect أو " خطأ خفي bug مع مضمون يقول أنه يجب تثبيت كلمات الأخطاء والعيوب، والأخطاء الخفية (مهما كلف الأمر). وبدلا من ذلك، يمكن عمل تقييم للتأثير[ من أجل تحديد ما إذا كانت التغيرات اللازمة لإزالة الشذوذ (أو التباين) ستكون مكلفة للنظام، أو ربما التحرير الجديد المجدول يجعل التغييرات غير لازمة. وليست كل القضايا هي ]تتوقف عليها الحياة [ أو ] تتوقف عليها المهمة[ في النظام. وكذلك، فمن المهم أن نتجنب الموقف الذي ربما يكون فيه التغيير أكثر إزعاجا للمستخدمين، وطويل المدى، أكثر من التعايش مع المشكلات المعروفة (حيث ربما يكون العلاج أسوأ من المرض). فبناء قرارات تقبل بعض من الأخطاء أو الشذوذ يمكن أن يتجنب ثقافة أمر " انعدام العيوب "، حيث ربما يتم إقناع الأشخاص بإنكار وجود المشكلات لكي تبدو النتيجة هي انعدام العيوب. وبتناول القضايا المرتبطة، مثل تقييم تأثير التكلفة مقابل المنفعة، فسوف تتوسع أساليب تصحيح الأخطاء لكي تحدد تكرار الأخطاء أو الشذوذ (عدد مرات حدوث نفس الأخطاء) من أجل المساعدة في تقييم تأثيرها على النظام العام.

الأدوات

يتفاوت تصحيح الخطأ من التعقيد إلي تثبيت أخطاء بسيطة من أجل أداء مهام مطولة ومتعبة لجمع البيانات وتحليلها وتحديثات الجدولة الزمنية. ومهارة المبرمج في تصحيح الخطأ يمن أن تكون عاملا رئيسيا في القدرة على تصحيح المشكلة، لكن صعوبة تصحيح الخطأ البرمجي تفاوت بدرجة كبيرة مع تعقيد النظام، وكذلك تعتمد إلي حد ما على لغة برمجة المستخدمة والأدوات المتاحة، مثل المصحح. والمصحح هي أدوات برمجية تساعد المبرمج على مراقبة تنفيذ البرنامج، أو إيقافه أو إعادة تشغيله، ووضع نقطة الانقطاع وتغيير القيم في الذاكرة. ويمكن لمصطلح مصحح debugger إن يشير إلي الشخص الذي يقوم بتصحيح الخطأ.
وبوجه عام، لغة البرمجة عالية المستوى مثل جافا (لغة برمجة) تجعل تصحيح الخطأ أسهل، لأن لها خصائص مثل لغة التعامل مع الاستثناء [exception handling التي تجعل المصادر الحقيقية للسلوك الشاذ سهل الاكتشاف. وفي لغات برمجة مثل سي أو لغة تجميع ربما تسبب الأخطاء مشكلات صامتة مثل إتلاف الذاكرة، وفي الغالب يكون من الصعب رؤية المكان الذي حدثت فيه المشكلة الأولى. وفي تلك الحالات، ربما تكون هناك حاجة إلي أدوات مصحح ذاكرة.
وفي مواقف معينة، يمكن لأدوات برمجة الأغراض العامة واليت هي لغات في الأصل أن تصبح مقيدة جدا. فهذه تتخذ شكل أدوات تحليل الكود الثابت. فتبحث هذه الأدوات عن مجموعة محددة جدا من المشكلات المعروفة، بعضها شائع وبعضها نادر، داخل كود المصدر. وكل تلك القضايا التي يتم اكتشافها عن طريق هذه الأدوات نادرا ما يتم التقاطها من خلال المصنف أو المفسر، وبالتالي فهي ليست مدقق نحوي syntax checkers، بل هي مدقق معاني semantic checkers. وتزعم بعض الأدوات قدرتها على اكتشاف أكثر من 300 مشكلة فريدة. وتوجد كل من الأدوات التجارية والمجانية في لغات متعددة. ويمكن لهذه الأدوات أن تكون مفيدة بدرجة كبيرة عند مراجعة أشجار المصدر الضخمة جدا source trees، حيث يكون من غير العملي تكويد عملية مراجعة التصميم walkthroughs. والمثال النموذجي لمشكلة تم اكتشافها سيكون إسناد مؤشري متغير والذي يحدث قبل تعيين قيمة للمتغير. ومثال أخر سيكون القيام بمراجعة قوية للنمط عندما لا تستلزم اللغة ذلك. وبالتالي، فهي أفضل في تحديد أماكن الأخطاء المحتملة، مقابل الأخطاء الفعلية. ونتيجة لهذا، فهذه الأدوات لها شهرة من الايجابيات الزائفة. وبرنامج لغة يونكس lint هي مثال مبكر.
وبالنسبة لتصحيح الأخطاء في الأجزاء الخارجية الإلكترونية (مثل عتاد الحاسوب) وكذلك البرامج ذات المستوى المنخفض (مثل بيوس ومشغل (برنامج حاسوبي() وبرنامج ثابت، فيتم استخدام أدوات مثل راسم إشارة والمحللات المنطقية[ أو ] محاكي الدوائر الداخلية، سواء على حدة أو معا. وربما يؤدي محاكي الدوائر الداخلية العديد من مهام تصحيح أخطاء برمجية نموذجية في برمجية حاسوب منخفضة المستوى وبرنامج ثابت.

عملية التصحيح النموذجي للأخطاء

من الطبيعي أن تكون الخطوة الأولي لتصحيح الأخطاء هي محاولة إعادة إنتاج المشكلة. وهذا يمكن أن تكون مهمة دالة، مثلا فيما يخص المعالجة المتوازية أو بعض من الأخطاء البرمجية غير العادية. وكذلك، فبيئة مستخدم معين وتاريخ الاستعمال يمكن أن يجعل من الصعب إعادة إنتاج المشكلة.
وبعد إن تتم إعادة إنتاج الخطأ، ربما يحتاج إدخال البرنامج إلي التبسيط لكي يكون من السهل تصيح الخطأ. مثلا، خطأ في ملف مؤلف يمكن أن يجعله ] يتوقف فجأة عند تحليل لغوي لبعض ملفات المصدر الضخمة. ومع هذا، فبعد تبسيط الحالة الاختبارية، فخطوط قليلة فقط من ملف المصدر الأصلي يمكن أن تكون كافية لإعادة إنتاج نفس التوقف المفاجئ. ويمكن عمل ذلك التبسيط يدويا، باستخدام مدخل Divide and conquer algorithm. وسوف يحاول المبرمج إزالة بعض أجزاء الحالة الاختبارية وفحص ما إذا كانت المشكلة لا تزال موجودة. وعندما تصحيح الخطأ في واجهة المستخدم الرسومية، فيمكن للمبرمج أن يحاول تخطي بعض من تفاعل المستخدم من وصف المشكلة الأصلية وفحص ما إذا كانت الأفعال الباقية كافية لظهور الأخطاء.
وبعد ما يكون قد تم تبسيط الحالة الاختبارية بشكل كافي، يمكن للمبرمج استخدام أداة المصحح لفحص حالات البرنامج (قيم المتغيرات، مع call stack) ويتتبع أثر أصل المشكلة أو المشكلات. وبالمثل، يمكن استخدام ] التتبع[. وفي الحالات البسيطة، يكون التتبع عبارة عن بيانات طباعة قليلة، والتي تقوم بإنتاج قيم المتغيرات عند نقاط معينة من تنفيذ البرنامج.