شعار ConstructiCat
CodeBust.
تصفح القسم ▾

الترميز الثابت.

الترميز الثابت هو تضمين بيانات مثل المسارات وبيانات الاعتماد والنِّسب مباشرة في الشيفرة المصدرية، فيتطلب تغييرها تعديل البرنامج وإعادة بنائه.

الترميز الثابت (Hard coding) هو ممارسة تطوير البرمجيات المتمثلة في تضمين البيانات مباشرةً في الشيفرة المصدرية لـبرنامج أو كائن قابل للتنفيذ آخر، بدلاً من الحصول على البيانات من مصادر خارجية أو توليدها في وقت التشغيل.

يمكن تعديل البيانات المُرمَّزة ثابتاً في العادة فقط عن طريق تحرير الشيفرة المصدرية وإعادة تصريفها للملف القابل للتنفيذ، وإن كان بالإمكان تغييرها في الذاكرة أو على القرص باستخدام المُنقِّح أو محرر HEX.

تُعدّ البيانات المُرمَّزة ثابتاً أنسب لقطع المعلومات التي لا تتغير، مثل الثوابت الفيزيائية وأرقام الإصدار وعناصر النص الثابت.

أما البيانات المُرمَّزة مرنةً (Soft-coded)، فتُشفِّر معلومات تعسفية عبر مدخلات المستخدم وملفات النص وملفات INI واستجابات خادم HTTP وملفات الضبط وقواعد البيانات ووسيطات سطر الأوامر، ويُحدَّد مضمونها في وقت التشغيل. أما ماكرو المعالج المسبق والثوابت المعرَّفة في ملف ترويسة أو وحدة منفصلة فليست ترميزاً مرناً بهذا المعنى: فهي تمنح القيمة اسماً وموضعاً واحداً، لكنها تظل مثبَّتة وقت الترجمة، ويتطلب تغييرها إعادة البناء.

نظرة عامة

يستلزم الترميز الثابت تغيير الشيفرة المصدرية للبرنامج في كل مرة تتغير فيها بيانات الإدخال أو الصيغة المطلوبة، في حين قد يكون أكثر ملاءمةً للمستخدم النهائي تغيير التفاصيل بطريقة ما خارج البرنامج.

كثيراً ما يكون الترميز الثابت ضرورياً، غير أنه يمكن أن يُعدَّ نمطاً مضاداً. فقد لا يكون لدى المبرمجين حلٌّ لواجهة مستخدم ديناميكية جاهزة للمستخدم النهائي، ولكنهم مع ذلك يجب أن يُسلِّموا الميزة أو يُصدِروا البرنامج. يكون هذا في العادة مؤقتاً، ولكنه يحلّ على المدى القريب ضغطَ تسليم الشيفرة. يُجرى لاحقاً الترميز المرن للسماح للمستخدم بتمرير معاملات تُتيح له تعديل النتائج أو المخرجات.

استُخدم مصطلح "الترميز الثابت" في الأصل استعارةً من توصيل الدوائر الكهربائية بصلابة، وكان يُعبِّر عن الجمود الناتج عن استخدامه في تصميم البرمجيات وتنفيذها. وفي سياق بيئات التطوير التعاوني القابلة للتمديد في وقت التشغيل مثل MUDs، يُشير الترميز الثابت أيضاً إلى تطوير المحرك الأساسي للنظام المسؤول عن المهام منخفضة المستوى وتنفيذ السكريبتات، في مقابل الترميز المرن الذي يعني تطوير السكريبتات عالية المستوى التي يُفسِّرها النظام في وقت التشغيل، بقيم من مصادر خارجية كـملفات النص وملفات INI وقواعد البيانات ووسيطات سطر الأوامر واستجابات HTTP الخادم وملفات الضبط ومدخلات المستخدم. في هذا السياق، لا يُعدّ المصطلح تحقيرياً، بل يُشير إلى التطوير العام لا إلى تضمين بيانات الإخراج تحديداً.

الأبواب الخلفية

يُعدّ ترميز بيانات الاعتماد ثابتاً طريقةً شائعة لإنشاء باب خلفي. لا تظهر بيانات الاعتماد المُرمَّزة ثابتاً في العادة في ملفات الضبط أو مخرجات أوامر تعداد الحسابات، ولا يمكن للمستخدمين تغييرها أو تجاوزها بسهولة. وإن اكتُشفت، قد يتمكن المستخدم من تعطيل هذا الباب الخلفي عن طريق تعديل البرنامج وإعادة بنائه من شيفرته المصدرية (إن كان المصدر متاحاً للعموم)، أو فكّ التصريف، أو الهندسة العكسية لـالبرنامج، أو التحرير المباشر لـالشيفرة الثنائية للبرنامج، أو إقامة فحص تكامل (كالتوقيعات الرقمية وآليات مكافحة التلاعب ومكافحة الغش) لمنع الوصول غير المتوقع؛ غير أن مثل هذه الإجراءات كثيراً ما تكون محظورة بموجب اتفاقية ترخيص المستخدم النهائي.

