مدونة مبرمج معماري

الداعي

مضيفكم وسام البهنسي يرحب بكم.

 

مبرمج بنزعة معمارية يهوى الثرثرة والحديث عن الأمور الجميلة في هذه الحياة كالمتغيرات والمؤشرات والرسوميات وأمور أخرى لا يسعني ذكرها في هذه المساحة الضيقة كما تلاحظون.

قائمة الصفحات

آخر التدوينات

أنا أولاً
التوقيت 20/صفر/1431 11:46 ص بقلم الكاتب وسام البهنسي

بعد أن أنهيتُ بعض الإصلاحات في نظام التدوين هذا يوم أمس قمتُ برفع النسخة المحدثة إلى الموقع، لأفاجأ بأن جميع رموز الابتسامات في التعليقات قد تحولت إلى عبارات غريبة وغامضة تشبه تلك الخاصة باستدعاء الجان أو حتى جورج بوش نفسه!

 

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

 

هممم… لو كان نظام التدوين مكتوباً بلغة ++C لقلنا أن هذه آثار استخدام متغير غير مهيأ، وبالتالي فإن قيمته تختلف في كل مرة يُعاد تشغيل البرنامج فيها. لكن النظام مكتوب بلغة #C، وكما نعلم فإن #C تقوم بتصفير كل القيم الغير مهيأة. إذن ليست هذه هي المشكلة.

 

الاحتمال الثاني هو ما يدعى بحالة سباق (race condition) بين مسارات تنفيذ مختلفة (threads). في هذه الحالة يتسابق مساري تنفيذ (أو أكثر) للوصول إلى أحد متغيرات البرنامج دون تنسيق، مما يتسبب بتصرفات مختلفة بناء على أي المسارات وصل قبل الآخر، وهذا أمر هلامي لا يمكن توقعه. حيث أن زمن تنفيذ مسار يختلف من لحظة لأخرى وتدخل به عوامل عدة كالبرامج التي تعمل في الخلفية في نظام التشغيل ودرجة حرارة المعالج ودوران القرص الصلب بل وحتى بُعد المشتري عن المريخ.

 

بعد أخذ هذا الاحتمال بعين الاعتبار، وإعادة النظر إلى الكود، وجدتُ أن هذا هو فعلاً ما يحدث. فنظام المدونة يملك قائمة بما يدعى الإضافات (extensions) تختص كل منها بوظيفة محددة كتحويل رموز الابتسامات إلى صور، أو تفعيل الروابط في التعليقات، أو إرسال الرسائل الإلكترونية التنبيهية … الخ.

 

هذه القائمة تتم تعبئتها بشكل مؤتمت من خلال كل إضافة. هذه عينة كود لإحدى الإضافات:

[Extension("تحول الابتسامات المكتوبة في التعليقات إلى صور ", "1.3", "مطوريّ المدونة")]
public class Smilies
{
    static Smilies()
    {
        Comment.Serving += new EventHandler<ServingEventArgs>(Post_CommentServing);
    }
 
    /// <summary>
    /// The event handler that is triggered every time a comment is served to a client.
    /// </summary>
    private static void Post_CommentServing(object sender, ServingEventArgs e)
    {
        if (!string.IsNullOrEmpty(e.Body))
        {
            e.Body = e.Body.Replace("(H)", Convert("cool", "هادئ"));
            e.Body = e.Body.Replace(":'(", Convert("cry", "باكي"));
            e.Body = e.Body.Replace(":$", Convert("embarassed", "خجل"));
            e.Body = e.Body.Replace(":|", Convert("foot-in-mouth", "منزعج"));
            e.Body = e.Body.Replace(":(", Convert("frown", "حزين"));
            e.Body = e.Body.Replace("(A)", Convert("innocent", "بريء"));
            e.Body = e.Body.Replace("(K)", Convert("kiss", "محب"));
            e.Body = e.Body.Replace(":D", Convert("laughing", "ضاحك"));
            e.Body = e.Body.Replace("($)", Convert("money-mouth", "نقود"));
            e.Body = e.Body.Replace(":-#", Convert("sealed", "محكم"));
            e.Body = e.Body.Replace(":)", Convert("smile", "مبتسم"));
            e.Body = e.Body.Replace(":-)", Convert("smile", "مبتسم"));
            e.Body = e.Body.Replace(":-O", Convert("surprised", "متفاجئ"));
            e.Body = e.Body.Replace(":P", Convert("tongue-out", "مازح"));
            e.Body = e.Body.Replace("*-)", Convert("undecided", "متردد"));
            e.Body = e.Body.Replace(";-)", Convert("wink", "غمزة"));
            e.Body = e.Body.Replace("8o|", Convert("yell", "صارخ"));
        }
    }
}

 

 

 

لاحظ أن الباني مُعلن عنه على أنه ثابت (static constructor)، مما يعني أن مكتبة دوت نت ستقوم باستدعاء هذا الإجراء تلقائياً عند تحميل كود الصنف في البرنامج. الإجراء يقوم بتسجيل حَـدَث (event) في نظام التدوين ليعالج محتوى التعليقات قبل أن يتم عرضها في المتصفح.

 

