كل مشروع برمجي يواجه في نهاية المطاف أكواداً مهملة، ومكونات مصنفة على أنها قديمة، أو غير مستحسنة، أو مقررة للإزالة. @deprecated التعليقات التوضيحية في جافا، DeprecationWarning في لغة بايثون، يشير الخط المائل في ميزة الإكمال التلقائي في بيئة التطوير المتكاملة (IDE) إلى أن شيئًا ما تستخدمه أو تُجري عليه صيانة قد تم استبداله. تجاهل هذه الإشارات يُراكم المخاطر تدريجيًا حتى تتم إزالة أحد التبعيات، أو يتجاوز تحديث أمني واجهة برمجة تطبيقات قديمة، أو يتسبب تحديث إطار العمل في تعطيل كل ما كان يعتمد على ما تم إيقافه منذ ثلاث إصدارات رئيسية.
يُعدّ فهم معنى "مهمل"، وأهميته، وكيفية التعامل معه بشكل منهجي، من أهم مهارات الصيانة العملية التي يمكن لفريق التطوير اكتسابها. يغطي هذا الدليل الصورة الكاملة: تعريفات واضحة، ومقارنة مع المصطلحات المشابهة، وتنبيهات الإهمال عبر مختلف اللغات، ومنهجية منظمة لإدارة التبعيات المهملة قبل أن تتحول إلى مشاكل في بيئة الإنتاج.
توقف عن اكتشاف حالات الإهمال في بيئة الإنتاج
SMART TS XL يُظهر هذا التقرير المكونات المهملة قبل أن تتحول إلى حوادث.
المزيد من المعلوماتما هو الكود المهمل؟
يشير مصطلح "البرمجيات المهملة" إلى الدوال، والأساليب، وواجهات برمجة التطبيقات، والمكتبات، أو حتى المكونات الكاملة التي لا تزال تعمل ولكن يُنصح رسميًا بعدم استخدامها. تستمر هذه البرمجيات في العمل، حيث يتم تجميعها وتنفيذها وإنتاج نتائج، ولكن القائمين على صيانتها أشاروا إلى أنه سيتم إزالتها في إصدار لاحق، أو استبدالها ببديل أفضل، أو ببساطة لن يتم صيانتها أو تحديثها. استخدام البرمجيات المهملة يعني الاعتماد على شيء توقف المسؤولون عنه عن الاهتمام به.
الإهمال آلية تواصل، وليست حالة تقنية. عندما يُعلِم مسؤول مكتبة ما بأن وظيفة ما مهملة، فإنه يقول: "هذه الوظيفة لا تزال تعمل اليوم، لكننا نعتزم إزالتها، ويجب عليك الانتقال إلى بديل آخر قبل ذلك". يختلف الوقت بين إشعار الإهمال والإزالة الفعلية، فقد يكون إصدارًا رئيسيًا واحدًا أو خمس سنوات، لكن الاتجاه واحد دائمًا. الإهمال يعني الإزالة في نهاية المطاف.
Deprecated مقابل Depreciated: الخلط الإملائي
كثيراً ما يتم الخلط بين هاتين الكلمتين، ولا تساعد برامج التدقيق الإملائي في ذلك لأن كلتيهما كلمتان إنجليزيتان حقيقيتان لهما معانٍ مختلفة.
مُهمل (في البرمجيات): مُصنّف على أنه قديم، غير مُستحب استخدامه، مُجدول للإزالة. هذا هو المصطلح الصحيح في سياقات البرمجيات.
الاستهلاك (في المحاسبة): انخفاض القيمة بمرور الوقت. كما في: "انخفضت قيمة أجهزة الخادم على مدى ثلاث سنوات".
إذا رأيتَ عبارة "deprecated code" في وثيقة تقنية، فغالبًا ما تعني "deprecated code"، حيث استخدم الكاتب المصطلح المحاسبي بدلًا من المصطلح البرمجي. هذا الخطأ شائع لدرجة أنه يظهر في بيانات Search Console لهذه المقالة. في مجال البرمجيات، استخدم دائمًا مصطلح " deprecated".
الكود المهمل مقابل الكود القديم مقابل الكود المهجور مقابل الكود غير المستخدم
هذه المصطلحات مترابطة لكنها تصف حالات مختلفة من الكود. الخلط بينها يؤدي إلى نقاشات غير دقيقة وقرارات خاطئة بشأن تحديد الأولويات.
| مصطلح | ماذا تعني | هل تمت إزالته؟ | هل يتم صيانته؟ | مستوى الخطر |
|---|---|---|---|---|
| غير مستحب رسمياً، ومُعلّم للإزالة مستقبلاً | لا، ما زال موجوداً | لا، توقفت أعمال الصيانة | متوسط، ينمو بمرور الوقت | |
| مهمل | لم يعد ذا صلة أو قابلاً للتطبيق؛ تم استبداله | أحيانا | لا | متوسطة عالية |
| إرث | كود قديم لا يزال يعمل وقد يكون لا يزال قيد الإنتاج | لا، ما زال نشطًا | نادرا | متغير، يعتمد على معدل التغير |
| كود ميت | لم يتم الاتصال به أو الوصول إليه أثناء التنفيذ | لا، ما زال في المصدر | غير متوفر، لا يعمل أبداً | مخاطر الهجرة/التدقيق منخفضة إلى متوسطة |
| قانون الولاية | الكود الذي لم يتم تعديله منذ فترة طويلة ولكنه لم يُعلن رسميًا عن إيقاف استخدامه | لا | غير واضح | قد يخفي موقع Medium بعض الافتراضات |
مُهمل مقابل مُتقادم: Deprecated هو تصنيف رسمي، وقد قام شخص ما بتحديده صراحةً بـ @deprecated أو أصدر إشعارًا بالإيقاف. يُعدّ مصطلح "مهجور" وصفًا أوسع، فقد يظلّ الكود يعمل، لكنّه لم يعد له استخدام منطقي في ظلّ البدائل الحديثة. جميع الأكواد المُهملة تُصبح في نهاية المطاف مهجورة، ولكن ليس كلّ كود مهجور قد تمّ إيقافه رسميًا.
الكود المهمل مقابل الكود المحذوف : الكود المهمل لا يزال موجودًا في قاعدة البيانات. أما الكود المحذوف فقد اختفى. فترة الإهمال هي الفترة الفاصلة بين الحالتين، وهي الوقت المتاح لك للانتقال إلى الكود الجديد قبل أن يتعطل.
الكود المهمل مقابل الكود القديم : الكود القديم هو كود إنتاجي قديم، غالبًا ما لا يزال يُستخدم ويُصان بنشاط، وقد كُتب في حقبة تقنية سابقة. أما الكود المهمل فهو مُحدد خصيصًا للإزالة. برامج COBOL القديمة التي تُعالج المعاملات اليومية ليست مهملة، بل هي قديمة ولكنها تُصان بنشاط. تُعتبر دالة واجهة برمجة تطبيقات COBOL التي صنّفها مُورّد المكتبة على أنها قديمة مهملة.
الإهمال مقابل الإيقاف : الإهمال إشارة تقنية ضمن قاعدة بيانات أو مكتبة برمجية. أما الإيقاف فهو قرار تشغيلي، يشمل إيقاف خدمة، أو إزالة بنية تحتية، أو إنهاء دعم منتج. قد تستمر واجهة برمجة التطبيقات المهملة في العمل لسنوات، بينما يتم إيقاف واجهة برمجة التطبيقات المتوقفة في تاريخ محدد.
كيف تبدو التحذيرات المتعلقة بالميزات المهملة: تحذيرات عبر اللغات
تتخذ تحذيرات الإهمال أشكالاً مختلفة تبعاً للغة والأدوات المستخدمة. ويُعدّ التعرف عليها من النظرة الأولى الخطوة الأولى لمعالجتها.
بايثون: تحذير بشأن الإهمال
الثعبان
import warnings
# Marking a function as deprecated
def old_function():
warnings.warn(
"old_function is deprecated, use new_function instead",
DeprecationWarning,
stacklevel=2
)
# original implementation
def new_function():
# improved implementation
pass
يُظهر بايثون تحذيرات بشأن الإهمال أثناء التشغيل. رسالة المُصرّف الشائعة هي:
DeprecationWarning: old_function is deprecated, use new_function instead
أو بالنسبة لحزم البرامج المقدمة من جهات خارجية:
DeprecationWarning: pkg_resources is deprecated as an API.
Use importlib.resources or importlib.metadata instead.
جافا: التعليق التوضيحي @Deprecated
جافا
public class LegacyProcessor {
@Deprecated
public void processData(String input) {
// old implementation
}
// Replacement method
public void processDataV2(String input, ProcessOptions options) {
// new implementation
}
}
ينتج مُترجم جافا ما يلي:
Note: SomeFile.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
جافا سكريبت/تايب سكريبت: JSDoc @deprecated
جافا سكريبت
/**
* @deprecated Use fetchUserById() instead.
* This function will be removed in version 4.0.
*/
function getUser(id) {
// old implementation
}
// Modern replacement
async function fetchUserById(id) {
// new implementation
}
نسخة مطبوعة على الآلة الكاتبة
class ApiClient {
/** @deprecated Use post() with typed options instead */
sendRequest(url: string): Promise<any> {
// deprecated implementation
}
}
عرض بيئات التطوير المتكاملة getUser مع وضع خط في وسطها أينما تم استدعاؤها، و TypeScript @typescript-eslint/no-deprecated يُشير هذا الأمر إلى وجود مشكلة في نظام التكامل المستمر (CI).
C++: سمة [[مهملة]]
حزب الشعب الكمبودي
// C++14 and later
[[deprecated("Use processV2() instead")]]
void process(int value) {
// old implementation
}
void processV2(int value, ProcessFlags flags = ProcessFlags::Default) {
// new implementation
}
تُنتج المترجمات ما يلي:
warning: 'process' is deprecated: Use processV2() instead [-Wdeprecated-declarations]
Swift: @available مع خاصية مهملة
سريع
@available(*, deprecated, renamed: "fetchUser(withID:)")
func getUser(id: String) -> User {
// old implementation
}
func fetchUser(withID id: String) -> User {
// replacement
}
Kotlin/Java: @Deprecated with ReplaceWith
kotlin
@Deprecated(
message = "Use processItems() instead",
replaceWith = ReplaceWith("processItems(items)"),
level = DeprecationLevel.WARNING
)
fun handleItems(items: List<Item>) {
// deprecated
}
fun processItems(items: List<Item>) {
// replacement
}
لماذا تُسبب التعليمات البرمجية القديمة مشاكل حقيقية؟
لا يقتصر استخدام التعليمات البرمجية القديمة على مجرد مسألة تنظيمية، بل إنها تخلق مخاطر ملموسة ومتراكمة عبر أربعة أبعاد:
ثغرات أمنية. لم تعد واجهات برمجة التطبيقات والمكتبات القديمة تتلقى تحديثات أمنية. تمثل المكتبة القديمة التي تحتوي على ثغرة أمنية غير مُعالجة (CVE) ثغرة دائمة، وقد توقف القائمون على صيانتها عن إصلاحها رغبةً منهم في إجبار الجميع على الانتقال إلى بدائل أخرى. إن المؤسسات التي تستخدم مكونات قديمة تُشغّل عن قصد برمجيات معروفة بثغراتها الأمنية.
انقطاع الاعتماد عند التحديثات. تم وضع إشعار الإيقاف تحديدًا لأن الإزالة قادمة. عند وصول التحديث الرئيسي للإصدار وإزالة واجهة برمجة التطبيقات المُهملة، ستتعطل جميع الأنظمة التي لا تزال تعتمد عليها في وقت واحد، في أسوأ لحظة ممكنة، أثناء عملية تحديث كان من المفترض أن تكون روتينية.
زيادة تعقيد الصيانة. يتطلب الكود المُهمل من المطورين استيعاب نموذجين ذهنيين في آنٍ واحد: ما يفعله الكود القديم وما يفعله الكود الجديد المكافئ له. يجب على كل عضو جديد في الفريق أن يتعلم أي أجزاء من قاعدة الكود يجب تجنبها ولماذا. يتراكم هذا التعقيد ذو المسارين مع كل مكون مُهمل إضافي.
تراكم الديون التقنية. كل تبعية مهملة تُعدّ وحدة من الديون التقنية. على عكس الديون الأخرى، فإنّ ديون الشيفرة المهملة لها موعد نهائي، إذ تتحول من "تحذير" إلى "عطل" بمجرد إزالة المكون المهمل فعليًا.
كيفية التعامل مع التبعيات المهملة في مشروع برمجي
الخطوة 1: جرد جميع الأصول المستهلكة
قم بإجراء مسح منهجي بدلاً من اكتشاف المكونات المهملة واحداً تلو الآخر. توفر معظم الأدوات طرقاً لعرض المخزون الكامل.
سحق
# Python: find all DeprecationWarning instances
python -W error::DeprecationWarning -m pytest
# JavaScript/Node.js: run with deprecation tracing
node --trace-deprecation app.js
# Java: compile with full deprecation details
javac -Xlint:deprecation *.java
# npm: find deprecated packages
npm outdated
npm audit
الخطوة الثانية: التصنيف حسب المخاطر
لا تتطلب جميع حالات الإهمال اتخاذ إجراء فوري. صنّف كل حالة منها:
| درجة الأهمية | المعايير | اكشن |
|---|---|---|
| حرج | مكتبة مهملة ذات أهمية أمنية بالغة؛ ثغرة أمنية معروفة (CVE)؛ سيتم إزالتها في الإصدار الرئيسي التالي | انتقل فوراً |
| مرتفع | تم إيقاف هذه الميزة في الإصدار الرئيسي الحالي؛ تحذيرات نشطة في نظام التكامل المستمر | جدول زمني للسباق الحالي أو السباق القادم |
| متوسط | تم إيقاف دعمه ولكنه لا يزال مدعومًا لأكثر من إصدارين رئيسيين؛ لا يوجد خطر أمني | أضف إلى قائمة المهام المتراكمة مع الجدول الزمني |
| منخفض | تم إيقاف استخدام التعليقات التوضيحية في التعليمات البرمجية الداخلية ذات معدل التغيير المنخفض | تتبع ومعالجة أثناء عملية إعادة الهيكلة ذات الصلة |
الخطوة 3: تحديد جميع الاستخدامات قبل الترحيل
قبل تغيير أي مكون مهمل، حدد جميع مواضع استخدامه. تغييره دون تحديد كامل لمواضع استخدامه قد يؤدي إلى تعطل النظام دون إشعار مسبق.
الثعبان
# Using grep for basic search
grep -r "old_function" src/
# Using ast-grep for code-aware search (TypeScript/JS)
ast-grep --pattern 'getUser($ID)' --lang ts
# Using ripgrep with file type filtering
rg "deprecated_method" --type java
بالنسبة لقواعد البيانات الكبيرة، تنتج أدوات التحليل الثابت الآلية خريطة مرجعية متقاطعة كاملة بدقة أكبر من البحث اليدوي grep، خاصة للاستخدامات غير المباشرة من خلال الإرسال الديناميكي أو الوراثة.
الخطوة الرابعة: الهجرة المنهجية
استبدل الاستخدامات المهملة واحدة تلو الأخرى، مع التحقق من صحة كل استخدام قبل الانتقال إلى الاستخدام التالي:
الثعبان
# Before: deprecated
import imp
module = imp.load_source('mymodule', '/path/to/mymodule.py')
# After: replacement
import importlib.util
spec = importlib.util.spec_from_file_location('mymodule', '/path/to/mymodule.py')
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
جافا سكريبت
// Before: deprecated event property
document.addEventListener('keydown', (event) => {
const key = event.keyCode; // deprecated
});
// After: modern replacement
document.addEventListener('keydown', (event) => {
const key = event.key; // current standard
});
الخطوة 5: إضافة بوابات الإهمال إلى التكامل المستمر/التسليم المستمر
منع الاستخدامات الجديدة المهملة من دخول قاعدة التعليمات البرمجية بعد عملية التنظيف:
يامل
# .github/workflows/deprecation-check.yml
- name: Check for deprecated API usage (Java)
run: javac -Xlint:deprecation -Werror src/**/*.java
- name: Check for deprecated packages (Node)
run: npm audit --audit-level=moderate
- name: ESLint no-deprecated rule (TypeScript)
run: npx eslint --rule '{"@typescript-eslint/no-deprecated": "error"}' src/
وضع سياسة الإهلاك
تُعامل المؤسسات التي تُحسن إدارة عملية إيقاف استخدام المنتجات والخدمات هذه العملية كمسألة سياسية، وليست مجرد مسألة تقنية. وتُحدد سياسة إيقاف استخدام المنتجات والخدمات ما يلي:
من يملك صلاحية إيقاف استخدام الميزات؟ لا يجوز لمطور واحد إيقاف استخدام واجهة برمجة تطبيقات داخلية شائعة الاستخدام بشكل منفرد دون مراجعة الفريق. يجب أن تشمل قرارات إيقاف الاستخدام مالكي المكونات المستخدمة.
مدة فترة الإيقاف. القيمة الافتراضية المعقولة: دورة إصدار رئيسية واحدة قبل الإزالة. بالنسبة لواجهات برمجة التطبيقات العامة، إصداران رئيسيان. بالنسبة لواجهات برمجة التطبيقات الداخلية، دورة إصدار واحدة.
كيفية إبلاغ المستخدمين بإيقاف بعض الميزات: عبر التعليقات التوضيحية في الكود، وسجلات التغييرات، والإخطار المباشر للمستخدمين المعروفين. لن يتم الإبلاغ عن إيقاف ميزة ما إذا كان موجودًا فقط في تعليق برمجي.
ما المقصود بـ "الإزالة" ؟ هل تم حذف الكود؟ هل تم نقله إلى حزمة اختيارية منفصلة؟ هل تم إخفاؤه خلف علامة ميزة؟ حدد الحالة النهائية بوضوح.
كيفية توثيق مسار الترحيل. يجب أن يتضمن كل تعليق إهمال إشارة إلى البديل. @deprecated Use fetchUserById() instead أكثر فائدة من @deprecated.
هل لا يزال الكود القديم يعمل؟
نعم، إلى أن يتوقف الأمر. يعمل الكود المُهمل بشكل طبيعي حتى الإصدار الذي يُزال فيه فعليًا. هذه هي أخطر سمات الكود المُهمل: فهو يُوهم المستخدم بأمان زائف. قد تبدو الأنظمة التي تعمل بواجهات برمجة تطبيقات مُهملة لسنوات مستقرة، بينما يزداد خطر حدوث عطل مفاجئ مع كل دورة إصدار.
الإجابة على سؤال "هل من الآمن تشغيل التعليمات البرمجية المهملة؟" هي: يعتمد ذلك على مدى قرب تاريخ الإزالة والوضع الأمني للمكون المهمل. فالوظيفة المهملة في إصدار فرعي من مكتبة يتم صيانتها بشكل فعال، ولا توجد بها ثغرات أمنية معروفة (CVEs)، تُشكل خطراً فورياً منخفضاً. أما مكتبة المصادقة المهملة التي تحتوي على ثغرة أمنية غير مُعالجة، والتي تم الإعلان عن تاريخ انتهاء صلاحيتها، فتُشكل خطراً فورياً عالياً.
كيفية SMART TS XL تحديد التعليمات البرمجية المهملة عبر أنظمة المؤسسة
في مشروع أحادي اللغة، يُعدّ العثور على التعليمات البرمجية المهملة مسألة تشغيل علامة المُصرّف أو قاعدة التدقيق المناسبة. أما في بيئة مؤسسية تشمل لغات COBOL وJCL وJava وPython والخدمات الحديثة، فيجب العثور على المكونات المهملة لكل لغة في آنٍ واحد، وتُعدّ العلاقات بينها بنفس أهمية الإهمال نفسه.
SMART TS XLالصورة تحليل الكود الثابت يفحص البرنامج جميع اللغات في بيئة العمل، ويكشف عن التعليقات التوضيحية المهملة، واستخدامات واجهة برمجة التطبيقات القديمة، وأنماط التعليمات البرمجية غير المستخدمة في جميع أنحاء قاعدة التعليمات البرمجية في آن واحد. عندما يتم وضع علامة "قديم" على ملف نسخ COBOL، SMART TS XL يُحدد كل برنامج يتضمنه. وعندما يتم إيقاف استخدام إحدى طرق واجهة برمجة تطبيقات جافا، فإنه يتتبع كل موقع استدعاء عبر كل خدمة في المجموعة.
تتجاوز خاصية تحليل الأثر ذلك خطوةً أخرى: فقبل إزالة أي مكون مهمل، تُنشئ نطاقًا كاملاً لما ستتأثر به هذه الإزالة، من برامج ومسارات عمل وخدمات لاحقة، وذلك عبر جميع اللغات. وهذا يحوّل سؤال "ما الذي سيتعطل؟" المحفوف بالمخاطر إلى قائمة منظمة ومفصلة بكل ما يجب التحقق منه قبل المضي قدمًا في عملية الإزالة.
تتيح ميزة البحث المؤسسي إمكانية الاستعلام عن المخزون: العثور على كل استخدام لوظيفة مهملة محددة، وكل إشارة إلى ملف نسخ مهمل، وكل استدعاء لواجهة برمجة تطبيقات قديمة، في ثوانٍ معدودة، عبر ملايين أسطر التعليمات البرمجية بلغات متعددة. بالنسبة لبرامج تحديث الأنظمة القديمة حيث يُعد مخزون المكونات المهملة نقطة انطلاق لتحديد نطاق الترحيل، فإن ميزة البحث هذه تُغني عن أسابيع من التدقيق اليدوي باستعلام مُوجَّه.