مسار التثبيت الثابت

إذا كان برنامج Windows مبرمجاً للافتراض بأنه دائماً مُثبَّت في C:\Program Files\Appname وحاول شخص ما تثبيته على محرك أقراص مختلف لأسباب تتعلق بالمساحة أو التنظيم، فقد يفشل في التثبيت أو التشغيل بعد التثبيت. قد لا تُكتشف هذه المشكلة في عملية الاختبار، إذ يُثبِّت المستخدم العادي على محرك الأقراص والدليل الافتراضيين ولا يشمل الاختبار عادةً خيار تغيير دليل التثبيت. غير أنه يُنصح المبرمجون والمطورون بعدم تثبيت مسار تثبيت البرنامج، إذ يعتمد المسار الافتراضي على نظام التشغيل وإصداره وقرارات مسؤول النظام. فمثلاً، تستخدم كثير من تثبيتات Microsoft Windows المحرك C: باعتباره القرص الصلب الرئيسي، لكن هذا غير مضمون.

المجلدات الخاصة

تحتوي بعض أنظمة تشغيل Windows على ما يُسمى المجلدات الخاصة التي تُنظِّم الملفات منطقياً على القرص الصلب. ثمة مشكلات يمكن أن تنشأ جراء الترميز الثابت:

مسار الملف الشخصي

تُرمِّز بعض برامج Windows مسار الملف الشخصي ثابتاً إلى مواقع يحددها المطور مثل C:\Documents and Settings\Username، وهو المسار الافتراضي في Windows 2000 وWindows XP، أو C:\Users\Username، وهو المسار الافتراضي منذ Windows Vista. يتعطل مثل هذا المسار عند تشغيل البرنامج على إصدار آخر من Windows أو حين يكون الملف الشخصي مخزَّناً على شبكة أو منقولاً بطريقة أخرى. الطريقة الصحيحة للحصول عليه هي استدعاء الدالة GetUserProfileDirectory أو حلّ متغير البيئة %userprofile%. افتراض آخر يشيع لدى المطورين هو أن الملف الشخصي موجود على قرص صلب محلي.

مسار مجلد المستندات

تُرمِّز بعض برامج Windows مسار My Documents ثابتاً على هيئة ProfilePath\My Documents. ستعمل هذه البرامج على الأجهزة التي تشغّل الإصدار الإنجليزي، لكن في الإصدارات المحلية من Windows يحمل هذا المجلد في العادة اسماً مختلفاً. فمثلاً، في الإصدارات الإيطالية يُسمَّى مجلد My Documents باسم Documenti. وقد يكون مجلد My Documents أيضاً قد أُعيد توجيهه باستخدام ميزة Folder Redirection في Group Policy في Windows 2000 وما فوق. الطريقة الصحيحة للحصول عليه هي استدعاء الدالة SHGetKnownFolderPath (أو SHGetFolderPath في الإصدارات السابقة لـ Windows Vista).

الحل

يمكن توسيع مرجع غير مباشر، كمتغير داخل البرنامج يُسمى "FileName"، عبر الوصول إلى نافذة حوار "استعراض ملف"، ولا يلزم عندئذٍ تغيير شيفرة البرنامج إن تحرَّك الملف.

يُعدّ الترميز الثابت مشكلةً بالغة الأثر تحديداً عند إعداد البرنامج للترجمة إلى لغات أخرى.

في حالات كثيرة، قد تظهر قيمة واحدة مُرمَّزة ثابتاً، كحجم مصفوفة، عدة مرات في الشيفرة المصدرية للبرنامج. سيكون هذا ما يُعرف بـالرقم السحري. وقد يُسبِّب هذا خطأً في البرنامج إذا عُدِّل بعض مواضع ظهور القيمة دون بعضها الآخر. مثل هذا الخطأ يصعب اكتشافه وقد يبقى في البرنامج فترةً طويلة. قد تنشأ مشكلة مماثلة إذا استُخدمت القيمة المُرمَّزة ثابتاً ذاتها لأكثر من قيمة معامل واحدة، مثل مصفوفة مؤلفة من 6 عناصر وطول حد أدنى لسلسلة الإدخال يبلغ 6 أحرف. قد يُغيِّر المبرمج خطأً جميع نسخ القيمة (باستخدام ميزة بحث واستبدال في المحرر) دون فحص الشيفرة لمعرفة كيفية استخدام كل نسخة. يُتجنَّب كلا الأمرين بتعريف الثوابت، التي تربط الأسماء بالقيم، واستخدام أسماء الثوابت لكل ظهور في الشيفرة.