هذا النسق مستخدم في كافة الأصناف الخاصة بالإضافات في المدونة. هذا يعني أن ترتيب استدعاء الإضافات محكوم بأيها يتم تحميله قبل الآخر في البرنامج، وهذه العملية غير محددة (كما تبين لي لاحقاً) وتخضع تماماً لأسلوب مكتبة دوت نت في تحميل الأصناف، والذي -فيما يبدو- أنه أسلوب متعدد المسارات لتسريع الأداء. وهكذا نجد أن ترتيب استدعاء الإضافات في المدونة يخضع تماماً للقوانين الكونية والفلكية والحرارية المحيطة بمخدم الموقع! وبما أن الإضافات يجب أن تعمل بترتيب معين، فإننا دخلنا في المحظور.

 

الآن وصلنا إلى "ما يستفاد من الحديث": لا تستخدم أسلوب الباني الثابت هذا، فهو كريه ومزعج ويفقدك السيطرة على زمام الأمور، فبدلاً من أن تكون أنت المتحكم ببرنامجك، سيصبح برنامجك عرضة للعمل وفقاً لمبدأ الصدفة.

 

هذا الكلام لن يعجب المبرمجين المخضرمين منكم، فمنكم من يقول: طيب طالما هذه الميزة في حكم المكروه، فلماذا وضعَـتْها مايكروسوفت أساساً؟

لهؤلاء الأذكياء أقول: لنفس السبب الذي وُضعت لأجله المتغيرات الثابتة في ++C. هناك ضوابط على استخدام هذه الميزة، وإلا فإنها ستكون وبالاً على المبرمج. باختصار، لا تتعامل مع أصناف خارجية من خلال الباني الثابت لأي صنف ما… وبما أننا معرضون للنسيان فإنني أقول: الباب الذي تأتيك منه الريح، سُدّه واستريح! وقد أعذر من أنذر!





مِحرف واحد بأربعة مَحارف
التوقيت 22/محرم/1431 02:18 م بقلم الكاتب وسام البهنسي

في لغة C و ++C نستطيع الإعلان عن متغيرات من نوع char، والتي تحمل محرفاً وحيداً بحجم بايت واحد فقط. كما نستطيع كتابة النصوص كسلسلة من المحارف المتتالية. كمثال:

char myChar = 'w'; // محرف وحيد
char anotherChar = '3'; // محرف وحيد آخر
char *text = "welcome"; // نص، سلسلة محارف

 

نلاحظ كيف أن المحرف يتم تحديده بوضعه بين فاصلتين أحاديتين كما في 'w' .  أما النصوص فتوضع بين علامتي تنصيص أو اقتباس "welcome" .  أعقد أن جميع من يبرمجون بلغة ++C يعرفون هذه المعلومات الأساسية. الآن إليكم الكود التالي:

int text = 'why?'; // نص، لكن بدون علامات اقتباس؟

 

جربوا وضع السطر أعلاه في برنامج ++C، وانظروا إن كان سيعتبره المترجم خطأ…

ها؟ ماذا وجدتم؟

لا توجد أية أخطاء ؟!

 

فعلاً! المترجم مصرّ على أن السطر صحيح ولا خطأ فيه. ولكن كيف؟ وما معنى هذا السطر الغريب؟ فما نعرفه أننا نستخدم الفاصلة الأحادية ' فقط عندما نودّ التعبير عن محرف وحيد، لكننا هنا كتبنا أربعة محارف دفعة واحدة! فما القصة؟

 

عندما انضممتُ إلى فريق EA كان مشروعي الأول هو لعبة الهوكي NHL2007، وقد تركز عملي آنذاك في مجال الرسوميات، وقد واجهتُ أسطراً مماثلة للسطر الغريب أعلاه في خضمّ كود اللعبة الشاسع، وتحديداً في القسم المسؤول عن قراءة ملفات الشخصيات في اللعبة، في تركيبة تشبه المثال التالي:

 

int recordID = GetNextRecordIDFromFile(characterFile); // Read from file
switch (recordID)
{
  case 'head':
    ReadHead(characterFile);
    break;
 
  case 'indx':
    ReadIndex(characterFile);
    break;
 
  case 'data':
    ReadData(characterFile);
    break;
}

 

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

 

هذه التركيبة تعني متغير عددي بسعة أربعة بايتات، حيث كل بايت يحمل قيمة محرف من المحارف الأربعة المكتوبة في جدول آسكي. أي أن 'head' هي طريقة أخرى للتعبير عن الرقم 1751474532. أما 'indx' فهي تقابل الرقم 1768842360 وهكذا.

 

يمكننا استخدام هذه التركيبة لترميز البيانات لكن بطريقة مقروءة. ففي المثال أعلاه، ملف المجسم يحتوي عدة أقسام، كالترويسة والفهرس والبيانات الأخرى. ونرمز لكل قسم بأربعة بايتات تخبرنا بنوعه. قيمة هذه البايتات تساوي إما 'head' أو 'indx' أو 'data' طبقاً لنوعية القسم.

 

آمل أن تستفيدوا من هذه الحيلة في برامجكم وملفاتكم الخاصة.

 

في النهاية أستعير المثل الشامي القائل: عشنا وشفنا ابتسامة

 

والسلام عليكم ورحمة الله





اللعبة الأولى
التوقيت 11/محرم/1431 04:44 ص بقلم الكاتب وسام البهنسي

ذكرتُ في مقابلة قديمة أجراها معي السيد أحمد دعدوش على موقع أفكاركم، ذكرتُ فيها لعبة هي ربما أول لعبة كنتُ قد أنجزتها في مسيرتي البرمجية وأعرضها أمام الجمهور. هذه اللعبة هي مونوبولي، وقد كانت هذه اللعبة هي مفتاحي للانتقال إلى لغة C فيما بعد.

 

أنهيتُ كتابة هذه اللعبة في الثانوية العامة، تقريباً عام 1418 هـ أو 1997 مـ، ولا أذكر بصراحة متى بدأتُ بالمشروع ككل. لكني أرجح أن ذلك كان خلال السنة الدراسية السابقة (الصف الثاني الثانوي).

 

هذه لقطة للعبة كما تظهر على شاشة الحاسوب القديمة :

  صورة للشاشة وهي تعرض رقعة لعب مونوبولي

 

حسناً، أنا في الواقع لم أنهِ إنجاز اللعبة، لكن انتظر لحظة قبل أن تتهمني بالكذب والادعاء. فإليك ملابسات القصة.

كتبتُ اللعبة باستخدام لغة بيسك، ضمن بيئة مايكروسوفت كيوبيسك Microsoft QBasic، وهي بيئة كانت تأتي مضمنة مع إصدارات نظام تشغيل دوس آنذاك، وصاحبكم كان مبتدئاً جداً بأساليب كتابة الكود المختصر، فكنت أكرر الكثير من الأسطر بدلاً من وضعها في إجراء وحيد ومناداة ذاك الإجراء كلما احتجتها. هذا واحد.

ثانياً، كامل رسوميات اللعبة "مبرمجة" وليست محفوظة في ملف صورة كما نفعل هذه الأيام. أي أنك ستجد في الكود أسطراً تقوم بكتابة الكلمات نقطة بنقطة، ورسم وتلوين الأشكال بأسلوب تحديد الشكل ثم تعبئته باللون المطلوب (Flood Fill).

 

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

 

إذن بوضعها الأخير، يستطيع اللاعبون (4 كحد أقصى) اللعب بها والتنقل بين الخانات وفتح بطاقات صندوق الجماعة والفرصة والدخول إلى السجن والخروج منه، لكنهم لا يستطيعون بيع أو شراء الأراضي (يع!!!)

 

حسناً، الآن كما ترى وقد بررتُ لك موقفي، لن تستطيع أن تتهمني بالكذب والادعاء، لكنك تستطيع أن تتهمني بعدم الخبرة والغباء ابتسامة لن أعترض على ذلك ابتسامة

 

هذه لقطة من كود اللعبة على شاشة كيوبيسك:

 

بيئة تطوير مايكروسوفت كيوبيسك، ويظهر بها بعض الكود المشين الذي كنت أكتبه سابقاً

 

على أنني كنتُ قد بذلتُ جهداً جاداً آنذاك لمحاولة الفكاك من قيد حجم الكود هذا، وقد وجدتُ تعليمة تسمح لك بتنفيذ برنامج كيوبيسك آخر من خلال برنامجك (تدعى CHAIN)، لكن ضريبتها أن البرنامج الأول سيتوقف تماماً عن العمل وستفقد متغيراته كافة قيمها لتبدأ من الصفر مرة أخرى.

 

ما علينا، المهم أن هذه الورطة كانت سبب انتقالي للغة C حيثُ لا توجد هذه المحدودية (لكني أيضاً توقفت عن عادة تكرار أسطر الكود!).

 

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

 

درع المشاركة المتميزة للعبة مونوبولي كيوبيسك 

(تباً! لقد أخطؤوا الخطأ الكريه بأن وضعوا نقطتين تحت الألف المقصورة ليتحول حرف الجر "على" إلى "علي"!!!)

 

أنتهز الفرصة هنا لأشكر أساتذتي الذين رعوني ورعوا هذا العمل في المدرسة الأستاذ عبد الله الدهمش مدرس مادة الحاسب، والأستاذ سعيد عبد الله بالبيد مدرس مادة الكيمياء (ومؤلف كتاب المساعد في الكيمياء) في مدرسة الجزيرة الثانوية، حفظهم الله وبارك لهم في أعمارهم وجزاهم خير الأجر عني.

 

لمن يودّ الاطلاع على الكود أو حتى تجريب اللعبة (لا أنصح بذلك إطلاقاً)، يمكنكم تحميله كاملاً من هنا كما وجدته في أرشيفي، عسى أن يكون دافعاً لمن يواجه موقفاً مماثلاً في حياته.

 

والسلام عليكم ورحمة الله وبركاته