حالة مهمة من حالات الترميز الثابت هي عندما تُوضَع السلاسل النصية مباشرةً في الملف، مما يُجبر المترجمين على تحرير الشيفرة المصدرية لترجمة البرنامج. (ثمة أداة تُسمى gettext تُتيح ترك السلاسل في الملفات بينما تُمكِّن المترجمين من ترجمتها دون تغيير الشيفرة المصدرية؛ إذ تُلغي في الفعل ترميزها الثابت.)

الترميز المرن

الترميز المرن (Soft coding) مصطلحٌ في برمجة الحاسوب يُشير إلى الحصول على قيمة أو دالة من مورد خارجي، مثل ملفات النص وملفات INI وملفات الضبط ووسيطات سطر الأوامر وقواعد البيانات ومدخلات المستخدم واستجابات خادم HTTP. وهو نقيض الترميز الثابت الذي يُشير إلى ترميز القيم والدوال في الشيفرة المصدرية.

ممارسة البرمجة

تجنُّب الترميز الثابت للقيم التي تُعدَّل عادةً ممارسةٌ برمجية جيدة. ينبغي لمستخدمي البرنامج أن يتمكنوا من تخصيصه وفق احتياجاتهم، في حدود المعقول، دون الحاجة إلى تحرير الشيفرة المصدرية. وبالمثل، يتجنب المبرمجون المتأنون الأرقام السحرية في شيفرتهم لتحسين قابليتها للقراءة والمساعدة في صيانتها. لا يُشار عادةً إلى هذه الممارسات بمصطلح الترميز المرن.

يُستخدم المصطلح عادةً حين يصبح الترميز المرن نمطاً مضاداً. قد يُفضي تجريد قيم وميزات كثيرة جداً إلى تعقيد أكبر ومشكلات صيانة أكثر مما كان يُعانى منه عند تغيير الشيفرة عند الحاجة. عُرض الترميز المرن بهذا المعنى في مقال على The Daily WTF.

مشكلات محتملة

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

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

لتجنب الترميز المرن، فكِّر في قيمة أي مرونة إضافية تقدمها للمستخدم النهائي، وقارنها بزيادة التعقيد وتكاليف الصيانة المستمرة المرتبطة بقابلية الضبط المضافة.

تحقيق المرونة

تتوفر عدة أنماط تصميم مشروعة لتحقيق المرونة التي يسعى إليها الترميز المرن. قد تستفيد التطبيقات التي تحتاج مرونة أكبر مما هو مناسب لملف الضبط من دمج لغة نصية. في كثير من الحالات، يكون التصميم المناسب هو لغة خاصة بالمجال مُدمجة في لغة نصية راسخة. نهج آخر هو نقل معظم وظائف التطبيق إلى مكتبة، مما يُوفِّر واجهة API لكتابة التطبيقات ذات الصلة بسرعة.

مثال

تُضمِّن هذه الوحدة في شيفرتها المصدرية عنوان قاعدة البيانات وبيانات الاعتماد ونسبة ضريبة القيمة المضافة. فتشغيل البناء نفسه على قاعدة بيانات اختبارية أو تغيير كلمة المرور أو مواكبة تعديل ضريبي يتطلب تعديل الشيفرة وإعادة نشرها، وينتهي الأمر بكلمة المرور في نظام التحكم في الإصدارات.

def connect():
    return Database(host="10.0.0.12", user="admin", password="s3cr3t!")


def price_with_vat(amount):
    return amount * 1.2

صارت القيم التي تختلف بين البيئات أو تتغير بمرور الوقت تُقرأ من البيئة، وبقي في الشيفرة المنطق وحده (انظر أيضاً الإعدادات المكتوبة بشكل مباشر).

import os
from dataclasses import dataclass


@dataclass(frozen=True)
class Settings:
    db_host: str
    db_user: str
    db_password: str
    vat_rate: float

    @classmethod
    def from_env(cls) -> "Settings":
        return cls(
            db_host=os.environ["DB_HOST"],
            db_user=os.environ["DB_USER"],
            db_password=os.environ["DB_PASSWORD"],
            vat_rate=float(os.environ["VAT_RATE"]),
        )


def connect(settings: Settings):
    return Database(host=settings.db_host, user=settings.db_user, password=settings.db_password)


def price_with_vat(amount, settings: Settings):
    return amount * (1 + settings.vat_rate)

مقتبس من مقالة ويكيبيديا “Hard coding” (المراجعة 1355219913)، والمتاحة بموجب رخصة CC BY-SA 4.0؛ تمت ترجمة النص وتحريره وإضافة أمثلة.