اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'تعلم البرمجة'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

  1. نوضح في هذا المقال الأسلوب الأمثل لدراسة تخصص هندسة البرمجيات، ونجيب على السؤال المهم حول إمكانية دراسة البرمجة بشكل ذاتي. ونسلط الضوء على أهم المميزات والتحديات التي ستواجهك إذا اخترت الدراسة الذاتية للبرمجة أو الدراسة الأكاديمية لها، ونختم المقال بجملة من النصائح التي تساعدك لتتعلم البرمجة باحترافية وكفاءة. هل يناسبني تخصص هندسة البرمجيات؟ لا شك أن البرمجة مهارة مميزة في عصرنا الحالي سريع التطور، وقرار تعلم البرمجة أو هندسة البرمجيات هو خيار ممتاز وخطوة صائبة، ويعد تخصص هندسة البرمجيات واحدًا من أسرع المجالات نموًا في العالم ويوفر للمرء فرص عمل متعددة ذات أجر مرتفع ويضمن له مستقبلًا مشرقًا، فكل الأعمال اليوم تحتاج لمن يطور لها البرامج والمواقع ويقوم بصيانتها وتحديثها بصورة مستمرة. إضافة لكونه مجالًا إبداعيًا ودائم التطور يمنح المتخصص فيه قدرة إبداعية ويحسّن طريقة تفكيره المنطقي ويمكّنه من تطوير برامج وتطبيقات بأفكار مميزة ونافعة، فإذا كنت مهتمًا بمجال البرامج الحاسوبية ولغات البرمجة ولديك رغبة دائمة في تطوير نفسك وصبر على تعلم الكثير من المفاهيم والأدوات والاطلاع على كل جديد في مجال التقنيات واستعداد لمواجهة التحديات وحل المشكلات وإتمام المهام وانتباه جيد للتفاصيل فدراسة تخصص هندسة البرمجيات خيار مناسب لك بكل تأكيد ويحقق لك الكثير من الفوائد والمميزات وأهمها: توفير العديد من فرص العمل في مختلف المجالات والقطاعات، فالطلب على المبرمجين ومهندسي البرمجيات في تزايد مستمر. الحصول على أجور مرتفعة مقارنة بالتخصصات والوظائف الأخرى. تعزيز القدرة على التفكير التحليلي والمنطقي وحل المشكلات بسهولة ومرونة. مرونة في اختيار ساعات ومكان العمل حيث يمكن العمل عن بعد من داخل المنزل أو أي مكان وخلال أي وقت تفضله. حرية العمل بشكل مستقل أو بدء عملك الخاص أو العمل في شركة مع فريق متكامل. القدرة على تحويل الأفكار إلى تطبيقات ومشاريع مبتكرة تفيد البشر وتسهّل عملهم. مواكبة التطور التقني وفهم طريقة التعامل مع التقنيات الحديثة بسرعة وسهولة. اكتساب مهارة التطوير الذاتي والقدرة على تعلم مهارات جديدة باستمرار. كيفية تعلم تخصص هندسة البرمجيات إذا قررت التخصص في مجال البرمجة وهندسة البرمجيات فسوف تجد أمامك خيارين أو نهجين متاحين للتعلم الأول هو الطريق الأكاديمية أي سيتوجب عليك الالتحاق بجامعة أو كلية تقنية متخصصة في هندسة البرمجيات أو علوم الحاسوب أو أي اختصاص مشابه، وهذا الخيار يمنحك تعليمًا شاملًا للبرمجة وفق منهج منظم ومحدد لكنه طريق طويل يلزمك بدراسة الكثير الكثير من المقررات ويمتد لفترة زمنية طويلة. الخيار الثاني هو الطريق المهني حيث يتوجب عليك دراسة تخصص هندسة البرمجيات بشكل ذاتي مستفيدًا من مصادر التعلم الكثيرة والمتنوعة من كتب ومقالات ودروس ومقاطع فيديو ودورات تدريبية متاحة عبر الإنترنت لتعلم لغات البرمجة والتقنيات وغيرها من الأدوات والمهارات المطلوبة لإتقان التخصص وهذا الخيار يمكّنك من التركيز على تخصصك واحترافه بوقت أقل. سنناقش في الفقرات التالية أبرز المميزات والعيوب لكل طريقة من هذه الطرق لنساعدك على اختيار الطريقة الأفضل والأنسب لك. الدراسة الجامعية لتخصص هندسة البرمجيات إذا قررت دراسة هندسة البرمجيات من خلال الالتحاق بإحدى الجامعات الأكاديمية حيث تستغرق الدراسة في هذا التخصص وسطيًا أربع سنوات وقد يختلف عدد السنوات والمواد من جامعة لأخرى. وهذا الخيار سيوفر لك عدة مميزات وسيضع أمامك جملة من العوائق والتحديات، لنناقش كلًا منها على حدا في فقراتنا التالية. مميزات الدراسة الجامعية لتخصص هندسة البرمجيات من أهم المميزات والإيجابيات التي ستحصل عليها عند دراسة تخصص هندسة البرمجيات في الجامعة ما يلي: الحصول على تعليم منهجي ومنظم وفق جدول زمني محدد فالمناهج الجامعية موضوعة بعناية ومرتبة وفق ترتيب منطقي يتدرج في تعليمك كافة الأساسيات التي تحتاجها والتي يمكنك من خلال تعلمها تطوير نفسك في أي مجال لاحقًا. الحصول على شهادة جامعية معترف بها تعزز مصداقيتك وتساعدك على الحصول على فرصة عمل. توفر دراسة البرمجة في الجامعة جو تعلّم جماعي وتمكّنك من التفاعل مع زملاء لهم نفس الاهتمامات وتنفيذ مشاريع جماعية ومناقشات مثمرة. توفر الجامعات مختبرات حواسيب ومكتبات ضخمة تضم الكثير من الكتب والمصادر البرمجية القيّمة التي تساعدك في عملية التعلم. صعوبات وتحديات الدراسة الجامعية لتخصص هندسة البرمجيات لا يخلو التعليم الجامعي في تخصص هندسة البرمجيات من بعض العوائق والصعوبات التي تحتاج لأن تأخذها بعين الاعتبار عند اختيار المسار الأفضل بالنسبة لك ومن أبرز هذه الصعوبات نذكر: تحتاج دراسة هندسة البرمجيات في الجامعة لمدة زمنية طويلة تستغرق 4 سنوات أو أكثر وتختلف المدة حسب كل جامعة. المقاعد الجامعية محدودة فقد لا تحصل على فرصة في دراسة هندسة البرمجيات في الجامعة التي تطمح لها وتضطر لدراسة تخصص آخر. يعتبر التعليم الجامعي مرتفع التكلفة مقارنة بالتعلم الذاتي حيث ستضطر لدفع تكاليف الرسوم الجامعية والكتب وأجور المواصلات وغيرها. ستضطر خلال فترة دراسة تخصص هندسة البرمجيات في الجامعة إلى تعلم الكثير من المواد النظرية المملة التي لن تفيد مطلقًا في سوق العمل. لا زال أسلوب تعليم البرمجة وتقييم معلومات الطالب في بعض الكليات معتمدًا على الأساليب التقليدية القديمة التي تختبر الحفظ بدل الفهم ولا تقيم مهارات الطالب تقييمًا صحيحًا، وهذا الأسلوب يناسب التخصصات النظرية لكنه لا يناسب تخصص هندسة البرمجيات والحاسوب الذي يعتمد على الفهم والإبداع والمنطق. لا تواكب بعض المناهج الجامعية التطور السريع في مجال البرمجة وتقنياتها أولًا بأول، وقد تعتمد لسنوات على نفس المناهج القديمة التي عفا عليها الزمن فإذا اكتفيت بما تعلمك إياه الجامعة ستخرج إلى سوق العمل وتفاجأ بالفجوة الكبيرة بين ما تعلمته في أروقة الجامعات وبين ما هو مستخدم في سوق العمل. الدراسة الذاتية لتخصص هندسة البرمجيات هل تعلم أن معظم المبرمجين الناجحين لم يكونوا خريجي كليات تقنية وليس لديهم شهادات جامعية في أحد التخصصات البرمجية بل اتبعوا أسلوب التعلم الذاتي وأثبتوا جدارتهم من خلال العمل على تطوير مشاريعهم البرمجية الخاصة حيث توفر الدراسة الذاتية لتخصص هندسة البرمجيات جملة من الفوائد والمميزات التي قد لا يوفرها لك خيار التعلم الجامعي التقليدي، وإذا كنت ترغب بالاطلاع على قصص نجاح لأشخاص تمكنوا من تحقيق النجاح والتميز من خلال دراسة هندسة البرمجيات بشكل ذاتي أنصحك بمطالعة قصص نجاح طلاب أكاديمية حسوب ففيها تجارب ملهمة حقًا. لكن الدراسة الذاتية لتخصص هندسة البرمجيات تتضمن أيضًا جوانب إيجابية وأخرى سلبية سنتعرف عليها في الفقرات التالية. مميزات الدراسة الذاتية لتخصص هندسة البرمجيات من أبرز الفوائد التي ستعود عليك في حال قررت دراسة هندسة البرمجيات بشكل ذاتي ما يلي: مرونة التعلم في أي وقت وتحديد عدد ساعات التعلم وجدول الدارسة وفق ما يناسب ظروفك. تعلم البرمجة من المنزل أو أي مكان يناسبك بدل تكبد عناء الذهاب لمقر الجامعة الذي قد يكون موجودًا في مكان بعيد عنك أو خارج مدينتك. التعلم بتكلفة بالمجّان أو دفع تكلفة منخفضة مقارنة بتكاليف التعليم الجامعي. التعلم بصورة أسرع من خلال التركيز على تعلم لغات البرمجة والتقنيات التي تفيدك في تخصصك البرمجي فقط. التعلم من مصادر حديثة ما يبقيك على اطلاع بأحدث التقنيات في تخصصك البرمجي بدل دراسة معلومات قديمة عفا عليها الزمن. توفر مصادر تعلم عديدة ومتنوعة تمكّنك من تحديد الأسلوب الذي تفضلّه وتحقيق أفضل استفادة. التركيز على التطبيق العملي وتنفيذ المشاريع المطلوبة في سوق العمل بدل التعلم النظري الممل. تعلم التنظيم وإدارة الوقت وتحديد أولويات التعلم يما يحقق أهدافك من التعليم. تطوير مهارة التواصل الفعال مع المجتمعات البرمجية عبر الإنترنت. زيادة الاعتماد على النفس واكتساب مرونة في مواجهة التحديات وحل أي مشكلات تواجهك بمفردك. صعوبات وتحديات الدراسة الذاتية لتخصص هندسة البرمجيات بالرغم مما توفره الدراسة الذاتية للبرمجة من مميزات ونقاط قوة إلا أنها لا تخلو من بعض الصعوبات والتحديات وإن لم تتعامل معها بشكل صحيح فقد تصاب بالإحباط وتفشل في تحقيق أهدافك، وإليك قائمة بأبرز هذه الصعوبات: التعلم الفوضوي وغير المنضبط فقد تشتتك كثرة المصادر ولا تعرف من أين تبدأ وما هي الخطوات الصحيحة التي عليك اتباعها. عدم وجود أستاذ يقيّمك ويمكّنك من تحديد مستواك ومعرفة نقاط ضعفك والعمل على تحسينها. عدم تنظيم الوقت والمماطلة وفقدان التركيز والانضباط والتحفيز. لا تحصل على شهادة أكاديمية تثبت ما تعلمته لكن يمكن حل هذه النقطة ببناء معرض أعمال قوي يثبت كفاءتك وهو الأهم حاليًا في سوق العمل والكل يبحث عنه بدلًا من الشهادة. إذا كنت شخصًا اجتماعيًا فقد يشعرك التعلم الذاتي بنوع من العزلة لعدم وجود زملاء أو فريق يشاركك التعلم ويتعاون معك في المشاريع، والانضمام للمجتمعات والمنتديات عبر الانترنت يساعدك في تخطي هذه الصعوبة. هل أتعلم البرمجة عبر الجامعة أم ذاتيًا؟ سواء اخترت تعلم البرمجة بشكل ذاتي أو في كلية أو جامعة فيجب أن تضع في الحسبان أن تعلم البرمجة ليس بالأمر اليسير بل يحتاج للكثير من الصبر والمثابرة وبذل الجهد والتعلم المستمر من مصادر حديثة والتطبيق العملي، ستحتاج إلى قضاء وقت كبير في البرمجة والعمل على مشاريع لتحسين مهاراتك لكن حلاوة الإنجاز ستهون عليك التعب. وختاًا إليك بعض النصائح لتصبح مهندس برمجيات ناجح: ابدأ بتعلم الخوارزميات والتفكير المنطقي قبل أن تبدأ في تعلم أساسيات البرمجة، ففهم هذه المواضيع أمر بالغ الأهمية لك كمبرمج أو مهندس برمجيات. تعرف على أهم مجالات البرمجة وأكثر التخصصات البرمجية المطلوبة في سوق العمل الذي تود التوجه له، وحدد بناءً على ذلك ما هو التخصص البرمجي الذي تود متابعة دراسته واحترافه، ثم ضع قائمة بأهم لغات البرمجة والتقنيات التي عليك تعلمها لتتقنها وضع خطة محكمة لتعلمها. طبق كل ما تتعلمه فكلما كتبت أكوادًا أكثر كلما استوعبت المفاهيم البرمجية بشكل أفضل، وتأكد أنك مهمًا قرأت من دروس وشاهدت من مقاطع فيديو فلن تصبح مبرمجًا كفؤًا إلا إذا مارست ما تتعلمه بشكل عملي وتدربت على حل المشكلات وتصحيح الأخطاء التي ستظهر عند تنفيذ الكود. فكّر ثم برمج ولا تكتب أي كود برمجي قبل أن تخطط وتحلل مشروعك بشكل جيد وتفهم الوظائف والمهام المطلوبة بوضوح ثم تنفذها من خلال الأكواد البرمجية. حدّث معلوماتك باستمرار فمهما كان مستوى خبرتك فهناك دومًا معلومات وتقنيات جديدة تحتاج لتعلمها. شارك في المنتديات والمجتمعات البرمجية وتبادل معلوماتك وتجاربك مع المبرمجين والمطورين الآخرين. من الجيد أن تتعلم أكثر من تقنية أو لغة لتطوير مشاريعك البرمجية فهذا يجعلك قابلًا للتكيف مع سوق العمل والتغير الكبير في المتطلبات. إذا كنت تشعر بالتشتت ولا تملك القدرة على تنظيم تعلمك وتقييم معلوماتك فإن اتباعك لدورات تدريبية منهجية في التخصص البرمجي الذي تحبه سيمكنك من اتباع الخطوات الصحيحة ويساعدك في التعلم بشكل أفضل وأسرع. كيف تساعدك دورات أكاديمية حسوب على دراسة هندسة البرمجيات تساعدك أكاديمية حسوب على تخطي العقبات التي قد تواجهها في في دراستك الذاتية لتخصص هندسة البرمجيات من خلال توفير تعلم منهجي منظم فهي توفر لك الكثير من مصادر التعلم المجانية لتعلم البرمجة من كتب ودروس ومقالات وسلاسل تعليمية تناسب كافة المستويات، كما توفر الأكاديمية دورات تعليمة متنوعة في أشهر التخصصات البرمجية المطلوبة في سوق العمل كما تضمن لك حداثة المحتوى التعليمي فالأكاديمية تضيف تحديثات مستمرة لمختلف الدورات لتواكب أحدث التطورات والاتجاهات. أضف إلى ذلك أنها توفر قسم الأسئلة والأجوبة كمجتمع برمجي فاعل يساعدك خلال رحلتك التعليمية. وعند اشتراكك في إحدى دورات أكاديمية حسوب ستضمن الحصول على شروحات برمجية ذات جودة عالية تدمج بين التعليم النظري والتطبيق العملي حيث تشمل دورات الأكاديمية العديد من المشاريع التطبيقية التي تمنحك خبرة عملية وتقيم مستواك البرمجي بشكل صحيح وتساعدك على بناء معرض أعمال احترافي. كما توفر لك دعمًا تفاعليًا حيث يمكنك التواصل مع فريق متخصص من المدربين المستعدين لشرح ما يصعب عليك خلال دراستك وإجابتك على على أي تساؤل تطرحه، والأهم أنك ستتمكن من خوص امتحان يقيّم ما تعلمته خلال الدورة لتتمكن من الحصول على شهادة معتمدة من أكاديمية حسوب في حال نجاحك فيه الأمر الذي يعزز فرصتك في الحصول على فرصة عمل مناسبة. وفي الختام تذكّر أن رحلة تعلم البرمجة قد لا تكون سهلة لكنها بالتأكيد ستكون رحلة مليئة بالتحديات والتشويق والمتعة إذا سلكتها بالطريقة المناسبة واتبعت الخطوات الصحيحة، لذا من المهم أن توازن إيجابيات وسلبيات كل طريقة من طرق تعلم تخصص هندسة البرمجيات وتختار الطريقة التي تناسب ظروفك ومتطلباتك وتلتزم بالنصائح التي ذكرتها لك، وستنجح بإذن الله في تحقيق كل أهدافك والتغلب على كل التحديات والصعوبات التي تواجهك. الخلاصة تعرفنا في مقال اليوم على أبرز الطرق التي يمكنك من خلالها دراسة تخصص هندسة البرمجيات ومميزات وتحديات كل طريقة منها، ويمكن أن نخلص في نهاية المقال بأن الدراسة الذاتية للبرمجة هي الخيار الأفضل لك إذا كنت شخصأ يسعى لدخول سوق العمل وكسب المال بسرعة وتريد أن تحافظ على حداثة معلوماتك وتبقى مطّلعًا على كل جديد لكن هذا يتطلب منك الكثير من الجهد والتنظيم والالتزام واعتماد مصادر تعلم جيدة والتحفيز الذاتي المتواصل لتجنب الفشل والإخفاق. أما الدراسة الجامعية فهي الأنسب لك إذا كان هدفك هو الحصول على شهادة جامعية والدراسة ضمن بيئة تعلم منظمة ومنهجية وإذا تمكنت من الجمع بين التعليم الجامعي والتعلم الذاتي فسيكون هذا أمرًا رائعًا بإمكانه تجاوز القصور الذي تعاني منه مناهج التعليم التقليدي. اقرأ أيضًا تعلم البرمجة ما هي فوائد تعلم البرمجة؟ أسهل لغات البرمجة مدخل إلى تطوير البرمجيات Software Development
  2. نسلط الضوء في مقال اليوم على مستقبل البرمجة أحد أكثر المجالات تغيرًا وتجددًا، فالتقنيات والتخصصات البرمجية المختلفة تتطور بوتيرة هائلة وسريعة جدًا ما يحتم على أي مبرمج أو مطور أن يواكب هذه التغييرات ويكون على دراية بأهم الاتجاهات التي يتوقع أن تشهدها البرمجة في السنوات القادمة وتأثيرها على سوق العمل والوظائف المستقبلية. الذكاء الاصطناعي ومستقبل البرمجة لعل أول تساؤل يخطر ببال أي مبرمج بشأن مستقبل البرمجة هل ستحل الروبوتات والذكاء الاصطناعي محل المبرمجين في المستقبل، والجواب هو أن الذكاء الاصطناعي سوف يساعد المبرمجين بدلًا من استبدالهم كما أن تقنيات الذكاء الاصطناعي ستتطور بشكل أكبر ويساعد البشر على القيام بمهامهم المختلفة والحصول على النتائج التي يريدونها حول أي موضوع بشكل أفضل وأسرع. وكما تعرف فقد بدأ الذكاء الصناعي بالفعل في الآونة الأخيرة يؤثر بشكل مباشر على مختلف جوانب حياتنا، ويتوقع أن يزداد تأثيره في المستقبل أكثر وأكثر نتيجة لتطوير البنية التحتية التي يعتمد عليها وتطوير معيار اتصال الواي فاي wifi7 فائقة السرعة والتي تصل لغاية 36 جيجا بت في الثانية بعرض نطاق ترددي يصل إلى 320 ميجاهرتز وانتشار شبكات اتصالات الجوال من الجيل الخامس 5G والبدء بشبكات الجيل السادس 6g التي ستكون أسرع 1000 مرة من شبكة 5G. سيحسن هذا التطور في البنية التحتية من سرعة نقل البيانات ويقلل زمن وصولها ويعطي المبرمجين المتخصصين في الذكاء الاصطناعي وتعلم الآلة القدرة على تحليل ومعالجة هذه البيانات بكفاءة عالية، كما سيزيد من قدرتهم على تطوير حلول إنترنت الأشياء IoT عالية الكفاءة وتطوير تطبيقات متقدمة لم تكن متاحة مع الشبكات السابقة، وسيزيد الطلب أيضًا على برمجة أجهزة ذكية قادرة على اتخاذ القرارات مثل السيارات ذاتية القيادة وروبوتات المحادثة والمساعدين الافتراضيين والروبوتات الصناعية التي ستعمل جنبًا إلى جنب معنا نحن البشر أو ربما تؤدي مهامنا وتستغني عن وجودنا بالكامل لكن في مهن وتخصصات محدودة. كما سيلعب الذكاء الصناعي وتعلم الآلة دورًا أساسيًا في مستقبل البرمجة وكتابة الكود وسيزداد التوجه إلى الإصدار الثاني من البرمجيات Software 2.0 وهي البرمجيات التي تستخدم خوارزميات تعلم الآلة ML والشبكات العصبية لتؤدي عملها دون تدخل بشري ولا بد أنك سمعت أو استخدمت بوت المحادثة الذكي ChatGPT من Open AI وأداة OpenAI Codex الأكثر تخصصًا والتي تساعدك على إنتاج الأكواد البرمجية وتدعم العديد من لغات البرمجة فهما مثالان على برمجيات تعتمد على الذكاء الاصطناعي والتي من شأنها مساعدة المطورين والمبرمجين في تحسين عملهم وزيادة إنتاجيتهم ليركزوا على الأمور الأكثر أهمية في عملية التطوير. فإذا كنت مهتمًا بهذا المجال من الضروري أن تحرص على تعلم لغات البرمجة الخاصة بالذكاء الاصطناعي وتعلم الآلة ولعل أهمها لغة البرمجة بايثون Python التي توفر الكثير من أطر العمل والمكتبات القوية في مجال الذكاء الاصطناعي مثل مكتبة SciKit-Learn و TensorFlow و PyTorch و Keras. ولمطالعة المزيد من المعلومات حول خارطة طريق تعلم الذكاء الاصطناعي ومعرفة أدواته وتقنياته المختلفة أنصح بقراءة مقال تعلم الذكاء الاصطناعي ومقال تعلم الآلة Machine Learning. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن مستقبل إنترنت الأشياء إنترنت الأشياء IoT هو التقنية التي تجعل الأجهزة من حولنا ذكية وتتفاعل مع بعضها البعض وترسل البيانات عبر شبكة الإنترنت وتحللها وهو بلا شك أحد الجوانب التي ستؤثر على مستقبل البرمجة بشكل كبير، ومن المتوقع أن يزداد تأثيره في السنوات القادمة ليطبق بشكل أكبر في أتمتة منازلنا والتحكم بمختلف الأجهزة التي نستخدمها في حياتنا اليومية كأجهزة الإنذار وأنظمة التدفئة وأنظمة الإضاءة الذكية وأنظمة التحكم بالأبواب والستائر ويمكننا من التحكم بها من خلال التطبيقات المثبتة على هواتفنا الذكية، ولن يقتصر تطبيق إنترنت الأشياء على منازلنا فحسب بل سيستخدم بصورة أكبر في مختلف المجالات الصناعية كصناعة السيارات ومجال الرعاية الصحية وغيرها. ربما ستزيد هذه التقنيات من اعتمادية الناس العادية على الأجهزة لكنها ستفرض على معشر المبرمجين بذل جهد أكبر في تعلم تقنيات تطوير تطبيقات الأجهزة المضمنة وتطبيقات الأجهزة قابلة للارتداء والاطلاع على أحدث التغييرات التي ستطرأ على تطوير تطبيقات الجوال وتطبيقات الويب، إلى جانب اكتساب مهارات كافية في علوم البيانات لجعل هذه التطبيقات قادرة على التعامل مع كمية ضخمة من البيانات Big data فأجهزة إنترنت الأشياء ستولد لنا كميات هائلة من البيانات وهذه البيانات الضخمة تحتاج إلى تحليلها ومعالجتها واتخاذ قرارات صائبة منها. كما يحتاج المبرمجون المهتمون بهذا المجال إلى التركيز بشكل أكبر على أمان التطبيقات والمواقع التي يطورونها، ويتعلموا بشكل جيد طريقة التعامل مع بروتوكولات الاتصال وأجهزة الاستشعار والمنصات السحابية المناسبة حسب نوع التطبيق المطلوب، ويتقنوا اللغات والبروتوكولات الخاصة بإنترنت الأشياء مثل MQTT و CoAP و Zigbee. مستقبل البرمجة وعلم البيانات علم البيانات Data Science هو مجال حديث يجمع بين الإحصاء والرياضيات وعلوم الحاسوب ويهتم بدراسة البيانات ويعتمد عليها في اتخاذ القرارات من خلال الاستعانة بخوارزميات الذكاء الاصطناعي وتعلم الآلة، ويتوقع أن يزداد الطلب عليه بشكل أكبر في المستقبل نتيجة التضخم الهائل في حجم البيانات الذي نشهده، كما يتوقع أن يكون علم البيانات أحد أكثر المجالات المطلوبة في المستقبل لأن كافة المؤسسات والمنظمات وقطاعات العمل بدأت في الاعتماد عليه لاتخاذ قراراتها المختلفة مثل كشف عمليات الاحتيال والتوصية بالمنتجات المناسبة للعملاء وستحتاج للاعتماد عليه بشكل أكبر مستقبلًا. فإذا كنت مهتمًا بمجال علم البيانات أنصحك بأن تبدأ من الآن بتعلم التقنيات ولغات البرمجة الشهيرة في هذا المجال مثل لغة بايثون python ولغة R ونظم إدارة قواعد البيانات وبرامج التحليلات الإحصائية والتمثيل الرسومي للبيانات مثل Tableau و Power BI ومنصات البيانات الضخمة وتفهم أطر البيانات الضخمة مثل Spark و Hadoop لضمان مهنة لها دور واعد في مستقبل البرمجة. لمطالعة مزيد من المعلومات حول علم البيانات وتخصصاته وكيفية تعلمه أنصح بمطالعة مقال علم البيانات Data science: الدليل الشامل ومقال الدليل الشامل إلى تحليل البيانات Data Analysis. مستقبل تقنية البلوكتشين Blockchain أحدثت تقنية البلوكتشين Blockchain ثورة في طريقة التعامل الرقمي مع البيانات وهي تقنية تعتمد على تخزين المعاملات في قاعدة بيانات عملاقة مشفرة وآمنة لا مركزية وغير قابلة للتعديل تسمى دفتر الأستاذ الموزع distributed ledger وقد اكتسبت هذه التقنية شهرتها من العملات المشفرة المبنية عليها. ففي هذه التقنية تتم المعاملات على قاعدة البيانات بترتيب تسلسلي وتكون المعاملات لامركزية أي أنها تعمل على حواسيب موزعة في جميع أنحاء العالم وتتم مباشرة بين المستخدمين دون تدخل طرف ثالث وتكون مؤمنة بشكل كبير، على سبيل المثال عندما يبيع شخصان السلع لبعضهما البعض باستخدام عملة بيتكوين Bitcoin فلن يحتاجوا إلى المرور عبر وسيط مثل بيبال لإتمام هذه المعاملة. تتطور تقنية بلوكتشين بشكل متسارع ويتوقع أن تشهد المزيد من الاستخدامات في المستقبل في عدة مجالات فإلى جانب تحويل العملات المشفرة عبر الأجهزة سيعتمد عليها في إنشاء عقود ذكية مخصصة قادرة على التعامل مع المعاملات المعقدة والتحقق من المعاملات متعددة الخطوات وتسريع معالجة البيانات ونقلها بأمان، وبدأت تعتمد في العديد من القطاعات والمجالات مثل عمليات التصويت للانتخابات وحفظ المعاملات المالية وسندات الملكية. يتوقع أن تؤثر هذه التقنية على مستقبل البرمجة وتزيد الطلب على مطوري البلوكتشين بمختلف تخصصاتهم سواء المطورين الأساسيين blockchain core أو مطوري تطبيقات blockchain أو مطوري التطبيقات اللامركزية DApps ومطوري العقود الذكية باستخدام لغات مخصصة مثل solidity، فإذا كنت ترغب في تعلم مجال رائد في مستقبل البرمجة يمكنك البدء بتعلم تقنيات تطوير البلوكتشين والتعرف على منصاتها وبروتوكولاتها المختلفة. الحوسبة الكمومية Quantum Computing ستحل الحوسبة الكمومية التي تستخدم البتات الكمومية quantum bits أو ما يعرف بالكيوبتات qubits محل بالحوسبة الكلاسيكية التي تستخدم البتات bits أو نظام الأرقام الثنائية binary digits لتمثيل البيانات وتنفيذ العمليات، وستلعب دورًا فعالًا في مستقبل البرمجة من خلال زيادة سرعة معالجة كميات هائلة من البيانات وتسهيل حل المشكلات المعقدة التي استعصى على البشرية حلها. لا تزال الحوسبة الكمومية في بدايتها ويقتصر استخدام الحواسيب الكمومية اليوم على المجالات البحثية ولازالت تواجه حتى اليوم بعض التحديات التقنية والعملية التي يعمل الخبراء على حلها، وحين تستقر سيبدأ استخدامها في تطبيقات فعلية مختلفة ويتوقع أن تطور العديد من تخصصات البرمجة وأبرزها الأمن السيبراني وتحليل البيانات وتطور مجال الرعاية الطبية وتساعد في اكتشاف الأدوية وتحسن من الاقتصاد. تستخدم الحوسبة الكمومية أسلوبًا مختلفًا في البرمجة وتحتاج لتطوير خوارزميات جديدة لذا يحتاج المبرمجون المهتمون بهذا المجال إلى تعلم لغات برمجة وأطر عمل جديدة مصممة للعمل على الحواسيب الكمومية مثل Q#‎ و Cirq و Qiskit، كما يمكنهم استخدام لغات برمجة تقليدية مثل بايثون لكن مع الاستعانة بمكتبات خاصة مصممة للعمل مع الأنظمة الكمومية مثل QuTip وسيحتاجون كذلك لفهم أساسيات الجبر الخطي وميكانيك الكم للتعامل مع هذه التقنية الرائدة. مستقبل البرمجة دون كود No-Code ستبقى البرمجة التقليدية التي تعتمد على كتابة الشيفرات البرمجية أو ما يعرف بالتطوير عالي الكود High-code development موجودة في مستقبل البرمجة بالتأكيد، لكن يتوقع أن يزداد الاعتماد كذلك على منصات التطوير بدون كود No-code development أو التطوير منخفض الكود Low-code development الذي يسمح لأي شخص غير مختص بالتقنية بتطوير البرامج والتطبيقات والمنتجات الخاصة به وأتمتة أعماله بنفسها. تتميز البرمجة منخفضة الكود بشكل أساسي بتوفير واجهات رسومية سهلة الاستخدام تعتمد السحب والإفلات ولا تحتاج لكتابة الشيفرات والتعليمات باستخدام إحدى لغات البرمجة المعقدة، ويمكن أن تعتمد أيضًا على أنظمة تصميم ومكونات مسبقة الصنع يمكن لأي شخص استخدامها مباشرة وإنشاء تطبيقاته بسرعة وسهولة. قد تتساءل هل هذا يعني أن الاعتماد على المبرمجين والمطورين المتخصصين سوف ينخفض في المستقبل؟ والجواب هو بالنفي فالحلول بدون كود مهما كانت مرنة وسهلة الاستخدام فلن تتمكن من الاستغناء عن دور المبرمجين بالكامل وستصلح للأنظمة البرمجية البسيطة نسبيًا وستبقى كتابة الأكواد مطلوبة لتطوير الأنظمة البرمجية الاحترافية والتحكم بهذه المنصات نفسها فهذه المنصات تعمل وراء الكواليس بواسطة الشيفرات البرمجية وستظل بحاجة لمبرمجين يطورونها ويقومون بصيانتها، كما يمكن أن تكون هذه المنصات بذات الوقت أداة مساعدة يمكن للمبرمجين دمجها مع أساليب البرمجة التقليدية لتحسن إنتاجيتهم وتسريع وتيرة عملهم. مستقبل تطبيقات الويب التقدمية PWA يتوقع أن تسيطر تطبيقات الويب التقدمية PWAs وهي اختصار لعبارة Progressive Web Applications على مستقبل برمجة تطبيقات الويب ويزداد الاعتماد عليها من قبل الشركات والمؤسسات المختلفة، فهذه التطبيقات وفرت أسلوبًا جديدًا لتطوير تطبيقات الأجهزة المحمولة ومكنت المبرمجين من تطوير تطبيقات ويب تتصرف مثل التطبيقات الأصيلة native applications وتعمل بكفاءة على كافة أنواع أنظمة التشغيل وتتوافق مع كافة الأجهزة وأحجام الشاشات سواء الحواسب المكتبية أو الأجهزة المحمولة ويتم الوصول لها من خلال مستعرض الويب وهي لا تتطلب من المستخدم تثبيت أي شيء لاستخدامها كما يمكنها العمل دون الحاجة للاتصال بالإنترنت. تستخدم تطبيقات الويب التقدمية تقنيات تطوير الويب الأساسية HTML و CSS وجافاسكريبت إلى جانب أدوات وأطر العمل المخصصة مثل Angular و React و Vue.js، فإذا مهتمًا بمجال برمجة وتطوير التطبيقات أنصحك بالبدء بتعلم تطوير PWAs واكتساب المهارات اللازمة في هذا المجال لضمان مهنة مطلوبة في سوق العمل في السنوات القادمة. لمطالعة مزيد من التفاصيل حول تطبيقات الويب التقدمية والتعرف على أهم مميزاتها يمكنك مطالعة مقال مدخل إلى تطبيقات الويب التقدمية PWA أهمية البرمجة في المستقبل لاشك أن مستقبل البرمجة واعد ومشرق في عصرنا الرقمي متسارع الخطى فالطلب على المطورين والمبرمجين يزداد بشكل كبير في الشركات التقنية المتخصصة، كما أن البرمجة قد تصبح مطلبًا أساسيًا للتوظيف في العديد من مجالات العمل الأخرى مثل الاقتصاد والصناعة ومؤسسات الرعاية الصحية إلى جانب زيادة الاعتماد عليها في مجالات الحياة اليومية. فالبرمجة لغة المستقبل وعلى الجميع تعلمها ولكن لنتذكر دومًا أن عالم البرمجة في تغير مستمر ومن الضروري لأي مهتم بالبرمجة أن يواكب التطورات الحاصلة فيها ويركز على تعلم الاتجاهات الحديثة التي يتوقع أن يزداد الطلب عليها إذا أراد أن يضمن البقاء في الصدارة في سوق العمل المستقبلي. إذا كنت مهتمًا بتعلم البرمجة واحترافها يمكنك البدء بأحد التخصصات البرمجية التي شرحناها سابقًا والتي يتوقع أن تشهد ازدهارًا وطلبًا مرتقعًا في مستقبل البرمجة، وتذكر أن مهنة البرمجة بلا شك بجميع مجالاتها وتخصصاتها الأخرى ستبقى واحدة من أكثر المهن التي تنبئ بمستقبل واعد، فإذا كنت مهتمًا بتعلم البرمجة وتقنياتها لا تتردد وابدأ من اليوم بتحديد المجال الذي يوافق ميولك وضع خطة لتعلمه مع الاهتمام إلى جانب ذلك بتنمية مهاراتك الناعمة مثل مهارات التواصل الفعال وحل المشكلات والقدرة على التعلم وتطوير الذات لأن هذه المهارات ستصبح أكثر أهمية في المستقبل وستمكنك من إثبات وجودك والتميز في سوق العمل. وإذا كنت مهتمًا بمعرفة مزيد من التفاصيل حول مستقبل البرمجة أنصحك بمشاهدة هذا الفيديو: الخلاصة حاولنا في مقال اليوم أن نستشرف مستقبل البرمجة ونعرفك على أهم التخصصات البرمجية التي يتوقع أن تشهد وجودًا قويًا في السنوات القليلة القادمة ومن أبرزها الذكاء الاصطناعي، والتعلم الآلي، والتعلم العميق، وإنترنت الأشياء، وعلم البيانات، وتقنيات البلوكتشين، والبرمجة بدون كود أو منخفضة الكود، وناقشنا أهمية تخصص البرمجة والمستقبل الواعد لدراسة هندسة البرمجيات وزيادة الطلب على المبرمجين والمطورين في سوق العمل المستقبلي. اقرأ أيضًا تعرف على أعلى تخصصات البرمجة أجرًا البرمجة والخوارزميات والذكاء الاصطناعي تطوير تطبيق وصفة لاقتراح الوجبات باستخدام ChatGPT و DALL-E في PHP برمجة الذكاء الاصطناعي
  3. نجيب اليوم في هذا مقال على سؤال ما هي البرمجة وما أهميتها في عصرنا الذي يشهد تطورًا تقنيًا غير مسبوق والذي أصبحت فيه الحواسيب والأجهزة الذكية جزءًا لا يتجزأ من حياتنا وأعمالنا اليومية، فلولا البرمجة لما كانت كل هذه الأجهزة والتقنيات قادرة على العمل بالشكل المطلوب. فالبرمجة هي التي تتيح لنا التفاعل والتواصل مع الحواسيب والأجهزة من حولنا وتمكننا من إعطائها التعليمات وتنفيذ المهام المتنوعة التي نحتاجها منها، كما أن تعلم البرمجة لم يعد حكرًا على المبرمجين والمطورين اليوم بل أصبح مهارة أساسية تفيد الجميع للانسجام مع ضرورات العصر الحالي ومتطلباته. ما هي البرمجة؟ البرمجة هي طريقة التواصل بيننا نحن البشر وبين أجهزة الحواسيب وغيرها من الأجهزة الإلكترونية القابلة للبرمجة، فالحاسوب لا يعرف بالأساس سوى لغة خاصة تسمى لغة الآلة machine language وهي لغة صعبة ومعقدة تتكون من مجموعة من الواحدات والأصفار، على سبيل المثال عندما نكتب حرفًا على لوحة المفاتيح، فإن هذا الحرف يحول إلى تسلسل من الأصفار والواحدات حتى يستطيع الحاسوب فهمه. باختصار يمكن أن نجيب على سؤال ما هي البرمجة بأنها كتابة الأوامر بلغة يمكن للحاسوب فهمها وتنفيذها. في بداية ظهور الحواسيب كان المبرمجون الأوائل يستخدمون طريقة يدوية وصعبة للتخاطب مع الحواسيب وإيصال المعلومات لها وذلك من خلال بطاقات مثقبة Punched cards فبعد كتابة الأوامر والتعليمات المطلوب من الحاسوب أن يفهمها يحولون هذه التعليمات إلى عدة بطاقات مثقبة لإدخالها للحاسوب، قد يحتاج كل أمر لبطاقة وكل بطاقة تحتوي على سلسلة من الثقوب بشكل معين تعبر عن هذا الأمر، ثم توضع البطاقات في جهاز مخصص يقرأ الثقوب على البطاقة ويترجمها إلى لغة الآلة التي يمكن للحاسوب فهمها وتنفيذها وإذا احتاج الحاسوب لإخراج المعلومات أو طباعتها فسيتم إخراجها كذلك على شكل بطاقات مثقبة. أما اليوم فنحن لا نحتاج إلى هذه التقنية المعقدة للتحدث مع الحواسيب فقد ابتكر علماء الحاسوب طريقة تساعدنا للتخاطب مع الحاسوب باستخدام لغات برمجة متطورة تكتب بصيغة معينة مفهومة أكثر لنا نحن البشر وتدخل إلى الحواسيب من خلال أجهزة الإدخال كلوحة المفاتيح والفأرة وصارت البرمجة مهمة ممتعة يمكننا من خلالها تحويل أفكارنا المختلفة لتطبيقات وبرامج حاسوبية مفيدة وممتعة ومشاركتها مع الآخرين. ما هي لغة البرمجة؟ لغة البرمجة هي لغة خاصة تستخدم للتخاطب مع جهاز الحاسوب وتوجيه الأوامر له بطريقة نستطيع نحن البشر فهمها ويستطيع الحاسوب ترجمتها للغة يفهمها وينفذها ويعطينا النتائج المطلوبة. هناك الكثير من أنواع لغات البرمجة لكل منها قواعدها واستخداماتها وأسلوب صياغتها، على سبيل المثال تعد لغات البرمجة C و C++‎ وجافا وجافا سكريبت وبايثون وسويفت أمثلة على لغات برمجة شائعة مستخدمة للتخاطب مع الحاسوب، تتشابه تعليمات هذه اللغات إلى حد ما مع اللغة الإنجليزية المحكية لكنها ليست مثلها تمامًا. لنفترض أنك تريد أن تخبر الحاسوب بأن يقوم بمهمة بسيطة مثل عرض رسالة ترحيبية على الشاشة، يمكنك أن تكتب له التعليمات بإحدى لغات البرمجة وتحفظها بشكل برنامج حاسوبي، فالبرنامج program هو مجرد تسلسل من التعليمات تُخبر الحاسوب بما يجب فعله، ثم تطلب منه بعد ذلك تنفيذ هذا البرنامج، سيفهم تعليمات البرنامج ويعرض لك الرسالة التي طلبتها منه. على سبيل المثال تبين الصورة التالية طريقة كتابة برنامج حاسوبي بسيط يطلب من الحاسوب أن يطبع رسالة ترحيبية "مرحبًًا بك في أكاديمية حسوب" باستخدام عدة لغات برمجة مختلفة، تعطي كافة هذه البرامج نفس النتيجة عند تشغيلها، حاول قراءة التعليمات البرمجية باللغات المختلفة، ألا ترى أن بعضها مفهوم وواضح وقريب جدًا للغة الإنجليزية المحكية؟ كيف يفهم الحاسوب لغات البرمجة؟ قد يتبادر لذهنك السؤال التالي: كيف يفهم الحاسوب هذه التعليمات إذا كان لا يعرف إلا لغة الأصفار والواحدات؟ إليك الإجابة: عندما تتخاطب مع الحاسوب بأي لغة من لغات البرمجة وتكتب برنامجًا باستخدامها يقوم برنامج خاص يسمى المترجم أو المصرّف compiler أو المفسر interpreter بعملية ترجمة أو تحويل الشيفرات البرمجية للبرنامج الحاسوبي إلى شيفرة مكتوبة بلغة الآلة ليتمكن الحاسوب من فهمها وتنفيذها وعرض النتائج المطلوبة للمستخدم. تعتمد هذه الخطوة على نوع لغة البرمجة التي تستخدمها فبعض اللغات تستخدم مصرف يقوم بترجمة البرنامج بأكمله إلى لغة الآلة في مرة واحدة ثم ينشئ ملف تنفيذي يمكن تشغيله مباشرة على الحاسوب وبعض اللغات تستخدم مفسر أو ما يعرف بالمصرف الفوري الذي تترجم البرنامج سطرًا سطرًا وتنفذ كل سطر على الفور دون الحاجة لإنشاء ملف تنفيذي منفصل وبمجرد ترجمة البرنامج إلى لغة الآلة يمكن تشغيله على الحاسوب وبهذا يمكن للمبرمج التخاطب مع الحاسوب دون الحاجة إلى التعامل مباشرةًً مع لغة الآلة. عندما تتعلم إحدى لغات البرمجة ستتعلم كيف تطلب من الحاسوب أن ينفذ لك أي أمر تريده سواء كان هذا الأمر بسيطًا كطباعة نصوص أو جمع أرقام أو حل معادلات الرياضية أو معقدًا كتصميم ألعاب أو إنشاء متاجر إلكترونية أو غيرها من التطبيقات المختلفة. ما هي الخوارزميات وما علاقتها بالبرمجة؟ يستخدم مصطلح الخوارزميات بشكل كبير في مجال البرمجة وعلوم الحاسوب والرياضيات، لأن البرمجة ترتبط بحل المشكلات وفهمها ثم كتابة بعض التعليمات البرمجية التي تنفذ هذا الحل من خلال الحاسوب، فإن لم تتمكن من فهم المشكلة وتحدد فيما إذا كانت مشكلة قابلة للحل برمجيًا وتقسمها لمشكلات أصغر ثم تبدأ بوضع الخطوات الصحيحة والمتسلسلة لحلها وإلا فلن تتمكن من برمجتها بشكل صحيح باستخدام أي لغة من لغات البرمجة، وهنا تأتي أهمية تعلم الخوارزميات وتطوير مهارات التفكير المنطقي التي تكسبك هذه المهارات. فالخوارزمية هي إجراء منطقي يستخدم لحل المشكلات من خلال وضع قائمة متسلسلة من التعليمات التي تحدد خطوة بخطوة كافة الإجراءات التي علينا اتباعها للوصول لحل المشكلة بكفاءة مع تحديد القيمة أو مجموعة من القيم التي نحتاج لمعرفتها لحل المشكلة والتي تمثل (المدخلات) واستنتاج القيمة أو مجموعة القيم التي تنتج كحل للمشكلة والتي تمثل (المخرجات) تكتب الخوارزميات بطريقة مشابهة لكتابة وصفات الطعام حيث يتم تحديد كل خطوة بطريقة وشرحها بطريقة مرتبة يمكن فهمها وتنفيذها، تخيل أنك تريد حل مشكلة طهي طبخة جديدة لأول مرة، مثل طبق الطاجن المغربي باللحم، عندها ألن تحتاج لمن يخبرك بكافة المكونات الأساسية المطلوبة في الطبق؟ وما هي الخطوات المتسلسلة لطهي الوصفة وتحويل هذه المكونات إلى الطبق المطلوب؟ حسنًا تعمل الخوارزمية الحاسوبية بنفس الطريقة فالحاسوب يحتاج منك أن تخبره كيف يتبع الخطوات الصحيحة في معالجة المدخلات ليعطيك النتيجة المطلوبة. أنواع لغات البرمجة هناك عدد كبير من لغات البرمجة المستخدمة من قبل المطورين والمبرمجين وعلماء الحاسوب، لكل لغة منها أغراضها ومجالات استخدامها وتصنف هذه اللغات وفق معايير وأنواع مختلفة بحسب مستواها ومجالات استخدامها وطريقة هيكلة شيفراتها وأسلوب تنفيذ تعليماتها وغيرها من العوامل المختلفة، وقد تندرج بعض لغات البرمجة تحت أكثر من تصنيف بذات الوقت. وإليك نبذة مختصرة عن أشهر أنواع لغات البرمجة: لغات البرمجة منخفضة المستوى Low-level languages لغات البرمجة عالية المستوى High-level languages لغات البرمجة الوظيفية Functional Programming Language لغات البرمجة النصية أو المكتوبة Scripting Programming Language لغة البرمجة المنطقية Logic Programming Language لغة البرمجة كائنية التوجه Object-Oriented Programming لغات برمجة منخفضة المستوى Low-level languages كانت لغات البرمجة الأولى لغات البرمجة منخفضة المستوى أي أنها أقرب لمستوى الأجهزة (كما أشرنا بمثال البطاقات المثقبة) وصعبة الفهم والتعلم والصيانة على البشر ومن الأمثلة عليها لغة الآلة ولغة التجميع Assembly، ويكون لكل نوع من أجهزة الحاسوب أو المعالجات لغة آلة خاصة به ولا يمكنه تنفيذ البرنامج عليه إلا إذا تم التعبير عنه بتلك اللغة. لغات البرمجة عالية المستوى High-level languages لغات البرمجة عالية المستوى هي لغات برمجة قريبة لفهم البشر فهي تستخدم مفردات وأوامر وبنية تتشابه مع مفردات اللغة الإنجليزية وتسمح بالتفاعل مع الحاسوب بسهولة وهي سهلة التعلم والصيانة ومن الأمثلة عليها لغة بايثون Python ولغة جافا سكريبت JavaScript وروبي Ruby. بعض اللغات أسهل في الاستخدام والفهم للمبرمجين (اللغات عالية المستوى) ولكنها توفر تحكمًا أقل في أجهزة الحاسوب. البعض الآخر أكثر ملاءمة للآلة (لغات منخفضة المستوى)، مما يجعلها أسرع في التنفيذ وأكثر كفاءة في الذاكرة، ولكن من الصعب على البشر فهمها. لغات البرمجة النصية Scripting languages هي لغات مكتوبة بشكل أوامر نصية تستخدم في العديد من المجالات مثل أتمتة المهام المتكررة وتطوير الويب والعديد من لغات البرمجة المشهورة اليوم هي لغات برمجة نصية، مثل لغة بايثون وجافا سكريبت ولغة PHP. لغات البرمجة المرئية Visual languages هي لغات برمجة لا تعتمد على أسلوب كتابة التعليمة البرمجية بل تعتمد البرمجة من خلال الرسومات والصور فهي توفر لك واجهات رسومية GUIs تساعدك في إنشاء البرامج، ومن أبرز الأمثلة على لغات البرمجة المرئية نذكر سكراتش Scratch وفيجوال بيسك Visual Basic. وهي أقل شهرة من لغات البرمجة النصية وتستخدم عادة لأغراض بسيطة وتعليمية فاستخدامها للعناصر المرئية يجعلها مفهومة أكثر من قبل المبتدئين. لغات البرمجة المنطقية Logic Programming Languages هي نوع خاص من أنواع لغات البرمجة لا تخبر الحاسوب بما يجب فعله بل تخبره بسلسلة من الحقائق والقواعد التي ترشده كيف يتخذ القرارات وهي تستخدم في تطبيقات الذكاء الاصطناعي ومعالجة اللغات الطبيعية وتحليل البيانات ومن الأمثلة على لغات البرمجة المنطقية نذكر لغة برولوغ Prolog، وداتا لوج Datalog. لغات البرمجة الإجرائية Procedural Programming تعتمد لغات البرمجة الإجرائية على تمثيل البرنامج الحاسوبي بشكل مجموعة من الإجراءات Procedures والإجراء هو سلسلة من الخطوات المتسلسلة أو الإجراءات التي تحقق النتيجة المطلوبة. ومن الأمثلة عليها لغة C وفورتران FORTRAN. لغات البرمجة كائنية التوجه OOP تعد البرمجة كائنية التوجه أو ما يعرف بلغة البرمجة بالكائنات من أشهر أنواع لغات البرمجة وهي تمثل برنامج حاسوبي من خلال مجموعة من الكائنات objects بحيث يتكون كل كائن من بيانات ووظائف تعالج هذه البيانات، وهذا الأسلوب يسهل على المبرمج إعادة استخدام التعليمات البرمجية وتوسيع نطاقها. ومن أشهر الأمثلة على لغات البرمجة كائنية التوجه نذكر لغة جافا وبايثون و C++‎. لغات البرمجة الوظيفية Functional Programming تعتمد لغات البرمجة الوظيفية كما يدل اسمها على استخدام الوظائف أو الدوال البرمجية Functions والوظيفة أو الدالة ما هي سوى قطعة من الشيفرة البرمجية تأخذ مدخلات وتعالجها وترجع نتيجة المعالجة، يركّز هذا الأسلوب في البرمجة على وصف طريقة حل المشكلة بدلاً كتابة خطوات متسلسلة لحلها، من أشهر لغات البرمجة الوظيفية جو Go ورست Rust وكوتلن Kotlin و #F. لغات البرمجة المصرفة والمفسرة كما ذكرنا سابقًا تحول التعليمات البرمجية إلى لغة مفهومة من قبل الحاسوب بأسلوبين إما من خلال تمرير هذه التعليمات على مصرّف يقرأها بالكامل ثم يحولها إلى كود مكتوب بلغة الآلة ثم ينفذ هذا الكود، وتسمى لغات البرمجة التي تعتمد هذا الأسلوب باللغات المصرفة compiled languages ومن الأمثلة عليها جافا و C++‎، و C#‎. الأسلوب الثاني أن تمر التعليمات البرمجية على مفسر يقرأها وينفذها سطرًا تلو الآخر ويعرض النتيجة مباشرةً وعندها تسمى لغات مفسرة interpreted languages ومن الأمثلة عليها لغة بايثون Python وجافا سكريبت JavaScript وروبي Ruby. ستجد العديد من الطرق لتصنيف لغات البرمجة وإذا كنت مهتمًا بمعرفة المزيد من التفاصيل حول أنواع البرمجة ولغاتها المختلفة والغرض من استخدامها أنصحك بمطالعة مقال أنواع لغات البرمجة. ما هي أسهل لغة برمجة؟ يرافق سؤال ما هي البرمجة سؤالًا آخر وهو ما هي أسهل لغة برمجة يمكن البدء بها؟ عمومًا، تتفاوت لغات البرمجة في صعوبتها فهناك لغات برمجة صعبة التعلم ومعقدة وتفرض الكثير من القواعد الصارمة والتفاصيل المعقدة، وهناك بالمقابل لغات سهلة وتملك قواعد صياغية ولغوية بسيطة وسهلة التعلم والفهم فإذا كنت في بداية رحلتك في تعلم البرمجة فمن الأفضل أن تبدأ بتعلم لغة سهلة يمكنك من خلالها فهم أساسيات البرمجة بسلاسة وبناء أساس قوي وبعد ذلك سيكون تعلم مفاهيم ولغات أخرى أكثر سهولةً ويسرًا، ومن أسهل لغات البرمجة التي يمكنك البدء بها: لغة HTML و CSS لغة جافا سكريبت JavaScript لغة PHP لغة بايثون Python لغة روبي Ruby لغة جافا Java لنشرح نبذة مختصرة عن كل لغة من هذه اللغات ونوضح أبرز مميزاتها واستخداماتها: لغة HTML و CSS من السهل تعلم HTML وCSS إلى حد كبير لأنهما لا يتطلبان منك التفكير المنطقي لحل المشكلات كما هو الحال في باقي لغات البرمجة، فلغة HTML أو لغة ترميز النص التشعبي هي أساس صفحات الويب وهي لغة توصيفية تصف وتنظم محتوى صفحات الويب وتحدد فيما إذا كان كل جزء من المحتوى هو فقرة نصية أو عنوان رئيسي أو قائمة من التعددات أو جدول أو غير ذلك. أما لغة CSS وهي اختصار لعبارة Cascading Style Sheets أي لغة صفحات الأنماط المتعاقبة فهي لغة تنسيقية مهمتها تعريف مجموعة من القواعد التي تطبّق على عناصر HTML وتعطيها مظهرًا جميلًا حيث يمكن من خلالها تحديد ألوان وخطوط وأحجام وأماكن تموضع العناصر المختلفة، يمكنك اعتبار HTML بمثابة الهيكل العظمي لصفحة الويب و CSS بمثابة الملابس التي تغطي هذا الهيكل وتعطيه منظرًا جميلًا. لغة جافا سكريبت JavaScript تتميز لغة جافا سكريبت JavaScript ببساطة ووضوح تعليماتها وهي لغة عالية المستوى وشائعة الاستخدام وتستخدم جنبًا إلى جنب مع HTML وCSS كواحدة من أهم لغات برمجة الويب فهي مدعومة من جميع متصفحات الويب الرئيسية وتستخدم لإضافة تأثيرات حركية وميزات تفاعلية لمواقع الويب، كما تستخدم في العديد من المجالات والتطبيقات الأخرى وتملك مجتمع دعم كبيرًا وضخمًا يوفر الكثير من المصادر التعليمية، مما يساعد المبتدئين على تعلم اللغة وحل المشكلات التي تواجههم بسرعة وسهولة. لغة PHP PHP هي اختصار تعاودي للعبارة Hypertext Preprocessor وهي لغة برمجة سهلة التعلم وشائعة الاستخدام، تستخدم بشكل أساسي في تطوير الويب وتمكنك من إضافة وإدارة المحتوى الديناميكي وقواعد بيانات إلى مواقع وتطبيقات الويب كما يمكنك تضمين هذه اللغة في HTML. وللاطلاع على مزيد من المعلومات حول لغة PHP وطريقة عملها وأبرز مميزاتها يمكنك مطالعة مقال تعرف على لغة PHP لغة بايثون Python تعد لغة بايثون Python واحدة من أسهل لغات البرمجة وأكثرها قوةً وفعاليةً، فهي تملك مفردات وعبارات قريبة جدًا من اللغة الإنجليزية وتعبّر عن المفاهيم البرمجية بطريقة مختصرة وواضحة، وهي لغة عامة الأغراض ويمكن أن تستخدم في العديد من المجالات والتطبيقات ومن أهمها تطوير الويب وتطبيقات الذكاء الاصطناعي والتعلم الآلي وتطوير تطبيقات سطح المكتب. لغة روبي Ruby تعد لغة روبي Ruby واحدة من أسهل لغات البرمجة وأكثرها مرونةً نظرًا لتركيبة جملها البسيط سهلة القراءة، وقد كان الهدف من إنشائها بالأصل هو جعل البرمجة ممتعة للمبتدئين وهي تعتمد البرمجة كائنية التوجه، أي يشتهر الكود المكتوب بلغة روبي بأنه منظم وسهل الفهم والصيانة. لغة جافا Java تتميز لغة البرمجة جافا Java بكونها لغة عامة الأغراض وكائنية التوجه وتحظى بشعبية كبيرة بين أوساط المبرمجين فهي تعتمد على مبدأ كتابة الكود مرة واحدة وإمكانية تشغيله في أي جهاز أو منصة. وهي لغة متعددة الاستخدامات مثل تطبيقات الويب وتطبيقات الهاتف المحمول وتطوير الألعاب ما يجعلها لغة مناسبة للبدء بتعلم البرمجة. كانت هذه نبذة سريعة عن أسهل لغات البرمجة للمبتدئين، ركّز في البداية على تعلم لغة برمجة واحدة تتوافق مع أهدافك ومتطلباتك، وبعدها سيكون تعلم أي لغة برمجة أخرى أمرًا في غاية السهولة. وللتعرف على مزيد من لغات البرمجة سهلة التعلم والمناسبة للمبتدئين في البرمجة أنصحك بمطالعة مقال أسهل لغات البرمجة أهمية البرمجة تكمن أهمية البرمجة في ضرورة مواكبة التطور التقني المتسارع الذي يعد سمةً مميزةً لعصرنا الحالي، فالبرمجة هي العصب المحرك لحياتنا والتواصل مع الحواسيب والأجهزة الذكية واستخدام التطبيقات والبرامج الحاسوبية أصبح أمرًا أساسيًا لا غنىً عنه لإنجاز المهام المختلفة كالتسوق ودفع الفواتير والبحث العلمي واللعب والترفيه والتواصل الاجتماعي وغيرها من الاستخدامات العديدة الأخرى. لذا تعد البرمجة اليوم واحدةً من أهم الوظائف المطلوبة في سوق العمل فلا تكاد تخلو مؤسسة اليوم من الاعتماد على التقنيات الرقمية وشبكة الإنترنت لإنجاز أعمالها ما يبرز الحاجة لتعيين مطورين ومبرمجين لتطوير هذه التقنيات المختلفة وتحسينها وصيانتها بشكل دوري وتعيين أشخاص قادرين على فهم آلية التعامل مع هذه التقنيات. كما أصبحت برمجة الحواسيب مهارة مطلوبة يبحث عنها أرباب العمل حتى بالنسبة للوظائف التي لا تتعلق بالحواسيب بشكل مباشر شأنها شأن المهارات الشخصية الأخرى مثل مهارة التواصل والاستماع أو مهارة التحدث بعدة لغات لأنها تدل ضمنيًا على أن الشخص الذي يملكها شخص منفتح تقنيًا ويملك مهارات في حل المشكلات والتفكير المنطقي. ومن أبرز المجالات والقطاعات التي تبرز فيها أهمية البرمجة نذكر: قطاع التعليم القطاعات الحكومية الاقتصاد وأسواق المال الرعاية الصحية الترفيه وصناعة الألعاب إنترنت الأشياء لنشرح أهم الفوائد التي تعود بها برمجة الحاسوب على كل مجال مما سبق: أهمية البرمجة في قطاع التعليم أصبحت مادة البرمجة جزءًا أساسيًا من المناهج الدراسية في العديد من البلدان فقد أدركت المؤسسات التعليمية أن تعليم البرمجة للطلاب يساعدهم في اكتساب العديد من المهارات القيمة مثل مهارة حل المشكلات والتفكير المنطقي والتحليلي ومهارة التواصل الفعال ويجعلهم أكثر إبداعًا وابتكارً ويوسع أفق تفكيرهم ويمكنهم من تعلم أي مفاهيم جديدة بسهولة أكبر كما يتوفر لهم العديد من فرص العمل في المستقبل. أهمية البرمجة في القطاعات الحكومية تفيد البرمجة في أتمتة وتسيير الأعمال الحكومية بصورة رقمية، فمعظم الحكومات اليوم بدأت بتنفيذ مشاريع التحول الرقمي وإنشاء بوابات إلكترونية تسهل على مواطنيها الوصول إلى الخدمات الحكومية والاستفادة منها. وهذا من شأنه أن يساعد الحكومات في تقديم خدمات أكثر شفافية وفعالية من حيث التكلفة وتحسن رضا المواطنين. إضافةً لذلك تساعد البرمجة المعلمين والأساتذة في تطوير تطبيقات ومنصات تعليمية احترافية وإنشاء محتوى تعليمي تفاعلي سهل الفهم وتقييم أداء طلابهم والتواصل معهم بشكل فعال لجعل عملية التعلم أكثر فعالية. أهمية البرمجة في الاقتصاد تساهم البرمجة في إدارة الأعمال وتعزيز النمو الاقتصادي فصناعة البرمجيات والمنتجات الرقمية المرتبطة بتقنية المعلومات من الصناعات الأكثر إنتاجيةً ونموًا في الاقتصاد. كما تستخدم بعض لغات البرمجة مثل لغة R ولغة بايثون والبرامج الإحصائية مثل إكسل و Stata و SAS من قبل المبرمجين ومحللي البيانات والمهتمين بالاقتصاد والأسواق المالية لتحليل البيانات الضخمة والتنبؤ بمستقبل الاقتصاد بشكل أفضل، واتخاذ قرارات تحسّن العمل وتزيد الأرباح. أهمية البرمجة في الرعاية الصحية يمكن أن تساعد مهارات البرمجة مؤسسات الرعاية الصحية على تطوير تطبيقات وبرامج تساعد في إدارة السجلات الطبية وتحسين رعاية المرضى ومتابعة حالتهم الصحية. كما تساعد البرمجة في مجال الأبحاث الطبية وتحليل بيانات الفحوصات والتحاليل الطبية وتساعد في تشخيص الأمراض والتنبؤ بوجود أمراض معينة بدقة عالية. أهمية البرمجة في الترفيه وصناعة الألعاب يستخدم المطورون لغات برمجة الألعاب مثل C++‎ و C#‎ وجافا Java لإنشاء ألعاب احترافية قابلة للتشغيل على منصات مختلفة كالحواسيب والهواتف الذكية. وقد أصبحت صناعة الألعاب الإلكترونية واحدة من المجالات سريعة النمو والتي تدرّ الكثير من الأرباح. أهمية البرمجة في إنترنت الأشياء لقد نما مجال إنترنت الأشياء IoT بصورة سريعة وبدأت تطبيقاته وأجهزته المختلفة تستخدم بشكل كبير في أعمالنا وحياتنا اليومية وساهم في زيادة راحتنا وأمننا. وهناك العديد من لغات البرمجة التي تفيد في تطوير مشاريع إنترنت أشياء مثل لغة جافا Java وبايثون Python و C و C++‎. نصائح لتعلم البرمجة للمبتدئين بعد أن تعرفت ما هي البرمجة وما أهميتها قد تتساءل كيف يمكن تعلم البرمجة وما أهم الخطوات التي عليك اتباعها لتتقن البرمجة وتعمل في أحد المجالات أو فرص العمل المختلفة التي توفرها. حدد هدفك من تعلم البرمجة وأي مجال من مجالات البرمجة يهمك أكثر من غيره هل هو تطوير مواقع الويب أو تطوير تطبيقات الجوال أو تحليل البيانات …إلخ فهذا يساعدك في اختيار لغات البرمجة والتقنيات الصحيحة التي عليك التركيز على تعلمها. ابدأ بتعلم إحدى لغات البرمجة السهلة التي تناسب المبتدئين والتي تمكنك من احتراف المجال أو التخصص البرمجي الذي اخترته. تعلّم كيف تستخدم الأدوات البرمجية المطلوبة لكتابة وتنفيذ التعليمات البرمجية مثل محررات الأكواد وبيئات التطوير المتكاملة والمحطات الطرفية. طبّق ما تتعلمه على تطوير تطبيقات بسيطة كالآلة الحاسبة أو تطبيق حساب العمر أو ترتيب كلمات حسب التسلسل الأبجدي، كما يمكنك محاكاة مشاريع برمجية قام بها مبرمجون آخرون والتدرب على استكشاف الأخطاء البرمجية وإصلاحها ثم تدرّج إلى تطوير مشاريع أكثر تعقيدًا وبمميزات أكثر. عندما تطور مشاريع متقدمة تحتاج لأن تتعلم أسس ومنهجيات تطوير البرمجيات Software Development وتكتسب مهارة إدارة المشاريع البرمجية مثل تقسيم المشروع إلى أجزاء منفصلة ووضع جدول زمني لإنجاز المشروع وتتبع سير العمل. اختر مصادر تعلم حديثة واحترافية ومنظمة من كتب أو دورات عبر الإنترنت أو معسكرات برمجية وانتبه أن لا تشتت نفسك بكثرة المصادر لتضمن تجربة تعلم منهجية ومتسلسلة، ستجد في أكاديمية حسوب الكثير من الدروس والمقالات والكتب البرمجية المناسبة للمبتدئين. كما توفر موسوعة حسوب توثيقات مفيدة وشاملة باللغة العربية لأشهر لغات البرمجة والتقنيات. خلال رحلة تعلم البرمجة الكثير من الصعوبات والتحديات وقد تقضي ساعات طويلة لحل مشكلة برمجية ما، الأمر الذي قد يصيبك بالإحباط، من الضروري أن لا تستسلم للإحباط وتذكّر دومًا أن مستقبل البرمجة واعد ويستحقّ بذل الجهد. حفّز نفسك باستمرار ومما يساعدك على ذلك التعلم مع أصدقاء يشاركونك نفس الاهتمام والانضمام في المجتمعات والمنتديات البرمجية عبر الإنترنت ففيها ستجد العديد من المبتدئين الذين يواجهون نفس مشكلاتك والخبراء الذين يقدمون النصح والدعم. ابحث عن فرصة عمل مناسبة لخبراتك ومجال تخصصك على مواقع التوظيف ومنصات العمل الحر، فالمشاريع العملية تعزز مهاراتك في التعامل مع العملاء وتعرّفك على متطلبات سوق العمل. لا تتوقف عن تطوير نفسك فرحلة تعلم البرمجة تستمر مدى الحياة والتقنيات تتطور باستمرار ومن الضروري أن تبقى على اطلاعٍ دائمٍ لكل ما هو جديد. إذا كنت تشعر بالفعل بالتشتت والضياع ولا تستطيع الالتزام بخطة تعلم ذاتية يمكن أن تساعدك دورات البرمجة المنهجية على تنظيم أمورك والدراسة بطريقة منهجية ومدروسة، ستجد في أكاديمية حسوب العديد من دورات البرمجة في أكثر المجالات طلبًا في سوق العمل، عند التحاقك بإحدى هذه الدورات ستتمكن من تعلم البرمجة وفق منهج متسلسل يبدأ بالمفاهيم الأساسية ويتقدم تدريجيًا لشرح مواضيع متقدمة كما ستتمكن من إنجاز العديد من المشاريع العملية لتعزز ما تعلمته، وتطرح أي أسئلة أو مشكلات تواجهك ليجيبك عليها مدربون متخصصون، كما ستحصل في نهاية الدورة على شهادة معتمدة تعزز فرصتك المهنية. الخلاصة تعرفنا في مقال اليوم ما هي البرمجة وما أهميتها وتعرفنا على مفهوم لغات البرمجة وأهم أنواعها ومجالات استخدامها واستعرضنا مجموعة من أسهل لغات البرمجة التي يمكن للمبتدئين في مجال البرمجة تعلمها وختمنا المقال بمجموعة من التوصيات والنصائح التي تساعد على تعلم البرمجة بكفاءة. آمل أن تساعدك هذه المعلومات على فهم البرمجة والبدء بتعلمها، وفي حال كان لديك أي سؤال يخص البرمجة يمكنك طرحه في التعليقات أسفل المقالة. اقرأ أيضًا أهمية البرمجة وأهم لغات البرمجة تعلم البرمجة المرجع الشامل إلى تعلم الخوارزميات كيف تتعلم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة برمجة الحاسوب للمبتدئين هل أنا حقا مبرمج؟ متى أسمي نفسي مبرمجًا لماذا يجب أن تعلم طفلك البرمجة؟
  4. لا يخفى على أحد اليوم مدى أهمية تطوير مواقع الويب فالجميع اليوم يسعى لإنشاء موقع إلكتروني خاص به بدءًا من الأشخاص ووصولًا للعلامات التجارية الكبرى إما للتعريف عن أنفسهم وإثبات وجودهم في الفضاء الرقمي، أو لبيع منتجاتهم وخدماتهم، أو تسيير معاملات عملائهم عبر الإنترنت، وغيرها من الفوائد التي لا حصر لها. لكن هل تعلم أن معظم مواقع الويب المتقدمة التي تتعامل معها لا تقتصر على الجزء الذي تراه أمامك على الشاشة والذي يعرف بالواجهات الأمامية لمواقع الويب بل هناك أيضًا الواجهات الخلفية الخفية المسؤولة عن إنجاز كافة الوظائف التي يتضمنها الموقع وجعل كل عناصره من أزرار وقوائم تتفاعل معك بالشكل الصحيح وهي تستخدم تقنيات وأدوات برمجية مختلفة عن تلك التي تستخدمها الواجهات الأمامية. نسلط الضوء في مقال اليوم على كل ما يخص تطوير الواجهات الخلفية لمواقع الويب، ونستعرض أهم المهارات والتقنيات التي تحتاج لتعلمها وأهم المسؤوليات المنوطة بها، فإذا كنت ترغب في العمل كمطور واجهة خلفية لكنك لا تعرف من أين تبدأ وما هي خطوات التعلم الصحيحة فهذا المقال سيفيدك حتمًا. كيف تعمل مواقع الويب؟ قبل الغوص في تفاصيل تطوير مواقع الإنترنت ومفهوم الواجهة الأمامية والخلفية لموقع الويب دعنا نتعرف بداية على المصطلحات الأساسية للويب والكيفية التي تعمل مواقع الويب وفقها. مبدئيًا لدينا نوعان من الأجهزة المتصلة بشبكة الإنترنت هما العميل client وهو جهازك الحالي وهو ببساطة هو الجهاز المتصل بالإنترنت التابع للمستخدم الذي يتصفح الإنترنت من خلال تطبيق خاص مثبت فيه هو متصفح الويب web browser مثل جوجل كروم أو فايرفوكس. خادم الويب web server وهو حاسوب بعيد مصمم للعمل كمستودع لملفات مواقع الويب من أكواد برمجية وملفات صور والنصوص وغيرها من العناصر التي تراها على موقع الويب وتسهل وصولك إليها فمطور المواقع يقوم بتحميل كل هذه الملفات إلى الخادم وأنت تتصل به وتعرض هذه الملفات على جهازك. يجب أن يزود الخادم ببرامج خاصة تمكنه من استقبال الطلبات الواردة إليه ومعالجتها والرد عليها ويجب أن يكون متصلًا بالإنترنت بصورة دائمة ويلبي طلبات العملاء بسرعة مع العلم بأن تسمية الخادم تختلف بحسب طبيعة الخدمة التي يقدمها فإذا كان الخادم يوفر خدمة قاعدة بيانات يسمى خادم قاعدة البيانات وإذا كانت يخزن صفحات الويب يسمى خادم ويب له عنوان URL فريد يمكن الوصول إليه عبر الإنترنت. الفرق بين الواجهة الأمامية Frontend والواجهة الخلفية Backend قبل الغوص في تفاصيل تطوير الواجهة الخلفية من الضروري أن تفهم الفرق بين الواجهة الأمامية frontend والواجهة الخلفية backend وهما مصطلحان يهدفان إلى فصل الاهتمامات بين طبقة العرض أو واجهة المستخدم أو ما يعرف بالواجهة الأمامية للتطبيقات والمواقع وبين طبقة الوصول إلى البيانات أو ما يعرف بالواجهة الخلفية التي تعمل خلف الكواليس. هل يبدو هذا صعب الفهم! حسنًا لنفترض أنك تتصفح أحد متاجر بيع الملابس على الإنترنت أنت تتفاعل الآن مع ما يسمى بالواجهة الأمامية للموقع فكافة أجزاء موقع الويب التي تراها أمامك والتي تعرض على متصفحك من عناوين وفقرات وصور وأزرار وأيقونات هي في الواجهة الأمامية للموقع. لكن من أين تم جلب قائمة المنتجات التي تراها في واجهة المستخدم؟ الجواب أنها خزنت في قاعدة البيانات المخزنة في الواجهة الخلفية وتم عرضها على الواجهة الأمامية لديك لتتصفحها، بعدها أعجبتك عدة قطع وقررت شراءها وحددت خياراتك المفضلة كاللون والقياس وما إلى ذلك ونقرت فوق زر إضافة لسلة المشتريات ثم أدخلت كافة بياناتك المطلوبة لكنك لم تكمل عملية الشراء لأن ثمن المشتريات لم يكن بحوزتك فخرجت من الموقع، برأيك أين تم حفظ هذه البيانات؟ نعم صحيح كما توقعت أيضًا في قاعدة بيانات الموقع المخزنة على الخادم. بعد ذلك بأيام عدت للموقع ونقرت فوق زر سلة المشتريات لتكمل عملية الشراء، سيقوم الكود المربوط بهذا الزر بسحب كل المعلومات التي أدخلتها من قاعدة البيانات ويحسب ثمنها ويرسلها إليك، كل هذا تم في الواجهة الخلفية للموقع، وبالتالي الواجهة الخلفية للموقع هي الجزء الخفي الذي يعمل وراء الكواليس، أما الكيفية التي ستعرض بها هذه البيانات لك فهي مسؤولية مطور الواجهة الأمامية. فأي كود مسؤول عن الجوانب المرئية لموقع الويب كتبه مطور الواجهة الأمامية وهو ينفذ في المتصفح، وأي كود يتعامل مع قواعد البيانات وواجهات برمجة التطبيقات كتبه مطور الواجهة الخلفية وهو ينفذ في الخادم. هناك نوع ثالث من المطورين يطلق عليه مطور الويب الكامل fullstack web developer أو المطور الكامل full stack developer وهو الذي يتولى بنفسه كتابة كل من كود الواجهة الخلفية والواجهة الأمامية للمواقع والتطبيقات ويملك خبرة بكليهما. للمزيد من التفصيل حول الواجهة الأمامية، يمكنك الرجوع إلى مقال تطوير الواجهة الأمامية لمواقع الويب Frontend Web Development الشامل. ما هو تطوير الواجهة الخلفية للويب؟ تطوير الواجهة الخلفية للويب أوما يعرف بتطوير النظم الخلفية backend development أو التطوير من طرف الخادم server-side هو عملية كتابة الشيفرات البرمجية التي تعمل على خوادم الويب web servers والتي تجعل موقع الويب يعمل خلف الكواليس ويتفاعل مع المستخدمين ويلبي كافة طلباتهم. الهدف من تطوير الواجهة الخلفية هو خلق تواصل بين الواجهات الأمامية وبين قاعدة البيانات عبر الخادم فالمستخدم يتفاعل مع الموقع عن طريق إدخال البيانات بعدها نخزن هذه البيانات في قاعدة البيانات الموجودة على نفس الخادم أو خادم منفصل، وأخيرًا يعيد الخادم النتائج المطلوبة ويعرضها على المتصفح أو ما يعرف بالعميل أو الواجهة الأمامية للموقع. لا غنى عن تطوير الواجهات الخلفية في مواقع الويب الديناميكية dynamic websites التي تتفاعل مع المستخدمين وتحتاج إلى تخزين البيانات وفهرستها وحفظها واستردادها وتعديلها وحذفه مثل مواقع التجارة الإلكترونية والمواقع التي تتطلب ملء نماذج وتخزين البيانات المتغيرة مثل وصف المنتجات والمنشورات وملفات تعريف المستخدمين وما إلى ذلك. أما مواقع الويب الثابتة أو الساكنة static websites فهي لا تتطلب تطوير الواجهة الخلفية وتكون مجرد مواقع بسيطة بمحتوى ثابت ولا تتفاعل مع المستخدمين ولا تستطيع تخزين أي شيء وتسعمل خوادم شبه جاهزة لتخديم البيانات. أهمية تطوير الواجهة الخلفية في سوق العمل لا شك أن أهمية تطوير الواجهة الخلفية ينتج عن انتشار تطبيقات الويب وليس فقط مواقع الويب والاعتماد الكبير على عالم الإنترنت والتطبيقات السحابية من برامج محاسبة وفيديو وإدارة مهام …إلخ. فجميع هذه التطبيقات تحتاج إلى بيانات ديناميكية وبالتالي تحتاج جميعها لتطوير واجهات خلفية. وحسب استطلاع الرأي الذي أجراه موقع موقع Stackoverflow الشهير للعام 2022 والذي يشارك فيه عدد كبير من المطورين والمبرمجين حول العالم تبين أن أكثر غالبية المشاركين في الاستطلاع ونسبتهم 46.82% هم في المقام الأول مطورون كاملون full-stack يليهم مباشرة مطورو الواجهة الخلفية back-end بنسبة 43.38% وبعدهم مطورو الواجهة الأمامية front-end بنسبة 25.96% ويلي ذلك باقي التخصصات البرمجية الأخرى. هذا يدل على أهمية مجال تطوير الويب عمومًا وتطوير الواجهة الخلفية على وجه الخصوص والطلب الكبير عليه في سوق العمل وإلا لم يكن الإقبال عليه ليصل لهذه النسب المرتفعة. كما يعد تطوير تطوير الواجهة الخلفية مجالًا وظيفيًا مربحًا وسريع النمو حيث متوسط الراتب السنوي لمطور الواجهة الخلفية وفق نفس الاستبيان في الولايات المتحدة، في عام 2022، بما قدر بـ 68 ألف دولار سنويًا وهذا الرقم بلا شك يختلف من بلد لآخر ويعتمد على سنوات خبرة المطور إلا أنه يظل رقمًا مرتفعًا مقارنة بباقي المهن والتخصصات. وبالتالي فإن استثمارك في تعلم تطوير الواجهات الخلفية للويب يفتح أمامك الكثير من فرص العمل المجزية والمضمونة، وطالما أن الأشخاص والشركات بحاجة إلى مواقع الويب والمتاجر الإلكترونية فستكون هناك حاجة إلى مطوري ويب. مهام ومسؤوليات مطور الواجهة الخلفية إذا قررت العمل كمطور واجهة خلفية فهذا يعني أنك ستكون المسؤول الأساسي عن تطوير كافة أجزاء موقع الويب التي تعمل من جانب الخادم وصيانتها واختبارها وتصحيحها. يمكن القول أنك مسؤول عن العمود الفقري لتطبيقات الويب والعمل في هذا المنصب يتطلب منك القيام بعدة مهام تشمل ما يلي: التواصل مع العملاء وأعضاء الفريق البرمجي وفهم احتياجات الموقع أو التطبيق وتحديد كافة البيانات والوظائف المطلوبة للعمل في الواجهة الخلفية. كتابة الشيفرات البرمجية التي تحقق وظائف الموقع باستخدام لغات البرمجة التي تعمل من جانب الخادم. معالجة كافة طلبات مستخدمي الموقع. صيانة عناصر الواجهة الخلفية واستكشاف أي أخطاء فيها وإصلاحها. إنشاء قواعد بيانات الموقع وتحسينها وإدارتها والاستعلام منها. إنشاء واجهات برمجة التطبيقات API من جانب الخادم والتي يحتاجها مطورو الواجهة الأمامية لاسترداد البيانات وعرضها. إعداد وإدارة بيئات الاستضافة وتثبيت البرنامج الضرورية على الخادم. تحسين أداء تطبيقات الويب وأمانها وتخفيف زمن تحميلها واستجابتها وتعزيز تجربة مستخدميها. دمج الخدمات الخارجية مثل بوابات الدفع والخدمات السحابية مثل Amazon Web Services و Azure مع الموقع. إجراء عمليات النسخ الاحتياطي واستعادة ملفات الموقع وقاعدة البيانات في حال وقوع أي طارئ. التأكد من أمان الموقع وحمايته من الاختراق. بعد الاطلاع على قائمة المهام أعلاه هل تجد مجال تطوير الواجهات الخلفية مناسب لك؟ أنصحك بمتابعة قراءة هذا المقال لتتعرف على أهم لغات البرمجة لتطوير الواجهات الخلفية وأهم النصائح التي تساعدك لتصبح مطور واجهات خلفية محترف. لغات تطوير الواجهة الخلفية Backend يمكن لمطوري الواجهات الخلفية استخدام العديد من لغات البرمجة والأدوات وأطر العمل التي تسهل عملية بناء تطبيقات تتصل بالخادم وتتفاعل مع قواعد البيانات، ستكون أول خطوة عليك القيام بها كمطور واجهات خلفية هو تحديد اللغات التي ستستخدمها، ولتسهيل المهمة عليك فقد جمعنا لك قائمة بأفضل لغات تطوير النظم الخلفية التي يمكنك استخدامها في عملك وأهم مميزاتها وأطر عملها. أهم لغات تطوير الواجهة الخلفية: لغة جافا سكريبت JavaScript مع Node.js لغة بايثون Python لغة PHP لغة روبي Ruby لغة جافا Java لغة C#‎ دعنا نتناول كل لغة من بينها بمزيد من التفصيل ونتعرف على وأطر عملها ودورها الفعال في تطوير الواجهات الخلفية للويب. لغة جافا سكريبت JavaScript تعد جافا سكريبت واحدة من أكثر لغات البرمجة شهرة وانتشارًا بين أوساط المبرمجين بفضل سهولتها وإمكانية استخدامها لكل من تطوير الواجهة الخلفية والأمامية للويب، فهي تستخدم بشكل أساسي لإنشاء مواقع تفاعلية وديناميكية من جانب العميل وتعمل ضمن المتصفحات فقط، لكن بات بمقدورها بفضل بيئة تشغيل Node.js العمل على جانب الخادم وبرمجة الواجهات الخلفية بخروجها من بيئة المتصفح وبهذا يمكنك تعلم جافا سكريبت من العمل كمطور كامل fullstack ويفتح لك فرصًا أكبر. توفر جافا سكريبت كذلك الكثير من أطر عمل تطوير الواجهة الخلفية التي توفر مجموعة من الأكواد والمكتبات الجاهزة للاستخدام والتي تبسط مهام تطوير المواقع وتجعلها أسرع وأكثر كفاءة ومن ضمنها Express.js و Meteor.js وBackbone.js لكل إطار عمل منها ميزات مختلفة ويصلح لأنواع مواقع معينة أكثر من غيرها لذا عليك البحث في الإطار الذي تود استخدامه والتأكد أنه يلبي متطلباتك بشكل جيد. لغة بايثون Python تعد لغة بايثون إحدى أسهل لغات البرمجة وأكثرها شعبية بفضل بنيتها البسيطة والمقروءة، وهي تستخدم في العديد من المجالات ومن بينها تطوير الواجهات الخلفية للويب وهي تستخدم من قبل كبرى الشركات التقنية مثل إنستغرام و Dropbox. ويمكن استخدام أطر عمل بايثون مثل إطار العمل جانغو Django أو فلاسك flask أو FastAPI لتقليل كتابة التعليمات البرمجية وتبسيط عملية تطوير الواجهات الخلفية لمواقع الويب المتقدمة بشكل أسرع و أكثر أمانًا. لغة PHP ذاع صيت لغة PHP لفترة طويلة كواحدة من أشهر لغات الويب وهي تستخدم في تطوير حوالي 80% مواقع الويب في العالم لكونها لغة سريعة ومرنة يمكنها تطوير كافة أنواع المواقع من المدونات البسيطة إلى المتاجر الرقمية المتقدمة. لم تفقد PHP قوتها أمام اللغات الأخرى بفضل قوة أطر العمل المبنية عليها ولعل أشهرها إطار العمل لارافيل Laravel وهو إطار عمل مفتوح المصدر لتطوير الواجهات الخلفية لمواقع الويب بشكل منظم وسهل وآمن وسهل الاستخدام. إلى جانب العديد من أنظمة إدارة المحتوى CMS التي تجعل من تطوير المواقع وإنشاء المحتوى وتعديله وإدارته غاية في السهولة ولا يستلزم أي مهارات تقنية ومن أشهرها ووردبريس WordPress ودروبال Drupal. لغة روبي Ruby روبي هي لغة برمجة نصية مفتوحة المصدر أطلقت عام 1995 وقد اكتسبت هذه اللغة شعبية كبيرة بين أوساط المبرمجين بفضل تركيبتها التي تشبه إلى حد كبير اللغة الإنجليزية المحكية لذا تعد من أسهل لغات البرمجة المستخدمة في تطوير تطبيقات للويب. ورغم أنها ليست بشهرة اللغات السابقة في العالم العربي إلا أن شعبيتها تزداد بالتدريج على مستوى العالم وستجد الكثير من الوظائف المتوفرة عند تعلمها لاسيما عندما تتقن إطار عملها الشهير Ruby on Rails في تطوير تطبيقاتك فهو يسهل ويسرع عملك بشكل لافت. لغة جافا Java جافا هي لغة برمجة عريقة تم إطلاقها عام 1991 وهي لغة قوية ومتعددة الأغراض تعتمد مبدأ البرمجة كائنية التوجه OOP وعلى الرغم من إمكانية تشغيلها على المتصفح إلا أنها مصممة بشكل أساسي لتطوير الواجهات الخلفية للتطبيقات. بالرغم من أن شعبية جافا آخذة في الانخفاض وكونها لغة صعبة التعلم مقارنة بلغات البرمجة الأحدث إلا أنها لاتزال تستخدم في الكثير من مواقع الويب نظرًا لقوتها وضمان أمان التطبيقات المبنية بها لأنها لا تنفذ على الجهاز نفسه بل تنفذ على آلة جافا الافتراضية Java Virtual Machine أو اختصارًا JVM ما يضمن حماية التطبيقات وعزلها. كما تتضمن جافا العديد المكتبات وأطر عمل الواجهة الخلفية التي تسهل تطوير التطبيقات وصيانتها مثل Spring لذا تعد أحد الخيارات التي يمكنك الاعتماد عليها كمطور واجهات خلفية. لغة C#‎ تعد لغة C#‎ واحدة من أفضل لغات البرمجة وهي لغة عريقة عمرها يزيد على عشرين عامًا ولازالت تصلح لجميع أنواع التطبيقات ولبناء تطبيقات الويب يمكن استخدامها مع إطار عمل دوت نت ‎NET Framework. الشهير الذي يستخدم لبناء تطبيقات ومواقع الويب بناء على لغة C#‎ ويوفر بيئة تطوير واجهات خلفية قوية وفعالة يوفر وظائف مخصصة لإدارة كميات كبيرة من البيانات وإعدادات أمان قوية والكثير من الميزات الجاهزة ويسمح بالعمل مع واجهات برمجة تطبيقات الويب الأصلية. تقنيات وأدوات مهمة لتطوير الواجهة الخلفية Backend بعد أن تعرفت على أهم لغات برمجة وأطر عمل تطوير الواجهات الخلفية للويب دعنا نتعرف الآن على التقنيات والمهارات والأمور الأخرى التي تفيدك بشكل كبير في العمل تطوير الواجهات الخلفية. واجهات برمجة تطبيقات API قواعد البيانات وأبرز أنواعها ونظم إدارتها معرفة أساسية بالشبكات وأمنها أسس التعامل مع الخوادم والاستضافات ومزودات الخدمة السحابية نظم التحكم بالإصدارات Git أدوات إدارة الحزم Package Management System استخدام الحاويات Containers الإحاطة بأساسيات لغتي HTML و CSS وإليك معلومات إضافية عن كل تقنية من هذه التقنيات وكيف تفيدك كمطور ويب. واجهات برمجة تطبيقات API من الضروري كمطور واجهة الخلفية أن تتعلم مفهوم واجهة برمجة التطبيقات Application Programming Interface أو اختصارًا API وهو آلية تمكن التطبيقات والمواقع من التواصل مع بعضها والحصول على البيانات الخاصة ببعضها مهما كانت التقنية التي طورت بها هذه التطبيقات وسواء كانت تطبيقات واجهة خلفية تعمل من طرف الخادم أو تطبيقات واجهة خلفية تعمل من طرف العميل. ومن أبرز الأمثلة على أنواع واجهات برمجة التطبيقات نذكر RESTful API الذي يستخدم تنسيق JSON لتبادل البيانات و GraphQL الذي يعد مفهومًا لنقل وتبادل البيانات على شكل استعلامات queries، ويجب أن تحيط بهذين المفهومين جيدًا كمطور واجهات أمامية. وللمزيد حول مفهوم واجهات برمجة التطبيقات وكيفية استخدامها أنصح بمشاهدة فيديو ما هي الواجهة البرمجية API التالي: قواعد البيانات وأبرز أنواعها ونظم إدارتها يحتاج أي مطور واجهات خلفية لامتلاك معرفة في طريقة التعامل مع قواعد البيانات ونظم إدارتها وأنواعها المختلفة ومن أهمها: قواعد البيانات العلائقية التي تستخدم لغة SQL وتخزن بيانات التطبيقات ضمن جداول مرتبطة ببعضها البعض ومن أبرز أنظمة إدارة قواعد البيانات العلائقية نذكر MySQL و SQLite و PostgreSQL. قواعد البيانات غير العلائقية NoSQL وهي أشهر بدائل قواعد البيانات العلائقية التي تخزن بيانات التطبيقات بطرق أخرى غير الجدول العلائقي ومن أشهر نظم إدراتها نذكر MongoDB وكاساندرا. وقد ناقشنا في مقال دليلك الشامل إلى قواعد البيانات DataBase المزيد من الأنواع وميزات واستخدامات كل نوع من بينها بالتفصيل. معرفة أساسية بالشبكات وأمنها تحتاج كمطور واجهة خلفية إلى امتلاك معرفة أساسية ببروتوكولات الاتصال عبر الويب مثل: بروتوكول HTTP بروتوكول HTTPS وشهادة SSL بروتوكول WebSocket كما يحتاج أي مطور ويب لفهم آلية عمل شبكة الإنترنت والمفاهيم الأساسية المرتبطة بها مثل عناوين بروتوكول الإنترنت IP Addresses وأسماء النطاقات في شبكة الإنترنت. ولا يجب أن يغفل عن مفاهيم أمن الويب واتخاذ كافة إجراءات الحماية اللازمة لحماية قواعد بيانات موقع الويب وحماية مسارات واجهة برمجة التطبيقات من الثغرات الأمنية ومن محاولة سرقة البيانات ويستخدم أساليب المصادقة والأذونات التي تتحكم في وصول المستخدمين للتطبيقات ويشفر أي بيانات حساسة ويتحقق من صحة أي مدخلات من قبل المستخدمين وغيرها الكثير من إجراءات الحماية. قد ترغب في مشاهدة الفيديو التالي للتعرف على مزيد من المعلومات حول أشهر طرق الاختراق وسبل الوقاية منها. معرفة جيدة بنظم التشغيل يحتاج مطور الواجهة الخلفية لامتلاك معرفة أساسية بنظم التشغيل وخصوصًا نظام التشغيل لينكس لأن أغلب الخوادم تعمل بنظام لينكس وبالتالي تعلمه يمكنك من معرفة أساسيات التعامل مع الخوادم والاستضافات ومزودات الخدمة السحابية والتعامل مع واجهات سطر الأوامر أو الطرفية وطرق رفع الملفات إلى الاستضافة والوصول إلى قاعدة البيانات المخزنة عليه. كما يحتاج لامتلاك معرفة كافية بمنصات استضافة الويب وطريقة نشر وتشغيل الموقع على خادم ويب مثل خادم أباتشي Apache و خادم إنجن إكس Nginx ومعرفة طريقة التعامل مع مزودات الخدمة السحابية والاستفادة من أنواع الخدمات السحابية المختلفة، ولمزيد من المعلومات يمكنك متابعة العديد من الدروس حول الحوسبة السحابية في أكاديمية حسوب. نظم التحكم بالإصدارات Git تساعد نظم التحكم بالإصدارات المطور في إدارة التغييرات التي يقوم بإجرائها على الشيفرات البرمجية لمشاريعه وتطبيقاته ومن أشهرها نذكر Git وهي عبارة أداة برمجية تمكنك من العودة بسهولة إلى إصدار سابق يعمل بشكل صحيح من مشروعك في حال حدث خطأ ما بدلاً من البحث عن سبب الخطأ ومحاولة التراجع عنه يدويًا، كما أنه يفيد المطور بشكل كبير عند العمل على مشروع مشترك مع فريق عمل فهو ينظم التعديلات المختلفة ويمنع تضاربها. والجدير بالذكر أن التعامل مع أنظمة التحكم بالإصدارات هو ضرورة ولا يستطيع أي مبرمج أو مطور ويب العمل دون خبرة بها وستجد في أكاديمية حسوب مجموعة غنية ومنوعة من المقالات والدروس حول Git التي تساعدك في تعلم التعامل مع نظم التحكم بالإصدارات من الصفر حتى الاحتراف. أدوات إدارة الحزم Package Management System تتضمن معظم التطبيقات اليوم حزمًا ومكتبات خارجية ومن الصعب تطوير التطبيقات اليوم دون الاعتماد على أحد الأدوات البرمجية المساعدة في إدارة هذه الحزم الخارجية وعدم تعارضها، ومن الأمثلة عليها مثل npm الذي يأتي مع Node.js الذي يُستخدم مع لغة جافا سكريبت أو composer المستخدم مع لغة PHP. فمعظم مشاريع الويب اليوم تتضمن الكثير من الحزم التي يعتمد بعضها على بعض وهذه البرمجيات أساسية لمساعدتك في تحديد الحزم اللازمة لمشروعك ويحدد التبعيات المناسبة بنفسه والتأكد من توافقها مع التبعيات الأخرى ويتحكم في إصدارات الحزم التي تقوم بتثبيتها. استخدام الحاويات Containers بالرغم من أن تعلم استخدام الحاويات Containers يعد مهارة إضافية وليس لزامًا عليك كمطور واجهة خلفية إلا أن تعلمها يساعدك في بناء مشاريعك واختبارها ونشرها بكفاءة فالحاويات هي عبارة عن حزم برمجية تتضمن كافة العناصر الضرورية لتشغيل التطبيق في أي بيئة أو نظام تشغيل لكنه يكون معزول ضمن حاوية معزولة منطقيًا عن التطبيقات الأخرى بحيث لا يتعارض معها. يمكنك إنشاء الحاويات وتشغيلها باستخدام تقنية مثل دوكر Dockerوهي تقنية حاوية مفتوحة المصدر تعتمد على نظام لينكس وتسمح للمطورين ببناء وتشغيل التطبيقات واختبارها ونشرها بسهولة، وللاطلاع على مزيد من التفاصيل حول مفهوم الحاويات وأهميتها لمطوري التطبيقات يمكنك مشاهدة الفيديو التالي: الإحاطة بأساسيات لغتي HTML و CSS يحتاج مطور الواجهات الخلفية معرفة الجوانب الأساسية لكل من HTML و CSS اللتان تستخدمان لبناء الواجهات الأمامية فحتى لو لم يستخدمها في عمله فهو يحتاج للتواصل مع مطوري الواجهة الأمامية بشأنها وهي تقنيات سهلة التعلم. من أهم الأساسيات التي ينبغي تعلمها في لغة HTML هي طريقة إنشاء صفحة ويب ثابتة وإنشاء النماذج ومعالجتها وآليات الإدخال المختلفة إضافة إلى معرفة طريقة إنشاء قواعد التنسيق في CSS وكيفية عمل المحددات والفرق بين المعرف id والصنف class. يمكنك معرفة المزيد حول هاتين اللغتين من خلال مطالعة مقال تعلم لغة HTML ومقال أساسيات لغة CSS. خارطة طريق لتعلم تطوير الواجهات الخلفية هل تشعر بالتشتت من كثرة التقنيات التي عليك تعلمها لتصبح مطور واجهة خلفية ولا تعرف من أي واحدة تبدأ وكيف تنظم خطوات التعلم؟ دعني أساعدك وأوضح لك خارطة طريق لتعلم مجال تطوير الواجهات الخلفية والتي تعرض بوضوح طريق مطور الواجهات الخلفية backend في مجال تطوير الويب بالكامل بدءًا من المرحلة الأساسية وحتى المتقدمة وأغلب تلك المواضيع تجد عنها في أكاديمية حسوب وموسوعة حسوب فابحث عنها: أفضل المصادر العربية لتعلم تطوير تطبيقات الواجهة الخلفية إذا كنت تبحث عن مصادر عربية لتعلم تطوير الواجهة الخلفية ستجد العديد منها في أكاديمية حسوب التي تعد أكبر منصة عربية لتعليم البرمجة فهي توفر عدة دورات تدريبية لتطوير التطبيقات منها: دورة تطوير التطبيقات باستخدام لغة JavaScript دورة تطوير تطبيقات الويب باستخدام لغة PHP دورة تطوير التطبيقات باستخدام لغة Python دورة تطوير تطبيقات الويب باستخدام لغة Ruby تتميز كل دورة من هذه الدورات بكونها معدة بعناية من نخبة من المبرمجين في المجال وتتضمن العديد من المسارات التي تبدأ معك من أساسيات اللغة وتعلمك أهم أطر عملها وتنتهي بك في تطوير تطبيقات عملية احترافية تؤهلك للدخول في سوق العمل كما أنك تحصل على متابعة دورية من قبل فريق من المدربين الذين يجيبون على كافة تساؤلاتك بخصوص ما تتعلمه ويوجهونك خلال تطبيق المشاريع، وستحصل في نهاية كل دورة على شهادة معتمدة من أكاديمية حسوب تؤهلك لدخول سوق العمل. كما توفر أكاديمية حسوب مئات المقالات والسلاسل التعلميمة توفر شروحات مميزة لكافة اللغات والأطر والتقنيات التي ذكرناها في سياق مقالنا مثل مقال المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع الذي يرشدك لكل ما يخص تطوير الويب بكافة أقسامه وتخصصاته وغيرها الكثير من المقالات المتقدمة لذا احرص على متابعة دروس الأكاديمية أولًا بأول. وإذا كنت تفضل الدراسة من الكتب لما توفره من تسلسل منهجي في طرح المعلومات ستجد في قسم الكتب في أكاديمية حسوب العديد من الكتب القيمة المتخصصة بشرح لغات البرمجة وقواعد البيانات وتقنيات تطوير الويب وغيرها من العناوين المهمة والمفيدة لأي مطور. أسئلة شائعة حول تطوير الواجهات الخلفية في بداية مشوارك في تطوير الواجهة الخلفية قد تدور بذهنك عدة تساؤلات حول هذا التخصص ومدى صعوبته وملائمته لك وإليك أبرز هذه التساؤلات والإجابات عليها 1. هل يمكن أن أتعلم تطوير الواجهة الخلفية بنفسي؟ نعم بكل تأكيد فتطوير الويب عمومًا وتطوير الواجهة الخلفية خصوصًا لا تتطلب منك الحصول على شهادة جامعية لتمارسها بل يمكنك تعلمها ذاتيًا واكتساب كافة المهارات اللازمة لتطوير مواقع وتطبيقات الويب بنفسك ولحسن الحظ موارد التعلم كثيرة ومتاحة ويمكنك الاعتماد عليها للتعلم الذاتي. وتذكر أن مفتاح نجاحك كمطور واجهة خلفية ليس مرتبطًا بالشهادات بقدر ما يعتمد على اكتساب المهارات المناسبة التي تمكنك من دخول سوق العمل وتطوير مشاريع تعكس تمكنك من هذه التقنيات والمهارات وتعزز فرصتك في العثور على العمل الذي يحقق طموحك. 2. هل وظيفة تطوير الواجهات الخلفية مناسبة لي؟ بالرغم من أن المهارات التقنية هي أول ما ينظر له عند توظيف مطور واجهات خلفية لكن هذا ليس كل شيء فكي تصبح مطور واجهة خلفية محترف يجب أن تمتلك بعض الصفات الأخرى مثل المهارات التحليلية والقدرة على حل المشكلات إلى جانب مهارات التواصل لاسيما عندما تعمل ضمن فريق عمل يضم عدة مطورين، كما يجب أن تمتلك حس الفضول والرغبة في تعلم كل جيد فكل يوم هناك إصدارات وأدوات وإضافات جديدة وعليك بذل الوقت والجهد لتعلمها، لذا تأكد من أنك شخص يمتلك هذه الصفات ولا تركز فقط على الجوانب الفنية وقرر بناء على ذلك إن كان العمل كمطور واجهات خلفية يناسبك أم لا. 3. هل يجب علي تعلم كل التقنيات الواردة في هذا المقال لأبدأ العمل كمطور واجهة خلفية؟ لحسن الحظ لا يلزمك تعلم كل هذه التقنيات لتبدأ تطوير الويب الخلفي فإذا امتلكت المهارات الأساسية بإحدى لغات الواجهة الخلفية وتعلمت إطار عمل واحد على الأقل وأتيحت لك فرصة عمل على مستوى المبتدئين لا تتردد واقبلها فورًا، سيطلب منك حينها البدء بمشاريع عملية صغيرة تناسب مهاراتك وبعدها ستتاح لك الفرصة لتوسيع مجموعة المهارات الخاصة بك وتعلم لغات وأدوات برمجة جديدة ومن جديد أؤكد لك بأن الخبرة العملية هي أكثر ما يساعدك على التطور. 4. ما هو الوقت اللازم لتعلم تطوير الواجهات الخلفية Backend؟ لا شك أن تعلم تطوير الواجهة الخلفية يتطلب معرفة ترسانة مختلفة من لغات البرمجة ومهاراتها وهذا يتطلب بلا شك بعض الوقت والالتزام لكن رغم ذلك تعتمد المدة اللازمة لتعلم تطوير الواجهة الخلفية على عدة عوامل أهمها مدى قابليتك وسرعتك في التعلم وكفاءة المصادر التي تتعلم منها ومدى التزامك بخطة منهجية وعدد الساعات التي تقضيهًا يوميًا في للتعلم. ولا شك أن المعرفة المسبقة بعلوم الحاسوب وأساسيات الشبكات وكنت على دراية بإحدى لغات البرمجة وكتابة الشيفرات البرمجية فهذا يختصر عليك زمن التعلم بشكل كبير، ويمكن القول أن فترة التعلم تتراوح وسطيًا بين 6 أشهر إلى عام لتصبح جاهزًا لدخول سوق العمل في حال اتبعت كل الخطوات والنصائح التي أوردناها في سياق المقال بعدها يمكن أن تتابع تطوير نفسك بشكل تدريجي وتصبح خبيرًا في المجال. 5. ما مدى صعوبة تعلم تطوير الواجهة الخلفية للويب؟ ستشعر بالطبع ببعض الصعوبات عند تعلم تطوير الواجهات الخلفية لأول مرة وستواجه الكثير من التحديات والعثرات خلال رحلة التعلم، لكن بقليل من المثابرة والاستعانة بمصادر تعلم مناسبة وفعالة يمكنك تجاوزها بسهولة وتذكر أنك تستثمر في مجال وظيفي مربح ومضمون لذا يستحق الأمر بذل الجهد. 6. أيهما أصعب تطوير الواجهة الخلفية أم الأمامية؟ برأيي الشخصي يعتمد الجواب على هذا السؤال على طبيعة الشخص وميوله فالبعض يرى أن تطوير الواجهة الخلفية هو الأصعب لكونه يتطلب تعلم تقنيات برمجية أكثر ويستلزم تعلم التعامل مع قواعد البيانات والخوادم والشبكات وضمان أمان التطبيقات كما أنه يتطلب امتلاك عدة مهارات شخصية أهمها التفكير المنطقي والتحليلي التي عليك تطويرها إلى جانب تطوير مهاراتك الفنية لتنجح في سوق العمل. بالمقابل يمكن أن يرى بعض الأشخاص أن تطوير الواجهات الأمامية هو الأصعب لكونه لا يخضع لقواعد ثابتة ويحتاج للاهتمام بالكثير من الجوانب المرئية مثل تجاوب التصميم مع كافة أنواع الأجهزة وأحجام الشاشات وفهم الاختلافات بين المتصفحات واختبار توافق التصاميم عليها ومراعاة تجربة المستخدم ولا ننسى الجانب الإبداعي والذوق في التصميم الإبداعي الذي قد لا يتوفر لدى جميع الأشخاص. ولمساعدتك في هذا الشأن أنصحك بالاطلاع على مقال دليلك الشامل إلى تطوير الواجهات الأمامية لتتعرف على كل ما يخص هذا المجال وتقرر بنفسك أين تبدو الأمور أسهل بالنسبة لك. الخلاصة تعرفنا في مقال اليوم على مجال تطوير الوجهة الخلفية للويب الذي يعنى بتطوير أجزاء تطبيقات ومواقع الويب التي تعمل من جهة الخادم وتعرفنا على أهم الفروقات بين تطوير الواجهة الأمامية الخلفية، وأبرز التقنيات واللغات والأطر المستخدمة في برمجة الواجهة الخلفية وتحقيق وظائف التطبيقات والمواقع الإلكترونية بكفاءة وأهم الخطوات والمصادر التي تساعدك على تعلمها بسهولة وكفاءة. وفي ختام مقالنا جاوبنا على أبرز الأسئلة التي قد تتبادر لذهن أي مبتدئ يرغب بتعلم تطوير الواجهات الخلفية، وفي حال كان لديك سؤال آخر لم نجب عليه في سياق المقال يمكنك تركه في قسم التعليقات أسفل المقال. اقرأ أيضًا المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع برمجة مواقع الويب: دليلك المختصر مدخل إلى تطوير البرمجيات Software Development ما هي صفحات الويب
  5. يتضمن مجال تطوير الويب قسمين أساسين هما تطوير الواجهة الأمامية front-end (فرونت إند) وتطوير الواجهة الخلفية back-end (باك إند) وهما من المجالات الرائدة اليوم فجميع النشاطات التجارية والأشخاص يسعون للتواجد على شبكة الإنترنت ويحتاجون لمطوري ويب لإنشاء مدونات أو مواقع أو تطبيقات أو متاجر إلكترونية خاصة بهم. سنخصص مقال اليوم للحديث عن تطوير الواجهة الأمامية ونوضح كافة المفاهيم المرتبطة وكافة الخطوات والتقنيات التي تحتاجها لتتعلم كي تصبح مطور واجهات محترف فإذا كنت مهتمًا بهذا المجال لكنك لا تملك أدنى فكرة عن كتابة الشيفرات البرمجية أو إنشاء صفحات الويب ولا تعرف من أين تبدأ أنصحك بأن تقرأ المقال للنهاية. ما هو تطوير الواجهة الأمامية Front End Web Development؟ قبل أن نشرح تطوير الواجهة الأمامية front-end تحتاج لأن تعرف مراحل بناء أي موقع إلكتروني، فإنشاء أي موقع أو تطبيق يبدأ بتحديد فكرته وتوثيقها، بعدها ترسل هذه الفكرة إلى مصمم الواجهات الأمامية الذي يرسم واجهات الموقع وصفحاته كلها بمختلف تفاصيلها وحالتها، حيث تُراجع هذه الواجهات ثم ترسل إلى مطور الواجهات لتكويدها وبرمجتها وهنا تقسم العملية إلى برمجة واجهات أمامية وخلفية وتبرمج كل واجهة وتتفاعل الواجهتان مع بعضهما للحصول على المواقع المتكامل. فمطور الواجهة الأمامية front end web developer أو ما يعرف بمطور واجهات المستخدم user interface developer هو المبرمج المسؤول عن إنشاء كافة الأجزاء المرئية التي يراها المستخدم ويتفاعل معها عند زيارة مواقع وتطبيقات الويب وبرمجة كافة الواجهات ومكوناتها من أزرار وقوائم ونصوص ورسومات وصور ونماذج وغيرها وتحديد كيف سيبدو كل جزء من موقع الويب وكيف سيتفاعل المستخدم معه. الفرق بين تطوير الواجهة الأمامية front-end وتطوير الواجهة الخلفية back-end والتطوير الكامل Fullstack من الضروري أن تفهم أبرز الفروقات بين تطوير الواجهة الأمامية وتطوير الواجهة الخلفية والتطوير الكامل والتي تعكس في واقع الأمر تخصصات تطوير الويب أو بمعنى آخر الدور الذي يساهم به مطور الويب عند بناء المواقع والتطبيقات والتقنيات التي يستخدمها لأداء عمله، كما أنها تعبر عن مكان تشغيل الشيفرات البرمجية لهذه المواقع والتطبيقات. بدايةً يجب أن تعرف أن عرض موقع الويب على جهازك يتم دومًا في لغة HTML وهي لغة توصيفية يستخدمها مطورو الويب لإنشاء وعرض الصفحات، هناك عدة تقنيات يمكنك إنشاء المواقع من خلالها لكن مهما كانت التقنية المستخدمة فإن عرض الموقع لديك في نهاية المطاف سيكون بلغة HTML. الآن يمكن أن تحدث عملية عرض ملفات المواقع مباشرة على جهازك كما في حال المواقع البسيطة ذات المحتوى الثابت فهي تخزن على خادم الويب بالأساس بشكل ملفات HTML وترسل لك هذه الملفات مباشرة عند طلبها وتعرض لك كما هي على متصفحك. من ناحية أخرى قد تتطلب عملية عرض المواقع بعض المعالجة المسبقة التي تحدث على جانب خادم الويب أو يسمى الخادم البعيد مثل مواقع الويب الديناميكية التي لا تعرض نفس المحتوى لجميع المستخدمين وتتغير بناء على إدخالات المستخدم، فعندما ترسل طلبًا لعرض صفحة ما من موقع ديناميكي يقوم الخادم بمعالجة طلبك هذا وبعد الانتهاء ويجلب لك البيانات المطلوبة والعرض الأخير على جهازك يكون بشيفرة HTML. كل ما يتعلق بأمور عرض الموقع من جانب متصفح الويب أو يسمى طرف العميل client side يندرج تحت مجال تطوير الواجهة الأمامية للموقع، وكل ما يتعلق بأمور معالجة الموقع من طرف خادم الويب من معالجة البيانات وتخزينها وحفظها وإجراء عمليات عليها وغيرها يندرج تحت مجال تطوير الوجهة الخلفية للموقع ولكل منهما تقنياته وأدواته، على سبيل المثال عندما تسجل في موقع يطلب تاريخ ميلادك، تراه يعرضها لك أحيانًا بشكل عمر أي عدد وليس تاريخ، هذه المعالجة تُرسل عادة من طرف الخادم. ليس لزامًا عليك كمطور ويب تعلم تطوير الواجهة الأمامية أو الخلفية معًا بل يمكنك التخصص في إحداهما فقط، فإذا كنت تحب تنفيذ الجوانب المرئية لواجهات المستخدم وجعلها تعمل وفق التصميم المقترح سيناسبك تطوير الواجهة الأمامية أكثر، وإذا كنت تفضل حل المشاكل المنطقية والتعامل مع قواعد البيانات وواجهات برمجة التطبيقات والخوادم والخدمات السحابية فإن تطوير الواجهة الخلفية يناسبك. أما إذا كنت متحمسًا للقيام بكل ما سبق وكانت لديك القدرة لتعلم كافة التقنيات والمهارات اللازمة لتطوير الواجهة الأمامية وتطوير الواجهة الخلفية والقيام بالأمرين معًا عندها سيطلق عليك اسم المطور الكامل fullstack developer وستفتح أمامك الكثير من الفرص المجزية. وإذا كنت مهتمًا بمعرفة مزيد من التفاصيل حول مجالات تطوير الويب أنصح بمطالعة مقال المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع ومقال دليلك الشامل إلى تطوير الواجهة الخلفية Backend. أهمية تطوير الواجهة الأمامية في سوق العمل إذا كنت مهتمًا بتطوير الويب فدعني أخبرك أن تبدأ به دون تردد فهو واحد من أكثر مجالات العمل نموًا مقارنة بباقي الوظائف فبحسب استبيان عام 2022 لموقع ستاك أوفر فلو الشهير الذي يضم آلاف خبراء البرمجة حول العالم فإن 25.96% من المشاركين في الاستبيان وعددهم 61,302 متخصصون في تطوير الواجهة الأمامية front-end، ويحتل هذا المجال المرتبة الثالثة بين أنواع المطورين بعد تطوير الواجهة الخلفية back-end والتطوير الكامل full-stack وهذا إن دلَّ على شيء فإنما يدل على مدى أهمية هذا المجال والطلب المرتفع عليه. أضف إلى ذلك فإن رواتب مطوري الواجهة الأمامية مرتفعة ومجزية ورغم كونها تتفاوت وتختلف حسب نوع الشركة ومقرها والمهارات المطلوبة للوظيفة ومستوى الخبرة إلا أن اكتسابك لمهارات عالية واحترافك لتطوير الواجهة الأمامية سيضمن لك الحصول على رواتب مرتفعة جدًا فمعظم جهات العمل تبحث عن مطور واجهة أمامية موهوب يمكنه إنشاء مواقع بتصاميم فريدة وبتجربة محسنة من شأنها زيادة رضا العملاء وجعل المواقع تتفوق على منافسيها. الجدير بالذكر أن أصعب جزء في مجال تطوير الواجهة الأمامية هو أنه متجدد باستمرار لذا يحتاج المطور للاطلاع بصورة دائمة على أحدث التقنيات في تطوير الويب ليتمكن من الاحتفاظ بالصدارة في سوق العمل لكنه مجال مجزٍ ويستحق الجهد. ما هي مهام مطور الواجهة الأمامية؟ مطور الواجهات الأمامية هو المسؤول بشكل عام عن إنشاء أجزاء المواقع والتطبيقات التي تعمل من جانب العميل (أو المتصفح)، وهذه المهمة تتضمن القيام بالعديد من المهام والتي تشمل: كتابة شيفرات HTML و CSS وجافا سكريبت لتنفيذ تصميم الموقع التي تكون عادة بشكل صور مصممة من قبل مصمم الواجهات الأمامية المسؤول عن تصميم واجهة المستخدم وتجربة المستخدم UI / UX بواسطة برامج متخصصة مثل فيجما Figma أو Sketch أو فوتوشوب. التواصل مع مطور الواجهة الخلفية المسؤول عن تحقيق وظائف الموقع والتأكد من توافق الواجهة الأمامية مع الواجهة الخلفية للموقع. تحسين أداء موقع الويب والتأكد من سرعة تحميله وتوفر تجربة مستخدم سهلة ومحسنة. التأكد من أن الموقع متوافق مع كافة متصفحات الويب ويعمل بالشكل الصحيح ومعالجة أي مشاكل توافق إن وجدت. التأكد من كون الموقع متجاوب ومتكيف مع كافة أحجام الشاشات بما في ذلك شاشات الهواتف الجوالة والأجهزة اللوحية وأجهزة الحاسوب. أهم أدوات تطوير الواجهة الأمامية إذا قررت التخصص في تطوير الواجهات الأمامية للويب ستجد الكثير من الخيارات المتاحة، فاللغات الثلاث الأساسية لأي مطور واجهة أمامية هي HTML و CSS وجافا سكريبت كما يمكنه إلى جانب ذلك استخدام العديد من اللغات وأطر العمل والمكتبات الأخرى الكثيرة التي تسهل عمله في تطوير الواجهات وفي الفقرات التالية سنسلط الضوء على أبرز هذه الأدوات. أهم لغات برمجة الواجهة الأمامية HTML CSS جافا سكريبت JavaScript تايب سكريبت TypeScript لنتناول بتفصيل أكثر كل لغة من هذه اللغات ودورها في تطوير الواجهات الأمامية للمواقع والتطبيقات. لغة HTML لغة HTML هي اختصار لعبارة HyperText Markup Language أي لغة ترميز النص التشعبي وهي اللغة الأساسية لتطوير الواجهة الأمامية للمواقع والتطبيقات وهي لغة وصفية أو لغة ترميز تصف البنية العامة لصفحات الويب ومحتوياتها من نصوص وأزرار وصور وقوائم باستخدام الوسوم وهي علامات موضوعة ضمن قوسي زاوية <> تحدد نوع المحتوى أو هيكليته على سبيل المثال لإنشاء صفحة ويب تتضمن عنوان وصورة ونص نكتب كود HTML التالي: <!DOCTYPE html> <html dir="rtl"> <head> <title>عنوان الصفحة</title> </head> <body> <h1>عنوان الصفحة</h1> <img id="myImage" src="html.png"> <p> HTML هي اختصار لـHyperText Markup Language أي لغة ترميز النص التشعبي وهي الأساسية لتطوير الواجهة الأمامية للمواقع والتطبيقات </p> </body> </html> احفظ الكود أعلاه في ملف نصي باسم index.html وقم بعرضه في متصفح الويب، عندها ستظهر الصفحة بالشكل التالي: للمزيد من المعلومات أنصح بمطالعة مقال تعلم لغة HTML الذي يشرح لك كافة الأساسيات التي تحتاجها للعمل مع هذه اللغة والاطلاع على توثيق HTML الشامل على موسوعة حسوب. لغة CSS لغة CSS هي اختصار لـ Cascading Style Sheets وهي لغة تصميم تستخدم لتحديد تنسيق صفحة الويب واختيار الألوان والخطوط والخلفيات وما إلى ذلك كما أنها تستخدم في جعل مواقع الويب متجاوبة مع مختلف الشاشات من خلال كتابة شيفرات تغير تنسيق وتخطيط العناصر بحسب أبعاد الشاشة. تستخدم لغة CSS قواعد تنسيق تستهدف عناصر HTML التي نريد تصميمها على سبيل المثال سنكتب التعليمات التالية لتنسيق صفحة الويب التي أنشأناها باستخدام HTML نكتب شيفرات CSS التالية ضمن الوسم <head>: <style> body { font-family: 'Cairo', sans-serif; background-color: #f2f2f2; margin: 0; padding: 0; } h1 { font-size: 36px; color: #333; text-align: center; margin: 50px 0; } img { display: block; margin: 0 auto; max-width: 100%; height: auto; } p { font-size: 18px; color: #666; text-align: center; margin: 50px; line-height: 1.5; } </style> تظهر الصفحة بعد إضافة التنسيقات كما يلي: وللمزيد من المعلومات يمكنك مطالعة سلسلة دروس CSS على أكاديمية حسوب إلى جانب توثيق CSS الشامل على موسوعة حسوب. لغة جافا سكريبت JavaScript بعد أن تقوم بتخطيط عناصر الواجهة الأمامية باستخدام HTML وتنسقها باستخدام CSS قد تحتاج إلى إضافة بعض التفاعلات إلى صفحاتك وهنا يأتي دور لغة جافا سكريبت JavaScript التي تعد واحدة من أشهر لغات البرمجة وأكثرها استخدامًا فهي تمكنك من تطوير كل من الواجهة الأمامية والخلفية. قد يكون تعلم جافا سكريبت هو الخطوة الأصعب لك كمطور واجهة أمامية لا سيما إن لم تكن تملك خبرة سابقة في البرمجة لكن بمجرد تعلمها ستتمكن من نقل الموقع إلى مستوى جديد وإضافة التأثيرات الديناميكية لصفحاته والاستجابة لتفاعل المستخدمين مع عناصره بدلًا من جعله يعرض معلومات ثابتة فقط. على سبيل المثال يمكنك كتابة شيفرات جافا سكريبت لعرض قائمة منسدلة أو إظهار رسالة منبثقة عند النقر فوق زر ما على الصفحة، أو إرسال طلب للتحقق من اسم المستخدم وكلمة المرور بعد النقر فوق زر تسجيل الدخول أو أي شكل من أشكال التفاعل مع الصفحة من طرف العميل. لنفرض أنك تحتاج لتكبير حجم صور الموقع قليلًا عند مرور مؤشر الفأرة فوقها، لن تتمكن من هذا إذا لم تكن تعرف جافا سكريبت وتدمجها مع HTML و CSS بدايةً عليك إضافة أكواد CSS التالية بعد الأكواد التي كتبتها في الخطوة السابقة: .zoom { transition: transform .2s; /* Add any other styles you want */ } .zoom:hover { transform: scale(1.5); /* Change the scale value to adjust the level of zoom */ } وبعدها عليك أن تضيف أكواد جافا سكريبت التالية قبل الوسم </body> ضمن كود HTML: const image = document.getElementById("myImage"); image.addEventListener("mouseover", function() { image.classList.add("zoom"); }); image.addEventListener("mouseout", function() { image.classList.remove("zoom"); }); تستمع شفرة جافا سكريبت هذه إلى حدث مرور مؤشر الفأرة فوق الصورة وتضيف تنسيق التكبير zoom إليه عند وقوع هذا الحدث. كما أنها تستمع إلى حدث خروج مؤشر الفأرة من عنصر الصورة وتزيل تنسيق التكبير منه عند وقوع هذا الحدث، وعند عرض الصفحة في المتصفح نحصل على التأثير التالي: للمزيد من التفاصيل أنصح بمطالعة مقال تعلم جافا سكريبت من الصفر حتى الاحتراف، كما توفر موسوعة حسوب توثيق لغة جافا سكريبت باللغة العربية يمكنك من خلالها تعلم كافة ما يتعلق بهذه اللغة. لغة TypeScript تعد لغة TypeScript لغة برمجة مفتوحة المصدر طورتها مايكروسوفت عام 2012 لتوفر ميزات إضافية تساعد على تطوير تطبيقات جافا سكريبت فهي تجعل تعليمات جافا سكريبت مفهومة بشكل أكبر وتوفر إمكانية تحديد أنواع المتغيرات كي تقلل من أخطاء الكود، وقد تزايدت شعبيتها بشكل كبير في الآونة الأخيرة لما توفره من ميزات لتحسين جودة التطبيقات وتسريع عملية التطوير . يمكنك مطالعة المزيد من المعلومات حول هذه اللغة وإمكانياتها من خلال مجموعة دروس TypeScript المتوفرة على أكاديمية حسوب أهم أطر عمل تطوير الواجهة الأمامية ظهرت أطر العمل frameworks والمكتبات البرمجية لتسهيل عمل المطور وتسريع عمله، لذا ستحتاج لاستخدامها في سوق العمل بدلًا من كتابة كل شيء بيدك من الصفر، وأطر عمل الواجهات الأمامية كثيرة ومن أبرزها: بوتستراب Bootstrap رياكت React أنغولار Angular فيو Vue جي كويري jQuery دعنا نلقي نظرة على كل تقنية منها ونشرح بمزيد من التفصيل دورها وأهميتها في تطوير الواجهة الأمامية. بوتستراب Bootstrap بوتستراب هو إطار ويب مجاني مفتوح المصدر مخصص للواجهة الأمامية فهو يستخدم لتصميم مواقع وتطبيقات ويب متجاوبة مع كافة أحجام الشاشات وذات مظهر احترافي بسرعة وسهولة فهو يحتوي على قوالب تصميم ومكونات جاهزة مكتوبة بلغة HTML ولغة CSS كما يوفر بالإضافة لذلك ملحقات تصميم مكتوبة بلغة جافا سكريبت. للاطلاع على المزيد من المعلومات يمكنك متابعة المقالات الدروس حول إطار عمل بوتستراب على أكاديمية حسوب إضافة لتوثيق بوتستراب الشامل على موسوعة حسوب. رياكت React رياكت React هي مكتبة جافا سكريبت مفتوحة المصدر طورتها شركة فيسبوك عام 2013 وهي تعد اليوم واحدة من أشهر مكتبات تطوير الواجهة الأمامية التي يمكنك من خلالها إنشاء مكونات قابلة لإعادة الاستخدام وتطوير واجهات مستخدم متجاوبة بسرعة وسهولة. يمكنك مطالعة المزيد حول هذه المكتبة وتعلم طريقة بناء واجهات المواقع والتطبيقات باستخدامها من خلال الدروس والمقالات الاحترافية حول React على أكاديمية حسوب وأيضًا توثيق React على موسوعة حسوب. أنغولار Angular أنغولار Angular هو إطار عمل مفتوح المصدر يعتمد على لغة TypeScript أطلقته شركة جوجل وهو يتميز بقدرته على تطوير تطبيقات ويب متطورة وضخمة وإدارتها بسهولة كبيرة فهو يوفر الكثير من الميزات التي تساعد مطوري الواجهة الأمامية مثل إدارة حالة التطبيق والتحقق من الصحة. كما يمكنك مطالعة المزيد من الدروس والمقالات الاحترافية حول Angular على أكاديمية حسوب لتتعرف على طريقة استخدامها في تطوير مواقع ويب احترافية. فيو Vue فيو Vue هو إطار عمل جافا سكريبت مفتوح المصدر طوره Evan You المبرمج في جوجل عام 2014 لتطوير واجهات المستخدم وتطبيقات الصفحة الواحدة وهو اليوم واحد من أكثر أطر عمل الواجهة الأمامية شيوعًا واستخدامًا. ما يميز إطار فيو Vue أنه مرن وخفيف الوزن وسهل الاستخدام فقد أزال كل المكونات الإضافية والمفاهيم غير الضرورية التي تأتي مع أطر عمل الواجهة الأمامية الأخرى مثل أنغولار Angular ورياكت React. وللمزيد من التفاصيل أنصح بمطالعة مقال مقارنة بين أطر الواجهات الأمامية: Angular و React و Vue لمعرفة الإطار الأنسب لمتطلباتك، كما أنصح بمتابعة الدروس والمقالات حول Vue التي توفرها أكاديمية حسوب بشكل دوري لتعلم المزيد حول استخدامات هذا الإطار. جي كويري jQuery جي كويري jQuery هي مكتبة مبنية بالاعتماد على لغة جافا سكريبت وهي توفر لمطوري الواجهة الأمامية الكثير من القوة والمرونة وتتضمن الكثير من الميزات التي تجعل كتابة شيفرات جافا سكريبت أبسط وأكثر اختصارًا. لمعرفة المزيد حول طريقة استخدام مكتبة jQuery عند تطوير مواقع الويب أنصح بمطالعات مجموعة المقالات والدروس حول jQuery المتوفرة على أكاديمية حسوب، كما أنصح بمطالعة توثيق jQuery على موسوعة حسوب. تقنيات وأدوات مهمة لتطوير الواجهة الأمامية إضافة لما سبق، يحتاج أي مطور واجهة أمامية لقائمة طويلة من المعارف والمهارات والأدوات الإضافية التي تعزز أداءه وتساعده في تطوير واجهات المستخدم وتكويدها بسرعة واحترافية، وإليك قائمة بأبرز هذه الأدوات نذكر: شجرة DOM والتعامل معها. معرفة أساسية بالشبكات وشبكة الإنترنت وأشهر برتوكولات التواصل مثل HTTP. لمحة عن قواعد التصميم وأساسيات تصميم واجهات المستخدم وتجربة المستخدم UX/UI. التصميم المتجاوب responsive design مع كافة أحجام الشاشات. التوافق مع المتصفحات Cross-browser. واجهة برمجة التطبيقات API. لمحة عن Node.js وأنظمة إدارة الحزم تحديدًا npm. نظام التحكم في الإصدارات git. شجرة DOM من الضروري أن يعرف أي مطور واجهة أمامية مهارات التعامل مع نموذج كائن المستند Document Object Model أو اختصارًا DOM أو شجرة DOM ومعالجته عبر لغة جافا سكريبت، و DOM هو مجموعة من المواصفات التي تمثل مستند الويب بشكل كائن وتعد أحد الطرق الأساسية في بناء مواقع تفاعلية حيث أنها تنشئ واجهة برمجة تطبيقات API تسمح للغات البرمجة مثل جافا سكريبت بالوصول لكافة عناصر صفحات الويب ومعالجتها والتحكم بها. ستساعدك معالجة DOM في تحديث بيانات الصفحة أو تغيير تخطيطها دون إعادة الحاجة لإعادة تحميلها على سبيل المثال يمكنك من خلال DOM إضافة عناصر HTML للصفحة أو إزالتها أو تعديل تنسيقات CSS لها عند وقوع حدث ما أو عند إعادة تحميل صفحة الويب. معرفة أساسية بالشبكات يحتاج مطور الواجهة الأمامية لامتلاك معلومات أساسية حول طريقة عمل الويب والشبكات الحاسوبية وشبكة الإنترنت ومفهوم العميل والخادم وكيفية التفاعل بينهما وبروتوكولات الاتصال عبر الويب مثل HTTP و HTTPS و SSL ومفهوم خدمة اسم المجال DNS فهذه المعرفة تمكنه من عرض واستدعاء المحتوى من الشبكة والاتصال مع الخادم بشكل آمن وتوفير تجربة مستخدم أفضل. للاطلاع على مزيد من المعلومات يمكنك مطالعة سلسلة المقالات والدروس حول الشبكات على أكاديمية حسوب. قواعد التصميم وأساسيات UX/UI ذكرنا سابقًا أن مطور الواجهة الأمامية قد يكون مسؤولًا عن تصميم موقع ويب من الصفر أو قد يكون مسؤولًا عن تحويل التصاميم الجاهزة إلى شيفرات برمجية، لكن في كلتا الحالتين أجد أنه من الضروري لأي مطور واجهة أمامية أن يعرف أفضل النصائح والقواعد لتصميم واجهة المستخدم والمبادئ والقواعد الأساسية في تصميم تجربة المستخدم UX وتصميم واجهة المستخدم UI فهذا من شأنه أن يساعده على فهم الواجهات وكيفية تفاعل المستخدمين معها بشكل أفضل وكيفية إنشاء واجهات أكثر جاذبية وسهولة في الاستخدام وبالتالي سيتمكن من كتابة شيفرات الواجهة الأمامية بشكل أفضل ويضمن أنها مطابق للقواعد التصميمة الصحيحة. التصميم المتجاوب مع كافة أحجام الشاشات التصميم المتجاوب Responsive Design هو تصميم يقوم بتغيير حجم عناصر صفحات الموقع أو إخفائها أو تصغيرها أو تكبيرها ليضمن ظهورها بطريقة واضحة وسهلة الاستخدام مهما كان نوع الجهاز المستخدم لعرضها. يحتاج مطور الواجهة الأمامية لمعرفة أساسيات تصميم الويب المتجاوب Responsive Web Design وطرق كتابة استعلامات الوسائط Media Queries في CSS بشكل صحيح كي يضمن ظهور المواقع بكفاءة على جميع أنواع وأحجام الأجهزة التي يستعملهما المستخدمون سواء الحواسيب ذات الشاشات الكبيرة أو الهواتف المحمولة ذات الشاشات الصغيرة. التوافق مع المتصفحات Cross-browser أحد المهارات الضرورية التي يجب على مطور الواجهة الأمامية تعلمها هو التأكد من أن الواجهات التي يبرمجها متوافقة مع مختلف المتصفحات وتظهر بشكل سليم ومتسق على المتصفحات الشهيرة مثل كروم وفايرفوكس وسفاري وEdge وOpera ويتعلم كيف يجري اختبارات التوافق مع المتصفحات cross-browser testing ويعالج أي مشكلات تواجهه في التوافق. يمكنك الاستعانة ببعض الأدوات والتقنيات المساعدة في اختبار توافق المتصفح Cross-browser مثل Markup Validation Service و CrossBrowserTesting و LambdaTest …إلخ. لكن تجدر الإشارة بأن أطر عمل الواجهات الأمامية مثل رياكت React وأنجولار Angular يمكنها أن تقوم بهذه المهمة عنك ولن تجعلك تكترث لها، يكفي أن تحدد لها أي نوع متصفح تريد أن نستهدف وهي تتولى الأمر لأنها تعالج دومًا الشيفرة التي تكتبها. استدعاء واجهة برمجة التطبيقات واجهات برمجة التطبيقات API هي صلة الوصل بين تطبيقات الواجهة الأمامية وبين النظم والوجهات الخلفية وبالرغم من أنك لا تحتاج كمطور واجهة أمامية لمعرفة كيفية كتابة واجهات برمجة التطبيقات لكونها مهمة مطور الواجهة الخلفية لكنك تحتاج لمعرفة طريقة الاتصال بهذه الواجهات وجلب البيانات منها وعرضها بشكل مناسب ومعرفة التقنيات المرتبطة بها مثل RESTful ومفهوم JSON. باختصار، يجري التواصل بين الواجهة الأمامية والواجهة الخلفية عبر واجهة برمجة التطبيقات وعادة ما ترسل البيانات من الواجهة الخلفية إلى الواجهة الأمامية بصيغة JSON لذا من الضروري معرفة هذه الصيغة، ويمكنك الرجوع إلى مقال تعلم JSON. تعلم Node.js وأنظمة إدارة الحزم يحتاج مطور الواجهة الأمامية إلى تعلم أحد أدوات إدارة الحزم Package Manager التي تجعل عملية تطوير الواجهة الأمامية أسرع وأسهل، فأدوات إدارة الحزم هي برمجيات تسمح لك بتثبيت الحزم المطلوبة للتطوير وإعدادها وتحديثها وإدارة تبعياتها وضمان عدم تعارضها بشكل تلقائي بدلًا من القيام بذلك بشكل يدوي ومن أشهرها npm و Yarn. وعادة يستعمل مطور الواجهات الأمامية مكتبة Node.js التي تأتي مع نظام إدارة الحزم الشهير npm والذي سيستعمله في تنزيل حزم المشروع وإدارتها ومكتبة Node.js هي أول أداة سيثبتها المطور على جهازه فبدونها لن يعمل مع لغة جافاسكريبت على الإطلاق، لذا يجب أن يتعرف عليها وعلى مدير الحزم npm. وقد شرحنا في مقال أساسيات إدارة الحزم في تطوير الويب من طرف العميل كل ما يتعلق باستخدام مدير الحزم وكيفية استخدامه في إدارة مشاريع الواجهة الأمامية. نظام التحكم في الإصدارات git يساعد نظام التحكم في الإصدار وأشهرها Git مطور الواجهة الأمامية على تتبع التغييرات التي يجريها على المواقع ويمكنه من العودة إلى إصدار كود سابق بكل سهولة إذا حدث خطأ ما في الكود كما يفيده في حال العمل على نفس المشروع مع فريق تطوير. تتوفر في أكاديمية حسوب مجموعة غنية ومنوعة من المقالات والدروس حول Git التي تساعدك في تعلم كافة المهارات اللازمة للتعامل مع نظام التحكم بالإصدارات Git. كانت هذه التقنيات جزءًا يسيرًا من التقنيات والأدوات التي على مطور الواجهة الأمامية معرفتها، وفي الفقرة التالية سنوضح المزيد من هذه التقنيات ونضع لك خارطة طريق منظمة تساعدك في تعلم تعلم تطوير الواجهة الأمامية. خارطة طريق تعلم تطوير الواجهة الأمامية إليك خارطة طريق لتعلم مجال تطوير الواجهات الأمامية والذي يعرض بوضوح طريق مطور الواجهات الأمامية بالكامل بدءًا من المرحلة المبتدئة وحتى المتقدمة وأغلب تلك المواضيع تجد عنها في أكاديمية حسوب وموسوعة حسوب: أهم مصادر تعلم تطوير الواجهة الأمامية إذا كنت مبتدئًا ولا تملك أي خبرة مسبقة وتبحث عن أقصر طريقة لتعلم تطوير الواجهة الأمامية أنصحك بالاطلاع على دروة تطوير واجهات المستخدم التي توفرها أكاديمية حسوب فهي دورة شاملة ومنظمة تزيد على 60 ساعة فيديو تدريبية ومن مسارات متعددة تبدأ معك من أساسيات تطوير واجهات المستخدم التي تشرح لك كل المفاهيم واللغات الأساسية وأطر ومكتبات العمل وتنتهي بك ببناء مشاريع عملية متقدمة ترسخ كل هذه الأساسيات وتساعدك في بناء معرض أعمالك. لن تكون وحدك خلال هذه الدورة بل سيكون معك فريق من المدربين لمساعدتك وإجابتك على أي تساؤل أو مشكلة تواجهك في رحلة التعلم، وفي نهاية الدورة ستحصل على شهادة معتمدة من أكاديمية حسوب تعزز سيرتك الذاتية. إضافة إلى ذلك توفر أكاديمية حسوب الكثير من مصادر التعلم المجانية باللغة العربية من دروس ومقالات وسلاسل تعلمية حول تطوير الويب تتعلم من خلالها كافة تقنيات ولغات برمجة الواجهات الأمامية وأطر العمل الشهيرة التي أوردناها في سياق المقال. وإن كنت تفضل الدراسة من الكتب بسبب شموليتها وتسلسلها في الشرح فإن الأكاديمية توفر لك مجموعة من الكتب القيمة التي تهم أي مطور واجهة أمامية من بينها: كتاب فهم أعمق لتقنيات HTML5 كتاب ملاحظات للعاملين في CSS كتاب البرمجة بلغة جافا سكريبت كتاب تصميم تجربة المستخدم سلسلة تطوير الويب وأخيرًا إذا كنت ترغب بمعرفة المزيد من المعلومات حول الواجهات الأمامية وأهم تقنيات برمجتها ومسار تعلمها أنصحك بمشاهدة هذا الفيديو. الخلاصة بهذا تكون وصلت إلى نهاية هذه المقالة الشاملة التي تناولنا فيها كل ما يتعلق بأساسيات تطوير الواجهة الأمامية front-end أو ما يعرف بتطوير واجهة المستخدم وتعرفنا على أهم اللغات وأطر العمل والأدوات التي تحتاجها كمطور واجهة أمامية لتنجز الجزء المرئي من الموقع الذي يتفاعل المستخدمون من خلاله مع التطبيقات والمواقع، كما شرحنا في ختامة أهم خطوات تعلم تطوير الواجهة الأمامية ومصادر تعلمها باللغة العربية. وفي حال كان لديك أي سؤال يتعلق بتطوير الويب وتحديدًا تطوير الواجهات الأمامية للويب فلا تتردد في كتابته في قسم التعليقات أسفل المقال، أو طرحه في قسم الأسئلة والأجوبة في أكاديمية حسوب ليجيبك عليه مبرمجون خبراء. اقرأ أيضًا المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع برمجة مواقع الويب: دليلك المختصر ما الفرق بين تصميم المواقع الإلكترونية وتطوير المواقع الإلكترونية؟ عالم الويب ومعاييره ما هي صفحات الويب؟
  6. توفر نماذج البرمجة طرقًا مختلفة لحل المشكلات البرمجية التي يواجهها المطورون بسيطة فبعض النماذج يناسب حل المشكلات البرمجية البسيطة وبعضها الآخؤ يناسب لحل المشكلات المعقدة ومعرفة كل نموذج من هذه النماذج يساعد المبرمج على اعتماد النموذج الأنسب الذي يلبي متطلبات عمله. وكنا قد تحدثنا في المقال السابق على لغة البرمجة الإجرائية وهو واحد من أقدم نماذج البرمجة المتبعة في تطوير البرامج والتطبيقات، ونكمل الحديث في مقال اليوم عن أحد أشهر نماذج البرمجة التي يحتاج أي مطور لمعرفتها وهو نموذج لغة البرمجة بالكائنات أو البرمجة كائنية التوجه OOP ونتعرف على مبادئ عمله وطريقة تنظيم الشيفرات البرمجية من خلاله وأهم لغات البرمجة التي تستخدم هذا النموذج، كما سنشرح بالتفصيل مفهوم الأصناف Classes والكائنات المشتقة منها Objects والفرق بينهما وأهمية تطبيق هذه المفاهيم في تطوير البرامج الحاسوبية المعقدة وتسهيل صيانتها. أنواع لغات البرمجة تصنف لغات البرمجة إلى أنواع مختلفة بناء على عدة معايير ومن بين هذه المعايير تصنيفها وفق المنهجية المتبعة لهيكلة الشيفرات البرمجية، حيث تقسم لغات البرمجة بناء على هذا المعيار إلى عدة أصناف أو نماذج برمجية تحدد الأساليب المستخدمة لتمثيل عناصر البرنامج وخطوات معالجة البيانات وسير التنفيذ. تقسم لغات البرمجة بناء على هذا المعيار إلى عدة نماذج تشمل: نموذج البرمجة الأمرية Imperative Programming: الذي يصف بالتفصيل المدخلات وكيفية الحصول على المخرجات منها ويندرج تحته نموذج البرمجة الإجرائية procedural programming ونموذج البرمجة بالكائنات. نموذج البرمجة التصريحية Declarative Programming: الذي يعبر عن المهام التي يجب أن ينجزها البرنامج دون أن يصف بالتفصيل سير التنفيذ الخاص به ويندرج تحته البرمجة الوظيفية functional programming والبرمجة المنطقية logic programming. يمكنك معرفة المزيد من المعايير التي تصنف لغات البرمجة بناء عليها وأهم خصائص كل نوع منها من خلال مطالعة مقال أنواع لغات البرمجة وسنفرد مقال اليوم لشرح نموذج البرمجة بالكائنات وأشهر لغات البرمجة التي تعتمده ونكتشف أبرز مزاياها وعيوبها. ما هي لغة البرمجة بالكائنات؟ لغة البرمجة بالكائنات أو بتعبير أدق لغة البرمجة كائنية التوجه Object-Oriented Programming -واختصارًا oop- هي أحد أشهر نماذج البرمجة وقد تم ابتكارها منذ الستينيات وهي تعتمد على تنظيم شيفرات البرامج باستخدام مفهوم الأصناف classes والكائنات المشتقة منها objects بشكل مشابه لكائنات العالم الحقيقي. الصنف class هو بمثابة نموذج أو مخطط عام لتمثيل الكائنات حيث تتضمن الأصناف تعريف البيانات التي تصف الكائنات والوظائف الخاصة التي تصف سلوك الكائنات وتعالج بياناتها وهو يستخدم كقالب لاشتقاق العديد من الأمثلة أو الحالات المختلفة من هذه الكائنات objects، ولهذا السبب يسمى الكائن نسخة من الصنف instance. على سبيل المثال يمكن تعريف صنف يمثل السيارة حيث يكون لكل سيارة سمات أو خصائص تصفها تسمى المتغيرات الأعضاء أو حقول البيانات مثل طراز السيارة وسنة تصنيعها ولونها …إلخ ولها وظائف أو دوال تسمى دوال الصنف class functions تحاكي الأفعال أو السلوكيات التي تقوم بها السيارة مثل تشغيل السيارة وإيقافها وتغيير سرعتها وتحريكها لليمين واليسار …إلخ. كما يجب أن يتضمن الصنف دوال أخرى أهمها الدالة البانية constructor وهي الدالة التي تستدعى بشكل تلقائي عند إنشاء أو اشتقاق كائن من الصنف ويمكن من خلالها تمرير قيم تحدد متغيرات الكائن الجديد ودوال لضبط قيم متغيرات الكائن setter وجلبها getter وبعد اكتمال تعريف الصنف يمكننا اشتقاق كائن لكل سيارة جديدة نريد إنشاءها. توفر البرمجة بالكائنات للمطورين طريقة قوية لتنظيم البرامج وهيكلة التعليمات البرمجية بشكل وكائنات متفاعلة فيما بينها لتأدية المهام المطلوبة وتساعدهم على إنشاء تطبيقات قابلة للصيانة والتوسعة وإعادة الاستخدام وتعديل التعليمات البرمجية لتلبية المتطلبات. مثال برمجي على تعريف صنف وإنشاء كائنات منه قد يكون الشرح السابق لمفهوم البرمجة بالكائنات مربكًا وصعب الفهم لذا سنوضح لك المفاهيم بمثال عملي برمجي، لنفرض أنك تحتاج إلى تطوير برنامج لإدارة مكتبة باستخدام لغة البرمجة بايثون، إذا كنت تستخدم نموذج البرمجة كائنية التوجه لتطوير هذا البرنامج فأول ما ستفكر به هو الأصناف التي ستحتاجها. على سبيل المثال ستحتاج لتعريف صنف يمثل الكتاب وليكن اسمه Book ثم ستفكر في الخصائص أو السمات المميزة لكل كتاب مثل العنوان واسم المؤلف وعدد الصفحات …إلخ. ثم ستفكر في الوظائف التي ستطبق على هذا الكتاب وهي استعارة الكتاب وحجز الكتاب وإعادته للمكتبة إضافة لطريقة البناء init التي تستدعى عند إنشاء كائن أو كتاب جديد من الصنف وتهيئ خصائص هذا الكتاب ودوال الضبط والجلب لكل خاصية. سنحقق هذا الوصف برمجيًا من خلال كتابة الكود التالي بلغة بايثون: # تعريف صنف يمثل كتاب class Book(object): # تعريف الدالة البانية للصنف def __init__(self,title, author, pages): self.title = title self.author = author self.pages = pages # دالة ضبط عنوان الكتاب def setTitle(self, title): self.title = title # دالة جلب عنوان الكتاب def getTitle(self): return self.title # دالة ضبط اسم الكاتب def setAuthor(self, author): self.author = author # دالة جلب اسم الكاتب def getAuthor(self): return self.author # دالة ضبط عدد الصفحات def setNumPages(self, numPages): self.numPages = numPages # دالة جلب عدد الصفحات def getNumPages(self): return self.numPages # دالة لطباعة متغيرات الكتاب def printbook(self): print('تم إنشاء الكتاب التالي') print('------------') print('العنوان: ' , self.title) print('الكاتب: ' , self.author) print('عدد الصفحات: ' , self.pages) # دالة لإعارة الكتاب def borrow_book(self): print(f"{self.title} تمت استعارة كتاب") # دالة لإرجاع الكتاب def return_book(self): print(f"{self.title} تمت إعادة كتاب") # دالة لحجز الكتاب def reserve_book(self): print(f"{self.title} تم حجز كتاب") بعد تعريف الصنف يمكننا في أي مكان في البرنامج إنشاء كائنات والتعامل معها بالشكل التالي: # إنشاء كائن أول من صنف الكتاب book1=Book("البرمجة بلغة بايثون", "أكاديمية حسوب", 480) book1.printbook() book1.borrow_book() print('\n') سنحصل على المخرجات التالية بعد تنفيذ الشيفرة: يمكننا إنشاء كتاب آخر بتنفيذ تعليمة واحدة سهلة بسيطة وهكذا: # إنشاء كائن ثاني من صنف الكتاب book2=Book("البرمجة بلغة جافا سكريبت", "أكاديمية حسوب", 450) book2.printbook() book2.reserve_book() سنحصل أيضًا على المخرجات التالية: لاحظ كيف خلصتنا البرمجة بالكائنات الكثير من العمل ومن تكرار الشيفرة وهذه هي أبرز ميزة تتميز فيها البرمجة كائنية التوجه. يمكنك مطالعة المزيد من المعلومات حول إنشاء الأصناف والكائنات في لغة بايثون في مقال مختصر البرمجة كائنية التوجه OOP وتطبيقها في بايثون. مبادئ لغات البرمجة بالكائنات تعتمد لغات البرمجة بالكائنات على أربع مبادئ أساسية تمكن المبرمجين من تنظيم الشيفرات البرمجية وتقلل أخطاءها وتسهل إعادة استخدامها وصيانتها وتوسيعها في تطبيقات مختلفة. تشمل المبادئ الأربعة للبرمجة كائنية التوجه ما يلي: التغليف Encapsulation تجريد البيانات Abstraction الوراثة Inheritance تعدد الأشكال Polymorphism لنتعرف على كل مبدأ من هذه المبادئ بمزيد من التفصيل! 1. التغليف Encapsulation يشير مبدأ التغليف إلى عملية دمج البيانات والطرق ضمن وحدة مستقلة ومعزولة عن الشيفرات البرمجية الأخرى لها خصوصيتها، ففي البرمجة كائنية التوجه يمكن الوصول إلى بيانات الكائن وتعديلها فقط باستخدام وظائف أو دوال الكائن نفسها فقط وهذا يسمح بإخفاء الحالة الداخلية للكائن عن الكود الخارجي ويحد من صلاحية الوصول إلى بيانات ووظائف كل كائن أو تعديلها خارج نطاق الكائن ويمنع إساءة استخدامها ضمن الكود البرمجي ويضمن تنظيم الكود وموثوقيته. 2. تجريد البيانات Abstraction يمكن اعتبار مبدأ التجريد جزءًا من مبدأ التغليف فهو يساعد على تبسيط الأنظمة المعقدة عن طريق التركيز على المنطق العام للبرنامج وإخفاء تفاصيل التنفيذ عن المستخدمين، فالمقصود بتجريد البيانات في البرمجة بالكائنات إنشاء بنى مجردة عالية المستوى تسهل التعامل مع المهام المعقدة حيث يتم تمثيل خصائص الكائن وإخفاء تفاصيل التنفيذ أو العمليات الداخلية التي تجري على هذه الكائنات عن المستخدمين. ففي مثال الكتاب الوارد سابقًا ستهتم فقط كمستخدم بمعرفة مواصفات الكتاب وطرق التعامل معه من إعارة وحجز وإعادة دون أن تهتم للطريقة التي تنفذ فيها هذه الوظائف ما يهمك أن تستخدمها وتعمل بشكل صحيح دون أن تشغل بالك بتفاصيل عملها. 3. الوراثة Inheritance يسمح مبدأ الوراثة بإمكانية نقل السلوك والبيانات من كائن إلى آخر ويمكن المبرمج من إنشاء أصناف جديدة فرعية أو أبناء من أصناف أساسية موجودة تصبح آباء لها بدلًا من إنشاء أصناف جديدة كل مرة حيث يرث الصنف الابن كل المتغيرات (الصفات) والدوال (الوظائف) الخاصة بالصنف الأب ويمكنه إعادة تعريف وتخصيص الأمور الخاصة به وإضافة ميزات جديدة لها حسب الحاجة مما يسهل تعديل التعليمات البرمجية وتوسيعها. يمكن على سبيل المثال إنشاء صنف أب يمثل مركبة متحركة أو وسيلة نقل ويتضمن الأمور العامة المشتركة ثم استخدامه لإنشاء كائنات أخرى مثل الدراجات النارية أو الشاحنات أو الحافلات. كما يمكن اعتبار صنف الكتاب هو الصنف الأب وإنشاء صنف ابن منه يمثل مجلة وصنف آخر يمثل رواية يرث كل منهما خصائص ووظائف الصنف الأب ويضيف لها خصائص ووظائف إضافية خاصة به وهكذا. 4. تعدد الأشكال Polymorphism يشير مبدأ تعدد الأشكال إلى قدرة الكائنات المختلفة على الاستجابة بشكل مختلف عند استدعاء نفس اسم الدالة، بمعنى آخر استخدام نفس الوظيفة بمنطق مختلف حيث يمكن للكائنات المختلفة امتلاك وظائف أو دوال بنفس الاسم ولكنها تستخدم تعليمات مختلفة. يتضح استخدام هذا المبدأ بشكل جلي في الوراثة فعلى سبيل المثال بالعودة لمثال السيارة إذا كانت السيارة وهي الصنف الأب تحتوي على دالة لتشغيل السيارة تنفذ التعليمات بطريقة معينة فيمكن للمبرمج إعادة تعريفها وتنفيذها بشكل مختلف في الصنف الابن الذي يمثل الدراجات النارية ويمكن معرفة الدالة التي يجب تنفيذها وقت تشغيل الكود. باتباع مبادئ التغليف والتجريد والوراثة وتعدد الأشكال يمكن للمطورين إنشاء برامج قوية وإعادة استخدامها عند الحاجة ويسهل صيانتها وتطويرها. عمومًا، إن شعرت أنك لم تفهم هذه المبادئ فهمًا تامًا ولم تتضح لك اتضاحًا جليًا، فلا تقلق يكفي أن تتعرف عليها وعلى اسمها ثم ستفهما عندما تبدأ بالتطبيق والكتابة بلغة كائنية التوجه. ما معنى خاص ومحمي وعام في البرمجة بالكائنات؟ ستصادف في كافة لغات البرمجة بالكائنات مصطلحات عام وخاص ومحمي وإليك وصفًا موجز لكل مفهوم من هذه المفاهيم. خاص private: يمكن استخدام أي متغير (صفة) أو دالة (وظيفة) من النوع خاص ضمن الكود الموجود داخل الكائن فقط. محمي protected: لا يمكن استخدام أي متغير أو دالة محمية إلا من قبل الكائن نفسه ومن أبنائه. عام public: يمكن استخدام أي متغير أو دالة عامة أو تعديلها في أي مكان خارج الكائن. وتجدر الإشارة لضرورة الكشف عن الحد الأدنى من المعلومات المطلوبة خارج الكائن والحفاظ على خصوصيته قدر المستطاع إلا إذا دعت الضرورة البرمجية لغير ذلك. أشهر لغات البرمجة بالكائنات تستخدم البرمجة كائنات التوجه OOP على نطاق واسع وتعتمدها العديد من لغات البرمجة ومن أبرز لغات البرمجة بالكائنات نذكر: بايثون Python: من أشهر لغات البرمجة الكائنية وأكثرها تفضيلًا في الأوساط البرمجية فهي لغة مرنة وسهلة التعلم ومتعددة الأغراض تصلح لكثير من المجالات أبرزها تطوير الويب وعلوم البيانات والذكاء الصناعي وتعلم الآلة وهي توفر العديد من المكتبات المساعدة التي تسهل عمل المطورين. جافا Java: من أقوى لغات البرمجة كائنية التوجه وهي لغة قوية وآمنة وتتميز بكونها مستقلة وتعمل على كافة أنظمة التشغيل وهي من أبرز لغات تطوير تطبيقات أندرويد،لكن يعاب عليها أنها بطيئة وتستهلك الكثير من الذاكرة. روبي Ruby: لغة برمجة قوية تشبه لغة باثيون من ناحية امتلاكها قواعد صياغة بسيطة سهلة التعلم وهي تدعم البرمجة بالكائنات وتوفر الكثير من الأدوات والمكتبات وأطر العمل التي تسهل عمل المطورين وأبرزها روبي أون ريلز Ruby on Rails. C++‎: لغة برمجة قوية تدعم نموذج البرمجة كائنية التوجه وتوفر أداء عالي وإدارة جيدة للذاكرة وتملك مجتمع دعم ضخم وهي تصلح لبرمجة أنظمة التشغيل والتطبيقات المضمنة لكنها لغة صعبة التعلم وأقل مرونة من لغات البرمجة الأخرى. C#‎‎: لغة برمجة عامة الأغراض تدعم البرمجة الكائنية وتتكامل مع نظام التشغيل ويندوز وهي تستخدم بشكل أساسي لتطوير تطبيقات سطح المكتب وتطبيقات الويب وتصميم الألعاب. PHP: لغة برمجة مثالية لبناء تطبيقات الويب من جانب الخادم وهي لغة مفتوحة المصدر وسهلة الاستخدام أضافت ميزات البرمجة كائنية التوجه منذ الإصدار PHP5 وهي توفر الكثير من دعم المكتبات وأطر العمل وتعتمدها معظم نظم إدارة المحتوى الشهيرة مثل ووردبريس ودروبال. تايب سكريبت TypeScript: هي لغة برمجة مفتوحة المصدر تدعم البرمجة كائنية التوجه وقد طورتها شركة مايكروسوفت بالاعتماد على لغة جافا سكريبت JavaScript وهي تستخدم بشكل أساسي لتطوير تطبيقات الويب الكبيرة، أما لغة جافا سكريبت فبالرغم من كونها لغة تعتمد بشكل كبير على الكائنات لكنها لا تدعم كافة مبادئ البرمجة بالكائنات. إيجابيات وسلبيات لغات البرمجة بالكائنات لكل نموذج برمجي مميزاته وعيوبه وفيما يلي نوضح أهم إيجابيات وعيوب لغات البرمجة كائنية التوجه oop. إيجابيات لغات البرمجة بالكائنات يسمح أسلوب البرمجة بالكائنات بنمذجة مشكلات العالم الحقيقي بشكل أبسط بكثير من باقي النماذج البرمجية. تسهل البرمجة بالكائنات إعادة استخدام التعليمات البرمجية الحالية وتوسيعها باستخدام مبدأ الوراثة بدلاً من الاضطرار إلى إعادة كتابة نفس الكود مرارًا وتكرارًا تخفي البرمجة كائنية التوجه تفاصيل التنفيذ عن المستخدمين الخارجيين وتتيح لهم استخدام الأصناف بسهولة دون الكشف عن تفاصيل تنفيذ كل دالة من الدوال. تنظم البرمجة بالكائنات عملية تصميم البرامج من خلال تمثيلها بالاعتماد على كائنات منفصلة تتفاعل مع بعضها البعض ولكل منها خصائصها وسلوكياتها. تسرع البرمجة الكائنية تطوير البرمجيات وتزيد إنتاجيتها من خلال إمكانية إعادة استخدامها في مشاريع لاحقة. تحسن صيانة البرامج لأن الكائنات معزولة عن بعضها ويمكن حل مشكلاتها وتحسينها دون الحاجة إلى تعديل كامل الكود. تحافظ على أمان البيانات وتحميها من أي تعديلات غير مرغوب بها. سلبيات لغات البرمجة بالكائنات لغات البرمجة بالكائنات صعبة التعلم للمبتدئين ويستغرق فهمها والتعرف على طريقة عملها بشكل جيد وقتًا وجهدًا. تسبب البرمجة بالكائنات زيادة في حجم كود البرامج حيث تتضمن البرامج المطورة باستخدام نموذج البرمجة كائنية التوجه عددًا أكبر من التعليمات البرمجية مقارنة بالبرامج المطورة بنموذج البرمجة الإجرائية. تعد البرامج المطورة باستخدام نموذج البرمجة بالكائنات أبطأ من البرامج المطورة باستخدام نماذج البرمجة الأخرى. قد لا تناسب البرمجة بالكائنات جميع أنواع المشاكل البرمجية كالأنظمة البسيطة إلى حد ما التي يفضل حلها باستخدام نموذج البرمجة الإجرائية أو الأنظمة البالغة التعقيد التي تضطر فيها إلى إنشاء الكثير من مستويات الوراثة لتحقيقها ما يجعل الكود مربك وصعب الفهم والتي يناسبها نموذج البرمجة الوظيفية. الخلاصة تعرفنا في مقال اليوم على نموذج البرمجة بالكائنات OOP وشرحنا أهم المفاهيم والمصطلحات المرتبطة به مثل الصنف والكائن ومبادئ التجريد والتغليف والوراثة وتعدد الأشكال وعددنا أهم لغات البرمجة بالكائنات وأبرز سلبيات وإيجابيات هذا النموذج البرمجي، كل ما عليك الآن هو تطبيق هذه المفاهيم بشكل عملي من خلال إحدى لغات البرمجة التي تدعمها كي تتمكن من فهمها واستيعابها بشكل أفضل. اقرأ أيضًا البرمجة كائنية التوجه مختصر البرمجة كائنية التوجه OOP وتطبيقها في بايثون مفهوم الكائنات Objects والبرمجة كائنية التوجه OOP البرمجة كائنية التوجه (Object Oriented Programming) في PHP تعلم أساسيات البرمجة
  7. يحتاج أي مطور محترف للتعرف على أنواع لغات البرمجة المختلفة ومعرفة ميزاتها ومحدوديتها كي يتمكن من استخدام النوع الأنسب عند في كتابة برامجه وتطبيقاته، وفي مقال اليوم سنتعرف على مفهوم لغة البرمجة الإجرائية التي هي أحد أقدم وأبسط نماذج البرمجة ونكتشف استخداماتها وآلية عملها وطريقة كتابة البرامج باستخدامها ونستعرض أهم خصائصها وعيوبها ومميزاتها. أنواع لغات البرمجة تختلف لغات البرمجة وتتفاوت في عدة أوجه ما يجعل علماء البرمجة والمطورين يصنفونها وفق تصنيفات مختلفة وفق السمات أو الخصائص المشتركة فيما بينها. ومن بين المعايير التي يتم اعتمادها لتصنيف أنواع لغات البرمجة هو أسلوب هيكلة الشيفرة وطريقة تنظيم عناصر البرنامج حيث تقسم لغات البرمجة بناء على هذا المعيار إلى ثلاثة أصناف أو نماذج رئيسية هي: لغات البرمجة الإجرائية Procedural Programming لغات البرمجة الوظيفية Functional Programming لغات البرمجة الكائنية Object-Oriented Programming من الضروري لك كمبرمج أن تفهم الفروقات بين هذه النماذج البرمجية واختيار النموذج المناسب لمشروعك، وسنخصص فقراتنا التالية لشرح لغات البرمجة الإجرائية والتي تعد أحد أقدم نماذج البرمجة ونكتشف معًا طريقة عملها وأشهر لغات البرمجة التي تعتمدها وأبرز مزاياها وعيوبها. إذا كنت مهتمًا بمعرفة المزيد من المعايير التي تصنف وفقها لغات البرمجة وأهم مميزات كل نوع يمكنك مطالعة مقال أنواع لغات البرمجة. ما هي البرمجة الإجرائية Procedural Programming؟ البرمجة الإجرائية Procedural Programming هي أحد نماذج البرمجة التي تعتمد بشكل أساسي على إخبار الحاسوب بالمهام التي تريد منه القيام به بدقة وخطوة بخطوة من خلال كتابة إجراءات procedures أو دوال برمجية functions تؤدي كل منها مهمة محددة. سابقًا في بدايات البرمجة كانت البرامج تتألف من إجراء واحد يتكون من سلسلة متتالية من التعليمات البرمجية التي تنفذ بالتسلسل من أعلى الكود إلى أسفله لتؤدي المطلوب وكان هذا يجعل الكود مكررًا وطويلًا جدًا، أما مع أسلوب البرمجة الإجرائية أصبح بإمكان المبرمج تقسيم البرامج الطويلة إلى مجموعة من الإجراءات تحل كل منها مشكلة فرعية منفصلة وإعادة استخدامها عند الحاجة ضمن الإجراء الرئيسي أو ضمن إجراءات أخرى لتحقيق الهدف الكلي للبرنامج. فالإجراءات procedures أو الدوال functions أو ما يعرف أيضًا البرامج الفرعية subroutines أو الوظائف هي عبارة عن كتل من التعليمات البرمجية لها اسم محدد تحصل على المدخلات من المستخدم وتعالجها بطريقة معينة لأداء المهمة المطلوبة ثم تعيد مجموعة من النتائج كمخرجات. وتجدر الإشارة بأنه لا يتم تنفيذ تعليمات الإجراءات مباشرة عند كتابته بل يجب استدعاء الإجراء من خلال كتابة اسمه وتمرير قيم المتغيرات المناسبة له ليتم تنفيذ كتلة تعليماته البرمجية، بعبارة أخرى الإجراء البرمجي هو كتلة من التعليمات المجمعة بشكل وحدة واحدة والتي تؤدي مهمة محددة ويتم استخدامها في البرامج عند الحاجة لتنفيذ هذه المهمة المعينة. تصنف البرمجة الإجرائية كذلك بأنها أحد أنواع البرمجة الأمرية imperative وهي برمجة نعطي فيها الحاسوب مجموعة من الأوامر أو التعليمات أو الخطوات المرتبة لنخبره بشكل مفصل بما يجب عليه القيام به من أجل تحقيق مهمة ما. أمثلة على لغات برمجة إجرائية قد تدعم بعض لغات البرمجة نموذج البرمجة الإجرائية فقط، لكن في الغالب ستجد أن معظم لغات البرمجة تدعم أكثر من نموذج برمجة بذات الوقت للاستفادة من ميزات كل نموذج ومنح المبرمج مزيدًا من المرونة في كتابة برامجه على سبيل المثال تدعم لغة بايثون Python ولغة C++‎ كلًا من نموذج البرمجة الإجرائية والبرمجة كائنية التوجه بذات الوقت. من الأمثلة الشائعة على لغات البرمجة الإجرائية نذكر: سي C: لغة برمجة إجرائية شهيرة تم تطويرها عام 1972 وتستخدم في العديد من المجالات أهمها تطوير نظم التشغيل والتطبيقات المضمنة وألعاب الفيديو. بيسك BASIC: لغة برمجة عالية المستوى تم تطويرها في عام 1964 بهدف جعل البرمجة سهلة التعلم والفهم للمبتدئين وكانت تستخدم لتطوير التطبيقات الإدارية البسيطة والبرامج التعليمية والألعاب. فورتران FORTRAN: من لغات البرمجة الإجرائية الشهيرة وهي أقدم لغة برمجة عالية المستوى طورت في خمسينيات القرن الماضي لتسهيل كتابة البرامج الرياضية والعلمية ولا تزال لليوم في المجالات العلمية والهندسية مثل التنبؤ بالطقس والفيزياء الحاسوبية والتحليل العددي. كوبول COBOL: لغة برمجة إجرائية قديمة عالية المستوى طورت بهدف تقديم لغة برمجة سهلة ومفهومة من قبل المبرمجين وهي لا تزال لليوم تستخدم في عالم الأعمال والمصارف (البنوك). الغول ALGOL: هي لغة برمجة إجرائية تستخدم لتطوير التطبيقات العلمية والهندسية وهي أول لغة برمجة أدخلت مفهوم الكتل البرمجية وسمحت بتداخل الإجراءات والدوال داخل بعضها البعض وتعد لغة مرجعية لتطوير معايير لغات البرمجة الأخرى. آدا Ada: لغة برمجة إجرائية صممت لتكون لغة آمنة وموثوقة للاستخدام في الأنظمة البرمجية المعقدة المستخدمة من قبل المنظمات الحكومية والمؤسسات الأكاديمية فهي تتضمن ميزات مثل الكتابة الصارمة ومعالجة الاستثناءات. باسكال Pascal: لغة برمجة عالية المستوى صممها عالم الحاسوب نيكلاوس ويرث بداية السبعينيات لتوفير لغة برمجة صارمة ومنظمة للمبتدئين في تعلم البرمجة، واستخدمت في البدايات لتطوير برامج معالجة البيانات وتطوير الألعاب وأثرت في تطوير العديد من لغات البرمجة الأخرى مثل دلفي وآدا. مثال عملي لبرنامج مكتوب بأسلوب البرمجة الإجرائية لتفهم البرمجة الإجرائية بشكل أفضل دعني أوضح لك الأمر بمثال عملي، إذا فكرنا بكتابة برنامج بلغة C لحساب المتوسط الحسابي لعلامات طالب ما، يمكن أن نفكر بكتابته مباشرة دون استخدام الإجراءات من خلال تخزين العلامات في مصفوفة ثم نستخدم حلقة for للتكرار خلال عناصر المصفوفة لحساب المتوسط وعرض قيمته ضمن البرنامج الرئيسي كما يلي: #include <stdio.h> int main() { int marks[] = {60, 70, 88, 95, 59}; int size = sizeof(marks) / sizeof(marks[0]); int sum = 0; for (int i = 0; i < size; i++) { sum += marks[i]; } float avg = (float)sum / size; printf("Average: %f", avg); return 0; } الآن لو احتجنا لحساب المتوسط الحسابي لدرجات طالب آخر سنحتاج لتعريف مصفوفة أخرى تتضمن علامات هذا الطالب ونكرر نفس الكود على المصفوفة الثانية ويصبح الكود كالتالي: #include <stdio.h> int main() { int marks1[] = {60, 70, 88, 95, 59}; int size1 = sizeof(marks1) / sizeof(marks1[0]); int sum1 = 0; for (int i = 0; i < size1; i++) { sum1 += marks1[i]; } float avg = (float)sum1 / size1; printf("Average1: %f", avg); int marks2[] = {76, 93, 78, 93, 86}; int size2 = sizeof(marks2) / sizeof(marks2[0]); int sum2 = 0; for (int i = 0; i < size2; i++) { sum2 += marks2[i]; } float avg2 = (float)sum2 / size2; printf("Average2: %f", avg2); return 0; } والآن ماذا لو أردنا حساب متوسط درجات 100 طالب تخيل حجم تكرار الكود الذي سيحصل في البرنامج! لذا سيكون من الأفضل التفكير في تعريف إجراء أو دالة تغلف تعليمات حساب المتوسط ونعيد استخدامها في البرنامج الرئيسي عند الحاجة كما يلي. لكتابة هذا البرنامج سنعرف إجراءً يسمى average()‎ يأخذ مصفوفة الدرجات كوسيط ويحسب هذا الإجراء حجم المصفوفة ومجموع كل العناصر في المصفوفة ويعيد المتوسط بقسمة المجموع على حجم المصفوفة. وفي الدالة main()‎ التي تمثل البرنامج الرئيسي نكتفي بتعريف مصفوفات الدرجات ونمررها كوسطاء للدالة average()‎ لنحصل مباشرة على النتيجة المطلوبة. #include <stdio.h> float average(int arr[]); int main() { int marks1[] = {60, 70, 88, 95, 59}; int marks2[] = {76, 93, 78, 93, 86}; printf("Average1: %f", average(marks1)); printf("Average2: %f", average(marks2)); return 0; } float average(int arr[]) { int size = sizeof(arr) / sizeof(arr[0]); int sum = 0; for (int i = 0; i < size; i++) { sum += arr[i]; } return (float)sum / size; } كما تلاحظ عندما استخدمنا الدوال أو الإجراءات لتحقيق المطلوب تمكنا من تنظيم البرنامج بشكل أفضل واختصرنا حجم الشيفرات البرمجية المكررة وأصبح بإمكاننا إعادة استخدام الإجراءات عدة مرات. خصائص البرمجة الإجرائية يتضمن نموذج البرمجة الإجرائية مجموعة من الخصائص أو الميزات الرئيسية وأبرزها: النمطية الدوال المعرفة مسبقًا تصميم البرنامج من أعلى لأسفل تمرير المعاملات parameters المتغيرات العامة المتغيرات المحلية لنتعرف على المزيد من التفاصيل حول كل خاصية من هذه الخاصيات! 1. النمطية تعني ميزة النمطية تقسيم البرامج المعقدة إلى وحدات أو أجزاء أصغر مستقلة بحيث يسهل حلها. كل قسم يؤدي مهمة محددة ثم يتم تجميعهما لأداء مهمة أكبر، تسمى هذه الوحدات في لغات البرمجة الإجرائية باسم الإجراءات أو الدوال وهي تساعد على تقليل تعقيد الأنظمة بشكل كبير وتجعل الكود أكثر كفاءة. 2. الدوال المعرفة مسبقًا تتضمن كافة لغات البرمجة الإجرائية دوال مضمنة أو معرفة مسبقًا predefined functions لا تضطر المبرمج إلى ترميز كل شيء من البداية حيث تؤدي هذه الدوال المدمجة في اللغة وظائف محددة مثل العمليات الحسابية أو عمليات إدخال أو إخراج البيانات وتُضمَّن في مكتبات قياسية جاهزة يمكن للمبرمج استدعاؤها مباشرة والاستفادة منها. 3. هيكلة البرنامج من أعلى لأسفل عندما تفكر في تطوير برنامج باستخدام إحدى لغات البرمجة الإجرائية تفكر من الأعلى للأسفل أي أنك تقسم البرنامج إلى أجزاء أصغر يتم تنفيذها بطريقة متسلسلة. حيث تفكر بداية في الهدف الأساسي العام للبرنامج ثم تقوم بتقسيمه إلى أجزاء أصغر لتنفيذ هذا الهدف وتكتب كافة الإجراءات أو الدوال المطلوب لتشغيله وتتحكم في تدفق الكود من خلال استدعاء هذه الدوال بالترتيب المناسب. 4. تمرير المعاملات تعتمد البرمجة الإجرائية على ميزة تمرير المعاملات parameter passing إلى الإجراءات أو الدوال والتي تمثل دخل الإجرائية وهي البيانات اللازمة لتنفيذ عمليات الإجرائية ثم إرجاع خرج، أي لكل إجرائية عادةً دخل تعطي بمقابله خرج ما. 5. المتغير المحلي Local Variable المتغير المحلي هو متغير يعرف ضمن كتلة تعليمات الدالة البرمجية ويمكن استخدامه فقط داخل الدالة المعرف فيها. فعند انتهاء تنفيذ الدالة وعودة التحكم إلى البرنامج مرة أخرى لا يمكن استخدام المتغيرات المحلية. 6. المتغير العام Global Variable المتغير العام هو متغير يعرف خارج كتلة تعليمات الدالة البرمجية وبالتالي يمكن استخدامه في أي مكان في البرنامج وفي أي دالة أخرى ضمن البرنامج ويمكن لأي وظيفة في البرنامج قراءته وتغيير قيمته، وتجدر الإشارة لضرورة استخدام المتغيرات العامة بحذر شديد ضمن كودك البرمجي. استخدامات اللغات الإجرائية تعد لغات البرمجة الإجرائية مناسبة للاستخدام في مجال تعليم البرمجة للمبتدئين لكونها تتميز بالوضوح وسهولة الفهم، كما أنها تستخدم لتطوير الأنظمة البرمجية البسيطة غير المعقدة التي لا تحتاج للكثير من المعالجات الفرعية وكتابة إجراءات متداخلة مع بعضها البعض. تناسب لغات البرمجة الإجرائية كذلك تطوير برامج الحسابات وحل كافة أنواع المشكلات العلمية والتقنية الواضحة. مميزات وسلبيات البرمجة الإجرائية يوفر نموذج البرمجة الإجرائية الكثير من المميزات للمبرمجين والمطورين لكنه لا يخلو من بعض العيوب التي قد تجعلهم يفضلون استخدام نماذج برمجة أخرى، وفيما يلي نناقش أهم إيجابيات وسلبيات البرمجة الإجرائية. مميزات البرمجة الإجرائية تتسم لغة البرمجة الإجرائية بالبساطة وسهولة الفهم ولهذا السبب يبدأ معظم من المبرمجين بتعلم إحدى لغات البرمجة الإجرائية وفهم أساسياتها قبل الانتقال لأساليب برمجة أخرى. تعتمد لغة البرمجة الإجرائية على تقسيم الكود إلى أجزاء أصغر مما يسهل على المبرمجين تنظيم العمل ومتابعة سير عمل البرنامج واختبار وتصحيح الأخطاء البرمجية بشكل أسرع. توفر البرمجة الإجرائية ميزة تعريف الإجراء مرة واحدة واستدعائه كلما دعت الحاجة مما يقلل الكثير من تكرار الشيفرات البرمجية ضمن البرنامج. تسهل البرمجة الإجرائية إعادة استخدام الكود في برامج خارجية من خلال حفظ هذه الإجراءات ضمن مكتبات واستيرادها إلى البرامج عند الحاجة. تسهل البرمجة الإجرائية ميزة توزيع المهام على فريق من المبرمجين عند العمل على البرامج الكبيرة حيث يمكن لكل مبرمج تطوير قسم من الإجراءات المطلوبة لإكمال البرامج بشكل أسرع. سلبيات لغة البرمجة الإجرائية في لغة البرمجة الإجرائية لا توجد حماية فعلية أو عزل للبيانات حيث يمكنك تمرير البيانات إلى الإجراءات واستخدامها وتعديلها لذا قد لا تكون أفضل لغة برمجة للتطبيقات التي تتضمن بيانات حساسة. استخدام مفهوم المتغيرات العامة في لغات البرمجة الإجرائية التي يمكن الوصول إليها وتعديلها بواسطة أي جزء من كود البرنامج قد يصعب عملية الصيانة ومعرفة مصدر الخطأ. يمكن للمطورين إعادة استخدام الإجراءات التي يكتبونها في نفس المشروع لكن لا يمكنهم إعادة استخدامها أو الاستفادة منها في مشاريع أخرى. في البرمجة الإجرائية لا يمكن تغيير البيانات بعد إنشائها داخل كود البرنامج ما يعطي بعض القيود في توسيع وتطوير البرامج. تعد لغات البرمجة الإجرائية أبطأ في التنفيذ مقارنة بأنواع لغات البرمجة الأخرى. قد لا تكون البرمجة الإجرائية هي النموذج الأنسب لتطوير برامج معقدة أو متقدمة كتطبيقات التعلم الآلي والذكاء الاصطناعي التي تتضمن الكثير من المعالجات. ما الفرق بين لغة البرمجة الإجرائية ولغة البرمجة كائنية التوجه؟ يقسم البرنامج في البرمجة الإجرائية إلى مجموعة من المتغيرات وهياكل البيانات والإجراءات وتكون هذه الإجراءات هي العناصر الأساسية للبرنامج فهي التي تتعامل مع المتغيرات وهياكل البيانات، بينما في البرمجة بالكائنات أو البرمجة كائنية التوجه OOP فيقسم البرنامج إلى مجموعة من الكائنات تمثل عناصره الرئيسية ويكون لكل كائن منها بياناته الخاصة والإجراءات التي تعالج هذه البيانات. ففي البرمجة الإجرائية تكون الإجراءات أو الدوال مكونات مستقلة قائمة بذاتها في البرنامج، بينما في البرمجة كائنية التوجه تكون الإجراءات جزءًا من بينة الكائنات نفسها وكما ذكرنا سابقًا لا تكون البرمجة الإجرائية هي أفضل لغة للمشاريع الحساسة للبيانات لذا توفر البرمجة بالكائنات نموذجًا أفضل لحماية البيانات ومنع التعديل عليها خارج الكائن. كما أن التحكم في سير تنفيذ كود البرنامج يتم في البرنامج الإجرائية يحدد من خلال ترتيب استدعاء الدوال أو الإجراءات في حين يتم التحكم به في البرمجة كائنية التوجه بالاعتماد على الحلقات والتعليمات الشرطية وعبارات التحكم الأخرى. وفيما يلي جدول مختصر للمقارنة بين البرمجة الإجرائية ولغة البرمجة كائنية التوجه: البرمجة الإجرائية البرمجة كائنية التوجه تركز لغة البرمجة الإجرائية على تنفيذ مجموعة من الخطوات المتسلسلة لحل المشكلة المطلوبة تركز البرمجة كائنية التوجه على البيانات التي يجب استخدامها لحل المشكلة المطلوبة الدوال هي العناصر الأساسية للبرنامج الأصناف والكائنات هي العناصر الأساسية للبرنامج لا تضمن حماية البيانات وأمانها تضمن حماية البيانات بشكل كبير عن طريق إخفاء البيانات الحساسة عن المستخدمين مناسبة للتطبيقات البسيطة عامة الأغراض وأنظمة التشغيل والبرامج المضنمة مناسبة للتطبيقات الكبيرة والمعقدة لا تمكنك من نمذجة مشكلات العالم الحقيقي بفعالية. تمكنك من نمذجة مشكلات العالم الحقيقي بفعالية ومرونة. وللمزيد من المعلومات حول البرمجة كائنية التوجه وأهم مفاهيمها واستخداماتها أنصحك بمطالعة مقال البرمجة كائنية التوجه. الخلاصة تعرفنا في مقال اليوم على كل ما يخص لغة البرمجة الإجرائية التي تعتمد بشكل أساسي على إخبار الحاسوب بما يجب القيام به خطوة بخطوة باستخدام قائمة واضحة ودقيقة من التعليمات المضمنة داخل إجراءات والتي تعامل البيانات والإجراءات ككيانين مختلفين ضمن البرامج الحاسوبية. فإذا كنت تخطط لتعلم البرمجة يمكنك أن تبدأ رحلة تعلمك بإحدى لغات البرمجة الإجرائية وتتعلم كيفية حل المشكلات باستخدامها وتقسيم برامجك إلى إجراءات فرعية واستدعاءها بالشكل المناسب. اقرأ أيضًا دليلك الشامل إلى لغات البرمجة تعلم أساسيات البرمجة قواعد البرمجة ببساطة للمبتدئين
  8. نسلط الضوء في مقال اليوم على فوائد تعلم البرمجة التي تشكل حجر الأساس لكافة التطبيقات والبرمجيات التي نستخدمها يوميًا سواء على أجهزة الحواسيب أو الجوالات أو غيرها من الأجهزة الذكية القابلة للبرمجة، فبدون البرمجة لن تكون كل هذه الأجهزة قادرة على تلبية متطلباتنا. إذا كنت مهتمًا بالتعرف أكثر على ماهية البرمجة والمميزات التي ستحصل عليها عند تعلم البرمجة واكتساب القدرة على كتابة الشيفرات البرمجية وفهمها على الصعيد الشخصي والعمل فتابع قراءة المقال للنهاية. ما هي البرمجة؟ قبل أن نشرح أهمية تعلم البرمجة دعنا نوضح بداية ما هي البرمجة بالتحديد وما هي استخدامات البرمجة ولماذا ينبغي عليك تعلمها؟ يمكنك التفكير في البرمجة على أنها طريقة تمكننا نحن البشر من إرسال التعليمات لأجهزة الحاسوب باستخدام لغة يمكن للحواسيب فهمها تسمى لغة البرمجة، وبعبارة أخرى البرمجة هي وسيلة للتخاطب مع الأجهزة الإلكترونية المختلفة مثل الحواسيب أو الهواتف الذكية أو أي أجهزة قابل للبرمجة وجعلها تحل مشكلة ما أو تنجز مهمة محددة. تتعدد أنواع لغات البرمجة مثل بايثون وجافا سكريبت وجافا و C#‎ وروبي …إلخ. لكن يمكن القول بأن كل هذه اللغات تتشارك نفس المفاهيم فالبرامج الحاسوبية ما هي إلا شيفرات برمجية مكونة من سلسلة مرتبة من الأوامر والتعليمات اللازمة لتأدية مهمة أو حل مشكلة ما، ثم يقرأ الحاسوب هذه التعليمات وينفذها واحدة تلو الأخرى ليعطينا النتائج المطلوبة. يتطلب تعلم البرمجة معرفة أساسية في عدة مواضيع منها الرياضيات والجبر والتفكير المنطقي، كما يحتاج امتلاك قدرة على تحليل المشكلات وفهمها بشكل صحيح وتحويلها إلى خوارزميات ثم البدء ببرمجة هذه الخوارزميات باستخدام لغات البرمجة وهذا يعني أنك قبل أن تتمكن من كتابة الشيفرات البرمجية يجب أن تمتلك تصورًا واضحًا لحل المشكلة بالشكل الصحيح. بناء على ذلك، يعتبر تعلم الخوارزميات أحد الخطوات الأساسية في تعلم البرمجة فإذا لم يكن لديك خوارزمية صحيحة تحقق الهدف المطلوب فلن يكون لديك برنامج صحيح، وتُعرَّف الخوارزمية بأنها تسلسل منطقي يوضح كافة الخطوات اللازمة لحل مشكلة أو مسألة ما وهو مفهوم لا يقتصر استخدامه على البرمجة أو تطوير البرامج بل يمكنك تطبيقه لحل أي مشكلة حياتية تواجهك، ويمكنك مطالعة المزيد حول الخوارزميات وطرق كتابتها في مقال المرجع الشامل إلى تعلم الخوارزميات للمبتدئين. مستقبل البرمجة ازدادت أهمية تعلم البرمجة اليوم أكثر من أي وقت مضى نظرًا للتطور التقني الحاصل في مجال التقنية والبرمجيات والذكاء الاصطناعي فلا يكاد يوجد عمل اليوم لا يتطلب استخدام البرامج الحاسوبية ما جعل البرمجة أحد المهارات الأساسية المطلوبة بكثرة في سوق العمل. أضف إلى ذلك فإن تعلم البرمجة سيحولك من مستهلك للتقنية إلى منتج لها ويكسبك القدرة على التعامل مع الأجهزة والبرمجيات باحترافية ومرونة كما يكسبك القدرة على إنتاج حلول تقنية وبرامج مفيدة لحل المشكلات التي تواجهها ويطور مهاراتك في التفكير. لذلك السبب، نجد أن معظم البلدان اليوم ومن بينها دول عربية قد أدركت فوائد تعلم لغات البرمجة و أدرجتها في المناهج الدراسية بدءًا من المراحل الابتدائية المبكرة لتهيئة الجيل الجديد للمستقبل وتوسيع أفق تفكيرهم ومساعدتهم على مواكبة التطور التقني بسهولة فمن يتعلم البرمجة في سن مبكرة سيفهم التقنية ويتعامل معها بشكل أفضل من أولئك الذين لا يتعلمونها. فوائد تعلم لغات البرمجة إن فوائد تعلم البرمجة كثيرة منها مساعدتك على تأدية الأعمال بكفاءة أكبر وضمان لك مستقبلًا واعدًا كما يقدم لك العديد من الفوائد الأخرى على صعيد العمل والحياة الشخصية. من أهم فوائد تعلم البرمجة: ضمان الحصول على عمل الحصول على رواتب مجزية إمكانية العمل عن بعد محو الأمية الرقمية مواكبة التطور التقني تحسين التفكير والقدرة على حل المشكلات أتمتة الأعمال اليومية وزيادة الإنتاجية تحسين مهارات التواصل اكتساب الصبر والتركيز لنناقش بمزيد من التفصيل كل فائدة من الفوائد الواردة أعلاه! ضمان الحصول على عمل نظرًا للطلب الكبير على المبرمجين بمختلف تخصصاتهم فإن أحد أهم فوائد تعلم البرمجة تحقيق الأمان الوظيفي وضمان العثور على فرصة مناسبة في سوق العمل لذا ابدأ من الآن بتعلم البرمجة كي تضمن العثور على الكثير من الفرص في حياتك المهنية. وحتى لو لم تكن ترغب بالعمل في مجال التقنية وتطوير البرمجيات إلا أن تعلم البرمجة هو مهارة أساسية تفيدك في كل مجال فكل الصناعات اليوم تعتمد على الحواسيب للقيام بالأعمال وترغب بالتأكيد في توظيف شخص يعرف كيفية عمل هذه الحواسيب ويستخدمها باحترافية. الحصول على رواتب مجزية تعد البرمجة من أكثر المهن المربحة التي تضمن لك أجرًا مرتفعًا لا سيما إذا كنت تملك الخبرة والمهارة الكافية ولديك معرض أعمال قوي فالطلب على المطورين والمبرمجين من مختلف التخصصات في تزايد مستمر. وبالرغم من أن رواتب المبرمجين تختلف حسب الموقع الجغرافي وعدد سنوات الخبرة والتخصص البرمجي إلا أن متوسط رواتب المبرمجين بشكل عام يبقى أعلى من متوسط الرواتب لبقية المهن. إمكانية العمل عن بعد أحد فوائد تعلم البرمجة الجلية التي ستجنيها من تعلمها والعمل بها هي حرية اختيار العمل عن بعد من داخل منزلك أو أي مكان هادئ تفضله والتعاقد مع أي عميل حول العالم أو العمل الحر بشكل مستقل خلال أوقات عمل مرنة لا تلزمك بساعات محددة يفرضها عليك صاحب العمل. فإذا كنت ممن يفضل العمل عن بعد على بيئات العمل التقليدية وتجد أن هذا يساهم في زيادة تركيزك وإنتاجيتك ومردودك فقرار تعلم البرمجة لبدء مهنة جديدة هو فرصتك لتحقيق هذا الأمر. محو الأمية الرقمية يمكن القول أن عدم القدرة على كتابة وفهم التعليمات البرمجية في عصرنا الحالي يكافئ عدم القدرة على القراءة والكتابة من سنوات قليلة مضت، فمعظم الوظائف اليوم تتطلب معرفة أساسية بالتعامل مع الحاسوب واستخدام التطبيقات والبرامج المختلفة. فإذا كنت لا تريد أن توصف بالجهل الرقمي أنصحك بأن تبدأ بتعلم البرمجة وتفهم كيفية عمل التطبيقات والبرامج التي تستخدمها في حياتك اليومية وتكون مرنًا ومتكيفًا مع المتطلبات المتغيرة في عالم التقنية سريع التطور. مواكبة التطور التقني من منا اليوم لا يستخدم التقنيات والتطبيقات والأجهزة الذكية! بدءًا من التسوق عبر الإنترنت ودفع الفواتير ووصولًا للسيارات المبرمجة ذاتية القيادة والروبوتات الذكية التي أصبحت تنوب عنا في أداء الأعمال اليومية. فقد أصبح كل شيء حولنا اليوم مزودًا بالتقنيات الحديثة وتعلم البرمجة يكسبنا القدرة على فهم طريقة عمل هذه التقنيات والتآلف معها بسرعة أكبر. تحسين التفكير والقدرة على حل المشكلات فتعلم إحدى لغات البرمجة شبيه بتعلم لغة ثانية ومن شأنه أن يزيد قدرات عقلك ويوسع مداركك، كما أن تعلم البرمجة يجعل تفكيرك أكثر تنظيمًا وإبداعًا ويكسبك مرونة أكبر في التعامل مع أي مشكلة تواجهك وحلها بذكاء، وهذا لا ينطبق على المشكلات التقنية فقط بل ينعكس على كافة مجالات الحياة والعمل. فالبرمجة مهارة تفيد الجميع وليست حكرًا على المبرمجين، وهنا تحضرني مقولة شهيرة لمؤسس شركة آبل ستيف جوبز: أتمتة الأعمال وزيادة الإنتاجية من فوائد تعلم البرمجة إكسابك القدرة على أتمتة الأعمال والمهام اليدوية المتكررة من خلال كتابة أكواد برمجية تنجز لك هذه المهام بسرعة ودون أخطاء وبهذا يمكنك استثمار وقتك وزيادة إنتاجيتك. على سبيل المثال إذا احتجت لتحميل مجموعة كبيرة من الملفات من موقع ما أو احتجت لإعادة تسمية عدة مستندات أو تصنيف رسائل البريد الإلكتروني الخاصة بك في مجلدات مخصصة فكل ما عليك هو كتابة بضعة أسطر من التعليمات البرمجية لإنجاز العمل بدلًا من قضاء ساعات في تأديته بصورة يدوية. تحسين مهارات التواصل تحتاج في مجال العمل البرمجي للتواصل مع أعضاء فريق التطوير أو مع زملاء في العمل من أقسام مختلفة أو ربما مع عملاء مختلفين متواجدين في أي مكان حول العالم إذا كنت تعمل بشكل مستقل وتعلم البرمجة يساعدك على تحسين مهارات التواصل وتوصيل الأفكار المعقدة للآخرين. حتى لو لم تكن تنوي احتراف البرمجة فإن أحد فوائد تعلم البرمجة هو مساعدتك على التواصل مع الموظفين التقنيين في بيئة عملك وفهمهم والنقاش معهم بشكل أفضل. تعلم الصبر والتركيز مهنة البرمجة من أكثر المهن التي تتطلب الهدوء والصبر والتركيز فعند العمل على حل مشكلة برمجية قد تحتاج لقضاء ساعات في كتابة الشيفرات البرمجية وحل الأخطاء وتحسين النتائج حتى تحصل على النتيجة المرجوة. ستجد بعد مدة من ممارسة البرمجة أنك تميل للصبر والهدوء عندما تواجه أي عقبات أو صعوبات في عملك أو حياتك اليومية وهذه مهارة مهمة نحتاجها جميعًا. نصائح لتعلم البرمجة بكفاءة بعد أن تعرفت على فوائد تعلم البرمجة لا بد أنك متحمس الآن لبدء رحلة تعلم البرمجة واحترافها لذا سأختم المقال بجملة من النصائح السريعة التي تساعدك على تعلم البرمجة بسرعة وتجنبك الفشل. البرمجة ليست مجرد كتابة شيفرات برمجية بل هي تعلم طريقة التفكير بطرق مبتكرة وحل المشكلات المعقدة لذا حسّن مبادئ التفكير المنطقي والخوارزمي لديك وجرب حل التحديات والألغاز البرمجية قبل أن تبدأ تعلم إحدى لغات البرمجة. إليك جملة نصائح لتعلم البرمجة بكفاءة: ابدأ بتعلم لغة برمجة سهلة وتناسب المبتدئين مثل بايثون Python أو جافا سكريبت JavaScript أو روبي Ruby كما يمكنك البدء بإحدى لغات البرمجة المرئية المعتمدة على الكتل مثل لغة سكراتش التي تعلمك البرمجة بطريقة ممتعة ومسلية. تعلم أساسيات البرمجة مثل الشروط والحلقات والمتغيرات والدوال وهياكل البيانات data structures وتأكد من إتقانها قبل الانتقال لمواضيع أكثر تقدمًا. ستجد الكثير من مصادر التعلم المتنوعة عبر الإنترنت، وهذا أمر رائع لكنه قد يشتتك لذا احرص على اتباع مصدر محدد وموثوق والتزم بالتعلم منه وفي حال واجهت صعوبة في فهم أمر ما يمكنك البحث عن مصادر إضافية. احرص على التطبيق العملي وممارسة كل ما تتعلمه فالاكتفاء بالمعلومات النظرية ومشاهدة الدروس ومقاطع الفيديو لن يساعدك على تعلم البرمجة بطريقة احترافية. لا تتوقف عن التعلم وتطوير مهاراتك والاطلاع على أحدث الأدوات والتقنيات واستخدامها في مشاريعك البرمجية. الخلاصة البرمجة كنز ثمين لمن يتعلمها ومهارة قوية تضمن مستقبلك وتهيئك لمواكية التطورات التقنية المتسارعة والنجاح في مجالات العمل المختلفة، ونأمل أن يكون هذا المقال قد ساعدك في التعرف على أهم فوائد تعلم البرمجة والمميزات التي ستعود عليك إذا احترفتها. ابدأ من الآن خطوتك الأولى لتعلم البرمجة فقد تكون أنت من سيطور برامج رائعة تخدم البشرية! اقرأ أيضًا مدخل إلى الخوارزميات أسهل لغات البرمجة أهمية البرمجة وأهم لغات البرمجة المرجع الشامل إلى تعلم لغة بايثون
  9. تنمو مجالات علوم الحاسب وهندسة البرمجيات أسرع من بقية مجالات العمل الأخرى، وتوفر للراغبين بدخوله مجموعة واسعة من الفرص والوظائف، فمعظم الصناعات اليوم تحتاج إلى مهندسي البرمجيات لتسيير أعمالها الرقمية. لذا سنشرح في مقال اليوم مجال هندسة البرمجيات الذي يعد أحد أهم التخصصات المطلوبة اليوم، ونوضح فرص العمل التي يمكن لمهندس البرمجيات التخصص بها، ونوفر مجموعة من النصائح الضرورية لتعلم هندسة البرمجيات بأقصر الطرق دون الحاجة لوجود أي خبرة تقنية مسبقة أو سلوك المسار الجامعي الطويل، ونختم المقال بأهم الميزات والتحديات المرتبطة بهذا التخصص لتكتشف بنفسك هل هذا المسار الوظيفي مناسب لك أم لا؟ ما هي هندسة البرمجيات؟ هندسة البرمجيات Software Engineering هي تخصص يهتم بتطبيق المبادئ الهندسية في تصميم البرمجيات وتطويرها وتنفيذها، وكما تلاحظ تتكون هندسة البرمجيات من كلمتين هما البرمجيات والهندسة ولتبسيط الأمور يمكنك القول أن هندسة البرمجيات هي العلم الذي يمكنك من تطبيق مفاهيم الهندسة على البرمجة. فإذا كانت البرمجة هي التي تمكنك من تطوير البرامج وكتابة شيفرات قابلة للتنفيذ، فالهندسة هي التي توفر لك تقنيات وآليات تساعدك في تنظيم عملك البرمجي بأفضل طريقة ممكنة وتضمن لك الجودة في كل مرحلة من مراحل إنتاج البرمجيات بدءًا من تحليل متطلبات البرنامج مرورًا بكتابة أكواده البرمجية وانتهاءً بصيانته وتحسينه. ومن خلال الجمع بين البرمجة وبين مبادئ الهندسة ستتمكن من إنشاء برامج وأنظمة ضخمة واحترافية قادرة على حل جميع أنواع المشكلات التي تواجه المستخدمين والشركات وتلبية متطلباتهم مهما كانت كبيرة ومعقدة. ما أهمية تخصص هندسة البرمجيات؟ برزت الحاجة إلى هندسة البرمجيات نتيجة لزيادة الطلب على البرامج والتغييرات الكبيرة في متطلبات المستخدمين والبيئات البرمجية فكان لا بد من إيجاد حل يسهّل عملية بناء هذه البرامج الضخمة واعتماد مبادئ هندسية تجعل عملية تطوير البرمجيات أسرع وأقل تكلفة وأسهل في التطوير وإجراء التحسينات. ولتوضيح الأمر بشكل أبسط لنفترض أنك تريد بناء منزل صغير وبسيط وطلبت من مقاول القيام بذلك، قد يبني لك المقاول المنزل المطلوب بنفسه بناء على خبرته العملية السابقة دون اتباع أي طرق علمية، لكن بالطبع لن يكون المنزل الذي ستحصل عليه بنفس جودة المنزل في حال بناه مهندس محترف، وقد يرتكب المقاول بعض الأخطاء البسيطة التي قد لا تنتبه لها بسبب صغر مساحة البيت وقلة حجم المتطلبات. الآن ماذا لو طلبت من نفس المقاول تشييد مبنى من 10 طوابق! بالطبع لن يتمكن من تلبية طلبك وقد يجازف ويوافق على طلبك وهنا ستكون الكارثة وسيفشل المشروع بعد فترة وجيزة، وقد ينهار المبنى قبل اكتماله بسبب جهل المقاول بالقواعد الأساسية التي تطبق لإنجاز البناء والنظريات المتعلقة بمقاومة المواد المطلوبة للبناء وسيتأخر إنجاز العمل ككل بسبب سوء التقديرات المناسبة للوقت والمواد المطلوبة. فكي تنجح في تشييد مبنى ضخم تحتاج إلى فهم وتطبيق مختلف تقنيات الهندسة المدنية والمعمارية خلال عملية البناء وإلى التخطيط المسبق والجيد لكافة الخطوات وتقدير الكميات وكلف المواد والأوقات اللازمة لإنجاز العمل، بعدها يمكنك أن تبدأ عملية البناء وأنت على دراية أكبر بسير العمل. الوضع نفسه ينطبق على مشاريع تطوير البرمجيات ففي حال كنت بحاجة لتطوير برنامج بسيط يحل مشكلة بسيطة يمكن أن ينجزه لك أي مبرمج وينجح في كتابة كود برمجي يحقق لك المطلوب مباشرة، لكنه بالتأكيد سيفشل في تطوير برمجيات ضخمة بمتطلبات معقدة تحتاج لكتابة آلاف الأسطر البرمجية إذا لم يكن على دراية بمبادئ هندسة البرمجيات ولم يقم بتسخير علم الهندسة وتوظيفها بشكل صحيح في بناء هذه البرمجيات. ويمكن هنا أن تلاحظ ما الفرق بين مطور التطبيقات ومهندس البرمجيات، فالمبرمج يمكن أن ينفذ المشروع ويكتب الكود البرمجي الخاص به وهو ما يعرف بتحقيق المشروع أو تنفيذه "Implementation" أما مهندس البرمجيات فيقوم بأكثر من ذلك بكثير فهو يخطط ويحلل متطلبات المشروع ويقدم أنسب الحلول لتحقيق المشروع بناءً على معرفته وخبرته الهندسية قبل البدء الشروع بكتابة الكود ويكون لديه تصور واضح عن العمل الذي يتم إنجازه بكافة مراحله. ما الفرق بين هندسة البرمجيات وعلوم الحاسوب؟ إذا كنت تتساءل عن الفرق بين هندسة البرمجيات وعلوم الحاسوب وهل هما الشيء نفسه؟ فيمكننا القول باختصار أن هندسة البرمجيات هي أحد المجالات الفرعية لعلوم الحاسوب وهي تركز على الحلول العملية وتمكننا من إنتاج برمجيات تحقق أعلى جودة بأقل وقت وتكلفة. لا تركز هندسة البرمجيات على تعليمك البرمجة وتطوير البرامج والتطبيقات المختلفة فحسب، بل تمكنك من تطوير هذه التطبيقات بأفضل طريقة وتعلمك منهجيات مختلفة لتطوير البرمجيات والمراحل التي يمر بها البرنامج خلال دورة حياته والتي تشمل التخطيط والتصميم وكتابة الكود البرمجي وصولاً لنشر البرنامج وصيانته إضافة لمهارات أخرى عديدة مثل التواصل الفعال وإدارة المشاريع. أما علوم الحاسوب فهي مجال أكثر تجريدًا وشمولية من هندسة البرمجيات ويركز بشكل أكبر على المفاهيم النظرية ومعمارية الحاسوب وطريقة عمله ويهتم بالخوارزميات ومعالجة البيانات وقواعد البيانات والذكاء الاصطناعي وأمن الشبكات …إلخ. كيف أتعلم هندسة البرمجيات؟ إذا وصلت لهذه الفقرة فلا بدّ أنك مهتم بتعلم هندسة البرمجيات وتتساءل عن المهارات الأساسية التي عليك تعلمها للتخصص في هذا المجال ودخول سوق العمل، وهنا دعني أخبرك أن أمامك طريقين أولهما هو الدراسة الأكاديمية المتخصصة في إحدى الجامعات وفي هذه الحالة قد تطول مدة دراستك لسنوات وقد تضطر لدراسة العديد من المواد النظرية التي لن تفيدك على الإطلاق في حياتك العملية، أو قد تضطر إلى دخول فرع علوم الحاسوب ثم التخصص في مجال هندسة البرمجيات في الدراسات العليا أي أنت مرتبط بحسب ما توفره المؤسسة التعليمية التي تنوي الالتحاق بها. وثانيهما هو التعلم الذاتي من المصادر الموثوقة والمنهجية المتوفرة عبر الإنترنت وهو طريق مختصر يركز على الجانب العملي ويمكنك من دخول سوق العمل بسرعة أكبر، ولحسن الحظ لم تعد معظم شركات التقنية تتطلب امتلاك شهادة متخصصة للعمل في مجال هندسة البرمجيات، وتركز بشكل أكبر على امتلاك الخبرة الكافية فيه. فيمكنك من خلال التعليم الذاتي والتدريب العملي اكتساب الخبرة الكافية كي تكون مؤهلًا للعمل في هذا المنصب، وإن كان الجمع بين المهارات والحصول على شهادة اختصاصية في مجال هندسة البرمجيات أو تطوير البرمجيات أو علوم الحاسوب أو الرياضيات أو أي مجال مشابه يوفر لك بلا شك فرصًا أفضل. وفي هذا الصدد أود مشاركة نتائج جديرة بالانتباه من أحدث استطلاع رأي نشره موقع Stack Overflow الشهير نهاية عام 2022 والذي يجمع كبار المبرمجين المحترفين حول العالم حيث أظهر أن الغالبية العظمى من المطورين المشاركين لم يتعلموا البرمجة من الكليات والجامعات وإنما تعلموها بشكل ذاتي من مصادر التعلم المختلفة والدورات التدريبية عبر الإنترنت، ولا عجب في ذلك فمصادر التعلم عبر الانترنت ليست متنوعة فحسب بل تتميز بأنها تُحدَّث باستمرار لتواكب عالم البرمجيات المتغير والمتجدد. وإذا كنت تبحث عن المزيد من الطرق والخيارات لتعلم البرمجة بسرعة وكفاءة، يمكنك الاطلاع على مقال كيف تتعلم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة. وكي تتعلم هندسة البرمجيات تحتاج بالطبع لأن تعرف أساسيات البرمجة وتحترف استخدام إحدى لغات البرمجة الشهيرة مثل جافا أو بايثون أو C++‎ كما تحتاج لأن تكون على دراية بأسس التفكير المنطقي والخوارزميات والأنماط البرمجية المختلفة مثل البرمجة كائنية التوجه OOP التي تسهل عليك عملية تصميم البرامج وتمكنك من تنظيمه ضمن كائنات تشبه كائنات العالم الحقيقي وأنماط التصميم التي تمكنك من اتباع حلول محددة لحل مشاكل برمجية معينة بشيفرة مكتوبة بشكل نموذجي وموثوق. كما تحتاج لتعلم مفهوم قواعد البيانات وأنواعها المختلفة ونظم إدراة قواعد البيانات وكيفية تخزين ومعالجة البيانات فيها وإجراء العمليات المختلفة عليها لإنشاء وحفظ بيانات التطبيقات والبرامج والتعامل معها بكفاءة. وبالطبع ستحتاج لتعلم أساسيات الهندسة وأهمها أساسيات الرياضيات حيث قد تتطرق إلى بعض المفاهيم الهندسية والرياضية، وغالبًا إن أتيت من خلفية دراسية علمية وانتهيت من مراحل الدراسة الثانوية فهذا يكفي للبداية والانطلاق، وأيضًا تحتاج إلى فهم دورة حياة البرنامج والمنهجيات المختلفة لتطوير البرمجيات وإدارة المشاريع البرمجية وتوثيق البرمجيات وضمان جودتها وطرق اختبارها. عند هذه النقطة يمكنك دخول سوق العمل والبحث عن فرص باسم مهندس برمجيات ويمكنك حينها أن تتخصص في مجال برمجي محدد كتطوير الويب أو أمن المعلومات أو تطوير الألعاب أو غيرها من المجالات المتنوعة، وتتعلم التقنيات والأدوات التي تؤهلك للعمل في أحد التخصصات تلك واحترافه. إذا كنت مهتمًا بمعرفة المزيد عن أسس هندسة البرمجيات وترغب في مصدر يمكنك من اكتساب كافة المهارات الضرورية التي تمكنك من بدء حياتك المهنية في هذا المجال ولكنك متردد لكونك لا تملك أي معرفة مسبقة حول مبادئ عمل الحاسوب أو مفاهيم البرمجة الأساسية فقد وفرت لك أكاديمية حسوب دورة علوم الحاسوب التي تأخذ بيدك خطوة بخطوة للبدء وتدمج لك المفاهيم النظرية والعملية في دورة مكثفة غنية بالمعلومات. تمتد دورة علوم الحاسب لأكثر من 60 ساعة تدريبية يمكنك أن تتعلم من خلالها الكثير عن الحاسوب ومكوناته وطريقة عمله وعن أنظمة التشغيل وقواعد البيانات ومبادئ البرمجة وكتابة الكود وتطوير الويب وأسس هندسة البرمجيات وغيرها الكثير من المعلومات المتجددة التي تكسبك الخبرة التي تحتاجها وتمنحك في النهاية شهادة معتمدة وتوفر لك فرصة عمل مناسبة لبدء مسارك المهني. مجالات عمل اختصاص هندسة البرمجيات قد تتساءل بعد أن تعلمت كل المهارات الضرورية للعمل كمهندس برمجيات أو مطور برمجيات هل يمكنني الحصول على فرصة عمل مناسبة لتخصصي وما هي مجالات العمل التي يمكنني العمل بها؟ والجواب نعم ستجد فرصة عمل تناسبك بلا شك فالطلب على مهندسي البرمجيات في سوق العمل كبير ومتنامٍ، فلا تكاد توجد مؤسسة أو صناعة أو قطاع من قطاعات العمل في عصرنا الحالي إلا وتحتاج للحلول البرمجية والتقنية لتحسين أداء عملها وتهتم بتوظيف مهندسي البرمجيات للاستفادة من خبراتهم ومهاراتهم في تطبيق هذه الحلول. لكن عند البحث عن مجال للعمل في مجال هندسة البرمجيات سيكون عليك التركيز على العمل أو التخصص في مجال محدد، فعندما تطلب الشركات والمؤسسات مهندسي برمجيات تحدد غالبًا مهندسين بتخصص معين، وفيما يلي قائمة بأهم تخصصات العمل التي يمكن لمهندسي البرمجيات العمل بها وما التقنيات اللازمة لها: مطور ويب مطور الويب هو الشخص المسؤول عن تصميم وإنشاء مواقع وتطبيقات الويب المختلفة، ويمكن أن يتخصص في تطوير الواجهة الأمامية للموقع التي تعمل من طرف العميل أو تطوير الواجهة الخلفية التي تعمل من طرف الخادم أو يقوم بكلا الأمرين معًا ويطلق عليه في هذه الحالة اسم مطور ويب كامل "Full-Stack". يمتلك مطورو الويب معرفة قوية باستخدام تقنيات الويب ولغات البرمجة مثل HTML و CSS وجافا سكربت وأجاكس …إلخ. ويقومون بكتابة تعليمات برمجية لإنشاء مواقع الويب ودمج قواعد البيانات مع الموقع الويب وتطوير ميزات جديدة للموقع الويب وصيانته. يمكنك الرجوع إلى مقال تعلم تطوير الويب لمزيد من التفصيل حول هذا التخصص. مطور تطبيقات الهاتف المحمول يعد تطوير تطبيقات الهاتف المحمول من مجالات هندسة البرمجيات الأكثر طلبًا في سوق العمل ومطور التطبيقات هو المسؤول عن إنشاء واختبار وبرمجة تطبيقات الهواتف المحمولة والأجهزة اللوحية المختلفة وهو يطور تطبيقات لأهداف عامة أو تطبيقات مخصصة لتلبية احتياجات محددة للعملاء. كي تعمل كمطور تطبيقات هاتف يجب أن تمتلك معرفة قوية بلغات برمجة مثل جافا سكربت وكوتلن وسويفت و Objective-C وأن تمتلك معرفة جيدة بأنظمة تشغيل الهواتف المحمولة مثل iOS و Android. إن أردت المزيد من المعلومات، فارجع إلى مقال برمجة تطبيقات الجوال. أخصائي دعم تقني يمكن لمهندس البرمجيات العمل كذلك كاختصاصي دعم تقني، وهذا المجال يحتاج إلى فهم شامل للبرمجيات والأجهزة وأنظمة الشبكات كي يوفر الدعم الفني التقني اللازم للشركات وموظفيها، ويحل مشكلات الأجهزة والبرمجيات والشبكات الحاسوبية ويقوم بتثبيت البرامج اللازمة وتحديثها وإصلاح أي خلل بها …إلخ. محلل أنظمة أو محلل نظم معلومات يحتاج محلل الأنظمة لامتلاك معرفة متعمقة بالأنظمة والبرامج وتحديد أفضل الطرق للاستفادة من موارد المؤسسة التي يعمل بها لأداء العمل بفعالية. فمهندس الأنظمة مسؤول عن تحديد احتياجات البنية التحتية التقنية وتحليل التكلفة والعوائد اللازمة لإعداد أنظمة المعلومات في المؤسسات والشركات التي يعمل بها. محلل أمن معلومات محلل أمن المعلومات هو المسؤول عن الحفاظ على أمان الحواسيب والشبكات ويجب أن يكون خبيرًا بتقنيات التشفير وجدران الحماية وتقييم المخاطر ويقدم التوصيات لتحسين وحماية البيانات الحساسة للشركة التي يعمل بها ويحدد الثغرات ونقاط الضعف التي تخل بأمن هذه البيانات. مسؤول قواعد البيانات يهتم مسؤول قواعد البيانات بإنشاء وتصميم قواعد البيانات ويعنى بإدارة وصيانة قواعد بيانات الشركة والحفاظ على استقرارها وإجراء النسخ الاحتياطية لقاعدة البيانات وتعديلها عند الحاجة، ويجب أن يمتلك معرفة قوية بلغات قواعد البيانات التقليدية أو العلائقية مثل Oracle و Microsoft SQL Server و DB2 أو قواعد البيانات غير العلائقية المصممة للتعامل مع البيانات الضخمة. للمزيد حول مجال قواعد البيانات، ارجع إلى مقال دليلك الشامل إلى قواعد البيانات. مهندس ضمان الجودة يهتم مهندس ضمان الجودة بوضع الخطط التي تضمن جودة تطوير البرمجيات ويحدد المشكلات التي قد تظهر أثناء عملية التطوير ويمتلك فهمًا جيدًا بدورة حياة تطوير البرمجيات ويعمل مع المطورين الآخرين في الفريق لتحديد وسائل التحسين الممكنة. كما يمكن لمهندس البرمجيات العمل في العديد من المجالات المهمة الأخرى مثل: مهندس DevOps محلل معلومات الأعمال مسؤول عن اختبار جودة البرمجيات QA Tester مبرمج ألعاب مهندس ذكاء صنعي مشرف على مختبرات الحاسوب مدرس برمجة وحاسوب ويمكنك الاطلاع على المزيد من المعلومات حول أكثر مجالات العمل انتشارًا في مقال مجالات البرمجة. كيف أبدأ بالعمل في أحد مجالات هندسة البرمجيات؟ لتعمل في أحد تخصصات أو مجالات هندسة البرمجيات التي ذكرناها في فقرتنا السابقة من الضروري أن تركز على تعلم اللغات والتقنيات التي ترتبط بشكل وثيق بالمجال أو التخصص الذي تفضل العمل فيه. لا تهمل كذلك تعلم المهارات غير الفنية كإدارة الوقت والتحكم بالتوتر والتنظيم والتخطيط والتفكير خارج الصندوق والعمل الجماعي والعمل مع العملاء ومهارات التواصل الفعال مع العملاء والقدرة على تحديد احتياجاتهم فهي ضرورية لك كمهندس برمجيات لأنك ستحتاج للتعامل مع فئات مجتمعية مختلفة كالبائعين والعملاء والمدراء وأعضاء الفرق المختلفة، وأصحاب العمل يقدرون الأفراد الذين يمتلكون مهارات ناعمة ويفضلون توظيفهم. وبعد أن تطور مهاراتك سواء التقنية وغير التقنية، عليك أن تضعها موضع التطبيق العملي وتحرص على إنجاز مشاريع عملية وتطوير برامج لشركات حقيقية أو وهمية لبناء معرض أعمال مناسب، كما يمكنك الانضمام إلى مشاريع مفتوحة المصدر فهذا يوفر لك طريقة رائعة لوضع مهاراتك موضع التنفيذ وتعزيز محفظة أعمالك. فأعمالك في النهاية هي التي ستتحدث عنك وهي التي ستفتح لك الأبواب والفرص المناسبة في سوق العمل. إذا قمت بكل ما سبق ستجد أمامك بالتأكيد الكثير من فرص العمل المتنوعة، وإذا كنت مهندس برمجيات مبتدئ أنصحك أن تبحث فورًا عن أول فرصة عمل مناسبة في شركة ملائمة حتى لو كانت شركة محلية وصغيرة لأجل اكتساب الخبرة لأن الخبرة في هذا المجال أمر مهم للتقدم الوظيفي، بعدها يمكنك الانتقال لشركات أكبر وذات رواتب مجزية. أخيرًا إذا كنت ترغب في العمل والتخصص في مجال هندسة البرمجيات، لكنك متردد حول إيجابيات وسلبيات هذا المجال وتراودك تساؤلات وشكوك فيما إذا كانت هذه المهنة مناسبة لك فعلًا، دعنا نختم مقالنا بمناقشة أبرز المزايا والعيوب المحتملة للعمل كمهندس برمجيات لعل ذلك يساعدك على اتخاذ القرار الأنسب لمستقبلك المهني. إيجابيات وسلبيات تخصص هندسة البرمجيات سنناقش أخيرًا إيجابيات وسلبيات هذا المجال الواسع الكبير، فلكل شيء في النهاية مزايا ومحاسن ويجب على الداخل الجديد إلى أي مجال معرفتها. إيجابيات تخصص هندسة البرمجيات يوفر تخصص هندسة البرمجيات العديد من الفوائد والإيجابيات وأهمها: تعد هندسة البرمجيات من الوظائف الأعلى أجرًا. الطلب على هندسة البرمجيات مرتفع ومعدل نموها أعلى من المهن الأخرى. حرية العمل عن بعد من داخل المنزل إما بمفردك أو مع فريق عمل وضمن ساعات عمل مرنة. إمكانية بدء مشروعك الخاص بأقل التكاليف، كل ما تحتاجه للبدء هو جهاز حاسوب واتصال بالإنترنت. القدرة على تطوير برامج ضخمة ومعقدة عالية الجودة لم تكن لتتمكن من إنجازها بنجاح دون تطبيق مبادئ هندسة البرمجيات. تطوير مهاراتك الحياتية وقدرتك على فهم المنطق وتحسين كفاءتك في حل المشكلات والتعامل مع التوتر والضغوطات. مهارة عالية في التكيف بسرعة مع أي تطورات تقنية جديدة، فالتقنية تتطور باستمرار ومهندسو البرمجيات أشخاص منفتحون على تعلم أشياء جديدة كل يوم. سلبيات تخصص هندسة البرمجيات لاشك أن أي مجال لا يخلو من بعض الجوانب السلبية، وفيما يلي نذكر لك أبرز التحديات التي قد تواجهك عند العمل في مجال هندسة البرمجيات: إذا قررت العمل كمهندس برمجيات فستضطر إلى الجلوس وراء حاسوبك لفترات طويلة جدًّا وهذا قد يعرضك لمشكلات صحية ويمكنك التغلب عليها باتباع نظام صحي ولعب تمارين رياضية. مهنة مرهقة وتشكل الكثير من الضغوط وقد لا تجد فيها الكثير من أوقات الفراغ لا سيما عند العمل في ظل قيود زمنية ومواعيد نهائية للتسليم قد تضطرك للعمل لوقت متأخر وفي أيام العطل. مهنة تتطلب الصبر والتركيز والانتباه الشديد للتفاصيل سواء في مرحلة كتابة الكود أو التصحيح أو الاختبار، وقد تضطر إلى قضاء ساعات في التنقل عبر الشيفرات البرمجية لاكتشاف سبب مشكلة أو إصلاح مشكلة معينة. قد تميل إلى العزلة والوحدة خاصة إذا كنت تعمل من المنزل مما يؤثر على حياتك الاجتماعية وتواصلك مع الأصدقاء. مجال هندسة البرمجيات متجدد ومتسارع النمو وهذا يتطلب منك التعلم المستمر وتطوير نفسك وتعلم أي أدوات وتقنيات جديدة لتضمن النجاح والاستمرارية. يجب أن تبقى حريصا على مسألة الأمان وتحرص على حماية نفسك وعملائك من هجمات المتسللين الذين يحاولون سرقة البيانات أو تخريبها وتحرص على اتخاذ الاحتياطات الأمنية المناسبة كي لا تفقد ثقة عملائك. ورغم ما سبق من سلبيات تذكّر أنك تستطيع تجاوزها إذا كنت تمتلك الشغف في مجال التقنية والبرمجة وكنت منفتحًا على تعلم كل جديد. الخلاصة تعرفنا في مقال اليوم على تخصص هندسة البرمجيات الذي يساعدنا على تطوير منتجات برمجية متطورة فعالة وموثوقة تعمل بأعلى جودة وأقل تكلفة وزمن، ووضحنا أهم المجالات التي يمكن لمهندس البرمجيات العمل فيها وأبرزها تطوير مواقع الإنترنت وتطبيقات الجوال أو الحفاظ على الأمن الإلكتروني للمؤسسات وغيرها من المجالات العديدة، وتناولنا في الختام أبرز إيجابيات وسلبيات العمل كمهندس برمجيات. وفي الختام تذكّر أن تعلّم هندسة البرمجيات طريق طويل يتطلب وقتًا وجهدًا، لكنه في ذات الوقت متاح للتعلم الذاتي بشكل مختصر بفضل توفر موارد تعلم رائعة عبر الإنترنت من دروس ومقالات ومقاطع فيديو وبودكاست وغيرها من المصادر المتنوعة التي تتيح لك التركيز على الموضوعات التي تهمك. هل أنت مهتم بأحد مجالات هندسة البرمجيات وترغب في تعلمه أو بدأت به فعلًا؟ شاركنا رأيك في المجال المفضل لديك وكيف تعلمته وما هي أبرز التحديات التي واجهتك في هذا المجال وكيف تخطيتها؟ اقرأ أيضًا الطريقة الأمثل لدراسة تخصص هندسة البرمجيات دليلك الشامل إلى برمجة التطبيقات دليلك الشامل لتعلم البرمجة تعرف على مجال تحليل البيانات علم البيانات Data science: الدليل الشامل
  10. في عصرنا الحالي الذي هيمنت فيه التقنية على نواحي الحياة المختلفة وباتت الروبوتات والآلات الذكية تحيط بنا في كل مكان أصبح تعلم برمجة الحاسوب أمرًا ضروريًا للجميع. قد تكون متحمسًا لتعلّم برمجة الحاسوب وبدء خطوتك الأولى في هذا المجال لكنك متردد وتشعر أنك تائه وأن البرمجة وعلوم الحاسوب والخوازميات مصطلحات معقدة وصعبة الفهم في هذه الحالة دعني أدعوك لقراءة هذا المقال. سأوفر في مقال اليوم كل المعلومات اللازمة للمبتدئين للتعرف على مفهوم برمجة الحاسوب ونوضح أهميتها وأهم الطرق لتعلّمها بسرعة وكفاءة وبطريقة ممتعة. ما هي برمجة الحاسب؟ برمجة الحاسب ببساطة ليست سوى إخبار جهاز الحاسوب بالأوامر التي تريد منه القيام بها فالحاسوب بدون برمجة ليس سوى خردة من البلاستيك والمعدن وهو يحتاج إلى برمجة كي يعمل بالشكل المطلوب وبرمجة الحاسوب هي العملية التي تمكنك من تصميم وبناء برامج تؤدي مهام محددة. تسمى جميع أجزاء الحاسوب التي يمكنك لمسها باسم العتاد Hardware أما الأجزاء التي لا يمكنك لمسها تسمى البرمجيات أو البرامج Software، عندما تشغل الحاسوب فإنه يقوم بتشغيل هذه البرامج، ولعل أهم برنامج يحتاجه الحاسوب ولا يعمل بدونه هو نظام التشغيل الذي يعتبر بمثابة القلب النابض للحاسوب لذا يجب أن يعمل طول الوقت في الخلفية دون أن تطلب منه العمل في حين تعمل البرامج الأخرى كالآلة الحاسبة ومشغل الموسيقى ومتصفح الإنترنت وألعاب الحاسوب عند الطلب. من أشهر أنظمة التشغيل للحواسيب نظام ويندوز ولينكس وماك، كما تحتاج الأجهزة الأخرى كالهواتف المحمولة والأجهزة اللوحية إلى أنظمة تشغيل خاصة بها مثل نظام أندرويد Android ونظام iOS. لغات برمجة الحاسوب ولغة البرمجة هي وسيلتك الوحيدة للتخاطب مع الأجهزة من حولك وتطوير البرامج المختلفة، وإذا كنا نحن البشر نستخدم لغات مختلفة كالعربية والإنجليزية والفرنسية للتواصل مع بعضنا فإننا نتواصل مع أجهزة الحاسوب كذلك بإحدى لغات البرمجة التي يفهمها. هناك مئات من لغات البرمجة التي تختلف فيما بينها حسب الغرض منها ونوع الجهاز الذي تتخاطب معه لكنها في النهاية تعمل وفق نفس المبدأ، وتستخدم لكتابة البرامج التي هي في النهاية سلسلة من الأوامر والتعليمات المفصلة والمرتبة وفق تسلسل معين لتحدد للحاسوب ما الذي يتوجب عليه القيام به. ركز على كلمة مفصلّة ومرتبة فالحاسوب ليس ذكيًا كالإنسان ويحتاج لأن تلقنه الأوامر بشكل بدائي للغاية، على سبيل المثال إذا طلبت من صديقي أن يحضر لي عبوة ماء من آلة البيع، فسوف يفهم قصدي ويجلب لي طلبي مباشرة لكن إذا طلبته من جهاز الحاسوب فلن يفهم الأمر بهذه السهولة. الخوارزميات واستعمالها في برمجة الحاسوب لكي ينجز لك الحاسوب أمرًا بسيطًا مثل الأمر السابق، يحتاج لأن تخبره بالتعليمات التفصيلية خطوة بخطوة كما يلي: اذهب إلى آلة البيع وقف أمامها. تأكد من وجودة عبوات ماء في الآلة. ضع مقدار المال المطلوب في المكان المخصص. اضغط على رقم الزر المخصص لطلب عبوة الماء. تأكد من أن عبوة الماء سقطت في المنفذ المخصص. أخرج عبوة الماء وأحضرها إلي. وربما كل خطوة من الخطوات السابقة تحتاج إلى تفصيل، فعندما تخاطب الحاسوب عليك أن تلقنه خطوات العمل بشكل مفصل وواضح على هذا النحو، ويمكن أن تطلق على هذه الخطوات اسم "خوارزمية" وهي مفهوم هام يساعدك على تحسين مهارات البرمجة لديك، وكما تلاحظ الخوازرمية ما هي إلا خطوات لحل مشكلة معينة، وهي غير مرتبطة بلغة برمجة محددة فيمكنك أن تكتبها بأي لغة برمجة تختارها أو حتى ترسمها ضمن مخطط لكن فهم الخوارزميات يساعدك على كتابة تعليمات برمجية أفضل. بالطبع كانت الخطوات السابقة مجرد خوارزمية بسيطة لشراء عبوة ماء من آلة بيع ويمكنك أن تنجزها بعدة طرق وتفصلّها إذا شئت بشكل أكبر من خلال مراعاة الحالات الخاصة التي قد تواجه الحاسوب خلال عملية البيع. على سبيل المثال إذا لم يتوفر في آلة البيع ماء يمكنك أن تجلب لي عصير برتقال أو إذا كانت الآلة معطلة ولم تخرج المطلوب فقم باسترداد النقود التي وضعتها …إلخ. وإذا أردت منه أن يشتري لي خمس عبوات ماء سأطلب منه أن يكرر كافة الخطوات أعلاه حتى يصل عدد العبوات لخمسة لأنك إن لم تخبر الحاسوب بكل ما تريده خطوة بخطوة بشكل منطقي وبتسلسل صحيح فلا تتوقع أن يتصرف من تلقاء نفسه! كيف يعمل برنامج الحاسوب؟ كي تكتب أي برنامج على الحاسوب تحتاج بداية لأن تعرف ما هي خطوات الحل أو الخوارزمية التي تحل المشكلة ثم تحولها إلى برنامج مكتوب بلغة برمجة ما وبالطبع إذا كتبت للحاسوب الخوارزمية بلغتك البشرية فلن يفهمها لذلك تحتاج لاستخدام لغة برمجة لها قواعد إملائية وصياغية محددة في كتابة التعليمات وتوفر للمبرمج كافة الوظائف الأساسية التي تمكنه من التحكم في سير عمل البرنامج. يستخدم المبرمجون لغات برمجة متنوعة لتصميم البرامج والتطبيقات التي نستخدمها على حواسيبنا أو هواتفنا الذكية أو أجهزتنا اللوحية، ومن أشهر لغات البرمجة التي تناسب المبتدئين: لغة بايثون ولغة جافا ولغة جافاسكربت ولغة C++‎ ولغة سكراتش …إلخ. وللمزيد في هذه النقطة، ارجع إلى مقال أسهل لغات البرمجة للمبتدئين. بعض لغات البرمجة نصية أي تحتاج لكتابة تعليماتها ضمن محرر نصوص، وبعضها الآخر رسومي وسهل التعلم حيث تمكنك من كتابة البرنامج بشكل مشابه لقطع الليغو بحيث تعبر كل قطعة فيها عن تعليمة وكل ما عليك هو تركيب هذه التعليمات فوق بعضها البعض لتشكل برنامجًا متكاملاً. على سبيل المثال البرنامج التالي يحل خوارزمية إيجاد العدد الأكبر بين عددين صحيحين من خلال لغة البرمجة الرسومية سكراتش. في حين سيبدو هذا البرنامج بلغة برمجة نصية مثل بايثون بالشكل التالي: # برنامج لطباعة العدد الأكبر بين عددين num1 = input (" أدخل العدد الأول ") num2 = input(" أدخل العدد الثاني ") if int(num1) > int(num2): print("العدد الأكبر هو",num1) else: print("العدد الأكبر هو",num2) بعد أن تكتب البرنامج بأي لغة برمجة تختارها لن يتمكن الحاسوب من فهمه وتنفيذه مباشرة، وإذا كنت تتساءل لماذا؟ فالجواب هو أن الحاسوب لا يفهم في الواقع سوى لغة الآلة المكونة من 0 و 1. لهذا السبب عليك أن تستعين ببرنامج خاص يأتي مع كل لغة وتطلب منه أن يقوم بتحويل كود البرنامج المكتوب بتلك اللغة إلى لغة الآلة لينفذها الحاسوب. يقوم المترجم أو المُحوِّل بالتأكد من أنك كتبت البرنامج بشكل صحيح أثناء تحويله ثم يقوم بتشغيله، وإذا كان البرنامج يحتوي على بعض الأخطاء فسيتم عرض الخطأ ويطلب منك المترجم تصحيحه قبل أن ينفذ أوامرك. فوائد تعلم برمجة الحاسوب يقدم تعلم برمجة الحاسوب لك العديد من الفوائد أهمها: تطور البرمجة قدرتك على حل المشكلات وتحسن قدرتك على التفكير المنطقي. سوق العمل في مجال برمجة الحاسوب كبير مما يسهل عليك الحصول فرصة عمل جيدة بسهولة. ذات مردود مالي مرتفع فالوظائف التي تتطلب خبرة برمجية مجزية وعالية الأجر. تمكنك من العمل بشكل حرّ إن أردت بأوقات عمل مرنة ومن أي مكان في العالم. بعيدًا عن مجال العمل، تعتبر البرمجة مهارة مهمة تساعدك على التكيف بسهولة مع التطور الرقمي الذي يطال كافة المجالات. يمكنك تعلمها بشكل ذاتي من عدة مصادر دون الحاجة للدراسة الجامعية. كيف أتعلم برمجة الحاسوب؟ تأكد أن تعلم البرمجة ليس بهذه الصعوبة في الواقع، إلا إذا كنت غير جديّ في التعلم أو كنت تتعلمها بطريقة خاطئة تركز على المعلومات النظرية المملة. وإليك خطوات سريعة تساعدك على تعلم برمجة الحاسوب: تعلم الرياضيات ومنهجية التفكير المنطقي، وبالطبع لا يستلزم تعلّم البرمجة تعلّم أمور رياضية متقدمة ويمكنك الاكتفاء بالأمور الأساسية التي تساعدك على إيجاد الحلول للمشكلات التي تواجهك برمجيًا. حدد مجالات البرمجة التي تفضلها والتي توافق ميولك ومجال اهتمامك مثل تطوير مواقع الويب أو تطوير الألعاب أو تطبيقات الجوال أو برمجة الروبوتات …إلخ. وركز على تعلم لغات البرمجة والأدوات التي تساعدك على تحقيق هذا الهدف. ابدأ تعلم البرمجة بلغة سهلة وبسيطة تناسب المبتدئين مثل بايثون وروبي. ويمكنك مطالعة مقال أسهل لغات البرمجة لتتعرف على المزيد من لغات البرمجة المناسبة لبدء التعلم. إذا لم تكن قادرًا حتى الآن على تحديد اللغة التي ينبغي عليك أن تتعلمها يمكنك البدء بتعلم أساسيات البرمجة بلغات برمجة مختلفة، وستجد العديد من الدروس والمقالات على الإنترنت التي تساعدك على فهم هذه الأساسيات بغض النظر عن اللغات المستخدمة. ثبت جميع البرامج والأدوات المطلوبة للتعلم مثل محرر الكود والمترجم لتنفيذ البرامج بنفسك وتطبيق ما تعلمته بشكل عملي. تعلم كيف تصحح أخطاء البرامج وتأكد أنك إن لم تخطئ وتتعلم كيف تعثر على هذه الأخطاء وتصححها فلن تتعلم أبدًا. إن تمكنت من التعلم مع صديق له نفس اهتماماتك فهذا سيساعدك ويحفزك على التعلم بصورة أفضل، كما يمكنك الانضمام للمنتديات والمجتمعات المختصة بالبرمجة والمشاركة فيها وتبادل الخبرات والأسئلة حول المواضيع التي تهمك. كن صبورًا ومستعدًا لتعلم الأشياء الجديدة فمجال البرمجة واسع ومتجدد ويتطلب شخصًا لديه قابلية التعلّم المستمر ومواكبة كل جديد ولا تستعجل النتائج. اختر ما يلائمك من مصادر التعلّم، فتعلّم البرمجة متاح بطرق عديدة متنوعة من بينها الحصول على التعليم الأكاديمي من جامعة أو مدرسة متخصصة، أو التعلم بشكل ذاتي من مصادر التعلم المتعددة مثل المعسكرات التدريبية والكتب والدروس والمدونات ومقاطع الفيديو عبر الإنترنت. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن إذا كنت تبحث عن مصدر موثوق لتعلم البرمجة توفر لك أكاديمية حسوب دورة تدريبية مميزة مختصة بتعليم البرمجة وعلوم الحاسوب وهي دورة تعلم علوم الحاسب التي تتيح لك دراسة البرمجة بشكل ذاتي وتمكنك من احتراف البرمجة بأقصر الطرق دون الحاجة لأي خبرة مسبقة والحصول على شهادة معتمدة وفرصة للعمل في هذا المجال. كما أنصح بمطالعة مقال كيف تتعلم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة الذي يستعرض لك خيارات منوعة لتعلم برمجة الحاسب لتختار منها ما يناسبك. الخلاصة شرحنا في مقال اليوم مفهوم برمجة الحاسوب وأهميتها لأجهزة الحاسوب التي لن تتمكن من فعل أي شيء دون البرمجيات، وبيّنا أهمية تعلم البرمجة على الصعيد المهني والشخصي، وكيف يمكنك تعلمها ذاتيًا بطريقة سهلة وسريعة وتذكّر أن إتقان البرمجة يحتاج للممارسة والتطبيق العملي فكلما مارستها أكثر كلما أصبحت أكثر كفاءة واحترافية. ماذا تنتظر؟ ابدأ من الآن وابدأ طريقك نحو أهم مهنة في المستقبل! وإذا كان لديك أي سؤال أو استفسار حول برمجة الحاسوب فنرحب بأن تشاركنا به وتكتبه في قسم التعليقات أسفل المقال. اقرأ أيضًا المدخل الشامل لتعلم علوم الحاسوب برمج خوارزميتك الأولى عبر سكراتش Scratch دليلك الشامل إلى: برمجة التطبيقات
  11. تلعب البرمجة في عصرنا الحالي دورًا حيويًا في كافة مناحي الحياة كالاتصالات والهندسة والتصميم والإدارة والطب وغيرها، ومجالات البرمجة كثيرة ومتنوعة وهي تخدم أغراضًا مختلفة وتتوسع بشكل مستمر كما تعدّ البرمجة من أكثر الوظائف نموًا في سوق العمل. لحسن الحظ، هذا يوفر للمبرمجين الكثير من الخيارات في سوق العمل ويتيح لهم الفرصة للتخصص في مجالات متنوعة كتطوير مواقع الويب أو تطبيقات الجوال أو التخصص في تحليل البيانات أو برمجة الشبكات …إلخ. نسلط الضوء في هذا المقال على أهم مجالات البرمجة ونساعدك في تحديد أهدافك واكتشاف المجال الذي يناسب اهتماماتك وميولك والتعرف على أهم التقنيات التي يتطلبها التخصص في كل مجال. ما هي مجالات البرمجة البرمجة هي أن تطلب من جهاز الحاسوب أو أي جهاز إلكتروني آخر قابل للبرمجة أداء مهمة مت أو حل مشكلة معينة من خلال كتابة مجموعة من التعليمات باستخدام إحدى لغات برمجة. ولغة البرمجة هي لغة خاصة تستخدم للتواصل بينك وبين الحاسوب، ويمكنك من خلالها تطوير مختلف أنواع البرامج والتطبيقات التي تخدم أغراضًا مختلفة، ونتيجة التباين في المهام والمشكلات التي يتم حلها بواسطة الحاسوب تتنوع مجالات البرمجة التي يمكن للمطورين والمبرمجين العمل بها. وقد اخترنا مجموعة من أهم هذه المجالات حسب استطلاع الرأي الذي أجراه موقع Stackoverflow الشهير للعام 2022 والذي يشارك فيه عدد كبير من المطورين والمبرمجين حول العالم: من أشهر مجالات البرمجة نذكر: تطوير الويب بأنواعه الثلاثة: التطوير الكامل وتطوير الواجهة الخلفية وتطوير الواجهة الأمامية تطوير سطح المكتب تطوير تطبيقات الهاتف التخصص في مجال DevOps هندسة البنية التحتية السحابية إدارة قواعد البيانات تحليل البيانات أو الأعمال الأمن السيبراني تطوير الألعاب الذكاء الاصطناعي وتعلم الآلة لنستكشف المزيد من المعلومات حول كل مجال من هذه المجالات ونتعرف معًا على أهم استخداماته وتقنياته في فقراتنا التالية. 1. تطوير الويب هو أحد مجالات البرمجة المفضلة لدى غالبية المبرمجين وهو يحتل المكانة الأولى بين وظائف المبرمجين على مستوى العالم ولا عجب في ذلك فهو مجال سهل التعلم وكثير الطلب في سوق العمل، فلا توجد شركة ناشئة أو نشاط تجاري إلا ويحتاج لتطوير موقع ويب خاص به ليثبت وجوده في العالم الرقمي، لذا فإن الطلب على المتخصصين في مجال تطوير الويب مرتفع ومستمر في النمو. يشمل تطوير الويب تخطيط وتصميم واجهات موقع الويب، وكتابة الكود البرمجي اللازم لعمل الموقع، كما يشمل صيانة مواقع الويب وتطويرها حسب الحاجة. ويقسم مجال تطوير الويب إلى ثلاث تخصصات هي: تطوير الواجهة الأمامية Frontend تطوير الواجهة الخلفية Backend التطوير الكامل Full-Stack مطور الواجهة الأمامية: هو المسؤول عن الجزء المرئي من الموقع الذي يراه المستخدمون النهائيون فهو الذي يصمم صفحات وأقسام الموقع والقوائم ويحدد أنواع الخطوط والألوان …إلخ. وهذا المجال يتطلب حسًا فنيًا وتفكيرًا إبداعيًا لابتكار تصاميم سهلة الاستخدام وتنفيذها من خلال التقنيات البرمجية المناسبة حيث يحتاج المتخصص في تطوير الواجهات الأمامية للمواقع إلى معرفة عدة تقنيات مثل HTML5 و CSS3 ولغة جافا سكريبت ومعرفة أهم المكتبات وأطر العمل الخاصة بها. دورة تطوير واجهات المستخدم ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة اشترك الآن مطور الواجهة الخلفية: هو المسؤول عن الجزء التقني من الموقع الذي يعمل على الخادم، وتشمل مسؤولياته إنشاء الوظائف الرئيسية للموقع والتعامل مع قواعد بيانات الموقع ومراقبة أداء الخادم ويحتاج مطور الواجهة الخلفية لامتلاك خبرة باللغات التي تعمل في طرف الخادم مثل جافا Java وروبي Ruby و PHP وبايثون Python والتعامل مع نظم إدارة قواعد البيانات مثل MySQL و MongoDB كما يحتاج إلى الإلمام بأساسيات لغات الواجهة الأمامية والتعاون مع مطوري الواجهة الأمامية. مطور الويب الكامل: أو ما يعرف باسم مطور المكدس الكامل Full-Stack Developer هو المبرمج الذي يمتلك المهارات التي تمكنه من تطوير الواجهة الأمامية والخلفية لموقع الويب فهو مسؤول عن كافة جوانب تطوير الموقع من طرف العميل والخادم. شرحنا هذين المجالين ومجال التطوير الشامل وعرضنا خارطة طريق لتعلم مجال تطوير الويب بالتفصيل في مقال المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع. 2. تطوير سطح المكتب رغم أن مجال تطوير برامج سطح المكتب تراجع في الآونة الأخيرة مقابل تطبيقات الويب والجوال والتطبيقات المستندة إلى السحابة، لا يزال بعض المستخدمين يعتمدون على تطبيقات سطح المكتب لإنجاز المهام الاحترافية لذا فإن تطوير سطح المكتب لا يزال أحد مجالات البرمجة المهمة والمجزية. فإذا كنت تعتقد أن تطوير سطح المكتب قد عفا عليه الزمن ولا جدوى منه فأنت مخطئ، بل على العكس يعد هذا التخصص من أصعب التخصصات وأعلاها أجرًا، لأن تطبيقات سطح المكتب تعمل بشكل أفضل من ناحية القوة والسرعة والموثوقية من تطبيقات الويب أو البرامج المستندة إلى السحابة لذا لا تزال مفضلة للعديد من الشركات وأصحاب الأعمال. مطور سطح المكتب هو المبرمج الذي يكتب الشيفرات البرمجية للبرامج والتطبيقات التي لا تحتاج إلى الاتصال بالإنترنت والمخصصة للعمل على أجهزة الحاسوب التي تعمل بأنظمة تشغيل مثل ويندوز Windows ولينكس Linux وماك MacOS، ويركز عادة على تطوير وإنتاج برامج متقدمة واحترافية كبرامج التصميم باستخدام الحاسوب CAD، وبرامج النمذجة ثلاثية الأبعاد، وبرامج تحرير الصور والفيديو والأصوات …إلخ. ومن أشهر لغات البرمجة المستخدمة في مجال تطوير تطبيقات سطح المكتب: C#‎ C++‎ Python Ruby Objective-C Swift JavaFX Go Scala Python وإضافة لتعلم التقنيات ولغات البرمجة اللازمة لتطوير برامج سطح المكتب يجب أن يمتلك مطور سطح المكتب مهارات مثل التفكير المنطقي والقدرة على حل المشكلات المعقدة بكفاءة ويتمكن من إيجاد حلول مبتكرة تجعل من البرامج أسرع وأسهل في الاستخدام. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن 3. تطوير تطبيقات الجوال يعد تطوير تطبيقات الجوال والهواتف المحمولة من مجالات البرمجة المهمة والمربحة والمطلوبة بكثرة في سوق العمل، والتخصص في هذا المجال يمكنك من تطوير تطبيقات متنوعة تستخدم على مختلف الأجهزة المحمولة مثل الهواتف الذكية والأجهزة اللوحية والساعات الذكية وكل شخص منا لديه اليوم هاتف ذكي يعتمد عليه لإنجاز معظم المهام اليومية سواء التسوق عبر الإنترنت أو دفع الفواتير أو تصفح وسائل التواصل الاجتماعي …إلخ. بناء على ذلك تحرص غالبية الشركات اليوم على تطوير تطبيقات هواتف ذكية لمنصاتها لتحقيق أقصى استفادة وهذا بدوره يساهم في نمو سوق تطبيقات الهواتف ويوفر الكثير من الفرص الوظيفية لمطوري هذه التطبيقات. كي تصبح مطور تطبيقات جوال عليك أن تتعلم إحدى لغات البرمجة المتخصصة في بناء التطبيقات وتتعلم إدارة قواعد البيانات وتصحيح الأخطاء، ومن الضروري أن تمتلك كذلك مهارات في مجال التصميم لإنشاء تطبيقات جذابة بصريًا وسهلة الاستخدام. تعتمد لغات البرمجة التي تمكنك تعلمها لإنشاء تطبيقات الهاتف المحمول على نظام الهاتف فإذا كنت ترغب في تطوير تطبيقات للأجهزة التي تعمل بنظام Android يمكنك تعلم لغة جافا Java وكوتلن Kotlin، ولتطوير تطبيقات للأجهزة التي تعمل بنظام iOS يمكنك تعلم سويفت Swift أو Objective-C، كما يمكنك تطوير تطبيقات جوال هجينة تعمل على عدة أنظمة من خلال تعلم لغات تعمل مع تقنيات الويب والجوّال مثل HTML5 و CSS3 وجافا سكريبت. من السهل اكتساب الخبرة في مجال تطوير التطبيقات بسبب ظهور العديد من تقنيات التطوير سهلة الاستخدام مؤخرًا، كل ما عليك هو تعلم إحداها وبناء معرض أعمال خاص بك يضم تطبيقات مفيدة بأفكار نافعة تلبي احتياجات المستخدمين فهذا يساعدك في الحصول على فرص عمل مميزة بسرعة. إن أردت المزيد من التفاصيل حول مجال تطوير تطبيقات الجوال، ارجع إلى مقال برمجة تطبيقات الجوال. 4. تخصص DevOps يهدف مجال DevOps أو ما يعرف بالتطوير والعمليات Development and Operations إلى تنظيم التعاون بين كل من فرق تطوير البرامج وفرق تقنية المعلومات وسد الفجوة بينهما من أجل تطوير برمجيات عالية الجودة. رغم حداثة هذا المجال إلا أن الاعتماد عليه يتزايد بسرعة، وقد أصبح متخصصو ومهندسو DevOps يلعبون دورًا أساسيًا في المؤسسات لتأثيرهم الكبير على زيادة قدرة المؤسسات على إصدار المنتجات والخدمات بسرعة وكفاءة وصيانتها بشكل أفضل. والطلب متزايد على محترفي DevOps في سوق العمل، ويتطلب العمل في هذا المجال توفر مجموعة متنوعة من المهارات مثل فهم أساسيات لينكس Linux ومعالجة الملفات وإدارة العمليات وتشغيل خوادم لينكس وإتقان لغات البرمجة مثل بايثون أو جافا Java أو جافا سكربت Javascript أو روبي Ruby …إلخ. إضافة لمهارات قوية في الحوسبة السحابية والتحكم في الإصدارات مثل Git، كما يجب أن يتمتع بمهارات شخصية كالتواصل الفعال والتعاون والتنظيم. للمزيد يمكنك الاطلاع على مجموعة منوعة من المقالات والدروس التي توفرها أكاديمية حسوب حول مفهوم DevOps وأهم أداوته وتقنياته. 5. تخصص هندسة البنية السحابية تسعى معظم الشركات والمنظمات اليوم إلى تغيير الطريقة التقليدية التي تتعامل بها مع مواردها وتتوجه لتحويل كافة خدماتها كالخوادم والتخزين وقواعد البيانات والشبكات والبرمجيات لتعمل عبر الإنترنت أو السحابة مما يوفر لها مرونة وكفاءة أكبر ويخفض تكاليف تشغيل بنيتها التحتية ويساعدها على توسيع نطاق عملها بسهولة عند تغير المتطلبات. لهذا السبب تعتبر هندسة السحابة Cloud infrastructure engineer أحد مجالات البرمجة الهامة، فمعظم الشركات أصبحت تحتاج إلى تعيين مهندس سحابة أو مطور سحابة أو مسؤول عن الأنظمة السحابية ليكون مسؤولًا عن كافة الواجبات التقنية المرتبطة بالحوسبة السحابية مثل تحديد أفضل حلول البنية السحابية التي تلبي الاحتياجات الاستراتيجية للشركة وإدارة هذه البنية السحابية والعمل على صيانتها وإدارة الخوادم والتخزين السحابي …إلخ. من الضروري لمهندس السحابة امتلاك مجموعة من المهارات وأهمها معرفة بخوادم لينكس Linux وصيانتها وإدارتها ومهارات في إدارة قواعد البيانات السحابية، إضافة لمعرفة بلغات البرمجة مثل جافا و بايثون وروبي و Golang و PHP …إلخ. 6. إدارة قواعد البيانات تعد إدارة قواعد البيانات Database administrator أحد مجالات البرمجة المرغوبة في العديد من المؤسسات والشركات وهي تتضمن جمع البيانات وتخزينها واستخدامها بطريقة آمنة وفعالة من حيث التكلفة. فمعظم أصحاب العمل يعتبرون البيانات أحد الأصول الهامة ويحتاجون إلى متخصصين يقومون بإدارة هذه البيانات وتخزينها وتحليلها بنجاح والكشف عن رؤى هامة منها واتخاذ قرارات استراتيجية تصب في صالح هذه الشركات وتساعدهم على تحسين أدائها وزيادة إيراداتها. من المهارات المهمة للعمل في هذا المجال امتلاك القدرة على التنقل في قاعدة البيانات والعثور على السجلات المطلوبة وإعداد التقارير المناسبة واستخدام أدوات الاستعلام وعرض مجموعات البيانات بعدة تنسيقات بهدف تحليلها من عدة وجهات نظر واستخلاص النتائج منها. 7. تحليل الأعمال وتحليل البيانات برزت أهمية هذا المجال مع ظهور مفهوم البيانات الضخمة الواردة من عدد كبير من المصادر واعتبارها أحد الأصول القيمة للشركات لما لها من أثر كبير في مساعدة المؤسسات على اتخاذ قرارات مهمة وتوسيع نطاق عملها، وزيادة المبيعات وإطلاق منتجات أو خدمات جديدة وزيادة كفاءة عملها. يعرف هذا المجال بعدة أسماء أخرى مثل علم البيانات أو التنقيب عن البيانات أو نمذجة البيانات أو تحليل البيانات الضخمة، والهدف الأساسي منه هو توفير آلية للعمل مع كل هذه البيانات ومعالجتها وفهمها باستخدام تقنيات عدة كالتعلم الآلي والإحصاء والاحتمالات للحصول على معلومات مفيدة تساهم في تحسين أداء الأعمال داخل المؤسسات. فمن خلال تحليل الأعمال يمكن للشركة اتخاذ قرارات واستراتيجيات مستقبلية صائبة، مثل هل يجب عليها تطوير خط إنتاج جديد أم لا؟ أو هل هناك تأثير للمناطق الجغرافية أو المواسم على تفضيلات العملاء عند الشراء؟ أو الإجابة على أي سؤال أو مشكلة مستقبلية قد تواجهها الشركة في أي من أقسامها من المبيعات إلى تطوير المنتجات إلى خدمة العملاء …إلخ. للعمل كمحلل أعمال أو محلل بيانات ستحتاج لمجموعة من المهارات أهمها وجود أساس قوي في الاحتمالات والإحصاء ومعرفة لغات البرمجة الإحصائية مثل R أو بايثون التي تمكنك كتابة برامج لإجراء تحليلات متقدمة على البيانات الضخمة، كما أن إتقان مفاهيم الذكاء الصناعي و خوارزميات التعلم الآلي يمنحك ميزة تنافسية. 8. الأمن السيبراني تهتم المؤسسات والشركات بمجال الأمن السيبراني بشكل خاص لحماية المعلومات الحساسة لعملائها وكسب ثقتهم، فهذا المجال هو المسؤول بشكل رئيسي عن حماية المعلومات الرقمية، ومراقبة شبكات الحاسب والتصدي لأي تهديدات أمنية تظهر فيها، ويهتم كذلك بتصميم أنظمة الأمان وتنفيذها وصيانتها وتطوير تطبيقات برمجية آمنة من الثغرات أو تحسين التطبيقات الحالية لتكون أكثر أمانًا. يتطلب هذا المجال معرفة قوية بالحواسيب والشبكات إضافة للبرمجة وعند التخصص فيه يمكنك أن تعمل في عدة أدوار وظيفية. على سبيل المثال يمكن أن تعمل كأخصائي أمن معلومات وتحمي الأجهزة والأنظمة داخل المؤسسة من الهجمات الإلكترونية أو محلل أمن معلومات لمراقبة الوصول إلى البيانات وتشفيرها وتمنع أي استخدام ضار أو غير مقصود للبيانات وتتأكد من وجود إجراءات حماية قوية وهكذا. كما يمكّنك التخصص في هذا المجال أن تعمل في مجال الاختراق الأخلاقي Ethical hacking فالشركات والمؤسسات المهتمة بأمنها توظف اليوم مخترقين أو متسللين أخلاقيين لديها كي يحاولوا اختراق أنظمتها وشبكاتها وكافة أصولها الرقمية بهدف العثور على نقاط الضعف فيها وإصلاح كافة ثغراتها الأمنية قبل أن يكتشفها المتسلل الحقيقي ويستغلها ضدهم. تحدثنا عن هذا المجال وأهميته وفرص العمل فيه بالتفصيل في مقال ما هو الأمن السيبراني وما أهميته؟ فارجع إليه للاستزادة. 9. تطوير الألعاب يعتبر تطوير الألعاب مجالًا مرغوبًا بشكل خاص في أوساط المبرمجين اليافعين. وتطوير الألعاب مجال متقدم يحتاج لعدة مهارات لا تقتصر على كتابة كود اللعبة بل يحتاج إلى تصميم وتحريك الشخصيات أو الكائنات الرسومية للعبة وإعداد الأصوات وتحديد منطق اللعب، وتطوير الذكاء الصناعي الخاص بها وتطوير محرك اللعبة واستكشاف الأخطاء وإصلاحها قبل إطلاق اللعبة. لهذا السبب يحتاج مجال تطوير الألعاب عادة فرقًا من المتخصصين وقد يستغرق تطويرها سنوات عدة ومن الضروري لمطوري الألعاب أن يكونوا على دراية بمحركات الألعاب وتعلم لغات برمجة الألعاب مثل C++‎ و C و Java و Lua …إلخ. وإذا كنت تخطط لتطوير ألعاب تعمل ضمن متصفح الويب سيفيدك تعلم HTML5 وجافا سكربت و WebGL …إلخ. قد يكون من المفيد أيضًا أن يكون لديك معرفة بتطوير قواعد البيانات ومهارات في التصميم ومعرفة بمحركات الألعاب Game engines مثل Godot أو Unity3D أو Unreal أو غيرها من المحركات التي تسهل وتسرع عملك في تطوير الألعاب بشكل كبير. 10. الذكاء الاصطناعي وتعلم الآلة تعلم الآلة هو أحد تطبيقات الذكاء الاصطناعي AI ومن خلاله يمكن للحواسيب اكتساب القدرة على التعلم وتحسين الأداء من خلال التجربة. يركز تعلم الآلة على تطوير برامج وتطبيقات يمكنها الوصول إلى البيانات واستخدامها للتعلم من تلقاء نفسها من خلال خوارزميات مخصصة تحسن أداءها مع زيادة عدد العينات المتاحة للتعلم. يعد هذا التخصص أحد أحدث مجالات البرمجة رواجًا اليوم وهو يستخدم لحل المشكلات واتخاذ قرارات حاسمة في العديد من القطاعات التي تستخدم كمية ضخمة من البيانات كالطب والاتصالات والصناعة وتداول الأسهم …إلخ. ويُعتمد عليه لحل المهام المعقدة التي تتضمن كمية كبيرة من البيانات والمتغيرات والتي لا تملك طريقة ثابتة أو صيغة محددة لحلها، في هذه الحالة يتم الاعتماد على البيانات الحالية لاتخاذ قرارات مستقبلية وكلما زادت البيانات الموجودة سنتمكن من الحصول على إجابات أفضل وأدق. على سبيل المثال عندما تسأل خرائط جوجل عن أقصر وجهة للوصول لهدف ما وتقترح لك الطريق الأسرع فهي في الواقع تستخدم التعلم الآلي وتستنتج الطريق الأسرع بناء على البيانات الضخمة للأشخاص الذين استخدموا خدمة الخرائط مسبقًا وعلى البيانات التي تم جمعها عن هذا المسار وعن كل شخص استخدمه للوصول لهذه الوجهة ومتوسط سرعته وبهذا يمكن لخرائط جوجل التنبؤ بحركة المرور المستقبلية واقتراح المسار الأفضل. كذلك الأمر يمكن استخدام الذكاء الصناعي في اقتراح توصيات للمنتجات لزيادة الإيرادات، على سبيل المثال عندما تتصفح منتجًا ما على أحد المتاجر الإلكترونية دون أن تشتريه ستفاجئ أنك عندما تتصفح الإنترنت أو وسائل التواصل الاجتماعي بظهور إعلان لنفس المنتج. فكيف حدث ذلك؟ الجواب أن جوجل طبق التعلم الآلي وتتبع بيانات سجل البحث الخاص بك وبناء على ذلك قام بالتوصية بالإعلانات المناسبة بناءً على ذلك. وللتخصص في مجال تعلم الآلة تحتاج لمعرفة عدة تقنيات مثل SQL ومبادئ علم الإحصاء ولغات برمجة مثل لغة بايثون التي توفر الكثير من مكتبات معالجة البيانات مثل numpy و pandas ومكتبات تمثيل البيانات مثل Matpotlib و seaborn والعديد من خوارزميات تعلم الآلة، كما يسهّل عليك تعلم MATLAB تطبيق التعلم الآلي من خلال توفير مجموعة من الأدوات والوظائف الخاصة بمعالجة وتحليل البيانات الضخمة. إن أردت الاستزادة عن هذا المجال والتخصص فيه، يمكنك البدء بكتاب مدخل إلى الذكاء الاصطناعي وتعلم الآلة من أكاديمية حسوب، كما ستفيدك دورة الذكاء الاصطناعي التي توفرها الأكاديمية والتي تشرح لك أساسيات تعلم الآلة والتعلم العميق وتمكنك من تطوير مشاريع عملية لأنظمة التنبؤ، وتحليل النصوص، وتصنيف الصور، ومعالجة البيانات، كما تعلمك طريقة دمج النماذج اللغوية الكبيرة مثل GPT من OpenAI و LLaMA 2 من Meta في تطبيقاتك إلى جانب العديد من المواضيع التي تؤهلك بشكل فعّال للمنافسة في مجال الذكاء الاصطناعي. دورة الذكاء الاصطناعي احترف برمجة الذكاء الاصطناعي AI وتحليل البيانات وتعلم كافة المعلومات التي تحتاجها لبناء نماذج ذكاء اصطناعي متخصصة. اشترك الآن الخاتمة تعرفنا في مقال اليوم على أكثر مجالات البرمجة التي يمكن للمبرمجين والمطورين التخصص بها، بالطبع هناك مجالات عديدة أخرى مثل إنترنت الأشياء IoT والبرمجة التنافسية Competitive Programming وبرمجة الشبكات وبرمجة الأنظمة وتطوير البرمجيات حرة المصدر وأتمتة الأعمال والروبوتيك وغيرها الكثير لكن حاولنا أن نسلط الضوء على بعض من أبرز هذه المجالات. وبعد الاطلاع على أشهر مجالات البرمجة نرجو أن يكون هذا المقال قد ساعدك في العثور على مجال اهتمامك الأنسب -إن لم تحدده بعد- والبدء بالتعرف عليه أكثر وبشكل عملي ودراسة أفضل التقنيات ولغات البرمجة التي تناسب هذا المجال لتحقيق طموحك المهني، كما أنصحك بمطالعة مقال أعلى تخصصات البرمجة أجرًا في حال رغبت في معرفة أكثر المجالات دخلًا ومردودًا من بينها. ما هو مجال البرمجة المفضل بالنسبة لك وما هي التقنيات التي تتعلمها في هذا المجال؟ يسرنا أن تشاركنا تجربتك وتساؤلاتك حول هذا الموضوع في التعليقات أسفل المقال. اقرأ أيضًا كيف تتعلم البرمجة تعلم البرمجة لغات البرمجة فوائد البرمجة أسهل لغات البرمجة تعلم لغة بايثون تعلم لغة PHP دليلك الشامل إلى برمجة التطبيقات تعلم الذكاء الصناعي
  12. لا يختلف اثنان على أهمية تعلم أساسيات البرمجة، فالبرمجة هي مهنة الحاضر والمستقبل، وهي تعتبر أحد المهارات الأساسية في عصرنا الذي بات يعتمد على التقانة في جميع جوانبه، فضلًا عن أن البرمجة قد أصبحت مادة أساسية في المناهج الدراسية في العديد من الدول بدءًا من المراحل الابتدائية. إذا اتخذت قررًا بتعلم أساسيات البرمجة من الصفر للاحتراف فهذا بلا شك قرار صائب، فالبرمجة توفر لك الكثير من فرص العمل، وتوسع مداركك، وتعزز تفكيرك النقدي، كما أنها تكسبك القدرة على حل المشكلات التي تواجهك بكفاءة أكبر، والأمر الجيد أن البرمجة تتميز عن غيرها من المجالات بكونها متاحة للجميع، ويمكنك تعلمها بشكل ذاتي بعيدًا عن أروقة الجامعات الطويلة. نشرح في مقال اليوم أساسيات البرمجة، ونستعرض أهم الأدوات التي تحتاجها كمبرمج، ونبين مفاهيم البرمجة الأساسية التي تشترك فيها معظم لغات البرمجة، وأهم المبادئ التي يمكنك اتباعها لتبرمج كالمحترفين. ما هي البرمجة؟ البرمجة باختصار هي إعطاء التعليمات لجهاز الحاسوب لينفذها باستخدام إحدى لغات البرمجة، ويتلقى الحاسوب هذه التعليمات ويترجمها ويفهمها وينفذها، ويُطلق على تسلسل التعليمات المكتوبة باستخدام لغة برمجة والتي تنجز مهمة محددة اسم برنامج. فنحن البشر نتواصل فيما بيننا بلغاتنا الطبيعية كالعربية أو الإنجليزية، أما الحاسوب فيحتاج لاستخدام لغة برمجة خاصة للتواصل معه، وعالم لغات البرمجة شامل ومنوع فهناك المئات من لغات البرمجة حاليًا، ونشير إلى أن لغة البرمجة هي لغة وسيطة بيننا وبين الحاسوب فحتى الحاسوب لا يفهم لغة البرمجة التي نكتبها بل تُحول كل لغة نكتبها إلى لغة يفهمها الحاسوب عبر أداة تحويل وتدعى اللغة التي يفهمها الحاسوب بلغة الآلة Machine Language التي تتكون من أصفار وواحدات. قبل أن تتعلم أساسيات البرمجة: حدد وجهتك قد تكون حددت لغة البرمجة التي تريد تعلمها وتبحث عن تعلم أساسيات هذه اللغة لذا وصلت إلى هنا، أو لم تحددها بعد، ولكن عمومًا تشترك كل لغات البرمجة بأساسيات واحدة إن تعلمتها سيسهل عليك التعامل مع أي لغة برمجة. قرار تعلم أساسيات البرمجة يشبه قرار الذهاب في إجازة، فأنت لن تذهب في إجازة دون أن تحدد الوجهة التي تريد الذهاب لها، وبناء على وجهتك تحدد مسارك الذي ستسلكه وتجهز مستلزماتك. وبالتالي السؤال الذي يجب أن تطرحه قبل أن تقرر تعلم أي لغة برمجة هو ما هو هدفي النهائي من تعلم البرمجة؟ وبناء على إجابتك تحدد مسار التعلم الصحيح واللغات والأدوات التي عليك تعلمها. ركز في البداية على لغة رئيسية واحدة تتعلم بها أساسيات البرمجة، ثم سيسهل عليك تعلم لغات أخرى حسب الضرورة، حيث الأساسيات والمفاهيم واحدة ولن تختلف من لغة إلى أخرى بل ما يختلف هو طريقة كتابة كل لغة والميزات التي توفرها للمبرمج، وبعبارة أخرى، الخطوة الصعبة هي الخطوة الأولى وهي خطوة تعلم أساسيات البرمجة. وتذكر أن تعلم البرمجة يحتاج لبعض الصبر والجهد، لا سيما عند تعلم إحدى لغات البرمجة لأول مرة كما أشرنا ويحتاج إلى تطبيق أيضًا لأن التعلم النظري شيء والتطبيق شيء آخر ففيه ستواجه الكثير من المشكلات وستتعلم بها حلها وتفاديها تدريجيًا حتى تكون مبرمجًا محترفًا. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن أهمية تعلم أساسيات البرمجة تعلم أساسيات البرمجة للمبتدئين يشبه إلى حد كبير تعلم قيادة السيارة، فعندما تجلس خلف مقود السيارة لأول مرة لن تكون قادرًا على القيادة بسلاسة على الفور، بالطبع! تذكَّر كيف تبدأ آنذاك باستكشاف أجزاء السيارة كالفرامل ودواسة البنزين وناقل الحركة، ثم التعرف على المفاهيم والمصطلحات الأساسية المرتبطة بالقيادة، وتلقي الكثير من التعليمات والملاحظات النظرية حول آلية القيادة أكثر من التركيز على القيادة بحد ذاتها. وبعدها تبدأ عملية التدريب على تنفيذ أوامر بسيطة مثل تشغيل السيارة وتحريكها رويدًا رويدًا في مكان مفتوح إلى أن تزداد التعليمات تعقيدًا وتصبح قادرًا على التحكم بالسيارة وقيادتها في كافة الظروف والطرق. بنفس الطريقة ستتعلم البرمجة، حيث عليك أن تتعلم بداية أساسيات البرمجة النظرية، ثم تكتب برامج باستخدام تعليمات بسيطة، ثم تتعلم كيف تكتب التعليمات بطريقة أكثر احترافية، ومع الممارسة والتطبيق ستتمكن من احتراف البرمجة وتطوير برامج متقدمة. وقد شرح مقال كيف تتعلم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة رحلة تعلم البرمجة بالتفصيل وقدم نصائح مهمة وأجاب على أسئلة شائعة حول تعلم البرمجة فارجع إليه للاستزدادة في هذا الموضوع. احصل على موقع إلكتروني مخصص لأعمالك أبهر زوارك بموقع احترافي ومميز بالاستعانة بأفضل خدمات تطوير وتحسين المواقع على خمسات أنشئ موقعك الآن أدوات مهمة لتعلم أساسيات البرمجة بعد أن تحدد اللغة التي ستتعلمها، تحتاج كخطوة أولى إلى إعداد بيئة التطوير لديك حتى تتمكن من كتابة شيفرة برمجية وتنفيذها كي تتواصل مع الحاسوب بتلك اللغة، والأدوات اللازمة لتعلم أساسيات البرمجة في البداية هي أداتين يحتاج إليهما كل مبرمج: محرر الشيفرة البرمجية أداة تحويل الشيفرة وتنفيذها محرر الشيفرة البرمجية تعتمد معظم لغات البرمجة على أوامر نصية، لذا ستحتاج إلى محرر أكواد لكتابتها، ومحرر الكود هو برنامج لتحرير النصوص مصمم خصيصًا لكتابة وتحرير الشيفرة المصدرية للبرامج، وتتميز بعض المحررات بأنها تتضمن ميزات تسهل كتابة الكود كتمييز الكلمات حسب بناء الجملة، ووضع مسافة بادئة لأسطر التعليمات البرمجية بشكل صحيح. ومن الأمثلة على محررات أكواد Notepad++‎ لنظام تشغيل ويندوز و gedit أو kate لنظام التشغيل لينكس. ملاحظة: بعض لغات البرمجة الموجهة للمبتدئين تعتمد على واجهات رسومية ولا تحتاج لمحررات نصية مثل لغة سكراتش والتي تدعى أحيانًا لغات برمجة رسومية، وللمزيد يمكنك الرجوع إلى مقال البرمجة باستخدام سكراتش. أداة تحويل الشيفرة وتنفيذها نكتب الكود المصدري عادة بلغة برمجة لا يفهمها جهاز الحاسوب مباشرة كما أشرنا، لذا يجب تثبيت برنامجًا يُحوِّل الشيفرة المصدرية للغة البرمجة بأكملها إلى لغة آلة Machine Code يفهمها الحاسوب ثم ينفذها، ويختلف هذا المُحول من لغة برمجة إلى أخرى ويُسمى إما مُصرِّف Compiler أو مُفسِّر Interpreter وبعض اللغات تحتاج إلى تصريف وآخر إلى تفسير وبعضها يحتاج إلى كلا العمليتين لتحويلها إلى لغة الآلة ثم تنفيذها. لتفهم الفرق بين المُصرِّف والمُفسِّر تخيل أن لديك وصفة مكتوبة باللغة التركية وأنت لا تعرف التركية وتريد أن تحضّرها. في هذه الحالة يمكن أن تطلب من أحدهم أن يترجم لك الوصفة بالكامل للغة العربية ويعطيها لك لتعدها متى ما أردت مستعينًا بهذه النسخة المترجمة Compiled، أو يمكنك أن تكلمه في كل مرة تريد فيها أن تحضر هذه الوصفة وتطلب منه أن يقرأها ويفسرها لك خطوة بخطوة Interpreted. بيئة التطوير المتكاملة IDE يمكنك أن تحصل على المحرر وأداة التحويل والتنفيذ على حدة وتثبتهما على جهازك، أو يمكنك بشكل بديل أن تعتمد على بيئة تطوير متكاملة IDE وهي اختصار العبارة Integrated Development Environment تتضمن كافة الأدوات اللازمة للتعامل مع لغة البرمجة. أمثلة على بيئات تطوير متكاملة: Microsoft Visual Studio NetBeans IntelliJ IDEA يمكنك في بيئة التطوير المتكاملة كتابة التعليمات البرمجية وتعديلها وتصحيحها وتحويلها ثم تنفيذها بسرعة وسهولة كل ذلك من مكان واحد، إذ توفر لك كافة الأدوات اللازمة لتكتب وتنفذ برامج بلغة معينة، كما توفر ميزات تساعدك في تطوير البرامج مثل تصحيح الأخطاء البرمجية، والإكمال التلقائي للتعليمات، وللتعرف أكثر على بيئة التطوير المتكاملة، يمكنك الرجوع إلى مقال مدخل إلى بيئة التطوير المتكاملة IDE. ملاحظة: يمكنك الاعتماد على مترجمات أو بيئات عمل برمجية متوفرة على الإنترنت، حيث توفر العديد من المنصات إمكانية كتابة وتنفيذ البرامج على متصفح الويب بدلًا من تثبيت وإعداد البرامج على الحاسوب المحلي. أساسيات البرمجة للمبتدئين تتنوع لغات البرمجة وتعدد استخداماتها إلا أنها تشترك في مجموعة من الأساسيات والمفاهيم، وتعلم هذه المفاهيم يمكّنك من التآلف من أي لغة برمجة، وإنجاز البرامج باستخدامها بمرونة أكبر، وأهم هذه الأساسيات: المتغيرات Variables الثوابت Constants أنواع البيانات Data types الكلمات المفتاحية Keywords التعليقات Comments بنى التحكم Control Structures الدوال Functions هياكل البيانات Data structure التكرار Iteration التعاود Recursion الكائنات Objects والأصناف Classes الوحدات Modules والمكتبات Libraries نشرح في الفقرات التالية كلًا من هذه الأساسيات البرمجية بمزيد من التفصيل، ونرفق بعض الأمثلة التوضيحية بلغات برمجة مختلفة. المتغيرات تستخدم المتغيرات Variables في البرمجة بشكل مشابه لاستخدامها في الرياضيات، فهي تخزن قيم البيانات من نوع محدد، ويمكن للمتغير احتواء قيمة واحدة في المرة الواحدة، فمتى ما وضعت فيه قيمة جديدة فإن القيمة السابقة المخزنة فيه سوف تحذف تلقائيًا. يمكن تشبيه المتغير بصندوق مفتوح في ذاكرة الحاسوب له اسم وعنوان خاص به، حيث يمكن إدخال القيم وإخراجها من هذا الصندوق حسب الطلب. وتسمى عملية وضع قيمة في المتغير بشكل مباشر الإدخال Input أو الإسناد Assignment أو أحيانًا الضبط Set، كما تسمى عملية الحصول على هذه القيمة وعرضها الإخراج Output أو الجلب Get. وتجدر الإشارة لأن بعض أنواع المتغيرات تكون محدودة الوصول، بمعنى أنها لا تسمح لك بالوصول المباشر لها سواء لتخزين البيانات ضمنها أو الحصول على القيم المخزنة فيها إلا عبر وسيط ويُسمى هذا الوسيط باسم ضابط setter وجالب getter على التوالي، والغرض من هذه العملية حماية المتغيرات من تعديلات غير مرغوبة كما سنوضح لاحقًا في فقرة الكائنات والأصناف التي أكثر ما تُستخدم فيها. لتعريف متغير في لغة البرمجة C++‎ عليك ذكر اسم المتغير ونوع البيانات التي تريد تخزينها في هذا المتغير وإسناد قيمة أولية فيه، على سبيل المثال لتعريف متغير باسم a لتخزين العدد الصحيح 10 بداخله نكتب ما يلي: int a = 10; كما يمكنك تعريف المتغير دون إسناد القيمة له في البداية وإسنادها لاحقًا بالشكل التالي: int a; a = 10; في حين لا تملك لغة بايثون أمرًا محددًا لتعريف المتغيرات، كل ما عليك هو كتابة اسم المتغير واستخدام علامة مساواة متبوعة بقيمة المتغير، وسوف تكتشف اللغة تلقائيًا نوع المتغير وحجم الذاكرة المناسب له كما يلي: a = 10 الثوابت تشير الثوابت Constants إلى قيمة أو كمية ثابتة لا نحتاج لأن نغيرها أو نعدلها أبدًا أثناء تنفيذ البرنامج، مثل سرعة الضوء، وعدد الدقائق في الساعة، والعدد Pi الذي يمثل نسبة محيط الدائرة إلى قطرها، وتسارع الجاذبية الأرضية، ومعدل نجاح الطالب وما إلى ذلك. فالثوابت البرمجية بمثابة صندوق تغلقه بإحكام بعد وضع قيمة فيه ولا يسمح لك بتغييرها في كود البرنامج، فبعد تحديد قيمة الثابت يسمح لك فقط بالوصول إلى قيمته، بخلاف المتغير الذي يمكنك الوصول إلى قيمته وإعادة تعيينها وتعديلها حسب حاجتك. لتعريف الثوابت في لغة C++‎ نستخدم الكلمة المفتاحية const ثم نكتب نوع البيانات واسم الثابت وقيمته كما يلي: const float PI = 3.14; const float GRAVITY = 9.8; const float SUCC_RATE = 0.5; في حين لا تميز بعض اللغات مثل لغة بايثون بين تعريف الثوابت والمتغيرات، حيث يمكنك تعريف الثوابت والتعامل معها كما تعرّف أي متغير، وتلتزم أنت بعدم تغيير قيمتها في سياق البرنامج، كما يمكنك التصريح الثوابت في ملف مختلف واستيرادها في برنامجك لتمييزها عن المتغيرات. PI = 3.14 GRAVITY = 9.8 ملاحظة: يشيع في أوساط المبرمجين تسمية الثوابت بحروف أجنبية كبيرة لتمييزها عن المتغيرات كما فعلنا في الأمثلة السابقة. أنواع البيانات أنواع البيانات Data types في لغات البرمجة هي عملية تحديد نوع وحجم القيمة التي يمكن أن تخزن في المتغير والتي يترتب عليها تحديد العمليات التي يمكن تطبيقها على هذه المتغير من طرف لغة البرمجة مثلًا السماح بتطبيق عملية الجمع والطرح على نوع الأعداد والسماح بعملية البحث والاستبدال على النصوص وهكذا. توفر لغات البرمجة العديد من أنواع البيانات مثل: الأعداد التي تنقسم إلى أعداد صحيحة integer numbers وأعداد عشرية floating point numbers، والمحارف Characters، والسلاسل النصية Strings، والقيم المنطقية Boolean …إلخ. على سبيل المثال في لغة البرمجة C++"‎" إذا كنت تحتاج في برنامجك إلى تخزين العمر، ستحتاج لمتغير من نوع بيانات عدد صحيح، ويمكنك تعريف هذا المتغير أو التصريح عنه باستعمال الكلمة المفتاحية int كما يلي: int age; فعندما استخدمنا الكلمة int هنا أخبرنا مترجم اللغة أن هذا المتغير مخصص لتخزين أعداد صحيحة فقط، ليحجز الحجم المناسب له في ذاكرة الحاسوب وينتظر منا إدخال قيم صحيحة فيه فقط، فإذا جربت تخزين نص أو عدد عشري فيه فستحصل على خطأ من أداة التحويل أثناء تحويل البرنامج إلى لغة الآلة وهذا ينطبق على الأمثلة الآتية أيضًا. وإذا احتجت لمتغير مخصص لتخزين قيمة عشرية مثل متوسط درجات الطالب، أو مساحة دائرة استخدم نوع البيانات float لهذا المتغير كما يلي: float avg; ولتعريف متغير مخصص لتخزين محارف مفردة يمكنك أن تستخدم نوع البيانات char كما يلي: char x; x = 'A'; أما لتخزين السلاسل النصية المكونة من عدة محارف فاستخدم نوع البيانات string كما يلي: string str = "This is a C++ string"; ولتخزين القيم المنطقية التي يمكنها أن تحتوي القيمة صواب true أو خطأ false والتي تفيد في اختبار الشروط، استخدم نوع البيانات bool كما يلي: bool con1 = false; bool con1 = true; إن التعامل مع أنواع البيانات أبسط في لغات أخرى مثل لغة بايثون، فأنت لا تحتاج لتحديد نوع بيانات للمتغير قبل استخدامه، لكون اللغة قادرة على استنباط وتعيين نوع بيانات المتغير تلقائيًا بمجرد أن تسند له قيمة ما، فبحسب نوع القيمة التي تسندها تحدد اللغة نوع البيانات المناسب له. إليك بعض الأمثلة على تعريف متغيرات من أنواع بيانات مختلفة في بايثون: v1 = "This is a Python string" #string v2 = 10 #int v3 = 10.33 #float v4 = True #bool لمزيد من المعلومات حول أنواع البيانات في لغات البرمجة، اطلع على مقال دليلك الشامل إلى أنواع البيانات. الكلمات المفتاحية تتضمن أي لغة برمجة مجموعة من الكلمات المفتاحية Keywords أو الكلمات المحجوزة Reserved Words، وهذه الكلمات لها معنى خاص ولا يمكن للمبرمج استخدامها لتعريف المتغيرات مثلًا. ولعلك انتبهت إلى قولنا كلمة مفتاحية على const وعلى int في الأمثلة السابقة في لغة C++‎ التي كانت كلمات محجوزة مخصصة لتعريف الثوابت البرمجية وأنواع البيانات، كما تعد الكلمتان True و False محجوزتين في بايثون لتمثيل القيمتين المنطقيتين صواب وخطأ على التوالي وقس على ذلك في أي لغة برمجة. وعليك أن تطلع على الكلمات المفتاحية ودلالة كل كلمة وطريقة استخدامها في اللغة التي تريد تعلمها ويكون عادة عددها محدود وبسيطة وقد تتكون من كلمة إنجليزية واضحة أو اختصار لها مثل الاختصار const لكلمة constants ثابت والاختصار init لكلمة integer عدد صحيح ومعرفة مما يتشكل الاختصار يُسهل عليك حفظ الكلمة خصوصًا وبما أن عددها محدود وبسيطة فلا تخف إن كانت لغتك الإنجليزية ضعيفة. التعليقات تعد التعليقات Comments من أساسيات البرمجة، والتعليقات هي عبارة عن نصوص وصفية تضاف للكود البرمجي لتسهيل فهمه وقراءته ويمكن أن تكون بأي لغة مثل اللغة العربية، وهي لا تنفذ في البرنامج حيث أن مترجم اللغة يتجاهلها ويعتبرها فراغات، لكنها مفيدة للمبرمج نفسه ليتذكر ما كتبه عند العودة للبرنامج لاحقًا، كما أنها تساعد أي شخص يقرأ الكود الذي كتبه المبرمج في فهم سير عمل البرنامج والهدف من كتابة تعليمات معينة فيه. تستخدم لغات البرمجة المختلفة أساليب مختلفة لكتابة التعليقات تنحصر عادة بالرموز الثلاثة # أو // أو /* */، على سبيل المثال في لغة C++‎ يمكنك كتابة التعليقات على سطر واحد بعد الرمز // وكتابة التعليقات متعددة الأسطر بين الرمزين /* */ كما يلي: /* هذا تعليق مكون من عدة أسطر */ //هذا تعليق مكون من سطر واحد أما في لغة بايثون فيمكنك كتابة التعليق أحادي السطر بعد الرمز # وكتابة التعليقات متعددة الأسطر بعد علامتي اقتباس أو ثلاث علامات اقتباس مفردة كما يلي: ''' هذا تعليق مكون من عدة أسطر ''' #هذا تعليق مكون من سطر واحد بنى التحكم تنفذ البرامج عادة بشكل متتابع من بداية الشيفرة إلى نهايتها تعليمة تلو الأخرى، لكن قد تحتاج في بعض الحالات لتغيير مسار التنفيذ وتجاوز بعض التعليمات أو تكرارها، وهنا يأتي دور بنى التحكم Control Structures التي تعتبر من أساسيات البرمجة لكونها تفيد المبرمجين في تحديد الاتجاه أو المسار الذي يجب الانتقال له بناء على عوامل معينة. بالعودة إلى مثال تعلم القيادة الذي ذكرناه بداية، تخيل أنك تسير في طريقك نحو مقر عملك، وصادفت إشارة حمراء أو اعترضتك سيارة إسعاف، ألن تحتاج عندها للتوقف لحين عودة الإشارة إلى اللون الأخضر أو التنحي لجانب الطريق لحين مرور الإسعاف ثم تتابع طريقك المعتاد. بنفس الطريقة تعمل بنى التحكم في الكود البرمجي، فهي تسمح للمبرمج بالتحكم في تدفق تنفيذ البرامج وفق حالات معينة، ومن أهم بنى التحكم البنى الشرطية if statement والبنى التكرارية loop statement. البنى الشرطية أما البنى الشرطية فتمكنك من اختبار شروط محددة قبل تنفيذ الكود البرمجي وتقوم بتنفيذه فقط عند تحقق هذه الشروط، مثلًا إذا كان لديك تعليمات برمجية تتضمن عملية قسمة، يمكنك اشتراط عدم تنفيذ هذه التعليمات عند محاولة القسمة على صفر. على سبيل المثال يقوم البرنامج التالي بلغة C++‎ بقسمة عددين عشريين ويختبر شرط القسمة على صفر: #include <iostream> using namespace std; int main() { float num1, num2, result; num1=18; num2=0; if (num2 == 0) { cout << "خطأ رياضي أنت تحاول القسمة على صفر"<<endl; } else { result=num1/num2; cout << "The result is "<< result << endl; } return 0; } تختبر التعليمة الشرطية if في الكود أعلاه إن كان المقسوم عليه num2 مساويًا للصفر (الذي يمكن أن يأتي من مواضع مختلفة مثل الطلب من المستخدم تزويدنا بقيمته)، وفي هذه الحالة تعرض العبارة "خطأ رياضي أنت تحاول القسمة على صفر" ولا تنفذ عملية القسمة num1/num2. الكود التالي كود مكافئ للكود السابق لكنه مكتوب بلغة بايثون: num1 = 18 num2 = 3 if num2 == 0: print("خطأ رياضي أنت تحاول القسمة على صفر") else: result = num1/num2 print(result) الأمثلة أعلاه كانت لشروط بسيطة، وستجد في لغات البرمجة أنواعًا عديدة من التعليمات الشرطية مثل if-else التي تمكنك من اختبار الشرط وعكسه، وتعليمة if المتداخلة التي تتضمن شرطًا فرعيًا داخل شرط رئيسي، وتعليمة switch التي تختبر شروط معتمدة على قيمة واحدة. كما ستتمكن من اختبار شروط مركبة من خلال المعاملات المنطقية مثل and و or و not. البنى التكرارية وأما البنى التكرارية أو حلقات التكرار فتمكنك من تكرار تنفيذ تعليمات معينة لعدد محدد أو مشروط من المرات، وتوفر على المبرمجين الكثير من الوقت في كتابة الكود. ستجد في أي لغة برمجة أنواعًا مختلفة من الحلقات مثل حلقات for التي تستخدم عندما تعرف عدد المرات التي تريد فيها تكرار التعليمات قبل التوقف، وحلقات while أو repeat التي تتشابه مع حلقات for لكنها تكرر مجموعة من التعليمات بعدد غير محدد من المرات يعتمد على استيفاء شرط معين. على سبيل المثال، إذا طلب منك أن تكتب برنامج لعرض ناتج ضرب العدد 5 بالأعداد من 1 إلى 10 فلا حاجة لأن تضرب العدد 5 في العدد 1 ثم في العدد 2 وهكذا وصولًا للعدد 10، يمكنك ببساطة كتابة حلقة تكرارية for كما في المثالين التاليين: حلقة for بلغة C++‎: int num=5; for (int i = 1; i < 11 ;i++) cout << num <<"X" << i << "="<< num*i << "\n"; حلقة for بلغة بايثون: num = 5 for i in range(1, 10): print(num, 'x', i, '=', num*i) الدوال الدوال Functions هي أجزاء مستقلة من الكود البرمجي لها اسم خاص بها وتشبه المصنع في عملها فتأخذ ممن يستخدمها دخلًا (إن وُجد) ثم تجري عمليات معالجة وتعيد إليه الناتج، ويدعى ما يُمرَّر إليها باسم المعاملات Parameters. تُكتب الدالة أو تعرّف مرة واحدة وتصبح بعدها قابلة لإعادة الاستخدام، حيث يمكن للمبرمج استدعاء أو مناداة الدالة في أي موضع في البرنامج مع تمرير قيم بيانات لها أو بدون، على سبيل المثال في حال أردت كتابة كود برمجي يعرض ناتج الضرب لعدد ما في الأعداد من 1 إلى 10 يمكنك تحويل الكود إلى دالة باسم displayMul وسيطها هو العدد المراد ضربه كما يلي: #include <iostream> using namespace std; // تعريف دالة لحساب نانج ضرب أي عدد في الأعداد من واحد لعشرة void displayMul(int num){ for (int i = 1; i < 11 ;i++) cout << num <<"X" << i << "="<< num*i << "\n"; } //استدعاء الدالة في البرنامج الرئيسي int main() { int num1 = 5; displayMul(num1); int num2 = 9; displayMul(num2); return 0; } عرفنا الدالة displayMul في المثال السابق بلغة C++‎ بكتابة نوع البيانات الذي تعيده الدالة وهو void أي لا شيء لأن الدالة تطبع القيمة ولا تعيد شيئًا، ثم اسمها ثم المعاملات الخاصة بها بين قوسين ()، ثم كتبنا التعليمات التي تقوم بها بين قوسين { }، ولاحظ أن الدالة لا تعيد شيئًا فلا يُشترط أن تأخذ أو تعيد شيئًا بل المهم أن تُنفِّذ عمليةً ما منوطة بها عند استدعائها. إليك أيضًا تعريف الدالة displayMul السابقة نفسها ولكن بلغة بايثون: def displayMul(num): for i in range(1, 10): print(num, 'x', i, '=', num*i) num = 5 displayMul(num) displayMul(9) ملاحظة: لا يمكنك استدعاء أو مناداة دالة في برنامجك إذا لم تقم بتعريفها أولًا، لأنك تحاول استخدام شيء غير موجود، لكن بعض الدوال تكون مضمنة ومعرفة مسبقًا في اللغة Built-in functions، ويمكنك استخدام هذه الدوال فورًا دون الحاجة لتعريفها بنفسك، على سبيل المثال الدالة "getline()‎"هي دالة جاهزة معرفة في لغة C++‎ تستخدم لإدخال السلاسل النصية من لوحة المفاتيح، والدالة print()‎ هي دالة جاهزة في لغة بايثون تستخدم لطباعة قيم المتغيرات على الشاشة. هياكل البيانات هياكل البيانات Data Structures هي بنى برمجية مصممة لتضم مجموعة من البيانات أو المتغيرات، وقد تكون هياكل أولية كالأعداد الصحيحة والأعداد العشرية والمحارف كما شرحنا في أنواع البيانات، أو هياكل مركبة يمكن تشبيهها بمجموعة صناديق متلاصقة في ذاكرة الحاسوب باستطاعتها تخزين عناصر أو متغيرات متعددة من نفس نوع البيانات ويمكن لبعض هياكل البيانات أن تتضمن مزيجًا من أنواع بيانات مختلفة. فالمصفوفة Array، والقاموس Dictionary والكائن Object وغيرها أحد أنواع هياكل البيانات الشهيرة، على سبيل المثال يمكنك استخدام المصفوفات عندما تحتاج إلى تخزين مجموعة مكونة من عدة قيم لها نفس النوع في متغير واحد بدلًا من تخزين كل قيمة في متغير منفصل، ويمكنك بعدها تحديد أي عنصر من العناصر الموجودة في المصفوفة والوصول له من خلال موقعه أو فهرسه داخل هذه المصفوفة، وإليك مثال على تعريف مصفوفة لتخزين 5 أعداد صحيحة: في لغة C++‎: int marks[5] = {50,99,78,66,59}; في لغة بايثون: marks=[50,99,78,66,59] ملاحظة: قد تختلف أسماء هياكل البيانات من لغة برمجة إلى أخرى ففي لغة بايثون لا يُطلق عليها اسم مصفوفة array كما في لغة C++‎ بل اسم قائمة list حيث تختلف التسميات والمعنى واحد. هنالك العديد من هياكل البيانات التي لا يتسع المقال الحالي لذكرها، لذا ارجع إلى مقال هياكل البيانات لمزيد من التفاصيل. التكرار يعتبر مفهوم التكرار Iteration أحد أهم مفاهيم أساسيات البرمجة، وستحتاج له لاسيما عند التعامل مع هياكل بيانات مركبة في شيفراتك البرمجية مثل المصفوفات، فالتكرار يعني المرور على كل عنصر من عناصر البيانات المركبة على حدة وعلى التوالي لتنفيذ عملية أو مهام محددة عليه، وستجد أن التكرار صفة أيضًا تُسمى iterable تُطلق على أي متغير أو نوع بيانات يمكن المرور عليه وستراها غالبًا في التوثيقات. يمكنك تنفيذ التكرار في لغات البرمجة بطرق مختلفة، لكنه يعتمد بشكل أساسي على استخدام الحلقات التكرارية بأنواعها المختلفة، كما توفر بعض اللغات مكررات Iterators وهي عبارة عن دوال أو عمليات مخصصة تمكنك من المرور على جميع عناصر هياكل البيانات بطريقة منهجية وسهلة. على سبيل المثال للمرور عبر عناصر المصفوفة marks التي عرفناها في الفقرة السابقة وطباعتها في لغة C++‎ يمكن أن نكتب حلقة for مع استخدام متغير i يمثل تعدادًا نستخدمه كفهرس للوصول إلى كل عنصر من عناصر المصفوفة كما يلي: #include <iostream> using namespace std; int main () { int marks[5] = {50,99,78,66,59}; cout << "The marks are:"; for (int i = 0; i < 5; ++i) { cout << marks[i] << " "; } } أما في لغة بايثون يمكنك المرور عبر عناصر المصفوفة وطباعتها كما يلي: marks=[50,99,78,66,59] for m in marks: print(m) التعاود يعتبر التعاود Recursion أحد المفاهيم البرمجية الأساسية، وهو يعتمد على تقسيم المشكلات البرمجية إلى مشكلات أصغر يمكن حلها بسهولة، ويرتبط هذا المفهوم بالدوال البرمجية، حيث أن الدالة التي تكرر استدعاء نفسها حتى تصل لحالة حدية أو أساسية Base case تجعلها تتوقف عن عملية استدعاء نفسها وتعيد نتيجة معروفة عند هذه القيمة تعرف باسم الدالة التعاودية Recursive Function، وإذا لم تكن هناك حالة حدية تصل لها الدالة فهذا يعني أن الدالة ستكرر استدعاء نفسها إلى مالا نهاية. هذا الأسلوب البرمجي يصلح لحل المسائل التي تملك نمطًا هرميًا والتي يمكن حلها بسهولة عن طريق تحويلها لمسائل فرعية مشابهة أصغر. لكن في حال كان بإمكانك حل مسألة معينة عن طريق الحلقات التكرارية بسهولة فلا توجد ضرورة لاستخدام أسلوب التعاود في هذه الحالة، ولا تقلق إن لم تفهم شيئًا فقد أضفنا مثالًا مع مخطط يوضح لك المفهوم تاليًا. على سبيل المثال مسألة حساب عاملي أو مضروب عدد ما "n!‎" هي أشهر مسألة تعاودية بطبيعتها، فكما تعرف مضروب العدد 0 هو قيمة معروفة تساوي 1، وبالتالي يمكن اعتبار n=0 هو الحالة الحدية التي يمكن من خلالها حل مسألة المضروب لأي عدد بناء على القاعدة التالية: n! = n * (n - 1) عندما تبلغ قيمة العدد n=0 فسوف يعيد القيمة 1 للدالة وينتهي الاستدعاء المتكرر أو التعاودي لها. إليك مثال على إيجاد مضروب أو عاملي العدد n: بلغة C++‎: #include <iostream> using namespace std; int factorial(int n) { if (n < 0) { return 0; } else if (n == 0) { return 1; } else { return factorial(n - 1) * n; } } // استدعاء الدالة في البرنامج الرئيسي int main() { cout<< factorial(4); } بلغة بايثون: def factorial(n): if n < 0: return 0 elif n == 1: return 1 else: return n * factorial(n-1) print (factorial(4)) المخطط التالي يوضح طريقة استدعاء الدالة التعاودية وإعادتها للقيمة عند وصولها للحالة الحدية لا تقلق مرة أخرى إن لم تفهمه فهو من المفاهيم المعقدة والمرعبة للمبرمجين المبتدئين، وستفهمه تدريجيًا ولا يمكن أن يتضح بالكامل إلا إن طبقته وحتى رسمته على ورقة أو مخطط كما المخطط السابق. الكائنات والأصناف تعتبر الكائنات Objects والأصناف Classes أحد أساسيات البرمجة كائنية التوجه "OOP" حيث أن الكائنات تعتبر وحدات تتضمن مجموعة من المتغيرات ومجموعة الدوال البرمجية. والصنف Class هو بمثابة نموذج أو مخطط عام لتمثيل الكائنات، يمكن تعريفه واستخدامه لاشتقاق العديد من الأمثلة أو الحالات المختلفة من هذه الكائنات، ولهذا السبب يسمى الكائن نسخة من الصنف "instance". لنأخذ مثالًا من الواقع، يمكنك تعريف صنف يسمى Car لتمثيل السيارة، سيكون لهذه السيارة خصائص مختلفة تميزها كاللون والنوع والطراز وسنة التصنيع والسعر …إلخ. كما سيكون لها أفعال أو سلوكيات تقوم بها كفعل التشغيل وزيادة السرعة وتغيير الاتجاه والتوقف …إلخ. لذا نعرف صنفًا خاصًا يمثل السيارة ونشتق منه نسخ لسيارات مختلفة. برمجيًا يعرف الصنف بداخله متغيرات ودوال، وتحدد المتغيرات الخاصة بالصنف مميزات هذا الصنف بينما تحدد دوال الصنف "class functions" ما الذي يمكن للكائنات القيام به كما يحوي الصنف على دوال خاصة منها دالة تُدعى الدالة البانية "constructor" التي تُستدعى تلقائيًا عند إنشاء واستنساخ كائن من الصنف المُعرَّف ويمكن عبرها تمرير قيم تضبط الكائن الجديد الناتج مثلًا تضبط متغيراته وإليك مثال لتوضيح ذلك. على سبيل المثال، يمكن تعريف صنف يمثل هيكل دائرة، سنعرف لهذا الصنف متغير خاص به أو خاصية تمثل قيمة نصف قطر الدائرة، ودالة بناء تضبط قيمة نصف القطر أثناء إنشاء كل دائرة، ودالة لحساب مساحة الدائرة، ودالة أخرى لحساب محيط الدائرة يمكن استدعاءهما بعد إنشاء كل كائن من الصنف دائرة. المثال التالي يعرف صنف يمثل دائرة بلغة البرمجة C++‎ ويشتق نسختين أو كائنين مختلفين من هذا الصنف لكل كائن نصف قطر مختلف: #include<iostream> using namespace std; class Circle { const float PI = 3.14; // data members float radius; public: // contractor Circle(float radius) { this->radius = radius; } // member function float Area() { return radius*radius*PI; } float Perimeter() { return 2*radius*PI; } }; int main() { Circle circle1(3); cout << circle1.Area() << endl; cout << circle1.Perimeter() << endl; Circle circle2(4); cout << circle2.Area() << endl; cout << circle2.Perimeter() << endl; return 0; } والمثال المكافئ التالي بلغة بايثون يعرف صنف دائرة ويشتق كائنين منه: #تعريف صنف يمثل دائرة class Circle(): def __init__(self, radius): self.radius = radius def get_area(self): return (self.radius ** 2) * pi def get_perimeter(self): return self.radius * 2 * pi # إنشاء كائنات من الصنف Circle pi = 3.14 circle1 = Circle(3) print(circle1.get_area()) print(circle1.get_perimeter()) circle2 = Circle(4) print(circle2.get_area()) print(circle2.get_perimeter()) لا تقلق إن لم تفهم شيئًا مما سبق فمهوم الأصناف والكائنات مفهوم دسم معقد على المبتدئين، ولكن حاول إعادة قراءة الفقرة وتطبيق الأمثلة أو يمكنك تخطيه ببساطة فالمهم أنك تعرفت على المفهوم، أما إن أردت المزيد من التفاصيل، فارجع إلى مقال البرمجة كائنية التوجه من سلسلة تعلم البرمجة. الوحدات والمكتبات لعلك لاحظت عبارات تبدأ بالكلمة using أو include أو import في الأمثلة البرمجية السابقة وتساءلت عن أهمية وجودها! هذه العبارات ليست سوى أمثلة على استخدام وحدات ومكتبات جاهزة مختلفة في لغات البرمجة. تعتبر الوحدات Modules والمكتبات Libraries أحد مفاهيم أساسيات البرمجة التي من الضروري أن تعيها جيدًا، والهدف الأساسي من وجودها تسهيل كتابة التعليمات البرمجية وتمكين المبرمج من إعادة استخدامها دون الحاجة إلى كتابة التعليمات البرمجية الخاصة بها في الكود من جديد. فالمكتبات والوحدات توفر على المبرمجين إعادة اختراع العجلة وتمكنهم من التركيز على حل المشكلة بسهولة ومرونة أكبر. توفر كل لغة برمجة العديد من المكتبات التي تضم مجموعة من الدوال والأصناف والوحدات التي يمكنك استخدامها مرارًا وتكرارًا في التعليمات البرمجية الخاصة بك لأداء مجموعة من الوظائف المفيدة دون الحاجة لإنشائها من البداية، كما يمكنك تعريف الوحدات الخاصة بك. هناك العديد من الوحدات المضمنة في لغة بايثون مثلًا والتي يمكنك استيرادها بكتابة التعليمة import ولنضرب مثلًا باستيراد الوحدة math للاستفادة من الدوال الرياضية التي توفرها بالشكل التالي: import math print (math.sqrt(25)) print (math.pi) print (math.degrees(2)) print (math.radians(90)) print (math.sin(2)) print (math.cos(0.5)) إلى هنا نكون قد انتهينا من شرح أساسيات البرمجة للمبتدئين والتي تناولنا فيها أهم المفاهيم التي ستتعرف عليها بالتفصيل في أي لغة برمجية تنوي تعلمها قبل أن تتمكن من تطوير برامجك وتطبيقاتك بهذه اللغة. ونختم مقالنا بأهم النصائح والتوصيات التي تساعدك على تعلم هذه الأساسيات. 10 نصائح لتعلم أساسيات البرمجة إليك مجموعة نصائح سريعة تساعدك في رحلة تعلم البرمجة: حدد هدفك من تعلم البرمجة، ثم تعلم ما يلزمك من تقنيات لتحققه. لا تشتت نفسك بكثرة اللغات والتنقل بينها وركز على المفاهيم وطبقها بلغة واحدة بإتقان وتركيز. ضع خطة للتعلم والتزم بها دون تسويف. لا تضيع وقتك في البحث عن أفضل المصادر التعليمية والتنقل بينها بل اختر واحدًا فقط والتزم به للنهاية. طور مهارات البحث الفعال فهذا سيوفر عليك وقتًا كبيرًا ويساعدك في إيجاد حلول لمشاكلك البرمجية. رافق المجدين ومن يشاركونك الهدف والاهتمام نفسه فإن الصاحب ساحب كما يُقال. لا تتوقف عن التعلم وطور نفسك باستمرار. تحلَّ بالصبر والأناة فإن العلم بالتعلّم والحلم بالتحلّم. تقبل الفشل والخطأ فالفشل هو وسيلة للنجاح. طبق ثم طبق ثم طبق ما تتعلمه. الخلاصة تطرقنا في مقال اليوم لشرح أساسيات البرمجة للمبتدئين وتعرفنا على أهم المفاهيم البرمجية التي ستصادفك عند تعلم أي لغة من لغات البرمجة وذكرنا في الختام أهم الأسس والنصائح التي تساعد أي مبرمج لتعلم أساسيات البرمجة من الصفر حتى الاحتراف. قد لا تتمكن من هضم جميع المفاهيم مرة واحدة خصوصًا إن كنت مبتدئًا، لذا ارجع للمقال مرة ومرتين حتى تتأكد من استيعابك لتلك المفاهيم وضعه ضمن قائمتك المفضلة وطبق الأمثلة بلغة البرمجة التي تتعلمها أو تريد تعلمها. وإذا كان لديك أي تساؤلات حول أي شيء مر معك في المقال أو كنت قد بدأت فعلا بتعلم إحدى لغات البرمجة ولديك نصائح مفيدة تود أن توجهها للمبتدئين في تعلم البرمجة، نرحب بأن تشاركنا بها في التعليقات أسفل المقال. اقرأ أيضًا أسهل لغات البرمجة البرمجة كائنية التوجه دليلك الشامل إلى: برمجة التطبيقات فوائد تعلم البرمجة
  13. لكل مهنة قواعد تنظمها وتضمن إنجاز الأعمال فيها بأفضل صورة ممكنة، ومهنة البرمجة ليست استثناء! حيث تعد قواعد البرمجة من الأمور التي ينبغي على أي مبرمج تعلمها، والحرص على اتباعها عند تطوير البرامج والتطبيقات المختلفة. نضعك في مقال اليوم على بداية الطريق، ونعرفك على أهم قواعد البرمجة، ونوضح لك أهمية استخدامها وكيف يمكنك تحقيقها، وبالتدريب والممارسة ستتمكن من اتباعها عندما تطور برامجك وتطبيقاتك. ما هي قواعد البرمجة؟ قواعد البرمجة هي مجموعة من التوصيات والإرشادات التي ينبغي للمبرمجين اتباعها والالتزام بها عند استخدام أي لغة من لغات البرمجة للحصول على كود برمجي عالي الجودة وسهل الصيانة. يضمن لك تطبيق قواعد البرمجة إنتاج برامج مفهومة وواضحة وسهلة القراءة والتعديل، وهو أمر مهم لأي مبرمج لاسيما عندما يعمل ضمن فريق عمل ويتشارك مع عدة مبرمجين أو مطورين على تطوير نفس المشروع. لاشك أن تطبيق قواعد البرمجة ليس بالأمر السهل ولن يتحقق بسرعة، فتطبيق القواعد يأتي في مرحلة لاحقة، فبعد أن تتمكن من أساسيات البرمجة، وتتدرب على طريقة التفكير البرمجي، وحل المشكلات، عليك أن تتقدم خطوة للأمام وتتعلم كيف تحسن من برامجك من خلال تطبيق القواعد البرمجية عليها. سنعرض الآن عددًا من أهم قواعد البرمجة فكن جاهزًا! أهم قواعد البرمجة إليك أهم ثمان قواعد أساسية ينبغي عليك اتباعها لتبرمج كالمحترفين: اتبع القواعد العرفية للغة التي تبرمج بها وثق الكود الذي تكتبه حافظ على البساطة KISS لا تكرر نفسك DRY ادمج الأجزاء الصغيرة لإنجاز الأعمال الكبيرة لا تبرمج ما لا تحتاجه افصل الأكواد في أجزاء مستقلة اكتب أكوادًا نظيفة نشرح في الفقرات التالية كل قاعدة من قواعد البرمجة هذه بمزيد من التفصيل ونوضح أهميتها وكيفية تطبيقها عند تطوير البرامج والتطبيقات. اتبع القواعد العرفية للغة التي تبرمج بها لكل لغة من لغات البرمجة قواعد كتابة خاصة بها تعرف باسم صياغة، واتباع هذه القواعد عند كتابة الكود البرمجي ليس خيارًا للمبرمج، لأن الكود البرمجي لن يعمل بشكل صحيح إذا لم يكن مكتوبًا وفق هذه القواعد. فليس المقصود هنا صياغة اللغة وقواعدها، ولكن ما أقصده هو مراعاة اصطلاحات اللغة المتعارف عليها أو ما يسمى في أوساط المبرمجين باسم "العرف" Conventions، فلكل لغة قواعد اصطلاحية متعارف عليها بين مبرمجي تلك اللغة، مثل ضرورة كتابة كل تعليمة على سطر جديد، ومراعاة قواعد التباعد، وأماكن وضع الأقواس مثل () و {} ضمن البرنامج، ووضع المسافات البادئة في كل سطر، وقواعد تسمية المتغيرات والدوال والأصناف …إلخ. هذه الأمور تتغير من لغة إلى لغة وليس لها معيار موحد، لذا عليك التعرف على اصطلاحات اللغة التي تبرمج بها وتحرص على اتباعها، فإن انتقلنا مثلًا إلى لغة جافاسكربت، فيعرض مقال نمط كتابة شيفرة جافاسكربت هذا الموضوع بالتفصيل ويتحدث عن العرف المتبع بين مبرمجي لغة جافاسكربت كما يشير أخيرًا في فقرة "شروحات لأنماط كتابة الشيفرة" أشهر المعايير والأعراف العالمية للغة جافاسكربت منها أسلوب Google وأسلوب Airbnb والأسلوب المعياري الرسمي وغيرها، فلا حاجة لكل فريق أي يخترع عرفًا ومعيارًا يسير عليه بل يقتدي بعرف شهير شائع منظم موجود مسبقًا. أضرب مثلًا عن أسلوب Airbnb في تعريف المتغيرات في لغة جافاسكربت بالشكل التالي: // سيء const items = getItems(), goSportsTeam = true; // جيد const items = getItems(); const goSportsTeam = true; لاحظ أن تعريف متغير واحد في كل سطر هو الأسلوب المتبع ويجب تجنب تعريف عدة متغيرات في سطر واحد رغم أنه لا فرق في التنفيذ بينهما. أتريد مثلًا آخر؟ خذ هذا المثال أيضًا من أسلوب PEP8 في لغة بايثون: # Line Break with Binary Operator # سيء income = (gross_wages + taxable_interest - student_loan_interest) # جيد income = (gross_wages + taxable_interest - student_loan_interest) # Imports # سيء import sys, os # جيد import os import sys قد تجد أن الاختلاف بسيط أحيانًا بين العُرف الجيد المتبع وبين الأسلوب السيء في كتابة الشيفرة وهذا صحيح، ولكن تذكر أن الشيفرة لا تُكتب مرة واحدة فقط ولن يعمل عليها شخص واحد فقط، بل ستُعدل مرارًا وتكرارًا ويمر عليها عشرات المبرمجين فإن اتبع كل مبرمج أسلوبه الخاص فُقد التنظيم وسادت العشوائية وأصبحت الشيفرة عرضة للخطأ عند تعديلها. وتذكر دومًا أن العُرف هذا يضعه مبرمجون أصحاب خبرة بعشرات السنوات يحاولون به نقل خبرتهم أفضل طريقة لكتابة شيفرة متسقة سهلة القراءة والتعديل وأقل عرضة للأخطاء. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن وثق الكود الذي تكتبه هذه القاعدة على بساطتها مفيدة للغاية، فمن الضروري أن تعتاد على كتابة تعليقات توضيحية في الأكواد التي تكتبها لتوثيق عملك، وتشرح ما الذي تقوم به، وتوضح وظائف الدوال والأصناف والمكتبات المختلفة. التعليقات أمر مهم لكل مبرمج، فهي من جهة تساعده على فهم ما كتبه عند العودة له لاحقًا لأن المبرمج سينسى الكثير مما كتبته ولماذا كتبته بعد مرور فترة من الزمن، كما أن التعليقات تفيد أي مبرمج آخر يقرأ الكود في فهمه بسرعة في حال احتاج إلى تطويره أو التعديل عليه. ومن الضروري أن تتعلم أفضل ممارسات كتابة التعليقات على الكود الخاص بك، وتعرف متى وأين يتوجب عليك كتابة التعليقات ومتى لا يلزمك ذلك. اكتب التعليقات عندما تحتاج لوصف أي ميزة غير واضحة في التعليمات البرمجية، وفي أي موضع ترى أنه يتطلب المزيد من الشرح والتوضيح للآخرين، أما عندما يكون الهدف من الكود واضحًا ومفهومًا فيمكنك الاستغناء عن كتابتها. باختصار التعليقات تساعد المبرمجين على فهم المشكلات التي كنت تحاول حلها في تعليماتك البرمجية دون الحاجة لبذل كثير من الجهد لفهم واستنباط ما كتبته ولكن الأفضل من كتابة التعليقات أن تكتب شيفرة مفهومة بدون تعليقات وهذه هي القاعدة دومًا. حافظ على البساطة KISS قاعدة KISS هي اختصار لعبارة "Keep It Simple, Sweetie" التي تعني أبقها بسيطة يا عزيزي! أو أبقِ أكوادك بسيطة ومباشرة، وهذه القاعدة تطبق عند تصميم كافة الأنظمة البرمجية فقد تبين أن هذه الأنظمة تعمل بشكل أفضل إذا كانت بسيطة وخالية من التعقيد. فإذا كنت تستطيع أن تحل مشكلة ما بعشرة أسطر من الكود البرمجي لا داعي لأن تكتب خمسين سطرًا لحلها، وإذا كنت تحتاج لبرمجة نموذج ما يحتوي 10 حقول، فلا تضع فيه 20 حقلًا من البيانات التي لن تقدم أي فائدة في سير عمل برنامجك. الخلاصة، إذا كنت تطور أحد البرامج وكنت تستطيع تجنب التعقيد في كتابة الكود، فتجنبه قدر الإمكان، واحرص على إبقاء الأكواد البرمجية التي تكتبها فيه بسيطة، وتلبي المتطلبات قدر المستطاع. لا تكرر نفسك DRY من قواعد البرمجة الهامة قاعدة DRY وهي اختصار للعبارة "Don't Repeat Yourself" التي تعني لا تكرر نفسك، والتي تؤكد على المبرمج أن لا يكرر كتابة نفس الكود البرمجي مرارًا وتكرارًا، وينبغي عليه عند وجود هذه الحالة أن يتخلص من هذا التكرار بطريقة ما. لا مشكلة من تكرار نفس الكود مرة واحدة، ولكن عندما تستخدم نفس الكود عدة مرات في مواضع مختلفة من برنامجك فعليك أن تفكر في تعديله، وتجد طريقة ذكية لكتابة الكود مرة واحدة وإعادة استخدامه كلما احتجت له لتكون مطبقًا لهذه القاعدة. من المنهجيات البرمجية التي تساعدك على تقليل الكود البرمجي المكرر وجعل برامجك سهلة القراءة والصيانة هي استخدام الحلقات التكرارية التي تجنبك تكرار نفس التعليمات البرمجية وتجعل الكود البرمجي أقصر، وأيضًا استخدام الدوال والإجراءات البرمجية، وتعريف المكتبات والوحدات البرمجية التي تغلف شيفراتك البرمجية وتمكنك من إعادة استعمالها كلما أردت. ستدرك أهمية هذه القاعدة البرمجية إذا احتجت لإجراء تعديل ما في هذا الكود البرمجي المكرر، أو اكتشفت فيه خطأً ما وأردت تصحيحه، عندها سيتوجب عليك إجراء التعديلات في جميع الأماكن التي قمت فيها بإدراج هذا الكود وسيكون الأمر مرهقًا وغالبًا ستنسى ما قد كتبته حقًا، و قد لا تعدله أنت بل يعدله مبرمج آخر قد لا يفطن للتكرار مما يولد أخطاء مستقبلية. وبالتالي عندما تطور برنامجًا لحل مشكلة ما، وتجد أنك تقوم بالكثير من عمليات النسخ واللصق لنفس الكود لاستخدامه في أكثر من موضع، فابحث عن طريقة أخرى لكتابة هذا الكود، وفكر كيف يمكن أن تتجنب تكرار نفسك. ادمج الأجزاء الصغيرة لإنجاز أعمال أكبر يعتبر الدمج Composition من قواعد البرمجة المهمة، وهو يعني تجزئة المسائل البرمجية إلى مجموعة عناصر أصغر، كل جزء يقوم بمهمة محددة وواضحة، بعدها يتم دمج هذه الأجزاء لتشكيل جزء أكبر وأكثر تعقيدًا ينجز العمل بأكمله. يمكنك على سبيل المثال تطبيق هذه القاعدة إذا كنت مطور واجهة أمامية وتريد تطوير واجهة تطبيق ما وكتابة الكود البرمجي اللازم لتحقيق تصميم معين، حيث يمكنك تحويل كل عنصر من عناصر التصميم إلى مكون مستقل له الكود الخاص به، ثم تجمع هذه المكونات مع بعضها في النهاية لتحصل على التصميم الكامل. كما يتم تطبيق هذا المبدأ بشكل واضح في البرمجة كائنية التوجه OOP، من خلال تعريف صنف Class مستقل لكل جزء أو سلوك محدد من نظامك البرمجي، وجعل هذه الأصناف تتعاون مع بعضها لتنجز العمل المطلوب. باتباع هذه القاعدة ستوفر على نفسك كتابة أكواد ضخمة ومعقدة وصعبة الفهم. وتركز على برمجة كل مكون ليقوم بشيء واحد فقط، وإذا احتجت لتعديل جزء ما في برامجك فستعدل فقط الأجزاء التي طرأ عليها التعديل بكل سلاسة. فإذا كانت لديك شيفرة برمجية ضخمة لمكون ما في أحد برامجك تنجز عدة أمور مختلفة في نفس الوقت، فكر إن كان بالإمكان تقسيمها لأجزاء منفصلة أكثر تحديدًا. لا تبرمج ما لا تحتاجه من أهم قواعد البرمجة التي عليك اتباعها قاعدة YAGNI وهي اختصار للعبارة "You Aren't Gonna Need It" التي تعني أنت لن تحتاجها! لذا لا تقم ببرمجتها. فلا ينبغي عليك أن تكتب في برامجك أي أكواد لإنجاز مهام أو وظائف معينة تحل من خلالها مشكلة غير موجودة بالأساس، أو تضيف ميزة لا تحتاجها الآن لكنك تتوقع أنك ستحتاجها في مرحلة لاحقة. فإذا طلب منك على سبيل المثال كتابة كود برمجي يتحقق من صحة البريد الإلكتروني وكلمة المرور عند تسجيل دخول المستخدمين، فلا داعي لأن تتحقق أيضًا من صحة اسم المستخدم ورقم هاتفه لأنك قد لا تحتاج لهذا أبدًا. باختصار، كي تطبق هذه القاعدة ركز فقط على كتابة القدر المطلوب من الكود البرمجي الذي يحقق متطلباتك الحالية بالضبط بلا زيادة ولا نقصان، ولا داعي لأن تستشرف المستقبل. افصل الأكواد في أجزاء مستقلة يطلق على هذه القاعدة اسم فصل الاهتمامات "Separation of Interests" وهي من قواعد البرمجة الضرورية، وتؤكد على أهمية تصميم البرنامج ضمن وحدات أو أجزاء فريدة معزولة عن بعضها البعض. يعتبر أسلوب نموذج وعرض ومتحكم MVC من أوضح الأمثلة على تطبيق هذه القاعدة، ففي هذا النموذج يتم تنظيم كود البرامج ضمن ثلاثة أجزاء هي: النموذج Model الذي يتفاعل مع البيانات ويجلبها من قاعدة البيانات، والعرض View الذي يمثل الواجهة المرئية التي يتفاعل معها المستخدم بشكل مباشر، والمتحكم Controller الذي يمثل الوسيط بين العرض والنموذج ويربط بينهما. فالمتحكم يتلقى طلبات المستخدم من العرض أو واجهة المستخدم، ويعالجها، ثم يتصل بالنموذج ويطلب منه جلب ما يريده المستخدم من قاعدة البيانات، ثم يعيد النتيجة مرة أخرى إلى العرض ويظهرها على واجهة المستخدم. عند كتابة برامجك بهذا الأسلوب لن يحتاج الكود البرمجي الذي يتعامل مع قاعدة البيانات إلى معرفة تفاصبل عمل كود عرض البيانات، فكود العرض يحصل على المدخلات من المستخدم، وكود المتحكم يعالج هذه البيانات، وبهذا يكون كل جزء من الكود مستقلًا تمامًا. إن اتباع هذه القاعدة في البرمجة يمكنك من الحصول على كود برمجي سهل التطوير والصيانة، فإذا احتجت على سبيل المثال إلى إعادة كتابة كود العرض، فيمكنك القيام بذلك أن يتأثر أي شيء في كود حفظ ومعالجة البيانات. هذا الأسلوب يستخدم في العديد لغات البرمجة وأطر العمل، فمن لغات البرمجة التي تستخدم نموذج MVC لغة C++‎ و‎C# ‎ و Java و Ruby …إلخ. ومن أطر العمل التي تستخدم نموذج MVC إطار العمل أنجولر Angular وجانغو Django وفلاسك Flask ولارافيل Laravel …إلخ.‏‏‏‏‏ اكتب أكوادًا نظيفة تعد قاعدة كتابة الأكواد البرمجية النظيفة والمفهومة وسهلة الصيانة مهارة ضرورية على كل مبرمج إتقانها، ويشير مصطلح الكود النظيف Clean Code ببساطة إلى الكود سهل القراءة والفهم من قبل المبرمجين الآخرين، وعادةً عندما تتبع كافة قواعد البرمجة التي وردت أعلاه ستحصل بالنتيجة على كود نظيف بصورة تلقائية. احرص كذلك على تنظيف أكوادك من كافة التعليمات لن تستخدم عند تنفيذ البرنامج، واحذف المتغيرات التي صرحت عنها لكنك لم تستخدمها، والدوال البرمجية التي عرفتها لكنها لم تنادها على الإطلاق، والأصناف التي لم تشتق منها أي كائنات برمجية، وكذلك الأكواد التي كتبتها ثم حولتها إلى تعليقات ضمن الكود لإبطال عملها …إلخ. فهذه كلها أكواد ميّتة وأنت لا تريد أن تجعل برنامجك مقبرة! وكي تعرف بسهولة إن كان الكود الذي تكتبه نظيفًا، اعرضه على مبرمج آخر لم يسبق له أن اطلع عليه واطلب منه تعديل أمر ما فيه، فإذا تمكن المبرمج من فهم الغرض من التعليمات البرمجية الخاصة بك، وعدلها وأضاف أكواده الخاصة عليها بسهولة ومرونة، فهذا يعني أن كتبت بالفعل كودًا نظيفًا. وتذكر أن كتابة الكود النظيف ليس مهارة يمكن اكتسابها بين عشيّة وضحاها بل هو ميزة يتم تطويرها بالممارسة والتدرب على تطبيق كافة هذه القواعد كلما قمت بكتابة كود برمجي ما حتى تكتسب الخبرة المطلوبة. ملخص لأهم قواعد البرمجة التي ينبغي للمبرمج اتباعها نعرض ما يلي ملخص قواعد البرمجة التي ذكرناها ليسهل عليك تذكرها وحفظها: احرص على كتابة كود سهل القراءة والفهم مع إضافة التعليقات التوضيحية إن لزم فهي ضرورية لتوثيق وتسهيل فهم الكود وصيانته عند العودة له لاحقًا. اكتب أكوادًا بسيطة ومباشرة والمقصود هنا أن تصمم برامجك ببساطة، وتحذف أي ميزة لا تحتاجها، فالأنظمة البرمجية تعمل بشكل أفضل وتكون أسهل في الصيانة كلما كانت أبسط. افصل الأكواد في أجزاء معزولة بحيث يكون كل جزء مسؤولًا على إنجاز مهمة محددة. لا تكرر نفسك ولا تنسخ وتلصق نفس الكود في أكثر من موضع، بل اكتبه مرة وأعد استخدامه كلما دعت الحاجة. لا تضف ما لن تحتاجه كي لا تهدر وقتك ومالك على أشياء لمجرد أنك تتوقع أنك ستحتاجها لاحقًا، فقد لا تحتاجها أبدًا. اكتب كودًا نظيفًا غير مكرر أو معقد، وهو ما ستحصل عليه إذا اتبعت كل القواعد السابقة. ماذا سيحصل لو لم أتبع قواعد البرمجة؟ عندما تبدأ تعلم البرمجة ستكون سعيدًا عندما يعمل أي برنامج بالشكل الصحيح، وقد لا تعير اهتمامًا لمدى أهمية اتباع قواعد البرمجة، لكن يجب أن تضع في الحسبان أنك إذا لم تعتد على اتباع القواعد الصحيحة في كتابة أكوادك البرمجية، فإن هذا سينعكس سلبًا على أداء برامجك على المدى البعيد. في تلك الحالة قد تحصل على كود سيء وفوضوي وغير مفهوم، وصحيح أن برنامجك يعمل، لكنه سيكون مكتظَا بالأكواد البرمجية المكررة، أو الوظائف غير المستخدمة، أو المتغيرات التي لا فائدة من وجودها، وبرنامج كهذا قد يتعطل أو يفشل بعد أول تعديل أو تطوير مطلوب. فتعلم هذه القواعد وتطبيقها من شأنه أن يحسِّن من خبرتك ويطور أسلوب كتابة شيفراتك البرمجية، وأغلب أصحاب الأعمال سيطلعون على عينة من كود كتبته سابقًا وسيفضلون مبرمجًا محترفًا يتبع هذه القواعد عمن لا يتبعها. وتذكر أن البرمجة لا تقتصر على كتابة تعليمات برمجية تعمل فحسب، بل هي كتابة تعليمات برمجية فعالة ذات جودة عالية ويمكن صيانتها وتعديلها بكل مرونة سواء من قبلك أو من قبل أي مبرمج آخر، لذا احرص على اتباع هذه القواعد البرمجية والتدرب على تطبيقها قدر المستطاع لأنها سبيلك لتكون مبرمجًا ناجحًا ومتميزًا. ماذا بعد تعلم قواعد البرمجة؟ بعد أن تتقن أساسيات البرمجة وتتعلم تطبيق قواعد البرمجة قد تتساءل: كيف يمكنني المضي قدمًا وتطوير مهاراتي البرمجية بصورة أكبر؟ سؤال جيد، سأجيبك! من الأمور التي ينبغي عليك تعلمها في رحلتك لاحتراف البرمجة مهارات إعادة التصميم لمشاريعك الحالية، والتعرف على مفهوم أنماط التصميم وتطبيقها لحل المشكلات التقنية التي تواجهك مستقبلًا. يشير مفهوم إعادة التصميم "Refactoring" إلى الخطوات التي ينبغي للمبرمج اتباعها لتعديل الشيفرات البرمجية وإعادة هيكلتها وتحسينها والعثور على أي أخطاء أو ثغرات كامنة فيها، مع المحافظة على وظائفها الأساسية. أما أنماط التصميم "Design Patterns"، فهي عبارة عن نماذج يضعها المطورون لحل المشكلات المتكررة والمتشابهة، وستكتسب من خلال تعلمها القدرة على إعادة استخدام نفس الأنماط في كل مرة تظهر فيها نفس المشكلة، ويمكنك اعتبارها بمثابة فكرة مجردة توضح طريقة حل المشكلة وتسهل عليك تحقيقها برمجيًا. الخلاصة تعرفنا في مقال اليوم على أهم قواعد البرمجة التي على المبرمج اتباعها، فلا ينبغي أن تتعلم أساسيات البرمجة فقط، بل عليك أن تتقدم خطوة للأمام وتحرص على اتباع أفضل الممارسات البرمجية عند كتابة الكود كي يكون المنتج الرقمي الذي تنشؤه أكثر كفاءة وموثوقية واحترافية. وتذكر أنه يمكن للجميع كتابة كود برمجي يفهمه الحاسوب لكن القليلين فقط يمكنهم كتابة كود جيد يفهمه الإنسان أيضًا، ومن خلال حرصك على اتباع قواعد البرمجة التي شرحناها تضمن أن تكون من هذه الفئة القليلة من المبرمجين المحترفين، كل ما تحتاجه هو التدريب الجيد على كتابة الأكواد والبرامج بصورة محسنة تراعي هذه القواعد بأفضل طريقة. اقرأ أيضًا تعلم تطوير الويب دليلك الشامل إلى لغات البرمجة أسهل لغات البرمجة ما هي فوائد تعلم البرمجة؟
  14. سنركز في هذا الجزء من السلسلة على بعض التطبيقات العملية التي يمكن استخدام لغة بايثون فيها، وكذلك وحدات المكتبات التي سنستخدمها في كتابة تلك التطبيقات، كما سنتعلم بعض التقنيات الجديدة أثناء كتابة تلك التطبيقات، مثل قواعد البيانات وشبكات الحواسيب والشبكة العالمية -الويب-، وكذلك بعض المزايا الأساسية لنظم تشغيل الحواسيب، لكننا لن نتعمق في هذه التقنيات كثيرًا لأننا نهتم بتعليم البرمجة فقط، ويمكنك الاستعانة بمواقع أخرى أو مصادر يمكن الاستزادة منها. وقد اخترنا موضوعات تعكس المجالات التي تتكرر في قائمة Python tutor البريدية (القائمة البريدية لمعلمي بايثون)، والتي يفترض أن تكون الأفضل في تلبية احتياجات المبرمجين الجدد، فإذا لم يكن المجال الذي تريده موجودًا فيها فقد تجد روابط إلى مصادر تتعلم فيها عن ذلك المجال. تعتمد جميع الفصول الباقية من السلسلة على بايثون وحدها، ولا شك أن الإمكانيات التي سنذكرها قد تكون موجودةً في جافاسكربت وVBScript، إلا أن الاختلافات في هذا المستوى من العمق والتفاصيل أكبر من أوجه التشابه بكثير، لأن هذه تطبيقات عملية وليست مفاهيم نظريةً.، فأسهل طريقة للوصول إلى ويندوز مثلًا من جافاسكربت أو VBScript ستكون من خلال مضيف سكربت ويندوز WSH الذي ذكرناه من قبل، لكن هذا يختلف كليًا عن وحدة نظام التشغيل في بايثون، فلا معنى للموازنة بينها. سننظر في هذا المقال من سلسلة تعلم البرمجة في كيفية تخزين البيانات ومعالجتها من خلال حزمة قاعدة البيانات، وقد رأينا سابقًا كيفية استخدام الملفات في تخزين كميات صغيرة من البيانات في برنامج دليل جهات الاتصال الذي مررنا عليه عدة مرات من قبل، غير أن استخدام الملفات يزداد تعقيدًا مع زيادة تعقيد البيانات نفسها، وزيادة حجمها، وتعقيد العمليات التي تُجرى عليها، مثل الفرز والبحث والترشيح filtering وغير ذلك، وتوجد عدة حزم لقواعد البيانات للعناية بإدارة الملفات، وكشف البيانات في شكل أكثر تجريدًا ويسهل التعديل عليه، بعضها عبارة عن مكتبات للشيفرات code libraries تبسط عمليات الملفات التي رأيناها من قبل مثل وحدتي pickle و shelve اللتين تأتيان مع بايثون، لكننا في هذا المقال سندرس حزمًا أكثر قوةً صممت للتعامل مع أحجام كبيرة من البيانات المعقدة، حيث سنشرح الحزمة SQLite، وهي حزمة مجانية مفتوحة المصدر وسهلة التثبيت والاستخدام، ومع هذا فهي قادرة على معالجة حاجات أغلب المبرمجين المبتدئين والمتوسطين أيضًا، ولا يحتاج المبرمج في الغالب إلى حزمة أقوى منها إلا إذا كان يتعامل مع مجموعات كبيرة للغاية من البيانات -ملايين السجلات مثلًا-، وحتى في تلك الحالة نستطيع نقل ما تعلمناه من SQLite إلى الحزمة الجديدة. يمكن تحميل حزمة SQLite من موقعها، فاختر حزمة سطر الأوامر -أي الأدوات- المناسبة لمنصتك، وبعد التحميل اتبع إرشادات التثبيت الموجودة في الموقع لتثبيت الحزمة. توجد عدة بيئات تطوير لـ SQLite، غير أننا لا نحتاجها في هذه السلسلة. سندرس في هذا المقال ما يلي: مفهوم قواعد البيانات وSQL. إنشاء الجداول وإدخال البيانات. استخراج البيانات والتعديل عليها. ربط مجموعات البيانات بعضها ببعض. الوصول إلى SQL من بايثون. مفاهيم قاعدة البيانات العلائقية يمكن وصف قواعد البيانات العلائقية relational databases بأنها مجموعة من الجداول، حيث يمكن لخلية في جدول فيها أن تشير إلى صف في جدول آخر، وتسمى الأعمدة في تلك الجداول بالحقول fields، كما تسمى الصفوف بالسجلات records. سيبدو جدول بيانات الموظفين في إحدى الشركات كما يلي: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } EmpID Name HireDate Grade ManagerID 1020304 Hasan Saleh 20030623 Foreman 1020311 1020305 Amin Akbar 20040302 Labourer 1020304 1020307 Ayat Othman 19991125 Labourer 1020304 نلاحظ بعض المصطلحات هنا: لدينا حقل معرِّف ID فريد يعرف كل صف، ويُعرف باسم المفتاح الأساسي primary key، ويمكن أن يكون لدينا عدة مفاتيح أخرى، لكن سيكون لدينا حقل ID دومًا لتعريف سجل ما، وهذا مفيد إذا كان لموظفين اثنين نفس الاسم مثلًا. يمكن ربط صف بآخر بأن يحمل حقلٌ ما المفتاحَ الأساسي لصف آخر، فمثلًا يُحدَّد مدير الموظف بواسطة معرف المدير ManagerID الذي هو مرجع إلى حقل EmpID آخر، ويتضح بالنظر إلى البيانات التي لدينا أن لكل من Amin وAyat المدير نفسه وهو Hasan، و Hasan هذا له مدير آخر لكننا لا نرى بياناته في هذا الجزء من الجدول. ويمكن إنشاء جدول آخر للرواتب Salary مثلًا، فلسنا مقيدين بربط البيانات داخل جدول واحد، ويُربط هذا بالدرجة Grade الخاصة بكل موظف، فنحصل عندها على جدول شبيه بما يلي: SalaryID Grade Amount 000010 Foreman 60000 000011 Labourer 35000 نستطيع الآن أن نبحث عن درجة موظف ما مثل Hasan، وسنجد أن درجته هي كبير عمال Foreman، وإذا بحثنا في جدول Salary فسنجد أن راتب هذه الدرجة هو 60000$، وإمكانية ربط صفوف الجداول معًا في علاقات هي التي تعطي قواعد البيانات العلائقية اسمها. توجد قواعد بيانات أخرى مثل قواعد بيانات الشبكات network databases، وقواعد البيانات الهرمية hierarchical databases، وقواعد بيانات الملفات المسطحة flat-file databases، ولكن القواعد العلائقية هي أكثرها شهرةً، رغم أن الاتجاه السائد الآن في معالجة الأحجام الهائلة من البيانات هو NoSQL -أي ليست SQL فقط "Not only SQL"-، وهي قواعد بيانات تبنى في الغالب على هياكل شبكية أو هرمية. يمكن إجراء استعلامات أعقد من تلك التي أجريناها، وسنرى كيفية ذلك فيما يلي، لكن يجب أن ننشئ قاعدة بيانات أولًا ونضع فيها بعض البيانات. لغة الاستعلامات الهيكلية SQL لغة الاستعلامات الهيكلية أو Structured Query Language - SQL هي أداة قياسية تُستخدم لتعديل قواعد البيانات العلائقية، ويسمى التعبير فيها عادةً استعلامًا query حتى لو لم يجلب أي بيانات، وتتكون SQL من جزأين هما: لغة تعريف البيانات Data Definition Language واختصارًا DDL، وهي مجموعة من الأوامر التي تُستخدم لإنشاء وتعديل هيكل قاعدة البيانات نفسها، وتكون عادةً خاصةً لكل قاعدة بيانات، ويوفر كل مزود قواعد بيانات صيغةً مختلفةً قليلًا لمجموعة أوامر SQL الخاصة بتعريف البيانات، أما الجزء الآخر فهو لغة تعديل البيانات Data Manipulation Language، واختصارًا DML، وهي قياسية أكثر بين قواعد البيانات، وتُستخدم لتعديل محتويات البيانات، وهي التي سنستخدمها غالبًا في التعامل مع قواعد البيانات، لذا سنتعلم بعض أوامر DDL التي تكفينا لإنشاء قاعدة بياناتنا باستخدام التعليمة CREATE، وتدمير جداولها باستخدام التعليمة DROP، ثم ننتقل بعدها إلى ملء الجداول بالبيانات، ثم نجلب تلك البيانات بطرق مختلفة باستخدام أوامر DML مثل INSERT وSELECT وUPDATE وDELETE وغيرها. ربما تجدر الإشارة إلى مزية أخرى في SQL، وهي أنها ليست حساسةً لحالة الأحرف، على عكس بايثون وجافاسكربت، لذا يمكننا استخدام CREATE أو create أو Create أو حتى CrEaTe، فلن يهتم مفسر SQL بهذا، ومع هذا يتبع مبرمجو SQL نسقًا بحيث تكون كلمات SQL المفتاحية بأحرف كبيرة، بينما تكون المتغيرات وأسماء الجداول والحقول بأحرف صغيرة، وسنتبع هذا النسق في الشرح، لكننا ذكرنا الملاحظة أعلاه لننبه إلى أن SQL لا تهتم لحالة الأحرف. ومن الأمور التي تجعل SQL مختلفةً عن اللغات الأخرى أنها مصممة للتعبير عن الخرج المطلوب بدلًا من إخبار الحاسوب بكيفية تنفيذه، أي أننا نخبر المفسر بما نريده فقط، وليس بالكيفية التي نريد تنفيذه بها، ونترك آلية التنفيذ للمفسر، ويستطيع المبرمجون الخبراء في قواعد البيانات أو مدراء النظم adminstrators أن يغيروا سلوك المفسر في تنفيذ المهام من خلال تعريف خطة التنفيذ أو تعديلها، غير أن هذا مستوىً متقدم خارج نطاق شرحنا. إنشاء الجداول نستخدم الأمر CREATE لإنشاء جدول في SQL، وهو أمر سهل ويأخذ الصورة التالية: CREATE TABLE tablename (fieldName, fieldName,....); نلاحظ أن تعليمات SQL تنتهي بفاصلة منقوطة ;، وهي لا تهتم بمستويات الإزاحة أو المسافات البيضاء، لكننا سنرى اتباع اصطلاح بعينه -مع أنه ليس لازمًا، ولا تهتم SQL له إطلاقًا- ولا نستخدمه إلا لاتساق سير العمل. لنجرب الآن إنشاء جداول الموظفين والرواتب في SQLite، حيث سيكون أول ما علينا فعله هو بدء المفسر عن طريق استدعائه مع وسيط هو اسم الملف، فإذا كانت قاعدة البيانات موجودةً فسيفتح الملف، أما إذا لم تكن موجودةً فسينشئها، وعليه فمن أجل إنشاء قاعدة بيانات الموظفين نبدأ SQLite كما يلي: E:\PROJECTS\SQL> sqlite3 employee.db سينشئ هذا قاعدة بيانات فارغةً اسمها employee.db، ويتركنا عند محث sqlite>‎ لنكتب أوامر SQL، ثم ننشئ بعض الجداول كما يلي: sqlite> CREATE TABLE Employee ...> (EmpID,Name,HireDate,Grade,ManagerID); sqlite> CREATE TABLE Salary ...> (SalaryID, Grade,Amount); sqlite>.tables Employee Salary sqlite> لاحظ أننا نقلنا قائمة الحقول إلى سطر منفصل لتسهيل رؤيتها، وتُرتَّب الحقول هنا بالاسم، وليس لها أي معلومات تعرِّفها -مثل نوع البيانات- وهذا في SQLite وحدها، إذ تطلب أغلب قواعد البيانات الأخرى تحديد النوع مع الاسم، ويمكن تحديد النوع في SQLite، كما سنرى بعد قليل. ونلاحظ أيضًا أننا تحققنا من عمل تعليمات CREATE باستخدام الأمر ‎.tables لسرد جميع الجداول في قاعدة البيانات، وتحتوي SQLite على العديد من هذه الأوامر المنقوطة، والتي نستخدمها لجلب معلومات عن قاعدة البيانات، وللحصول على قائمة بتلك الأوامر يُستخدم الأمر ‎.help. يمكننا تحديد قيود على القيم، بالإضافة إلى التصريح عن أنواع البيانات في كل عمود، فمثلًا NOT NULL تعني أن القيمة إلزامية ويجب ملؤها، ونجعل عادةً حقل المفتاح الأساسي غير خالٍ NOT NULL وفريدًا UNIQUE، كما نستطيع تحديد الحقل الذي سيكون المفتاح الأساسي PRIMARY KEY. سنترك تعريف الجدول الأساسي كما هو، وننتقل إلى التعديل في البيانات نفسها. إدخال البيانات أول ما نفعله بعد إنشاء الجداول هو ملؤها بالبيانات، وذلك باستخدام تعليمة INSERT في SQL، والتي لها هيكل أساسي بسيط هو: INSERT INTO tablename ( column1, column2... ) VALUES ( value1, value2... ); كما توجد لها صيغة أخرى تستخدم استعلامًا لاختيار البيانات من مكان آخر في قاعدة البيانات، لكن هذا مستوىً متقدم ننصح بالقراءة عنه في دليل SQLite. يمكننا أن ندخِل بعض الصفوف في جدول موظفينا كما يلي: sqlite> INSERT INTO Employee (EmpID, Name, HireDate, Grade, ManagerID) ...> VALUES ('1020304','Hasan Saleh','20030623','Foreman','1020311'); sqlite> INSERT INTO Employee (EmpID, Name, HireDate, Grade, ManagerID) ...> VALUES ('1020305','Amin Akbar','20040302','Labourer','1020304'); sqlite> INSERT INTO Employee (EmpID, Name, HireDate, Grade, ManagerID) ...> VALUES ('1020307','Ayat Othman','19991125','Labourer','1020304'); وكذلك في جدول الرواتب: sqlite> INSERT INTO Salary (SalaryID, Grade,Amount) ...> VALUES('000010','Foreman','60000'); sqlite> INSERT INTO Salary (SalaryID, Grade,Amount) ...> VALUES('000011','Labourer','35000'); وبهذا نكون قد انتهينا من إنشاء جدولين وملئهما بالبيانات الموافقة للقيم الموصوفة في المقدمة أعلاه، وسننتقل الآن إلى إجراء بعض التجارب على البيانات. استخراج البيانات تُستخرج البيانات من قاعدة البيانات باستخدام الأمر SELECT في SQL، والذي هو لب SQLite، وهو أعقد الأوامر هيكلًا، لذا سنبدأ بأبسط صورة ثم نضيف مزايا جديدةً أثناء العمل. ستبدو أبسط صورة ممكنة لتعليمة SELECT كما يلي: SELECT column1, column2... FROM table1,table2...; فلاختيار أسماء جميع العاملين نستخدم: sqlite> SELECT Name FROM Employee; حيث سنحصل على قائمة بجميع الأسماء في جدول الموظفين، وهي ثلاثة أسماء في حالتنا، لكن إذا كان لدينا قاعدة بيانات كبيرة فسنحصل على معلومات أكثر مما نريد، وسنحتاج إلى تحسين بحثنا بطريقة ما للتحكم في الخرج، وتسمح لنا SQL بفعل ذلك بإضافة الشرط WHERE إلى تعليمة SELECT، كما يلي: SELECT col1,col2... FROM table1,table2... WHERE condition; حيث الشرط condition هو تعبير بولياني معقد وعشوائي، ويمكن أن يتضمن تعليمات SELECT متشعبةً داخله، لنستخدم الشرط WHERE لتحسين بحث الأسماء، حيث نريد البحث عن أسماء الموظفين العمال فقط، أي أصحاب الدرجة labourer. sqlite> SELECT Name ...> FROM Employee ...> WHERE Employee.Grade = 'Labourer'; سنحصل الآن على اسمين فقط، ونستطيع توسيع الشرط باستخدام معامِلات بوليانية مثل AND وOR وNOT وغيرها، لاحظ أن استخدام الشرط = في حالة السلسلة النصية مهم، فلم يكن البحث عن labourer لينجح لولاه، وسنرى كيفية حل هذه المشكلة لاحقًا. كما نلاحظ أننا استخدمنا الصيغة النقطية dot notation في شرط WHERE لإبراز حقل Grade، ولم يكن ذلك ضروريًا في هذه الحالة لأننا نعمل مع جدول واحد، لكن عند وجود عدة جداول محددة فسنحتاج إلى توضيح الجدول الذي ينتمي إليه الحقل، فمثلًا لنغير استعلامنا ليبحث عن أسماء جميع الموظفين الذين يحصلون على راتب أكثر من 50000$، حيث سنحتاج إلى النظر في بيانات كلا الجدولين: sqlite> SELECT Name, Amount FROM Employee, Salary ...> WHERE Employee.Grade = Salary.Grade ...> AND Salary.Amount > '50000'; نلاحظ استخدام المسافات البيضاء لترتيب شكل الاستعلام، وقد وضعنا شرط FROM هذه المرة في السطر الأول، وهذا أمر تنسيقي بحت يُستخدم لتحسين القراءة، فلغة SQLite لا تهتم بالفراغات. سنحصل هنا على اسم واحد كما توقعنا، وهو اسم كبير العمال foreman، لكن انتبه إلى أننا سنحصل على الراتب لأننا أضفنا Amount إلى قائمة الأعمدة المحددة، ولدينا شرط WHERE مكوَّن من جزأين مدمجين معًا باستخدام المعامِل البولياني AND، حيث يربط الجزء الأول الجدولين معًا عن طريق ضمان تساوي الحقول المشتركة، وهو ما يُعرف بالربط join في SQL، وقد يصبح أمر الربط معقدًا للغاية وفقًا لكل حالة، ولهذا يفضل القائمون على اعتماد المزايا الجديدة في SQL صورةً أكثر صراحةً من الربط، وهي مشروحة بالتفصيل في موقع guru99. علينا تحديد كلا الجدولين اللذين ستظهر النتيجة منهما، لأن الحقول التي نختارها تأتي من جدولين، ويكون ترتيب أسماء الحقول هو الترتيب الذي نحصل به على البيانات مرةً أخرى، لكن ترتيب الجداول نفسه لا يهم طالما أن الحقول تظهر في تلك الجداول. لقد حدَّدنا اثنين من أسماء الحقول الفريدة، فإذا أردنا عرض الدرجة الوظيفية Grade التي تظهر في كلا الجدولين، لكنا استخدمنا الصيغة النقطية لتحديد الجدول الذي نريده، كما يلي: sqlite> SELECT Employee.Grade, Name, Amount ...> FROM Employee, Salary etc/... آخر ما نريد الحديث عنه من مزايا SELECT هي القدرة على تصنيف الخرج، رغم وجود عدة مزايا أخرى يمكن الرجوع إليها في توثيق SQL، فقواعد البيانات تحتفظ بالبيانات بالترتيب الذي يسهل به إيجادها أو بالترتيب الذي أُدخلت به، وفي كلا الحالتين لا يكون هو الترتيب الذي نريد عرض البيانات به، لذا نستخدم الشرط ORDER BY الخاص بتعليمة SELECT لحل هذه المشكلة: SELECT columns FROM tables WHERE expression ORDER BY columns; نلاحظ أن شرط ORDER BY الأخير قد يأخذ عدة أعمدة، وهذا يمكننا من الحصول على طلبات الفرز والتصنيف الأولية والثانوية، لنستخدم ذلك الآن للحصول على قائمة بأسماء الموظفين مصنفة وفق تاريخ التوظيف HireDate: sqlite> SELECT Name FROM Employee ...> ORDER BY HireDate; لم يبقَ إلا ذكر أننا لم نستخدم شرط WHERE هنا، فإذا استخدمناه فسيأتي قبل شرط order by، لذا ورغم أن SQL لا تمانع إذا أهملنا الشرط إلا أنها تدقق كثيرًا في ترتيب الشروط داخل التعليمة. تعديل البيانات توجد طريقتان لتعديل البيانات في قواعد البيانات، إما بتغيير محتويات سجل واحد أو مجموعة سجلات، أو بحذف السجلات أو الجدول كاملًا، والحالة الأشهر هي تغيير محتويات سجل موجود بالفعل من خلال الأمر UPDATE في SQL، وأبسط صورة هي: UPDATE tablename SET column = value WHERE condition; نستطيع تجربة ذلك في قاعدة البيانات التي لدينا بتغيير راتب كبير العمال foreman إلى 70000$: sqlite> UPDATE Salary ...> SET Amount ='70000' ...> WHERE Grade = 'Foreman'; لاحظ أن جميع البيانات التي أدخلناها واخترناها كانت أنواعًا نصيةً string types، لأن SQLite تخزن بياناتها داخليًا في سلاسل نصية، لكنها تدعم عدة أنواع مختلفة من البيانات بما فيها الأعداد، لذا كان بالإمكان تحديد الراتب في صيغة رقمية لتسهيل العمليات الحسابية، وسنرى كيفية فعل ذلك فيما يلي. لكن المشكلة هنا أن SQL ستعدل كل الصفوف التي تطابق الشرط، فإذا كنا نريد تعديل صف واحد فقط فعلينا أن نتأكد أن الشرط WHERE يحدد حتمًا صفًا واحدًا فقط، إذ كثيرًا ما يغير المبرمجون المبتدئون دون قصد حقلًا في كل صف في الجدول أو فرع منه، لذا يجب الحذر عند استخدام أوامر التعديل لصعوبة إصلاح هذا الخطأ، ومن الأفضل التحقق من شرط WHERE بوضعه في تعليمة SELECT أولًا لمعرفة القيمة المعادة. أما الصورة الأخرى للتغيير الجذري الذي نستطيع تنفيذه على بياناتنا فهو حذف صف أو مجموعة صفوف، باستخدام الأمر DELETE FROM، كما يلي: DELETE FROM Tablename WHERE condition فإذا أردنا حذف Ayat Othman من جدول الموظفين فسنكتب ما يلي: sqlite> DELETE FROM Employee WHERE Name = 'Ayat Othman'; فإذا طابق شرطنا أكثر من صف فستُحذف تلك الصفوف جميعها، لأن SQL تنفَّذ على جميع الصفوف التي تطابق الاستعلام، فهي ليست مثل استخدام البحث المتتابع sequential search لملف ما أو سلسلة نصية باستخدام تعبير نمطي. أما لحذف الجدول كله بمحتوياته فنستخدم الأمر DROP، ويجب توخي الحذر الشديد عند استخدام مثل هذه الأوامر التدميرية مثل DELETE وDROP لما لها من آثار قد لا يمكن إصلاحها. ربط البيانات بين الجداول تحدثنا عن ربط البيانات بين الجداول من قبل في القسم الخاص بتعليمة SELECT، أما الآن فننتقل إلى جزء مهم في نظرية قواعد البيانات. قيود البيانات Data Constraints تمثل الروابط بين الجداول علاقات Relations بين وحدات البيانات التي تعطي قاعدة البيانات العلائقية -مثل SQLite- اسمها، وتحتفظ قاعدة البيانات بالبيانات الخام عن الكيانات، بل تحتفظ بمعلومات عن العلاقات بينها أيضًا. تُخزَّن المعلومات عن العلاقات في صيغة قيود لقاعدة البيانات، والتي تتصرف مثل قواعد تحدد نوع البيانات الذي يمكن تخزينها، بالإضافة إلى مجموعة قيمها الصالحة، وتطبَّق تلك القيود عندما نعرِّف هيكل قواعد البيانات باستخدام تعليمة CREATE، عادةً نعبر عن قيود كل حقل على حدة، لذا نستطيع توسيع التعريف الأساسي في تعليمة CREATE حيث نعرِّف أعمدتنا من: CREATE TABLE Tablename (Column, Column,...); إلى: CREATE TABLE Tablename ( ColumnName Type Constraint, ColumnName Type Constraint, ...); حيث أغلب القيود: NOT NULL PRIMARY KEY [AUTOINCREMENT] UNIQUE DEFAULT value يسهل فهم عمل القيد NOT NULL إذ يشير إلى أن القيمة يجب أن تكون موجودةً أي ليست NULL، حيث تشير القيمة NULL إلى قيمة غير محددة أو معرَّفة، وبالتالي فالعبارة NOT NULL تعني أنه يجب إعطاء قيمة لذلك الحقل، وإلا فسنحصل على خطأ ولن تُدخَل البيانات. أما المفتاح الرئيسي PRIMARY KEY فيخبر SQLite أن تستخدم هذا العمود مفتاحًا رئيسيًا لعمليات البحث، مما يُحسّن تنفيذ عمليات بحث أسرع. كما تعني AUTOINCREMENT أن قيمة النوع هي INTEGER ستُسنَد تلقائيًا عند كل عملية إدخال INSERT، وتتزايد القيمة بمقدار واحد، مما يوفر على المبرمج كثيرًا من حيث المحافطة على أعداد مستقلة، ولا تُستخدم الكلمة المفتاحية AUTOINCREMENT حقيقةً، وإنما تكون مضمنةً في تجميعة نوع/قيد بدمج INTEGER PRIMARY KEY، وهذه خاصية غير واضحة في توثيق SQLite إلى الحد الذي يجعلها من أبرز الأسئلة في الأسئلة الشائعة حول SQLite. وتدل UNIQUE على أن القيمة يجب أن تكون فريدةً في العمود، فإذا حاولنا إدخال قيمة موجودة مسبقًا في عمود له قيد UNIQUE فسنحصل على خطأ ولن يُدخَل الصف، ويُستخدم قيد UNIQUE عادةً لأعمدة المفاتيح الرئيسية غير العددية. يصاحب القيد DEFAULT قيمة دومًا، وهذه القيمة هي التي تخبرنا بما ستدخِله SQLite في ذلك الحقل إذا لم يقم المستخدم بذلك صراحةً، وهذا يفيد في أن الأعمدة التي لها القيد DEFAULT لا تكون NULL إلا نادرًا، لأن علينا ضبط القيمة NULL بصراحة إذا أردنا إنشاءها، ونستطيع رؤية مثال سريع على استخدام DEFAULT هنا: sqlite> CREATE TABLE test ...> (id Integer PRIMARY KEY, ...> Name NOT NULL, ...> Value Integer DEFAULT 42); sqlite> INSERT INTO test (Name, Value) VALUES ('Alan',24); sqlite> INSERT INTO test (Name) VALUES ('Heather'); sqlite> INSERT INTO test (Name,Value) VALUES ('Linda', NULL); sqlite> SELECT * FROM test; 1|Alan|24 2|Heather|42 3|Linda| sqlite> نلاحظ هنا كيف تعينت القيمة الافتراضية لحقل value الموافقة للاسم المدخَل Heather، وأن قيمة value للمدخل Linda غير موجودة أو NULL، وهذا اختلاف جوهري بين NOT NULL وDEFAULT، فالأول لن يسمح بقيم NULL افتراضيًا أو صراحةً، والقيد DEFAULT يمنع NULL غير المحددة، لكنه يسمح في نفس الوقت بالإنشاء المتعمد لها. لقد استخدمنا محرف النجمة * مكان قائمة الحقل في آخر تعليمة SELECT، وهذه طريقة بسيطة لجلب جميع الحقول في الجدول، وهي ممتازة لمثل هذه التجارب، لكن يجب ألا تُستخدم في البرامج العملية لأن أي تغيير في هيكل البيانات سيتسبب في تغيير النتائج أو تعطيل أي شيفرة تعتمد على عدد أو ترتيب الحقول التي طُلبت. توجد قيود يمكن تطبيقها على الجدول نفسه، لكننا لن نناقشها في هذه السلسلة. أما النوع الآخر من القيود الذي نستطيع تطبيقه كما ذكرنا من قبل فهو تحديد نوع العمود، وهو يشبه مفهوم الأنواع في لغة البرمجة، ومجموعة الأنواع الصالحة في SQLite هي ما يلي: TEXT. INTEGER. REAL. NUMERIC. BLOB. NULL. يجب أن تكون هذه الأنواع مفهومةً وواضحةً، باستثناء NUMERIC وBLOB، فالأول يسمح بتخزين أعداد الفاصلة العائمة floating-point numbers والأعداد الصحيحة، أما BLOB فيُستخدم لتخزين البيانات الثنائية، مثل الصور أو المستندات غير النصية، فهو أفضل في تخزين مثل تلك العناصر في ملفات منفصلة مع وجود مرجع reference فقط يشير إليها في قاعدة البيانات. أما NULL فهو ليس نوعًا حقيقيًا، وإنما يشير إلى أننا لا نحتاج إلى تحديد نوع مطلقًا، فأغلب قواعد البيانات تأتي بمجموعة واسعة من الأنواع بما فيها النوع DATE، لكن SQLite لديها أسلوب غير تقليدي في الأنواع التي تجعل مثل هذه التفاصيل غير مهمة. تطبق أغلب قواعد البيانات الأنواع المحددة بصرامة، لكن SQLite تتبع نهجًا أكثر ديناميكيةً ومرونةً، حيث يكون النوع المحدَّد أشبه بالتلميح أو الإرشاد hint، ويمكن تخزين أي نوع من البيانات في الجدول، وعند تحميل بيانات من نوع مختلف إلى الحقل فإن SQLite ستستخدم النوع المصرَّح عنه لتحاول تحويل البيانات إليه، فإن لم تستطع فستخزنها في صورتها الأصلية، فإذا صُرِّح عن حقل على أنه عددي INTEGER ثم مُررت القيمة النصية '123'، فستحول SQLite السلسلة النصية '123' إلى العدد 123، لكن إذا كانت القيمة النصية TEXT هي 'Amindy' فلن ينجح تحويلها إلى عدد، وستخزنها SQLite في صورتها كما هي في الحقل، وقد يسبب هذا سلوكًا غريبًا إذا لم يكن المبرمج على علم بهذا العيب، أما بقية قواعد البيانات فتعدّ التصريح عن الأنواع قيدًا صارمًا، وتفشل عند تمرير قيمة غير مسموح بها. نمذجة العلاقات مع القيود لنر الآن كيف تساعدنا هذه القيود في صنع نماذج للبيانات والعلاقات، من خلال العودة إلى قاعدة البيانات البسيطة ذات الجدولين التي بدأنا المقال بها: الجدول 1: EmpID Name HireDate Grade ManagerID 1020304 Hasan Saleh 20030623 Foreman 1020311 1020305 Amin Akbar 20040302 Labourer 1020304 1020307 Ayat Othman 19991125 Labourer 1020304 الجدول 2: SalaryID Grade Amount 000010 Foreman 60000 000011 Labourer 35000 ينبغي أن يكون نوع قيمة المعرِّف ID عددًا صحيحًا، أي INTEGER، ويحمل القيد PRIMARY KEY، أما العمود الآخر فيجب أن يكون NOT NULL، باستثناء ManagerID الذي يجب أن يكون عددًا صحيحًا. ونرى هنا في جدول الرواتب Salary أن معرِّف الراتب SalaryID يجب أن يكون عددًا صحيحًا INTEGER مع قيد PRIMARY KEY، كما يجب أن يكون عمود مقدار الراتب Amount عددًا صحيحًا، وسنطبق القيمة الافتراضية DEFAULT التي مقدارها 10000، وأخيرًا يجب أن يكون العمود Grade مقيدًا بقيد التفرد Unique بما أننا لا نريد أكثر من راتب واحد لكل درجة وظيفية، رغم أن هذه الفكرة غير عملية، لأن الراتب يتغير بعوامل عدة، مثل مدة العمل والدرجة، لكننا سنتجاهل هذا التفصيل الآن لتبسيط الشرح، فلو كان هذا الجدول في حالة حقيقية لسميناه جدول الدرجات وليس الرواتب. ستبدو SQL المعدلة كما يلي: sqlite> CREATE TABLE Employee ( ...> EmpID INTEGER pRIMARY kEY, ...> Name NOT NULL, ...> HireDate NOT NULL, ...> Grade NOT NULL, ...> ManagerID INTEGER ...> ); sqlite> CREATE TABLE Salary ( ...> SalaryID INTEGER PRIMARY KEY, ...> Grade UNIQUE, ...> Amount INTEGER DEFAULT 10000 ...> ); يمكنك تجربة هذه القيود بإدخال البيانات التي تتسبب في تعطيلها لترى ما يحدث، وينبغي أن ترى رسالة خطأ. الأمر الذي تجب الإشارة إليه هنا هو أن تعليمات INSERT التي استخدمناها من قبل لم تعد مناسبةً، فقد أدخلنا قيمنا الخاصة من قبل لحقول ID، أما الآن فهي تُملأ تلقائيًا، فينبغي أن نهملها من البيانات المدرجة، غير أن هذا يفتح الباب لصعوبة جديدة، فكيف نملأ حقل معرِّف المدير managerID إذا كنا لا نعرف المعرف التوظيفي EmpID له؟ والإجابة هي أننا نستخدم تعليمة SELECT متشعبة، وقد رأينا أن ننفذ هذا على مرحلتين باستخدام حقول NULL أولًا، ثم استخدام تعليمة update بعد إنشاء جميع الصفوف، ولتجنب تكرار الكتابة قد وضعنا جميع الأوامر في بضعة ملفات، سميناها employee.sql لأوامر إنشاء الجداول، وemployee.dat لتعليمات الإدراج، وهذا يشبه إنشاء ملف سكربت بايثون ذي الامتداد ‎.py لتوفير كتابة كل الأوامر في محث ‎>>>‎. سيكون ملف employee.sql كما يلي: DROP TABLE IF EXISTS Employee; CREATE TABLE Employee ( EmpID INTEGER PRIMARY KEY, Name NOT NULL, HireDate NOT NULL, Grade NOT NULL, ManagerID INTEGER ); DROP TABLE IF EXISTS Salary; CREATE TABLE Salary ( SalaryID INTEGER PRIMARY KEY, Grade UNIQUE, Amount INTEGER DEFAULT 10000 ); نلاحظ هنا أننا أسقطنا الجداول -أي حذفناها- قبل إنشائها، فأمر DROP TABLE الذي ذكرناه من قبل يحذف الجدول وأي بيانات موجودة فيه، وهذا يضمن أن قاعدة البيانات ستكون خاليةً نظيفةً قبل أن ننشئ جدولنا الجديد، كما أضفنا شرط IF EXISTS الذي يمنعنا من محاولة حذف جدول حذف سابقًا. أما ملف employee.dat فسيكون كما يلي: INSERT INTO Employee (Name, HireDate, Grade, ManagerID) VALUES ('Hasan Saleh','20030623','Foreman', NULL); INSERT INTO Employee (Name, HireDate, Grade, ManagerID) VALUES ('Amin Akbar','20040302','Labourer',NULL); INSERT INTO Employee (Name, HireDate, Grade, ManagerID) VALUES ('Ayat Othman','19991125','Labourer',NULL); UPDATE Employee SET ManagerID = (SELECT EmpID FROM Employee WHERE Name = 'Hasan Saleh') WHERE Name = 'Amin Akbar' OR Name = 'Ayat Othman'; INSERT INTO Salary (Grade, Amount) VALUES('Foreman','60000'); INSERT INTO Salary (Grade, Amount) VALUES('Labourer','35000'); نلاحظ هنا استخدام تعليمة SELECT المضمنة في أمر UPDATE، وكذلك استخدامنا لأمر UPDATE واحد لتعديل صفَّي الموظف باستخدام شرط OR البولياني، ويمكن إضافة موظفين أكثر مع نفس المدير بسهولة بتوسيع شرط OR، وهذا مثال للمشاكل التي قد نواجهها عند ملء قاعدة بيانات للمرة الأولى، إذ سنحتاج إلى تخطيط ترتيب التعليمات بعناية لضمان توفير البيانات لكل صف يجب أن يحتوي على قيمة مرجعية إلى جدول آخر، وذلك من أجل الإشارة إليها، وهذا أشبه بالبدء من أوراق شجرة ما إلى جذعها، إذ يجب إنشاء وإدراج البيانات التي لا تحوي مراجع في البداية، ثم البيانات التي تشير مرجعيًا إلى تلك البيانات الأولى، وهكذا. فإذا أضفنا البيانات بعد الإنشاء الأولي فسنحتاج إلى استخدام استعلامات للتحقق من وجود البيانات التي نحتاج إليها، وإضافتها إن لم تكن موجودةً، وهنا تبرز أهمية لغة مثل بايثون. ثم نشغل هذه الملفات من محث sqlite كما يلي: sqlite> .read employee.sql sqlite> .read employee.dat تأكد أولًا من حل أي مشاكل تتعلق بمسارات الملفات، إما بتشغيل Sqlite من نفس مجلد سكربتات SQL كما فعلنا هنا، أو بتوفير المسار الكامل إلى السكربت. والآن لنجرب استعلامًا للتحقق من عمل هذه الملفات كما يجب: sqlite> SELECT Name FROM Employee ...> WHERE Grade IN ...> (SELECT Grade FROM Salary WHERE amount >50000) ...> ; Hasan Saleh يبدو أننا نجحنا هنا، إذ أن Hasan Saleh هو الموظف الوحيد الذي يتقاضى أكثر من 50000$، ونلاحظ أننا استخدمنا الشرط IN مع تعليمة SELECT مضمنة أخرى، وهذه صورة مختلفة عن استعلام مشابه أجريناه سابقًا باستخدام وصلة بين الجداول cross-table join، ورغم أن كلا التقنيتين ستعملان إلا أن طريقة الوصلة أسرع. العلاقات التعددية بين الجداول أحد السيناريوهات التي لم نتحدث عنها هو ربط جدولين معًا بعلاقات تعددية، أي يُربط صف في أحد الجدولين بعدة صفوف في الجدول الآخر، في نفس الوقت الذي يمكن ربط صف من الجدول الآخر بعدة صفوف من الجدول الأول، فمثلًا لنفرض أننا نكتب قاعدة بيانات لدعم دار نشر للكتب، حيث سيكون لدينا قائمة من المؤلفين وقائمة من الكتب، وسيكتب كل مؤلف كتابًا أو أكثر، وفي نفس الوقت قد يكون للكتاب الواحد عدة مؤلفين، فكيف نعبر عن هذه العلاقات في قاعدة بيانات؟ الجواب هنا هو تمثيل العلاقة بين الكتب والمؤلفين في جدول مستقل بذاته، ويُدعى هذا الجدول بجدول التقاطع intersection table أو جدول الربط mapping table، وكل صف في ذلك الجدول يمثل علاقةً من النوع كتاب/مؤلف، فقد يكون لكل كتاب عدة علاقات كتاب/مؤلف، لكن لكل علاقة كتابًا واحدًا ومؤلفًا واحدًا، وبذلك نكون قد حولنا علاقة متعدد-متعدد إلى علاقتي واحد-متعدد، وبما أننا نعرف كيف نبني مثل هذه العلاقات باستخدام المعرِّفات، فلنر ذلك عمليًا: DROP TABLE IF EXISTS author; CREATE TABLE author ( ID INTEGER PRIMARY KEY, Name TEXT NOT NULL ); DROP TABLE IF EXISTS book; CREATE TABLE book ( ID INTEGER PRIMARY KEY, Title TEXT NOT NULL ); DROP TABLE IF EXISTS book_author; CREATE TABLE book_author ( bookID INTEGER NOT NULL, authorID INTEGER NOT NULL ); INSERT INTO author (Name) VALUES ('Jane Austin'); INSERT INTO author (Name) VALUES ('Grady Booch'); INSERT INTO author (Name) VALUES ('Ivar Jacobson'); INSERT INTO author (Name) VALUES ('James Rumbaugh'); INSERT INTO book (Title) VALUES('Pride & Prejudice'); INSERT INTO book (Title) VALUES('Emma'); INSERT INTO book (Title) VALUES('Sense & Sensibility'); INSERT INTO book (Title) VALUES ('Object Oriented Design with Applications'); INSERT INTO book (Title) VALUES ('The UML User Guide'); INSERT INTO book_author (BookID,AuthorID) values ( (SELECT ID FROM book WHERE title = 'Pride & Prejudice'), (SELECT ID FROM author WHERE Name = 'Jane Austin') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'Emma'), (SELECT ID FROM author WHERE Name = 'Jane Austin') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'Sense & Sensibility'), (SELECT ID FROM author WHERE Name = 'Jane Austin') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'Object Oriented Design with Applications'), (SELECT ID FROM author WHERE Name = 'Grady Booch') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'The UML User Guide'), (SELECT ID FROM author WHERE Name = 'Grady Booch') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'The UML User Guide'), (SELECT ID FROM author WHERE Name = 'Ivar Jacobson') ); INSERT INTO book_author (BookID,AuthorID) VALUES ( (SELECT ID FROM book WHERE title = 'The UML User Guide'), (SELECT ID FROM author WHERE Name = 'James Rumbaugh') ); يمكن أن نجرب الآن بعض الاستعلامات لنرى كيف ستعمل، فمثلًا لنبحث عما نشرته جين أوستن Jane Austin من كتب: sqlite> SELECT title FROM book, book_author ...> WHERE book_author.bookID = book.ID ...> AND book_author.authorID = (SELECT ID FROM author ...> WHERE name = "Jane Austin"); لعل الأمر صار معقدًا قليلًا، لكن الفكرة ستتضح مع التكرار والتدريب، ولاحظ كيف نحتاج إلى إدراج كل من الجدولين المشار إليهما book وbook_author في قائمة الجداول بعد SELECT، أما الجدول الثالث author فليس موجودًا هناك لأنه مدرج مقابل تعليمة SELECT الخاصة به. لنجرب الآن بالطريقة المعاكسة، أي لنر من ألف كتاب The UML User Guide: sqlite> SELECT name FROM author, book_author ...> WHERE book_author.authorID = author.ID ...> AND book_author.bookID = (SELECT ID FROM book ...> WHERE title = "The UML User Guide"); بالنظر إلى تلك الشيفرة سنجد تطابق هيكل الاستعلامين، فلم نغير إلا أسماء الحقل والجدول. سنعود الآن إلى مثال دليل جهات الاتصال الذي تركناه في مقال التعامل مع الملفات في البرمجة، ويُفضل الرجوع لهذا المقال قبل متابعة القراءة لنرى كيف سنحوله من تخزين مبني على الملفات إلى قاعدة بيانات كاملة. إعادة النظر في دليل جهات الاتصال في دليل جهات الاتصال الذي كتبناه من قبل وبنيناه على الملفات، استخدمنا قاموسًا فيه اسم الشخص هو المفتاح، وعنوانه عنصر بيانات وحيد، ولا بأس بهذا إذا كنا نعرف الاسم الذي نريده، أو إذا أردنا تفاصيل العنوان كلها، لكن ماذا لو أردنا جميع الأسماء الموجودة في مدينة بعينها؟ أو كل من اسمه Hasan؟ يمكننا كتابة شيفرة بايثون لكل استعلام، لكن مع زيادة عدد الاستعلامات الخاصة سيزيد الجهد المطلوب لكتابة تلك الشيفرات، وهنا يأتي دور قواعد البيانات حيث يمكننا فيها إنشاء استعلامات ديناميكيًا باستخدام SQL، وسيبدو دليل جهات الاتصال قاعدة بيانات من جدول واحد، ويمكن تقسيم البيانات إلى عنوان وشخص، ثم ربطهما معًا، فقد يكون لدينا عدة أصدقاء يعيشون في نفس المنزل، لكننا سنلتزم بالتصميم الأصلي ونستخدم جدولًا بسيطًا، إلا أننا سنقسم البيانات إلى عدة حقول، حيث سنقسم الاسم إلى الاسم الأول والاسم الأخير، والعنوان إلى أجزائه المكونة له، بدلًا من أن يكون لدينا هيكل لاسم واحد وعنوان واحد، وعلى الرغم من كثرة الدراسات التي أجريت حول أفضل الطرق لتقسيم هذه البيانات إلا أننا لم نصل إلى إجابة محددة، لكنها جميعًا تتفق في أن حقل العنوان الواحد فكرة سيئة لأنها تفتقر للمرونة، وستكون حقول جدول قواعد البيانات والقيود التي نريد تطبيقها كما يلي: Field Name Type Constraint First Name String Primary Key Last Name String Primary Key House Number String NOT NULL Street String NOT NULL District String Town String NOT NULL Post Code String NOT NULL Phone Number String NOT NULL نلاحظ عدة أمور هنا: لدينا مفتاحان رئيسيان primary keys وهذا غير مسموح به، وسنتعامل معه بعد قليل. جميع البيانات من نوع TEXT رغم أن House Number قد يكون عددًا صحيحًا INTEGER، إلا أن أرقام المنازل تتضمن أحرفًا، لذا يجب استخدام TEXT. الحقل الاختياري الوحيد هو الحقل district. الرمز البريدي محدد الصيغة للغاية، لكنه يختلف وفقًا لكل دولة، وهذا يعني أن علينا أن نجعله من النوع TEXT ليناسب جميع الاحتمالات. رغم أن رقم الهاتف Phone Number قد يبدو مناسبًا لوضع قيد UNIQUE إلا أن هذا لن يسمح بوجود شخصين يتشاركان نفس رقم الهاتف، وهي حالة محتملة. بالعودة إلى النقطة الأولى -وجود مفتاحين رئيسيين- وهذا غير مسموح في SQL، لكن نستطيع جمع عمودين معًا في ما يسمى بالمفتاح المركب composite key، والذي يسمح بمعاملتهما مثل قيمة واحدة فيما يخص تعريف الصف، وعلى ذلك يمكن إضافة سطر في نهاية تعليمة create table ليجمع الاسم الأول FirstName وLastName في مفتاح رئيسي واحد، وسيبدو ذلك كما يلي: CREATE TABLE address ( FirstName NOT NULL, LastName NOT NULL, ... PhoneNumber NOT NULL, PRIMARY KEY (FirstName,LastName) ); نلاحظ هنا السطر الأخير PRIMARY KEY (FirstName,LastName)‎ الذي يحوي الأعمدة التي نريد استخدامها لتكون مفتاحًا مركبًا، وهو مثال على قيد قائم على الجدول table-based constraint، غير أن هذه الفكرة غير سديدة، فإذا كنا نعرف شخصين بنفس الاسم فلن نستطيع تخزينهما معًا، ولن نخزن إلا واحدًا فقط منهما، وسنتعامل مع هذا بتعريف حقل integer primary key لتعريف جهات اتصالاتنا تعريفًا فريدًا رغم أننا لن نستخدم ذلك في الاستعلامات إلا نادرًا. نعرف كيفية التصريح عن قيد INTEGER PRIMARY KEY حيث فعلنا ذلك في مثال الموظف، ونستطيع تحويل ذلك مباشرةً إلى سكربت إنشاء بيانات SQLite كما يلي: -- احذف الجداول إذا كانت موجودة من قبل وأعد إنشاءها. -- استخدم القيود لتحسين كفاءة البيانات. DROP TABLE IF EXISTS address; CREATE TABLE address ( ContactID INTEGER PRIMARY KEY, First NOT NULL, Last NOT NULL, House NOT NULL, Street NOT NULL, District, Town NOT NULL, PostCode NOT NULL, Phone NOT NULL ); السطران الأولان في الشيفرة السابقة ما هما إلا تعليقات، فأي شيء متبوع بشرطتين -- هنا يُعد تعليقًا في SQL، كما في حالة رمز # في بايثون. نلاحظ أننا لم نعرّف النوع لأن TEXT هو النوع الافتراضي في SQLite، فإذا أردنا تحويل هذا المخطط أو تخطيط الجدول -أو نقله port بالاصطلاح الحاسوبي- إلى قاعدة بيانات أخرى فسيتوجب علينا إضافة بعض المعلومات. أما الخطوة التالية فهي تحميل بعض البيانات إلى الجدول لنبدأ تنفيذ الاستعلامات، وسنترك ذلك تدريبًا للقارئ -باستخدام رمز الإدراج أعلاه قالبًا-، لكن سنستخدم مجموعة البيانات التالية في الأمثلة أدناه: First Last House Street District Town PostCode Phone Mona Akbar 42 Any Street SomePlace MyTown ABC123 01234 567890 Jamil Masoud 17 Any Street SomePlace MyTown ABC234 01234 543129 Yousef Mohammad 9 Crypt Drive Hotspot Metropolis ABC345 01234 456459 Yasein Akbar 42 Any Street SomePlace MyTown ABC123 01234 567890 Yasein Akbar 12A Double Street AnyTown DEF174 01394 784310 Amal Akbar 12A Double Street AnyTown DEF174 01394 784310 لدينا الآن بعض البيانات ونريد إجراء التجارب عليها، لنرى كيفية استخدام الإمكانيات الموجودة في SQL لاستخراج البيانات بطرق لم نكن لنحلم بها في مثال القاموس المبني على الملفات في بايثون. من يعيش في هذا الشارع؟ هذا الاستعلام بسيط ومباشر نوعًا ما، لأننا قسمنا بيانات العنوان إلى حقول منفصلة، فلو لم نفعل ذلك لاحتجنا إلى كتابة شيفرة تحليل لاستخراج بيانات الشارع، وهذا أكثر تعقيدًا لا شك، وسيبدو استعلام SQL الذي نريده كما يلي: sqlite> SELECT First,Last FROM Address ...> WHERE Street = "Any Street"; من يحمل اسم Akbar؟ هذا أيضًا تعبير SELECT/WHERE بسيط في SQL: sqlite> SELECT First,Last FROM Address ...> WHERE Last = "Akbar"; ما هو رقم هاتف Yasein؟ وهذا أيضًا استعلام بسيط إلا أننا سنحصل على عدة نتائج: sqlite> SELECT First,Last, Phone FROM Address ...> WHERE First LIKE "Yas%"; نلاحظ أننا استخدمنا LIKE في شرط WHERE، وهذا يستخدم أسلوب الموازنة الخاص بمحرف البدل wild card، ويتجاهل حالة الأحرف، لاحظ أن رمز محرف البدل في SQL هو % بدلًا من محرف * الشائع، ونتيجةً لهذا نحصل على مطابقة أكثر مرونةً من التساوي الذي يتطلب تطابقًا تامًا، ونلاحظ أننا لو استخدمنا %Y فقط في محرف البدل لحصلنا على Yosef في النتائج أيضًا. ما هي الأسماء المتكررة؟ هذا استعلام أكثر تعقيدًا، وسنحتاج إلى اختيار مداخل الجدول التي تكررت أكثر من مرة، وهنا يبرز دور المفتاح ContactID: sqlite> SELECT DISTINCT A.First, A.Last ...> FROM Address AS A, Address AS B ...> WHERE A.First = B.First ...> AND A.Last = B.Last ...> AND NOT A.ContactID = B.ContactID; نستخدم هنا بعض المزايا الجديدة، حيث نضيف A وB -وهما اسمان بديلان aliases- إلى الجداول في شرط FROM، كما نضيف أسماءً بديلةً للقيم الناتجة أيضًا لتقليل الكتابة، ونستخدم هذه الأسماء عند الإشارة إلى الحقول الناتجة باستخدام الصيغة النقطية المعتادة، يمكن استخدام الاسم البديل في أي استعلام، لكننا مجبرون على استخدامه هنا لأننا نستخدم نفس الجدول Address في المرتين -ومن ثم نضمه إلى نفسه-، لذا نحتاج إلى اسمين بديلين للتمييز بين النسختين في شرط where، كما نضيف الكلمة المفتاحية DISTINCT التي تحذف أي نتائج مكررة. وخلاصة الفقرات السابقة أن الاستعلام يبحث عن الصفوف التي لها نفس الاسم الأول والأخير، لكن لها معرِّف جهة اتصال ContactID مختلف، ثم يحذف الصفوف المتشابهة قبل عرض النتائج. لمحث SQLite التفاعلي نفس قوة محث بايثون من حيث القدرة على تطوير استعلامات معقدة مثل هذا، فقد نبدأ باستعلام بسيط ثم نزيد التعقيد لاحقًا، فمثلًا آخر جزء أضفناه إلى الاستعلام الأخير كان كلمة DISTINCT، على الرغم من أنها الكلمة الثانية فيه. الوصول إلى SQL من بايثون توفر SQLite واجهة برمجة تطبيقات API تتكون من عدد من الدوال القياسية التي تسمح للمبرمجين بتنفيذ جميع العمليات الممكنة في محث SQL، وقد كُتبت API الخاصة بـ SQLite بلغة C، لكن توجد مغلِّفات لها للغات الأخرى، بما في ذلك بايثون. الاتصالات Connections أول ما نحتاج إليه للتعامل مع قواعد البيانات هو الاتصالات، ويأتي الاسم من حقيقة أن أغلب قواعد البيانات ما هي إلا برامج مخدمات server programs تعمل على حاسوب مركزي في مكان ما في الشبكة، ونريد أن نتصل بها، عادةً بواسطة التسجيل باسم مستخدم وكلمة مرور. ورغم أن SQLite ما هي إلا ملف موجود في نظام الملفات لدينا، إلا أن API تطلب الاتصال به -أي فتحه- للحفاظ على اتساق العمليات. المؤشرات Cursors من المهم عند استخدام قاعدة بيانات من داخل برنامج ما أن نعرف كيفية الوصول إلى الصفوف المتعددة التي يُحتمل أن تعيدها تعليمة SELECT، وذلك باستخدام ما يُعرف بمؤشرات SQL أي SQL cursors، والمؤشر هنا يشبه تسلسل بايثون في القدرة على الوصول فيه إلى صف واحد في كل مرة، وعليه فإن استخراج بياناتنا إلى مؤشر ثم استخدام حلقة تكرارية loop للوصول إليه يمكّننا من معالجة تجميعات كبيرة من البيانات. ولا يخزن المؤشر كل البيانات الناتجة، وإنما يخزن مرجعًا إليها يُحفظ في جدول مؤقت داخل قاعدة البيانات، وهذا أقل أهميةً بالنسبة لـ SQLite التي تكون في الغالب على نفس الحاسوب الذي عليه البرنامج، لكنه مهم عند التعامل مع قاعدة بيانات متصلة بشبكة العميل/الخادم. يسمح المؤشر بجلب البيانات بكميات صغيرة، وهذا أسرع وأوفر للذاكرة من نسخ جميع البيانات الناتجة إلى البرنامج مرةً واحدةً، وتبرز أهمية ذلك عند العمل على قواعد بيانات كبيرة جدًا أحجامها بالجيجابايت، لكن هذا يعني أننا عندما نعالج جزءًا من البيانات الناتجة في وقت ما، فيجب ألا ننفذ أي استعلامات أخرى باستخدام نفس المؤشر، وإلا فسنفقد الوصول إلى مجموعة النتائج الأصلية، لذا يجب إنشاء مؤشر جديد للاستعلام الجديد. أما في البرامج الصغيرة -مثل التي لدينا- فنستطيع نسخ جميع البيانات إلى هيكل بيانات بايثون لحل المشكلة، لكن يجب الانتباه إلى أننا قد نحتاج إلى عدة مؤشرات في البرامج الكبيرة. الواجهة البرمجية لقواعد البيانات DB API يمكن قراءة توثيق الإصدار الأخير من واجهة برمجة التطبيقات لقواعد البيانات DB API في بايثون على موقع بايثون في قسم Database Topic Guide، ويجب قراءته بعناية خاصةً عند برمجة قواعد بيانات ذات أهمية باستخدام بايثون. تثبيت تعريفات SQLite تأتي تعريفات SQLite في مكتبة بايثون القياسية افتراضيًا، فإذا أردنا استخدام قاعدة بيانات أخرى، مثل SQL Server الخاصة بمايكروسوفت أو MySQL أو Oracle، فسنحتاج إلى تنزيل الوحدات المناسبة لكل منها وتثبيتها، ويمكن الحصول على تعريفات أغلب قواعد البيانات المشهورة من pip أو في ملفات تنفيذية. سيكون أمر استيراد SQLite كما يلي: import sqlite3 استخدام DBI الأساسي لن نغطي جميع المزايا الموجودة في DBI، لكننا سنذكر ما يكفي ليمكننا من الاتصال بقاعدة بياناتنا، وتنفيذ بعض الاستعلامات، ومعالجة النتائج، وسنختم بإعادة كتابة برنامج دليل جهات الاتصال ليستخدم قاعدة بيانات جهات الاتصال بدلًا من ملف نصي. >>> db = sqlite3.connect('address.db') >>> cur = db.cursor() >>> cur.execute('SELECT * FROM address') >>> print( cur.fetchall() ) ستكون النتيجة ما يلي: [(1, 'Mona', 'Akbar', '42', 'Any Street', 'SomePlace', 'MyTown', 'ABC123', '01234 567890'), (2, 'Jamil', 'Masoud', '17', 'Any Street', 'SomePlace', 'MyTown', 'ABC234', '01234 543129'), (3, 'Yousef', 'Mohammad', '9', 'Crypt Drive', 'Hotspot', 'Metropolis', 'ABC345', '01234 456459'), (4, 'Yasein', 'Akbar', '42', 'Any Street', 'SomePlace', 'MyTown', 'ABC123', '01234 567890'), (5, 'Yasein', 'Akbar', '12A', 'Double Street', '', 'AnyTown', 'DEF174', '01394 784310')] تعيد cursor.fetchball()‎ قائمةً من الصفوف tuples، وهذا مشابه لما بدأنا به في مقال مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية، ونستطيع استخدام هذه القائمة في برنامجنا كما لو قرأناها من ملف مستخدمين قاعدة البيانات آليةً ثابتةً، غير أن قوة قواعد البيانات الحقيقية تكمن في قدرتها على تنفيذ استعلامات معقدة باستخدام SELECT. دليل جهات الاتصال لا زال برنامج دليل جهات الاتصال الخاص بنا يعتمد على سطر الأوامر وليست له واجهة رسومية، فإذا أردنا إضافة واجهة مستخدم فيجب أن نعيد هيكلة الشيفرة refactoring لفصل الوظائف عن العرض، على كل سنضيف واجهة ويب للبرنامج. لن نشرح كل تفصيل في الشيفرة هنا، فيجب أن يستطيع القارئ في هذا المستوى أن يفهمها بنفسه، لكننا سنركز على بعض النقاط ونناقشها. ############################### # Addressbook.py # # Author: A J Gauld # ''' Build a simple addressbook using the SQLite database and Python DB-API. ''' ############################### # set up the database and cursor import sqlite3 dbpath = "D:/DOC/Homepage/Tutor2/sql/" def initDB(path): try: db = sqlite3.connect(path) cursor = db.cursor() except sqlite3.OperationalError: print( "Failed to connect to database:", path ) db,cursor = None,None raise return db,cursor # Driver functions def addEntry(book): first = input('First name: ') last = input('Last name: ') house = input('House number: ') street = input('Street name: ') district = input('District name: ') town = input('City name: ') code = input('Postal Code: ') phone = input('Phone Number: ') query = '''INSERT INTO Address (First,Last,House,Street,District,Town,PostCode,Phone) VALUES (?,?,?,?,?,?,?,?)''' try: book.execute(query,(first, last, house, street, district, town, code, phone)) except sqlite3.OperationalError: print( "Insert failed" ) raise return None def removeEntry(book): name = input("Enter a name: ") names = name.split() first = names[0]; last = names[-1] try: book.execute('''DELETE FROM Address WHERE First LIKE ? AND Last LIKE ?''',(first,last)) except sqlite3.OperationalError: print( "Remove failed" ) raise return None def findEntry(book): validFields = ('first','last','house','street', 'district','town','postcode','phone') field = input("Enter a search field: ") value = input("Enter a search value: ") if field.lower() in validFields: query = '''SELECT first,last,house,street,district,town,postcode,phone FROM Address WHERE %s LIKE ?''' % field else: raise ValueError("invalid field name") try: book.execute(query, (value,) ) result = book.fetchall() except sqlite3.OperationalError: print( "Sorry search failed" ) raise else: if result: for line in result: print( line ) else: print("No matching data") return None def testDB(database): database.execute("SELECT * FROM Address") print( database.fetchall() ) return None def closeDB(database, cursor): try: cursor.close() database.commit() database.close() except sqlite3.OperationalError: print( "problem closing database..." ) raise # User Interface functions def getChoice(menu): print( menu ) choice = input("Select a choice(1-4): ") return choice def main(): theMenu = ''' 1) Add Entry 2) Remove Entry 3) Find Entry 4) Test database connection 9) Quit and save ''' try: theDB, theBook = initDB(dbpath + 'address.db') while True: choice = getChoice(theMenu) if choice == '9' or choice.upper() == 'Q': break if choice == '1' or choice.upper() == 'A': addEntry(theBook) elif choice == '2' or choice.upper() == 'R': removeEntry(theBook) elif choice == '3' or choice.upper() == 'F': try: findEntry(theBook) except: ValueError: print("No such field name")) elif choice == '4' or choice.upper() == 'T': testDB(theBook) else: print( "Invalid choice, try again" ) except sqlite3.OperationalError: print( "Database error, exiting program." ) # raise finally: closeDB(theDB,theBook) if __name__ == '__main__': main() نلاحظ عدة أمور هي: استخدمنا الشرط try/except لالتقاط أي أخطاء في قاعدة البيانات، وبما أن الخطأ هو نوع مخصص معرَّف داخل وحدة sqlite3، فسنحتاج إلى سبقه باسم الوحدة. استخدمنا الكلمة المفتاحية raise بعد طباعة رسالة الخطأ، فنتج عن ذلك رفع الاستثناء الأصلي إلى المستوى التالي، والذي هو main في حالتنا، حيث التقط وطُبعت رسالة أخرى. استخدمنا كذلك محرف البدل ? في سلاسل الاستعلامات لتحمل متغيرات البيانات، وهذا يشبه محدِّدات % المستخدمة في صياغة السلاسل النصية، لكن تُدخل القيم هنا جزءًا من تنفيذ الاستعلام بواسطة book.execute، حيث نمرر صف القيم المدرجة وسيطًا ثانيًا، وميزة هذا تكمن في التحقق الأمني من قيم الدخل مما يحسِّن من أمان الشيفرة، فإذا لم نتحقق من الدخل، أو استخدمنا الصياغة القياسية للسلاسل النصية؛ فقد يكتب أحد المستخدمين شيفرةً بدلًا من قيمة الدخل، لتدخل تلك الشيفرة إلى الاستعلام وتخرب قاعدة البيانات، وهذا يُعرف بهجمات الحقن injection attack في دوائر الأمن الرقمي، وهو أحد أكثر الاختراقات الأمنية شهرةً في الويب هذه الأيام. نستخدم كلًا من اسم الحقل وقيمة البحث حقول إدراج في الدالة findEntry، مما يجعل دالة البحث أكثر تنوعًا، ولولاه لاحتجنا إلى دالة بحث لكل معيار بحث criteria وهذا أمر مرهق جدًا. لكن توجد مشكلة هنا سببها أن آلية معامِلات SQLite تعمل للقيم فقط، وليس لعناصر SQL، مثل أسماء الحقول أو الجداول، ولحل هذا نحتاج إلى استخدام صياغة السلاسل النصية في بايثون لإدراج اسم الحقل، ونحتاج إلى التحقق من أن اسم الحقل هو أحد الأسماء المعرّفة قبل إدراجه في الاستعلام، لنضمن أن الاستعلام آمن، فإذا لم يكن الحقل صالحًا فسنرفع استثناء بايثون قياسي من النوع ValueError، ثم نحتاج إلى التقاط ذلك في دالة main()‎، ونلاحظ أن الاستعلام يستخدم تعبير البحث LIKE الذي يسمح لنا باستغلال خيار محرف البدل % في SQL في سلسلة البحث الخاصة بنا. تحتوي الدالة closeDB على استدعاء commit، وهذا يجبر قاعدة البيانات على كتابة جميع التغييرات في الجلسة الحالية إلى الملف، ويمكن النظر إليها على أنها تشبه التابع file.flush، فهي تنهي العملية transaction نوعًا ما. تغلف الدالة main كل شيء داخل بنية try/except/finally، ويلتقط الشرط except الاستثناءات التي رفعتها دوال المستوى الأدنى كما ذكرنا أعلاه، لكن نلاحظ أنه يحوي تعليمة raise التي أُخرجت من التنفيذ بوضع علامة تعليق قبلها، لأن التعقب الخلفي الكامل للخطأ مفيد جدًا في تنقيح الأخطاء رغم كونه غير مفضل للمستخدم من حيث قابلية القراءة، لذلك يمكن إلغاء التعليق من raise التي في المستوى الأعلى أثناء التطوير لنحصل على تعقب خلفي كامل على الشاشة، وبعد حلّ جميع الزلات البرمجية bugs نعيد التعليق إلى تعليمة raise مرةً أخرى لاستعادة العرض النهائي للبرنامج، وهذا الأسلوب ليس مقصورًا على قواعد البيانات وحدها، بل يمكن استخدامه في أي برنامج يحتمل رفع أخطاء كثيرة فيه ولا نريد إظهار ذلك للمستخدمين، لكننا نحن المكورون نريد أن نراها. يُستخدم الشرط finally في دالة main لضمان إغلاق قاعدة البيانات بأناقة بغض النظر قابلنا أخطاءً أم لا، وهذا يقلل خطر تخريب البيانات. ملاحظة عن الأمن الرقمي ذكرنا أعلاه أن استخدام DB API لمحددات ? بدلًا من استخدام % المعتادة كان بداعي الأمان، ويمكن استخدام صياغة السلاسل النصية المعتادة في الشيفرة، وسنجد أنها ستعمل، مما يغري باستخدامها، غير أنه يُفضل عدم فعل ذلك لما نعلم من كثرة الهجمات السيبرانية، فيجب هنا اتباع هذه الإرشادات لتصبح عادات للمبرمج للحفاظ على أمان الشيفرة. ورغم أنها حل غير كامل وقد نخسر معها رؤية استعلامات SQL الحقيقية المرسَلة إلى قاعدة البيانات، والذي كنا سنستفيد منه في تنقيح الأخطاء، لكن هذه أفضل طريقة للتغلب على احتمال أن يُدخل المستخدم بيانات شاذةً. كلمة أخيرة استخدمنا SQLite في أمثلتنا لأنها متاحة مجانًا، وسهلة التثبيت والاستخدام، ومرنة في مدى الأخطاء التي تسمح بها، غير أن هذه البساطة تعني أن المزايا الأكثر تقدمًا والموجودة في الحزم الأقوى غير موجودة فيها، فإمكانيات معالجة النصوص ومجال القيود المتاحة محدود للغاية، ويجب قضاء وقت كافٍ في قراءة الوثائق المرجعية عند التعامل مع قواعد بيانات مثل Oracle أو قاعدة بيانات DB2 من IBM، لأن استخدام المزايا التي توفرها قاعدة البيانات يقلل من كم الشيفرات المخصصة التي ستُكتب، ويحسن الأداء أيضًا. المزايا المتقدمة لقواعد البيانات المفاتيح الخارجية تحتوي أغلب قواعد البيانات -بما فيها SQLite- على مفاتيح خارجية foreign keys، تسمح لنا بتحديد الروابط أو العلاقات بين الجداول، بحيث تتكون هذه المفاتيح من مفاتيح رئيسية لجداول أخرى، وأحيانًا في قواعد بيانات أخرى. ورغم أننا لم نتحدث كثيرًا عن الروابط بين الجداول إلا أنها من أكثر المزايا شيوعًا في قواعد البيانات العلائقية خاصةً عند زيادة حجم البرامج. التكامل المرجعي التكامل المرجعي Referential integrity هو القدرة على عدم السماح بقيم بيانات في عمود إلا إذا كانت موجودةً في مكان آخر، ففي قاعدة بيانات الموظفين مثلًا، كان بإمكاننا تقييد القيمة في حقل Employee.Grade لتسمح بالقيم المعرَّفة في جدول Salary.Grade فقط، وهذه أداة بالغة القوة في الحفاظ على اتساق البيانات عبر قاعدة البيانات، خاصةً عندما تُستخدم القيم مفاتيح لربط جدولين، كما هو الحال في أعمدة grade. تدعم SQLite صورةً محدودةً من التكامل المرجعي في صورة قيد، لكنها تتطلب بعض المعالجة الخاصة، وهي أقل شموليةً من قواعد البيانات الأقوى. الإجراءات المخزنة الإجراءات المخزنة Stored Procedures هي دوال مكتوبة بلغة برمجة خاصة proprietary programming language يوفرها مزود قاعدة البيانات، وتُخزَّن في قاعدة البيانات، ومزيتها أنها إجراءات مصرَّفة compiled، وبالتالي أسرع كثيرًا من استخدام أوامر SQL المكافئة، كما أنها توفر من استهلاك الإنترنت وحجم البيانات المطلوب، من خلال طلب اسم الدالة والوسطاء فقط ليرسلها برنامج العميل، ولكونها مبنيةً داخل الخادم فهي تسمح لنا ببناء سلوكيات مشتركة -مثل قواعد العمل المعقدة- في قاعدة البيانات حيث يمكن تشاركها بواسطة جميع التطبيقات باستمرار، لكن عيبها أنها خاصة ومغلقة، فإذا أردنا تغيير مزود قاعدة البيانات لدينا فيجب إعادة كتابة جميع الإجراءات المخزنة، في حين أن SQL القياسية ستعمل دون تغيير على أي قاعدة بيانات، ولا تدعم SQLite أي إجراءات مخزنة. العروض العروض Views هي جداول افتراضية مكونة من جداول حقيقية أخرى، وقد تكون مجموعةً فرعيةً من البيانات في جدول آخر من أجل تبسيط التصفح، وفي الحالة الأشهر تكون بعض الأعمدة من جدول وبعضها من جدول آخر بحيث يكون الجدولان مرتبطين معًا بمفتاح ما. ويمكن النظر إليها على أنها استعلام SQL يُنفّذ باستمرار وتُخزن النتيجة في العرض، وسيتغير العرض مع تغير البيانات التي فيه، وقد تسمح بعض قواعد البيانات بقراءة البيانات في العرض، غير أنها جميعًا تسمح بالتحديثات. تُستخدم العروض في الغالب لتقسيم البيانات بحيث يستطيع المستخدم الواحد أن يرى مجموعة البيانات المتعلقة به فقط، وتدعم SQLite العروض، لكننا لم نشرحها هنا. عمليات الحذف المتتالية إذا أجرينا حذفًا متتاليًا cascaded delete بين عنصري بيانات فهذا يعني أنه عند حذف العنصر الرئيسي فستُحذف العناصر الثانوية أيضًا، وأحد أشهر الأمثلة على ذلك هو الطلبات orders، حيث يتكون الطلب عادةً من الطلب نفسه بالإضافة إلى العناصر المطلوبة، ويُخزن كل منها عادةً في جدول منفصل، فإذا حذفنا الطلب فإننا نرغب بالتأكيد في حذف عناصره، وتُهيأ عمليات الحذف المتتالية في تعليمات DDL لقواعد البيانات المستخدمة لإنشاء مخططات قواعد البيانات، وهي أحد أنواع القيود، ولا تدعم SQLite عمليات الحذف المتكررة. المحفزات تشبه المحفزات Triggers الأحداث إلى حد ما، فهي جزء من SQL يُنفَّذ عند وقوع حدث معين، كما في حالة إدراج صف جديد في جدول ما مثلًا، وهي مفيدة في التحقق من صلاحية البيانات تحققًا أعمق من مجرد النوع والقيم، كما تكون مفيدةً للغاية عند ربطها بالإجراءات المخزنة. أما عيبها فهو إمكانية إساءة استخدامها، وشرهها الزائد للموارد، مما يؤدي لإبطاء قاعدة البيانات كثيرًا، لذا يجب استخدامها بحذر، وتدعم SQLite محفزات SQL الأساسية والخالصة. أنواع البيانات المتقدمة تسمح بعض قواعد البيانات بتخزين مجموعات متنوعة من أنواع البيانات، فقد يكون لدينا عناوين شبكية network addresses وكائنات ثنائية binary كبيرة يشار إليها اختصارًا باسم BLOBS لملفات الصور وغيرها، إضافةً إلى البيانات العددية وبيانات المحارف والتاريخ والوقت المعتادة، ومن أنواع البيانات المشهورة أيضًا نوع يسمى بالنوع العشري ذي الدقة الثابتة fixed precision decimal type، وهو يُستخدم في البيانات المالية لتجنب أخطاء التقريب الموجودة في أعداد الفاصلة العائمة التقليدية، وتدعم SQLite بيانات BLOB لكنها لا تدعم بقية الأنواع المتقدمة، وللاطلاع على المزيد من الاستخدامات المعقدة لـ SQLite يمكن العودة إلى موقع sqlitetutorial الذي يحتوي على شرح ممتاز يسهل تعلم ما فيه بناءً على ما شرحنا هنا. خاتمة في نهاية هذا المقال نرجو أن تكون تعلمت ما يلي: قواعد البيانات تنظم البيانات في جداول. تتكون السجلات من حقول، وتشمل صفوف الجداول. SQL هي لغة تُستخدم في إدارة البيانات. الأوامر الأساسية في لغة SQL هي: CREATE وINSERT وSELECT وUPDATE. توفر لغات البرمجة مغلِّفات SQL للوصول إلى البيانات من البرامج. تخزن المؤشرات نتائج استعلامات SQL في صورة مؤقتة، لكن يمكن الوصول إليها. تُستخدم محدِّدات DB API لإدراج قيم في الاستعلامات، ولا تُستخدم صيغة السلاسل النصية القياسية. ترجمة -بتصرف- للفصل الرابع والعشرين: Working with Databases من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: التواصل مع نظام التشغيل عبر بايثون المقال السابق: دراسة حالة برمجية التعامل مع البيانات (الإدخال، الحذف والتعديل) في SQL دوال التعامل مع البيانات في SQL مقارنة بين أنظمة إدارة قواعد البيانات العلاقية: SQLite مع MySQL مع PostgreSQL
  15. مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية يحتاج أي عمل إبداعي إلى ثلاثة مكونات أساسية هي: الأدوات التي يُنجَز بها، والخامات التي يتكون منها، والأساليب والتقنيات التي تُستغل الأدوات والخامات بها لإنجاز ذلك العمل، فأدوات الرسم مثلًا هي الفرش والأقلام ولوحات الرسم، كما أن من أساليب الرسم الخلط والرش وغيرها، ثم تأتي الخامات التي هي الدهانات والأوراق والماء ونحو ذلك. وبصورة مماثلة نجد أن أدوات البرمجة هي لغات البرمجة ونظم التشغيل وعتاد الحواسيب التي ستعمل عليها البرامج؛ أما الأساليب والتقنيات فهي هياكل البرامج التي تحدثنا عنها في المقال السابق، والخامات هي البيانات التي نعدل فيها ونعالجها، وهي ما سننظر فيه في هذا المقال. هذا المقال طويل بسبب طبيعة البيانات نفسها، لكننا كتبناه بحيث لا تجب قراءته كله من أجل إدراك الفهم الكامل للبياناتوتستطيع البدء فيه من البداية التي نمر فيها على الأنواع البسيطة للبيانات. البيانات Data من المعلوم بالمشاهدة في عالم البرمجة أن البيانات هي أكثر المصطلحات المستخدمة حاليًا، رغم قلة من يفهمها على حقيقتها، وما يهمنا في هذه السلسلة في موضوع تعريف البيانات نفسها؛ هو أن تعلم أنها الحقائق أو الأرقام التي يمكن استخلاص النتائج والمعلومات المفيدة منها، ورغم أن هذا يكاد يكون تسطيحًا لمفهومها، إلا أنه يعطينا نقطةً نبدأ منها على الأقل، وسنرى فيما يلي إن كنا نستطيع توضيح ذلك بالنظر في كيفية استخدام البيانات في البرمجة. البيانات هي تلك المعلومات الخام التي يعدّل فيها البرنامج ويغيرها، فلا تستطيع البرامج تنفيذ أي وظيفة ولا مهمة ذات قيمة بغير تلك البيانات، وتتوقف أنواع التعديلات التي تجريها البرامج على البيانات على تلك الأنواع نفسها، فكل نوع له عدد من العمليات التي يمكن إجراؤها عليه، فقد رأينا مثلًا أننا نستطيع جمع الأعداد معًا، إذ تحدث عملية الجمع على النوع العددي من البيانات، مما يعني أن البيانات تأتي في عدة صور وأشكال، وسننظر في كل نوع من أشهر تلك الأنواع، إضافةً إلى العمليات المتاحة على ذلك النوع. المتغيرات Variables تخزَّن البيانات في ذاكرة الحواسيب، ويمكن تشبيه تلك الذاكرة بذاكرة مكاتب البريد القديمة، إذ توضع صناديق صغيرة على حوائط تلك المكاتب لتصنيف الرسائل البريدية، ويجب كتابة الوجهة التي تُرسَل إليها رسائل كل صندوق على الصندوق نفسه، إذ لا قيمة للرسائل من دون وجهة تُرسل إليها، وهنا نُسقط مثالنا على البرمجة، إذ إن المتغيرات هي العناوين التي تكتَب على الصناديق داخل ذاكرة الحاسوب. بهذا نكون قد عرفنا نوع البيانات الآن، لكننا لا نستطيع تعديلها قبل أن تكون لنا صلاحية الوصول إليها، وهذه هي وظيفة المتغيرات، فنحن ننشئ نسخًا من أنواع البيانات ونسندها إلى المتغيرات، والنسخة instance هي مجرد جزء من البيانات وليكن 3 أو 5 مثلًا، وهي نُسخ لأعداد؛ أما المتغير فهو إشارة إلى منطقة محددة في ذاكرة الحاسوب تحتوي على البيانات. قد تتطلب بعض لغات البرمجة أن يُصرَّح عن المتغير declared ليطابق نوع البيانات التي يشير إليها، فإذا حاولنا إسناد نوع خاطئ من البيانات إليه، فسنحصل على خطأ، ويفضل بعض المبرمجين ذلك النوع المسمى بالكتابة الثابتة static typing، لأنه يحول دون ارتكاب الزلات البرمجية bugs الدقيقة التي يصعب اكتشافها، على أن جميع اللغات التي نستخدمها هنا مرنة إلى الحد الذي نستطيع معه إسناد أي نوع من البيانات إلى المتغيرات، وهو ما يُعرف بالكتابة الديناميكية dynamic typing. تتبع أسماء المتغيرات قواعدًا محددةً تختلف باختلاف لغة البرمجة التي تستخدمها، فلكل لغة قواعدها للأحرف التي يُسمح أو لا يُسمح بها، كما تشترط بعض اللغات مثل جافاسكربت وبايثون أن ينتبه المبرمج إلى حالة الأحرف التي يكتبها، بحيث تختلف python عن Python مثلًا، كما توجد لغات أخرى مثل VBScript لا تهتم لهذا، لكن يفضل أن يُتبَّع أسلوب ثابت في تسمية المتغيرات لتجنب الأخطاء الشائعة عند الانتقال من لغة لأخرى، ومن الأساليب المستخدمة في تسمية المتغيرات هو بدء اسم المتغير بحرف صغير، ثم استخدام حرف كبير لبداية كل كلمة تالية في اسمه، كما يلي: aVeryLongVariableNameWithCapitalisedStyle لن نتحدث هنا عن القواعد التي تحكم المحارف المسموح بها في لغات البرمجة التي سنستخدمها، لكن إذا كنت تستخدم الأسلوب الذي في المثال؛ فستجنب نفسك كثيرًا من المشاكل في هذا الشأن. ومن الأساليب المستخدمة في تسمية المتغيرات أيضًا فصل الكلمات في اسم المتغير بشرطة سفلية، كما في another_variable_name؛ أما في لغة بايثون فيأخذ المتغير نوع البيانات المسندة إليه، ويحتفظ بهذا النوع ويحذرك إذا حاولت خلط البيانات بطرق تختلف عنه، كأن تحاول إضافة سلسلة نصية إلى عدد مثلًا، وهي نفس حالة المثال الذي عرض لنا رسالة الخطأ في المقال السابق، ويمكن تغيير نوع البيانات التي يشير إليها المتغير عن طريق إعادة الإسناد إلى المتغير reassigning. >>> q = 7 # عددًا الآن q صار >>> print( q ) 7 >>> q = "Seven" # ليكون سلسلة نصية q أعد إسناد >>> print( q ) Seven لاحظ أن المتغير q ضُبط ليشير إلى العدد 7 ابتداءً، وقد حافظ على تلك القيمة إلى أن جعلناه يشير إلى سلسلة المحارف "Seven"، وعلى هذا نستنتج أن متغيرات بايثون تحافظ على النوع الذي تشير إليه، لكننا نستطيع تغيير ذلك عن طريق إعادة الإسناد إلى المتغير، وتلك هي الكتابة الديناميكية التي ذكرناها قبل قليل. ويمكن التحقق من نوع المتغير باستخدام الدالة type()‎ كما يلي: >>> print( type(q) ) <class 'str'> تُفقد البيانات الأصلية عند إعادة الإسناد، وتمسحها بايثون من الذاكرة ما لم يكن ثمة متغير آخر يشير إليها، وهذا المحو يُعرف باسم جمع المهملات Garbage Collection، والذي يمكن تشبيهه بموظف غرفة البريد الذي يأتي مرةً واحدةً كل فترة ويزيل أي طرود في صناديق البريد لا توجد عليها ملصقات، فإذا لم يستطع العثور على مالك لها أو لم يوجد عنوان على الطرد؛ فسيرميها في المهملات. لننظر الآن في بعض الأمثلة على أنواع البيانات. متغيرات جافاسكربت و VBSCript تختلف جافاسكربت عن أختها VBScript قليلًا في طريقة استخدام المتغيرات، فكلاهما ترى وجوب التصريح عن المتغير قبل استخدامه، وهي خاصية تشترك فيها اللغات المصرَّفة compiled مع اللغات ذات الكتابة الثابتة statically typed، بل حتى في اللغات الديناميكية مثل تلك التي نستخدمها، حيث نستفيد من التصريح عن المتغيرات في حالة حدوث خطأ إملائي عند استخدام متغير، إذ سسيدرك المترجم أن متغيرًا غير معروف قد استُخدم، وسيرفع خطأً؛ أما عيب هذا الأسلوب فهو الحاجة إلى مزيد من الكتابة من قِبل المبرمج. VBScript يصرَّح عن المتغير في لغة VBScript باستخدام التعليمة Dim، وهي اختصار لكلمة Dimension أو بُعد، وهي إشارة إلى الجذور الأولى للغة VBScript في لغة BASIC ولغات التجميع من قبلها، حيث كان يجب علينا إخبار المجمِّع بكمية الذاكرة التي سيستخدمها المتغير -أو أبعاده-، وظل الاختصار موجودًا حتى الآن. ويبدو التصريح عن المتغير في VBScript كما يلي: Dim aVariable نستطيع بمجرد التصريح عن المتغير أن نعين قيمًا له كما فعلنا في بايثون، ويمكن التصريح عن عدة متغيرات في تعليمة Dim واحدة بسردها جميعًا مع فصلها بفواصل إنجليزية "," كما يلي: Dim aVariable, another, aThird ويبدو الإسناد بعدها كما يلي: aVariable = 42 another = "هذه جملة قصيرة." aThird = 3.14159 قد نرى كلمةً مفتاحيةً أخرى هي Let، وهي من جذور BASIC أيضًا، لكننا لن نراها إلا نادرًا لقلة الحاجة إليها، وهي تُستخدم كما يلي: Let aVariable = 22 ولن نستخدمها على أي حال في هذه السلسلة. جافاسكربت نستطيع التصريح عن المتغيرات مسبقًا في جافاسكربت باستخدام الكلمة var، كما يمكن التصريح عن عدة متغيرات كما في VBScript في تعليمة var واحدة: var aVariable, another, aThird; كما تسمح جافاسكربت بتهيئة -أو تعريف- المتغيرات مثل جزء من تعليمة var، كما يلي: var aVariable = 42; var another = "A short phrase", aThird = 3.14159; يوفر هذا قليلًا من وقت الكتابة، لكنه لا يختلف عن أسلوب VBScript مع المتغيرات والمكون من خطوتين. يمكن التصريح عن متغيرات جافاسكربت وتهيئتها من غير استخدام var، بنفس الطريقة المتبعة في بايثون: aVariable = 42; غير أن المتعصبين لجافاسكربت يرون أن استخدام var أفضل، لذا سيكون هذا أسلوبنا في هذه السلسلة أيضًا. نأمل أن تكون تلك النبذة المختصر عن متغيرات جافاسكربت وVBScript قد أوضحت الفرق بين التصريح عن المتغيرات وبين تعريفها، أما متغيرات بايثون، فتعريفها يعني ضمنيًا التصريح عنها كذلك. أنواع الكتابة: صارمة أم متغيرة أم ثابتة لقد أشرنا إلى الكتابة الثابتة والديناميكية فيما سبق من المقال، وتوجد أنواع أخرى من الكتابة مثل الكتابة الصارمة strict -أو القوية أحيانًا أخرى-، والكتابة الفضفاضة loose أو الضعيفة، وسنحاول هنا أن نوضح الاختلافات بينها. تُنشأ المتغيرات مثل أنواع بيانات مرنة أو ثابتة، ويقال أن النوع الثابت مكتوب كتابةً ثابتةً أي أنه لا يتغير أبدًا-، أما المتغير الذي قد يشير إلى عدة أنواع من البيانات فيُكتب ديناميكيًا، لذا تشير البيانات الثابتة والديناميكية إلى أنواع البيانات التي يمكن تخزينها داخل المتغير. ويمكن دمج المتغيرات في العمليات المختلفة عند البرمجة، حيث ستتطلب كل عملية احتواء متغيراتها على أنواع بعينها، مثل الأعداد أو المحارف، فإذا رفضت اللغة السماح لعملية ما باستخدام أنواع خاطئة؛ فسيقال أن هذا النوع من الكتابة كتابةٌ صارمة. تحاول بعض اللغات إجبار القيم على الأنواع الصالحة المسموح بها، بينما تسمح لغات أخرى بأي نوع ثم تفشل العملية وتخرِج خطأً، وتلك هي الكتابة الفضفاضة، وعلى هذا تشير كل من الكتابة الصارمة والفضفاضة إلى أسلوب التحقق من أنواع المتغيرات المستخدَمة في العمليات، وبالنسبة للغات التي سنستخدمها في هذه السلسلة، فجميعها تستخدم كتابةً ديناميكيةً قويةً. الأنواع الأساسية للبيانات تسمى أنواع البيانات الأساسية primitive data types بهذا الاسم لأنها أبسط أنواع البيانات التي يمكن معالجتها والتعامل معها، أما الأنواع الأعقد من البيانات فما هي في الواقع إلا تجميعات من الأنواع الأساسية، فهي اللبنات الأساسية التي تكوَّن منها جميع الأنواع الأخرى، وبناءً عليه تكون هي أساس الحوسبة كلها، وتشمل الأنواع الأساسية الأرقام والأحرف ونوعًا آخر اسمه النوع البولياني boolean type. سلاسل المحارف Strings لقد رأينا هذه السلاسل من قبل، وهي أي سلسلة من المحارف التي يمكن طباعتها على الشاشة، وقد توجد فيها محارف تحكم لا تُطبع ولا تُرى على الشاشة. تُعرض تلك السلاسل في صورة أحرف، لكن الحاسوب يخزنها في صورة تسلسلات من الأرقام، ويطلق على ربط تلك الأرقام بالمحارف اسم الترميز encoding، وتوجد العديد من الترميزات المختلفة، رغم أن المنتشر حاليًا منها هو واحد من ثلاثة ترميزات معرَّفة بواسطة معيار الترميز الموحد Unicode Standard، وسننظر في الترميز الموحد أو اليونيكود في مقال لاحق، لكن يجب أن تعلم أن غرضه توفير مخطط ترميز يمثل أي حرف من أي أبجدية في أي مكان في العالم، إضافةً إلى المحارف الخاصة التي تحتاجها الحواسيب مثل الأقواس والتحكم والتهريب وغيرها. لن نعير هذا الترميز كثير الانتباه أثناء العمل، لكن قد نحتاج إلى التحويل بين الرموز الرقمية والأحرف، كما في مشكلة الاقتباسات في مثال VBScript من المقال السابق. ويمكن تمثيل السلاسل النصية في بايثون بعدة طرق: باستخدام علامات اقتباس مفردة: 'هذه سلسلة نصية' أو باستخدام علامات اقتباس مزدوجة: "وهذه سلسلة نصية تشبهها" أو بعلامات اقتباس ثلاثية مزدوجة: """ أما هذه فسلسلة نصية أطول ونستطيع إطالتها وتقسيمها على ما نشاء من الأسطر وستحافظ بايثون على هذه الأسطر """ يُستخدم النوع الأخير في إنشاء توثيقات لدوال بايثون التي ننشئها بأنفسنا كما سنرى في مقال تال، ويمكن استخدام علامات اقتباس ثلاثية مفردة، لكننا لا ننصح بهذا، إذ قد يصعب تحديد ما إذا كانت العلامات ثلاثيةً مفردةً أم علامةً مزدوجةً داخل أخرى مفردة. نستطيع الوصول إلى المحارف المنفردة في السلسلة النصية بمعاملتها مثل مصفوفة من المحارف -انظر المصفوفات أدناه-، كما توجد بعض العمليات التي توفرها لغة البرمجة لتساعدنا في التعامل مع السلاسل، مثل العثور على سلسلة فرعية أو ربط سلسلتين معًا، ونسخ واحدة إلى أخرى، وهكذا. تجدر الإشارة إلى أن بعض اللغات فيها نوع منفصل للمحارف، أي لحرف واحد فقط، وفي تلك الحالة تكون السلاسل مجرد مجموعات من قيم تلك الأحرف، لكن بايثون -على نقيض هذا-ـ إذ تستخدم سلسلةً طولها وحدة واحدة لتخزين الحرف الواحد، ولا يلزم وجود صياغة خاصة. العوامل النصية String Operators توجد عدة عمليات يمكن إجراؤها على السلاسل النصية، وبعضها مضمّن مسبقًا في بايثون، لكن يمكن توفير عمليات إضافية باستخدام الوحدات المستورَدة كما فعلنا مع وحدة sys في المقال السابق حول التسلسلات البسيطة. table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } العامل الوصف S1 + S2 ضم كل من S1 و S2 S1 * N تكرار قدره N من S1 يمكننا أن نرى ذلك في الأمثلة التالية: >>> print( 'Again and ' + 'again' ) # ضم السلسلة Again and again >>> print( 'Repeat ' * 3 ) # تكرار السلسلة Repeat Repeat Repeat >>> print( 'Again ' + ('and again ' * 3) ) # '*' جمع '+' و Again and again and again and again كما يمكن إسناد سلاسل أحرف إلى متغيرات: >>> s1 = 'Again ' >>> s2 = 'and again ' >>> print( s1 + (s2 * 3) ) Again and again and again and again لاحظ أن المثالين الأخيرين أنتجا نفس الخرج. هناك الكثير من الأمور التي يمكن تنفيذها باستخدام السلاسل النصية، وسننظر فيها بتفصيل في مقالات تالية بعد أن نكتسب خبرةً جيدةً في المواضيع التي تسبقها. ربما تجب ملاحظة أن السلاسل النصية في بايثون لا يمكن تعديلها، أي أننا نستطيع إنشاء سلسلة نصية جديدة مع تغيير بعض الأحرف، لكن لا يمكن تعديل أي حرف داخل سلسلة تعديلًا مباشرًا، ويُعرف نوع البيانات ذاك الذي لا يمكن تغييره باسم النوع غير القابل للتغير immutable. متغيرات السلاسل النصية في VBScript تسمى المتغيرات في VBScript باسم المتغايرات variants، لأنها قد تحتوي على أي نوع من البيانات، وتحاول VBScript أن تحولها إلى النوع المناسب وفق الحاجة، وعليه فقد نسند عددًا إلى متغير ما، لكن إذا استخدمناه مثل سلسلة نصية فستحاول VBScript أن تحوله نيابةً عنا، وهذا يشبه -من الناحية العملية- سلوك أمر print في بايثون، غير أنه هنا يمتد إلى أي أمر VBSCript. ويمكن إعطاء VBScript لإشارة على أننا نريد قيمةً عدديةً في صورة سلسلة نصية من خلال تغليفها بعلامتي اقتباس مزدوجتين: <script type="text/vbscript"> MyString = "42" MsgBox MyString </script> يمكن دمج سلاسل VBScript معًا في عملية تسمى بالضم concatenation، باستخدام العامل &: <script type="text/vbscript"> MyString = "Hello" & "World" MsgBox MyString </script> سلاسل جافاسكربت النصية تحاط سلاسل جافاسكربت النصية بعلامات اقتباس مفردة أو مزدوجة، ويجب أن نصرّح عن المتغيرات قبل استخدامها، وذلك بكلمة var المفتاحية. في المثال التالي سنصرح عن متغيري سلاسل نصية ونعرّفهما: <script type="text/javascript"> var aString, another; aString = "Hello "; another = "World"; document.write(aString + another); </script> كما تسمح لنا جافاسكربت بإنشاء كائنات سلاسل نصية، ويمكن القول بأنها سلاسل نصية مع بعض المزايا الإضافية، والاختلاف الرئيسي بينهما هو طريقة إنشائها، والتي هي بالشكل: <script type="text/javascript"> var aStringObj, anotherObj; aStringObj = String("Hello "); anotherObj = String("World"); document.write(aStringObj + anotherObj); </script> قد تكون تلك كتابةً كثيرةً قياسًا على المثال السابق مع أنهما ينجزان العمل نفسه -وهذا صحيح نوعًا ما-، غير أن كائنات السلاسل تعطينا مزايا في بعض المواقف تجعلنا نفضل استخدامها عما سواها، كما سنرى لاحقًا. الأعداد الصحيحة Integers الأعداد الصحيحة هي الأعداد الكاملة غير الكسرية، من أكبر قيمة سالبة إلى أكبر قيمة موجبة، وهذا التحديد لمجال القيم مهم في البرمجة على عكس الرياضيات، إذ لا نعير اهتمامًا لقيمة العدد غالبًا طالما ينتمي إلى مجموعة أساسية أو المجموعة التي نعمل عليها، أو لم يكن يؤثر في الناتج؛ أما في البرمجة فهناك حدود عظمى وحدود دنيا، ويعرَف الحد الأعلى باسم MAXINT، كما يعتمد على عدد البتات bits المستخدَمة في حاسوبك لتمثيل عدد ما. يكون في أغلب الحواسيب ولغات البرمجة الحالية العدد 64-بت في المعماريات الحديثة، لذا فإن قيمة الحد الأعلى هنا MAXINT تساوي 10 مرفوعة إلى الأس 19، وتستطيع بايثون إخبارنا بقيمة maxint باستخدام وحدة sys، فإذا كانت معمارية النظام 64-بت مثلًا فستكون قيمة sys.maxsize هي 9223372036854775807، وهو رقم كبير؛ أما في VBScript فتكون تلك القيمة محدودةً بـ (‎+/- 32000‎) لأسباب تاريخية. تُعرَف الأعداد التي تحمل إشارةً موجبةً أو سالبةً بالأعداد الصحيحة ذات الإشارة signed integers، ومن الممكن استخدام أعداد صحيحة لا إشارة لها، غير أن هذا مقصور على الأعداد الموجبة، بما في ذلك الصفر، وهذا يعني أن الأعداد الصحيحة التي لا إشارة لها ضعف عدد ذوات الإشارة، بما أننا سنستغل المساحة التي كانت مخصصةً للأعداد السالبة لضمها إلى الأعداد التي لا إشارة لها، مما يعني زيادة قيمة الحد الأقصى إلى الضعف أيضًا "‎2 * MAXINT"، ونظرًا لأن حجم الأعداد الصحيحة مقيد بقيمة MAXINT، فإذا جمعنا عددين صحيحين وكان ناتج الجمع أكبر من الحد الأقصى؛ فسنحصل على خطأ، لكن قد تعيد بعض الأنظمة واللغات تلك القيمة الخاطئة كما هي مع رفع راية سرية secret flag نستطيع التحقق من وجودها إذا كنا نشك في الإجابة، وفي مثل هذه الحالة يكون التحقق عادةً هو برفع حالة خطأ، فإما أن يكون البرنامج حينها قادرًا على معالجة ذلك الخطأ فيعالجه، أو ينهي البرنامج نفسه إذا لم يستطع. تحوّل كل من جافاسكربت وVBScript العدد إلى صيغة تستطيعان التعامل معها، ولا تهتمان بالدقة هنا، إذ قد تختلف الصيغة الجديدة اختلافًا طفيفًا؛ أما لغة بايثون فتستخدم شيئًا اسمه العدد الصحيح الطويل Long Integer، وهي ميزة خاصة لها تسمح بأعداد صحيحة غير محدودة الحجم. >>> import sys >>> x = sys.maxsize * 1000000 >>> print(x) 9223372036854775807000000 >>> print (type(x)) <class 'int'> كما نرى فالنتيجة أكبر بكثير من القيمة التي تتوقعها من الحاسوب في العادة، رغم احتسابها int، أما إذا استخدمنا شيفرةً مكافئةً لهذا المثال في جافاسكربت وVBScript؛ فسيخرج لنا العدد بصيغة تختلف عن العدد الصحيح الذي نتوقعه، وسنتعلم المزيد عن هذا في قسم الأعداد الحقيقية. <script type="text/vbscript"> Dim x x = 123456700 * 34567338738999 MsgBox CStr(x) </script> العمليات الحسابية رأينا معظم العمليات الحسابية التي نحتاج إليها في المقال السابق في التسلسلات البسيطة، ولكن للتلخيص نعيدها مرةً أخرىً: مثال العامل الوصف M + N جمع M و N M - N طرح N من M M * N ضرب M في N M / N قسمة M على N، سيكون الناتج عددًا حقيقيًا كما سنبين لاحقًا M // N القسمة الصحيحة لـ M على N، ستكون النتيجة عددًا صحيحًا M % N باقي القسمة: أوجد ما تبقى من قسمة M على N M**N الأس: M مرفوعًا إلى الأس N بما أننا لم نرى المتغير الأخير من قبل، فلننظر في مثال على إنشاء بعض متغيرات الأعداد الصحيحة ونستخدم عامل الأس: >>> i1 = 2 # i1 أنشئ عددًا صحيحًا وأسنده إلى >>> i2 = 4 >>> i3 = i1**i2 # i3 أسند نتيجة 2 إلى أس 4 إلى >>> print( i3 ) 16 >>> print( 2**4 ) # أكد النتيجة 16 تحتوي الوحدة math في بايثون على بعض الدوال الرياضية الشائعة مثل sin و cos وغيرهما. عوامل الاختصار إحدى العمليات الشائعة في البرمجة هي زيادة قيمة المتغير التدريجية، فإذا كان لدينا المتغير x الذي قيمته 42، ونريد زيادة تلك القيمة إلى 43، فسيكون ذلك كما يلي: >>> x = 42 >>> print( x ) >>> x = x + 1 >>> print( x ) لاحظ السطر التالي: x = x + 1 لا معنىً لهذا السطر من حيث المنطق الرياضي، لكنه في البرمجة يعني أن x الجديدة تساوي قيمة x السابقة مضافًا إليها 1، فإذا كنت معتادًا على المنطق الرياضي؛ فستستغرق بعض الوقت لتعتاد على هذا النمط الجديد، لكن الفكرة هنا أن علامة = تُقرأ "ستكون" وليست "تساوي"، وعليه فإن السطر يعني أن x ستصبح قيمتها الجديدة هي x+1، وهذا النوع من العمليات شائع جدًا في الممارسة العملية إلى حد أن بايثون وجافاسكربت توفران عاملًا مختصرًا له من أجل توفير الكتابة على المبرمج: >>> x += 1 >>> print( x ) وهذان العاملان مساويان تمامًا لتعليمة الإسناد السابقة لكنهما أقصر، توجد عوامل اختصار لباقي العمليات الحسابية بنفس المنطق السابق، نبينها في الجدول التالي: مثال العامل الوصف M += N M = M + N M -= N M = M - N M *= N M = M * N M /= N M = M / N M //= N M = M // N M %= N M = M % N الأعداد الصحيحة في VBScript لقد قلنا إن الأعداد الصحيحة في VBScript محدودة بقيمة عظمى أقل من بايثون وجافاسكربت، وهي تقابل 16-بت على خلاف 64-بت التي رأيناها من قبل، أي حوالي "‎+/- 32000"، فإذا احتجنا إلى عدد صحيح أكبر من هذا؛ فنستخدم العدد long الذي يساوي حجمه حجم العدد الصحيح من معمارية 32-بت (أي 2 مليار)، كذلك لدينا النوع byte الذي هو عدد ثماني البتات، وحجمه الأكبر يساوي 255، وسيتضح بالممارسة العملية أن النوع القياسي للعدد الصحيح كافٍ لأغلب العمليات، فإذا كانت نتيجة العملية أكبر من MAXINT؛ فستحول VBSCript النتيجة تلقائيًا إلى عدد ذي فاصلة عائمة أو حقيقي، كما سنبين لاحقًا. ورغم دعم VBScript لجميع العمليات الحسابية المعتادة، إلا أن عملية الباقي modulo تمثَّل تمثيلًا مختلفًا، باستخدام العامل MOD، وقد رأينا ذلك في فصل التسلسلات البسيطة، كذلك فإن تمثيل الأسس مختلف، إذ يُستخدم محرف الإقحام ^ بدلًا من ** في بايثون. أعداد جافاسكربت تحتوي جافاسكربت على نوع عددي في صورة كائن كما سنصفه فيما بعد، وهي تسميه Number، لكن أحيانًا قد يكون عدد جافاسكربت "ليس عددًا" أو Not a Number، ويشار إليه بـ NaN اختصارًا، وهو ما نحصل عليه أحيانًا كنتيجة لبعض العمليات المستحيلة رياضيًا، والهدف منه هو السماح لنا بالتحقق من أنواع أخطاء بعينها دون تعطيل البرنامج، كما تحوي لغة بايثون كذلك النوع NaN أيضًا. تحتوي جافاسكربت على نسخ عددية خاصة لتمثيل اللانهاية الموجبة والسالبة، وهي ميزة نادرة نسبيًا في لغات البرمجة، وقد تكون كائنات جافاسكربت العددية إما أعدادًا صحيحةً أو حقيقيةً كما سنرى لاحقًا، وتَستخدم جافاسكربت نفس العوامل التي تستخدمها بايثون، باستثناء الإجراءات الأسية التي تستخدم كائنًا خاصًا بها اسمه Math. الأعداد الحقيقية Real Numbers الأعداد الحقيقية هي نفسها الأعداد الصحيحة لكن مع إضافة الكسور، وقد تمثل أعدادًا أكبر من الحد الأقصى MAXINT لكن مع دقة أقل، وهذا يعني أننا قد نرى عددين حقيقيين على أنهما متطابقين، لكن الحاسوب يراهما غير متطابقين عندما يوازنهما معًا، لأنه ينظر في أدق التفاصيل بينهما، حيث يمكن تمثيل العدد 5.0 في الحاسوب بإحدى الصورتين 4.9999999 أو (‎5.000000…01) مثلًا، وهذه التقاربات مناسبة لأغلب الاستخدامات، لكن قد نحتاج أحيانًا إلى تلك الدقة، فتذكر هذا الأمر إذا حصلت على نتيجة غريبة لا تتوقعها عند استخدام الأعداد الحقيقية. كما تُعرَف الأعداد الحقيقية أيضًا باسم أعداد الفاصلة العائمة floating point numbers، ولها نفس العمليات الحسابية التي تطبّق على الأعداد الصحيحة، مع زيادة هنا وهي قدرتها على اقتطاع العدد ليكون قيمة صحيحة. تدعم لغات البرمجة الثلاث بايثون وجافاسكربت وVBScript الأعداد الحقيقية، وننشئها في بايثون بتخصيص عدد بعلامة عشرية فيه كما رأينا في المقال السابق للتسلسلات البسيطة؛ أما جافاسكربت وVBScript فلا يوجد تمييز واضح بين الأعداد الصحيحة والحقيقية، فما عليك إلا استخدامها وستتعامل اللغة مع ما تدخله إليها وفق المناسب. الأعداد المركبة أو التخيلية Complex numbers إذا كانت لديك خلفية رياضية فقد تتساءل أين الأعداد المركبة complex في هذا الشرح، والواقع أننا لا نحتاج إليها غالبًا في البرمجة، لكن على أي حال فبعض اللغات مثل بايثون توفر دعمًا مضمّنا فيها للأعداد المركبة، بينما توفر بعض اللغات الأخرى مكتبةً من الدوال التي تستطيع التعامل مع الأعداد المركبة، ونفس الأمر ينطبق على المصفوفات. يمثَّل العدد المركب في بايثون كما يلي: (real+imaginaryj) وبناءً عليه تبدو عملية جمع بسيطة لعدد مركب كما يلي: >>> M = (2+4j) >>> N = (7+6j) >>> print( M + N ) (9+10j) تنطبق جميع عمليات الأعداد الصحيحة على الأعداد المركبة كذلك، كما توجد وحدة cmath التي تحتوي بعض الدوال الرياضية الشائعة التي تعمل على قيم الأعداد المركبة، ولا توفِّر جافاسكربت وVBScript دعمًا للأعداد المركبة. القيم البوليانية - True و False سُمي هذا النوع من القيم بهذا الاسم نسبةً إلى عالم الرياضيات George Boole الذي كان يدرس المنطق في القرن التاسع عشر، ولا يحوي هذا النوع من البيانات إلا قيمتين فقط، هما True عند التحقق أو الصحة، و false عند عدم التحقق أو الخطأ، وتدعم بعض اللغات هذا النوع دعمًا مباشرًا، بينما تستخدم بعض اللغات الأخرى اصطلاحًا تمثل فيه قيمةً عدديةً القيمة false، وتكون تلك القيمة غالبًا هي الصفر؛ بينما تمثَّل القيمة true بالعدد (1) أو (‎-1)، وقد كان هذا سلوك بايثون حتى الإصدار 2.2، لكنها صارت تدعم القيم البوليانية مباشرةً بعد ذلك باستخدام القيمتين True و False، وهما كما ترى تبدآن بحرف كبير، فتذكر أن بايثون حساسة لحالة الأحرف. تعرَف القيم البوليانية أحيانًا باسم قيم الحقيقة لأنها تُستخدم للتحقق مما إذا كان شيء ما صحيحًا أم لا، فإذا كتبنا برنامجًا يأخذ نسخةً احتياطيةً من جميع الملفات في مجلد ما مثلًا، فنستطيع نسخ كل ملف على حدة ثم نطلب اسم الملف التالي من النظام، وإذا لم تتبق ملفات لنسخها، فسيعيد النظام سلسلةً نصيةً فارغةً، حيث سنتحقق هنا مما إذا كان الاسم هو سلسلةً فارغةً أم لا، ونخزن النتيجة مثل قيمة بوليانية تكون قيمتها True إذا كان الاسم سلسلةً فارغةً، و False إذا لم يكن كذلك، وسنرى كيفية استخدام تلك النتيجة لاحقًا في هذه السلسلة. العوامل البوليانية أو المنطقية العامل الوصف الأثر A and B الإضافة أو AND صحيح إذا كان كل من A و B صحيحًا أو متحققًا، وخطأ في الحالات الأخرى A or B الاختيار أو OR صحيح إذا كان أحدهما أو كلاهما صحيحًا، وخطأ إذا كان كل من A و B خاطئًا A == B التساوي صحيح إذا كان A يساوي B A != B عدم التساوي صحيح إذا كانت A لا تساوي B not B النفي صحيح إذا لم يكن B صحيحًا تدعم VBScript القيم البوليانية كما تفعل بايثون على الصورة True و False، أما جافاسكربت فتدعمها لكن على الصورة true و false -لاحظ حالة الأحرف الصغيرة هنا-. كما ستجد أسماءً مختلفةً لنوع البيانات البولياني أو المنطقي في كل لغة، ففي بايثون ستجدها باسم bool، أما في جافاسكربت وVBScript فاسمه Boolean، ولا تشغل بالك بهذا لأننا لن ننشئ متغيرات من هذا النوع، لكننا سنستخدم نتائجه في الاختبارات. الوقت والتاريخ يُعطى التاريخ والوقت في العادة أنواعًا خاصةً بهما في البرمجة، لكن قد يمثَّلان أحيانًا في صورة عدد كبير (عدد الثواني منذ وقت أو تاريخ قديم، مثل الوقت الذي كُتب فيه نظام التشغيل)، لكن قد يكون نوع البيانات في أحيان أخرى هو ما يُعرف بالنوع المعقد الذي سنذكره في الفصل التالي، وهو يسهل استخراج الشهر واليوم والساعة… سننظر في استخدام بايثون لوحدة time في مقال تالٍ، أما جافاسكربت وVBScript فلديهما آليات خاصة للتعامل مع الوقت، لكننا لن ندرسها. النوع الذي يعرفه المستخدم User Defined Type قد لا تكفي الأنواع التي ذكرناها سابقًا لاحتياجاتنا البرمجية حتى لو دمجناها معًا، فقد نريد جمع عدة أجزاء من البيانات معًا ثم نعاملها مثل عنصر واحد، كما في وصف العنوان مثلًا، حيث يكون على هيئة "رقم المنزل والشارع والمدينة ، ثم الرمز البريدي". تسمح أغلب اللغات بجمع مثل هذه المعلومات معًا في سجل أو هيكل بيانات أو في هيئة صنف Class، وهذا الأخير في البرمجة كائنية التوجه Object Oriented. VBScript تبدو تعريفات السجلات في VBScript كما يلي: Class Address Public HsNumber Public Street Public Town Public ZipCode End Class تعني الكلمة المفتاحية Public أن البرنامج يستطيع الوصول إلى البيانات، وعليه توجد كلمة Private التي يمكن استخدامها لجعل البيانات خاصةً ومقصورةً على أجزاء بعينها من البرنامج، كما سنرى لاحقا. بايثون يختلف الأمر قليلًا في بايثون: >>> class Address: ... def __init__(self, Hs, St, Town, Zip): ... self.HsNumber = Hs ... self.Street = St ... self.Town = Town ... self.ZipCode = Zip ... سنترك شرح معنى كل من self و def __init__(...)‎ إلى حين الحديث عن البرمجة كائنية التوجه، أما الآن فنريد ملاحظة أن هناك شرطتين سفليتين حول init، وهذا أسلوب متبع في بايثون. لاحظ كذلك ضرورة استخدام المسافات الموضحة أعلاه، ذلك أن بايثون دقيقة في تحديد المسافات. قد يواجه البعض مشاكل أثناء كتابة ما يتشابه مع هذا المثال في محث بايثون، وستجد في نهاية هذا المقال شرحًا مختصرًا لهذه المشكلة، ثم سنشرحها بالتفصيل في جزء تالٍ من هذه السلسلة، فإذا أردت كتابة المثال أعلاه في محث بايثون؛ فتأكد من نسخ المسافات البادئة لكل سطر. والأمر الذي نريد التوكيد عليه هنا هو أننا جمعنا عدة أجزاء من بيانات مرتبطة ببعضها بعضًا ثم وضعناها في هيكل واحد هو Address، كما فعلنا في VBScript قبل قليل. جافاسكربت توفر جافاسكربت اسمًا غريبًا لهيكل بيانات العنوان في حالتنا، وهو function، إذ ترتبط الدوال عادةً بالعمليات وليس تجميعات البيانات، غير أن دوال جافاسكربت تستطيع التعامل مع كليهما، فإذا أردنا إنشاء كائن العنوان في جافاسكربت؛ فسنكتب الآتي: function Address(Hs,St,Town,Zip) { this.HsNum = Hs; this.Street = St; this.Town = Town; this.ZipCode = Zip; } نريد مرةً أخرى تجاهل الصياغة واستخدام الكلمة this هنا، والنظر إلى النتيجة التي ستكون مجموعةً من عناصر البيانات التي نستطيع القول بأنها تصف عنوانًا، ويمكننا معاملته على أنه وحدة واحدة. والآن، كيف نصل إلى تلك البيانات بعد إنشاء هياكلها؟ الوصول إلى الأنواع التي يعرفها المستخدم من الممكن إسناد نوع بيانات معقد إلى متغير، لكن لا يمكن الوصول إلى الحقول المنفردة دون استخدام بعض آليات الوصول الخاصة التي تحددها اللغة، وتكون نقطة . في الغالب. VBScript إذا استخدمنا حالة صنف العنوان الذي عرّفناه أعلاه، فسنكتب ما يلي: Dim Addr Set Addr = New Address Addr.HsNumber = 7 Addr.Street = "High St" Addr.Town = "Anytown" Addr.ZipCode = "123 456" MsgBox Addr.HsNumber & " " & Addr.Street & " " & Addr.Town نحدد هنا بُعد متغير جديد هو Addr باستخدام Dim، ثم نستخدم الكلمتين Set و New لإنشاء نسخة جديدة من صنف Address، ثم نسند القيم إلى حقول نسخة العنوان الجديدة، ثم نطبع العنوان في صندوق رسالة. بايثون على فرض أننا كتبنا تعريف الصنف أعلاه: >>> Addr = Address(7,"High St","Anytown","123 456") >>> print( Addr.HsNumber, Addr.Street, Addr.Town ) 7 High St Anytown ينشئ هذا نسخةً من نوع Address ويسند إليه المتغير Addr، ونستطيع تمرير قيم الحقل إلى الكائن الجديد عند إنشائه في بايثون، ثم نطبع حقول HsNumber و Street للنسخة المنشأة حديثًا باستخدام عامل النقطة .. كما يمكن إنشاء نسخ عنوان متعددة لكل منها قيمه المستقلة لأرقام البيوت والشوارع وغيرها. جرب هذا بنفسك لتتدرب عليه، فهل تستطيع معرفة كيفية استخدام هذا في مثال دفتر العناوين؟ جافاسكربت تشبه آلية جافاسكربت هنا ما سبق ذكره لكن مع بعض التعديل، غير أن الآلية الأساسية بسيطة ومباشرة: var addr = new Address(7, "High St", "Anytown", "123 456"); document.write(addr.HsNum + " " + addr.Street + " " + addr.Town); إحدى الآليات التي يمكن استخدامها في جافاسكربت أيضًا هي معاملة الكائن مثل قاموس واستخدام اسم الحقل كمفتاح: document.write( addr['HsNum'] + " " + addr['Street'] + " " + addr['Town']); وما لم نُعط اسم الحقل في هيئة سلسلة نصية كما في حالة قراءة ملف أو إدخال مستخدم للبرنامج، فلا ننصح باستخدام هذا النموذج. العوامل التي يعرفها المستخدم يمكن للأنواع التي يعرِّفها المستخدم أن تكون لها عمليات معرفة لها كذلك، وذلك أساس ما يعرف بالبرمجة كائنية التوجه. الكائن هو عبارة عن تجميعة من عناصر البيانات والعمليات المرتبطة بتلك البيانات، وهي مغلفة جميعًا في وحدة واحدة، حيث تستخدم بايثون الكائنات على نطاق واسع في مكتبتها القياسية للوحدات، كما تسمح لنا كوننا مبرمجين بإنشاء أنواع الكائنات الخاصة بنا. يحصل الوصول إلى عمليات الكائنات بنفس الطريقة التي يمكن الوصول بها إلى أعضاء البيانات لنوع معرَّف من قِبل المستخدم، أي من خلال عامل النقطة؛ أما غير هذا فتكون أشبه بالدوال، وتسمى تلك الدوال الخاصة بالتوابع methods، وقد رأيناها في حالة العملية append()‎ في القوائم، أينما تذكر أنه من أجل استخدامها يجب أن نربط استدعاء الدالة باسم المتغير. >>> listObject = [] # قائمة فارغة >>> listObject.append(42) # استدعاء تابع لكائن القائمة >>> print( listObject ) [42] يجب استيراد الوحدة عند توفير نوع كائن - يُسمى صنفًا- في وحدة بايثون كما فعلنا في sys من قبل، ثم كتابة اسم الوحدة قبل اسم نوع الكائن عند إنشاء نسخة يمكن تخزينها في متغير مع استخدام الأقواس طبعًا، بعد ذلك نستطيع استخدام المتغير دون استخدام اسم الوحدة، ولتوضيح هذا لنَعُد إلى وحدة array التي ذكرناها من قبل، فهي توفر الصنف array، ولنستورد هذه الوحدة ثم ننشئ نسخةً من array، ونسند اسم myArray إليها، ثم نستخدم myArray فقط للوصول إلى عملياتها وبياناتها كما يلي: >>> import array >>> myArray = array.array('d') # array of reals(d), use module name >>> myArray.append(42) # use array operation >>> print( myArray[0]] ) # access array content 42.0 >>> print( myArray.typecode ) # access array attribute 'd' نستورد الوحدة array في السطر الأول إلى البرنامج، ثم نستخدم تلك الوحدة في السطر الثاني لإنشاء نسخة من صنف array باستدعائها مثل دالة، ونحتاج هنا إلى توفير سلسلة الرموز النوعية typecode string التي توضح نوع البيانات التي يجب تخزينها. تذكر أن المصفوفات الخالصة تخزن نوعًا واحدًا من البيانات، حيث سنصل في السطر الثالث إلى إحدى عمليات صنف المصفوفة، وهي append()‎ التي تعامل الكائن myArray كأنه وحدة وكأن العملية داخل الوحدة، ثم نستخدم الفهرسة لجلب البيانات التي أضفناها، نستطيع في الأخير الوصول إلى بعض البيانات الداخلية، إذ يخزن typecode النوع الذي مررناه عند إنشاء المصفوفة، من داخل كائن myArray صياغةً تشبه صياغة الوحدة. لا يوجد فرق كبير بين استخدام الكائنات التي توفرها الوحدات، وبين الدوال الموجودة في الوحدات، باستثناء الحاجة إلى إنشاء نسخة instance، ويمكن النظر إلى اسم الكائن على أنه عنوان يحفظ الدوال والمتغيرات المرتبطة به مجموعةً معًا. إحدى الطرق الأخرى التي ننظر بها للأمر هي أن الكائنات تمثل أشياء من العالم الحقيقي ونحن نستخدمها أو نفعل بها أمورًا تنفعنا، وهذا المنظور على بساطته إلا أنه الفكرة التي نشأت بسببها الكائنات في البرمجة، فنحن نكتب -برمجيًا- محاكاةً لمواقف في العالم الحقيقي. تستطيع كل من جافاسكربت وVBScript أن تتعامل مع الكائنات، وقد كان هذا ما استخدمناه في كل أمثلة العناوين أعلاه، فقد عرفّنا صنفًا ثم أنشأنا نسخةً أسندناها إلى متغير كي نستطيع الوصول إلى خصائص تلك النسخة، ولهذا ارجع إن شئت إلى ما سبق من الشرح عن الأصناف والكائنات، وانظر كيف توفر الأصناف آليات لإنشاء أنواع جديدة من البيانات في برامجنا من خلال الربط بين بيانات النوع الجديد وعملياته معًا. العوامل الخاصة ببايثون إنّ الهدف من هذه السلسلة هو تعليم البرمجة للمبتدئين، ورغم أننا نستخدم بايثون في الشرح؛ إلا أنك تستطيع قراءة لغة برمجة أخرى واستخدامها بدلًا منها، بل إن هذا هو عين ما نتوقعه منك، إذ أنه لا توجد لغة برمجة بما فيها بايثون، تستطيع تنفيذ جميع المهام وحل كل المشاكل التي تواجهك برمجيًا، وبسبب ذات الهدف لن نشرح جميع الخصائص الموجودة في بايثون، بل سنركز على تلك التي يمكن إيجادها في لغات البرمجة الأخرى كذلك، ولهذا سنهمل شرح بعض الخصائص بالغة القوة في بايثون، والتي تميزها عما سواها، مثل العوامل الخاصة special operators، ذلك أن أغلب لغات البرمجة تدعم عمليات بعينها لا تدعمها لغات أخرى، وتلك العوامل الفريدة هي التي تسبب ظهور لغات برمجة جديدة، وهي من العوامل المهمة في تحديد شهرة تلك اللغات من حيث الاستخدام فيما بعد. حيث تدعم بايثون مثلًا عمليات غير شائعة نسبيًا في لغات البرمجة الأخرى، مثل تشريح القائمة spam[X:Y]‎ (إلى شرائح) list slicing من أجل استخراج شريحة من وسط القائمة أو السلسلة النصية أو الصف tuple، كما تدعم إسناد الصف Tuple الذي يسمح لنا بإسناد عدة قيم متغيرات مرةً واحدةً: X, Y = (12, 34)‎. كما تسهل تنفيذ العمليات على كل عضو من أعضاء تجميعة ما باستخدام الدالة map()‎ التي سنشرحها في مقال لاحق من هذه السلسلة، إضافةً إلى الكثير من الخصائص التي جعلت بايثون تشتهر بأنها تأتي "مع البطارية" إشارةً إلى كثرة الملحقات والمزايا التي تأتي معها. ارجع إلى توثيق بايثون للمزيد عن تلك المزايا. تجدر أخيرًا الإشارة إلى أنه رغم قولنا بأن تلك العوامل خاصة ببايثون؛ إلا أن هذا لا يعني أنها لا توجد في لغات برمجة أخرى، بل أنها لن توجد مجتمعةً في كل لغة، فالعوامل التي نشرحها في هذه السلسلة تكون متاحةً بشكل أو بآخر في أغلب لغات البرمجة الحديثة. يلخص هذا نظرتنا على المواد الخام للبرمجة، وسننتقل الآن إلى موضوع آخر نرى فيه كيف نستغل تلك المواد الخام في البرمجة الحقيقية. شرح لمثال العناوين رغم قولنا أننا سنشرح تفاصيل هذا المثال لاحقًا، إلا أننا رأينا صعوبة تنفيذ مثال بايثون من بعض القراء، ولهذا سيشرح هذا القسم شيفرة بايثون سطرًا سطرًا. ستبدو شيفرة المثال كاملة كما يلي: >>> class Address: ... def __init__(self, Hs, St, Town, Zip): ... self.HsNumber = Hs ... self.Street = St ... self.Town = Town ... self.Zip_Code = Zip ... >>> addr = Address(7,"High St","Anytown","123 456") >>> print( addr.HsNumber, addr.Street ) وسنشرح الآن سطرًا سطرًا: >>> class Address: تخبر التعليمة class بايثون أننا على وشك تعريف نوع جديد اسمه Address في هذه الحالة، وتشير النقطتان الرأسيتان إلى أن أي أسطر مزاحة تالية ستكون جزءًا من تعريف الصنف، وينتهي التعريف عند أول سطر غير مزاح، فإذا كنت تستخدم IDLE؛ فسترى أن المحرر قد أزاح السطر التالي تلقائيًا، أما إذا كنت تعمل من محث بايثون في سطر أوامر DOS مثلًا، فسيكون عليك إزاحة الأسطر كما هو موضح أعلاه، ولا تهتم بايثون بمقدار الإزاحة طالما أنها نفسها لكل سطر. أما السطر الثاني: ... def __init__(self, Hs, St, Town, Zip): يطلق على العنصر الأول في الصنف الخاص بنا "تعريف التابع method definition"، ويجب أن يكون حول الاسم شرطتان سفليتان على كل ناحية منه، وهي طريقة بايثون للأسماء التي لها أهمية خاصة، ويسمى ذلك التابع __init__، وهو عملية خاصة تنفذها بايثون حين ننشئ نسخةً من الصنف الجديد الخاص بنا كما سنرى بعد قليل؛ أما النقطتان الرأسيتان فتخبران بايثون أن مجموعة الأسطر المزاحة التالية ستكون هي التعريف الحقيقي للتابع. والسطر الثالث: ... self.HsNumber = Hs يُسنِد هذا السطر -والأسطر الثلاثة التالية- قيمًا إلى الحقول الداخلية للكائن الخاص بنا، وهذه الأسطر مزاحة من تعليمة def لتخبر بايثون أنها تشكل التعريف الحقيقي لعملية __init__، أما السطر الفارغ، فيخبر مفسر بايثون بأن تعريف الصنف قد انتهى، لنعود مرةً أخرى إلى محث بايثون المعتاد ‎>>>‎. >>> addr = Address(7,"High St","Anytown","123 456") ينشئ هذا نسخةً جديدةً من النوع Address، وتستخدم بايثون عملية __init__ المعرَّفة أعلاه لإسناد القيم التي أعطيناها إلى الحقول الداخلية، وتسنَد النسخة إلى متغير addr كما تسنَد أي نسخة لأي نوع بيانات آخر. >>> print( addr.HsNumber, addr.Street ) نطبع الآن قيم حقلين من الحقول الداخلية مستخدمين عامل النقطة للوصول إليهما. خاتمة يُعَد هذا المقال دسمًا وغنيًا بالمعلومات النظرية التي تؤسس لتعلم البرمجة على أسس سليمة، وسنعود إلى ما فيه مرات كثيرة أثناء الشرح، بما أن البيانات وأنواعها هي اللبنات التي تُصنع منها البرامج، لكن نريد التذكير هنا بأن بايثون تسمح لنا بإنشاء أنواع البيانات التي نريدها بأنفسنا ونستخدمها مثل أي نوع مضمّن فيها، وأن المتغيرات تشير إلى بيانات، وقد نحتاج إلى التصريح عنها قبل تعريفها، وهي تأتي في أنواع شتى، ويتوقف نجاح العملية التي نجريها على نوع البيانات الذي نستخدمه. ومن أنواع البيانات البسيطة سلاسل المحارف والأعداد والقيم البوليانية أو قيم "الحقيقة"، كما تشمل أنوع البيانات المعقدة التجميعات والملفات والبيانات وأنواع البيانات المعرّفة من قِبل المستخدم. توجد أيضًا العديد من العوامل في كل لغة برمجة، وتيُعَد تعلّم تلك العوامل جزءًا من التعود على أنواع بياناتها وعلى العمليات المتاحة لتلك الأنواع، وقد يكون العامل الواحد متاحًا لعدة أنواع، غير أن النتيجة قد لا تكون هي نفسها في كل مرة، بل ربما تختلف اختلافًا كبيرًا. سنتابع مع المقال الموالي مع ذكر نوع أخر مهم من البيانات، وهو التجميعات Collections. ترجمة -بتصرف- للفصل الخامس: The Raw Materials من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: مدخل إلى البيانات وأنواعها: التجميعات Collections المقال السابق: التسلسلات البسيطة في البرمجة مدخل إلى البيانات الوصفية (microdata) في HTML5 هياكل البيانات: الكائنات والمصفوفات في جافاسكريبت
  16. تصف التعليمات الشرطية في البرمجة قدرتنا على تنفيذ تسلسل واحد من بين عدة تسلسلات محتملة من الشيفرات -التي تمثل الفروع- وفقًا لوقوع حدث ما، وقد كانت أبسط صورة لتلك التعليمات الشرطية في الأيام الأولى لاستخدام لغة التجميع Assembly هي تعليمة JUMP التي تجعل البرنامج يقفز إلى عنوان ما في الذاكرة، غالبًا عندما يكون ناتج التعليمة السابقة صفرًا، وقد استُخدمت هذه التعليمة في برامج بالغة التعقيد، دون استخدام أي صورة شرطية أخرى وقتها، ليؤكد هذا قول ديكسترا Dijkstra عن الحد الأدنى المطلوب للبرمجة، ثم ظهرت نسخة جديدة من تعليمة JUMP مع تطور لغات البرمجة عالية المستوى، وهي GOTO، التي لا تزال متاحةً حتى الآن في لغة QBASIC، والتي يمكن تحميلها واستخدامها من www.qbasic.net، لننظر إلى الشيفرة التالية مثلًا -بعد تثبيت QBASIC-: 10 PRINT "Starting at line 10" 20 J = 5 30 IF J < 10 GOTO 50 40 PRINT "This line is not printed" 50 STOP لاحظ كيف تحتاج إلى بضع ثوان لتعرف الخطوة التالية رغم صغر البرنامج، إذ لا يوجد هيكل للشيفرة، بل عليك أن تكتشف ما يفعله البرنامج بينما تقرؤه بنفسك، وهذا الأمر مستحيل في البرامج كبيرة الحجم، لهذا لا تحتوي أغلب لغات البرمجة الحديثة بما فيها لغة بايثون وجافاسكربت وVBScript، على تعليمة JUMP أو GOTO بحيث يمكن استخدام أي منهما مباشرةً، وإن وجدت فستحثك اللغة على عدم استخدامها، فما العمل إذًا في حالة البرمجة الشرطية؟. تعليمة if الشرطية إن أول ما يرد إلى الذهن عند التفكير في حالات شرطية هي البنية if.. then.. else، والتي تعني "إذا حدث س، فسيكون ص، وإلا سيكون ع"، فهي تتبع منطقًا لغويًا بحيث إذا تحقق شرط بولياني ما -أي كان true-، فستُنفَّذ كتلة من التعليمات، وإلا ستنفَّذ كتلة أخرى. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن بايثون إذا أردنا كتابة مثال GOTO السابق بلغة بايثون، فسيبدو كما يلي: import sys # فقط exit لنستطيع استخدام print( "Starting here" ) j = 5 if j > 10: print( "This is never printed" ) else: sys.exit() هذه الصورة أسهل من سابقتها في القراءة وفهم المراد منها، ونستطيع وضع أي شرط اختباري نريده بعد تعليمة if، طالما أنه يقيَّم إلى True أو False، جرب تغيير علامتي ‎>‎ و ‎<‎ وانظر ما سيحدث. لاحظ النقطتين الرأسيتين : في نهاية سطري التعليمتين if وelse، إذ تخبرنا هاتان النقطتان أن ما يليهما كتلة مستقلة من الشيفرة، بينما تخبرنا إزاحة تلك الكتلة ببدايتها ونهايتها. VBScript سيبدو المثال السابق في VBScript كما يلي: <script type="text/vbscript"> MsgBox "Starting Here" DIM J J = 5 If J > 10 Then MsgBox "This is never printed" Else MsgBox "End of Program" End If </script> يكاد يكون هذا المثال مطابقًا لمثال بايثون، مع فرق أن كلمة Then مطلوبة للكتلة الأولى، وأننا نستخدم End If لنعلن نهاية بنية if/then، ولعلك تذكر أننا استخدمنا كلمة Loop لإنهاء حلقة Do While في مثال VBScript من مقال سابق، ذلك أن VBScript تستخدم في اصطلاحها محددًا لنهاية التعليمة. جافاسكربت يبدو مثال if في جافاسكربت كما يلي: <script type="text/javascript"> var j; j = 5; if ( j > 10 ){ document.write("This is never printed"); } else { document.write("End of program"); } </script> لاحظ أن جافاسكربت تستخدم أقواسًا معقوصةً لتحديد كتل الشيفرات الموجودة داخل الجزء الخاص بتعليمة if والجزء الخاص بتعليمة else، وأن الاختبار البولياني يوجد بين قوسين، وليس هناك استخدام صريح لكلمة then. من المنظور الجمالي للتنسيق، يمكن وضع الأقواس المعقوصة في أي مكان، لكننا اخترنا صفها كما في المثال لإبراز بنية الكتلة البرمجية، ويمكن إهمال الأقواس المعقوصة كليًا إذا كان لدينا سطر واحد فقط داخل الكتلة كما في حالتنا هذه، لكن يفضل بعض المبرمجين وضعها للحفاظ على اتساق الكتابة، ولاحتمال إضافة سطر آخر مستقبلًا، فوضعها الآن أفضل من نسيانها لاحقًا. التعابير البوليانية لعلك تذكر أننا ذكرنا في مقال البيانات وأنواعها، نوعًا من البيانات اسمه النوع البولياني، وقلنا إن هذا النوع لا يحوي إلا قيمتين فقط، هما True وFalse، ورغم أننا لا ننشئ متغيرًا بوليانيًا إلا نادرًا، إلا أننا نحتاج إلى إنشاء قيم بوليانية مؤقتة باستخدام التعابير، والتعبير هو تجميعة من المتغيرات و/أو القيم، تجمعها معًا عوامل لإخراج قيمة ناتجة، لننظر إلى المثال التالي: if x < 5: print( x ) التعبير هنا هو x < 5، والنتيجة ستكون True إذا كانت x أقل من 5، وFalse إذا كانت x أكبر من (أو تساوي) 5. قد تكون التعابير معقدةً بما أنها تقيَّم إلى قيمة نهائية وحيدة، إذ يجب أن تكون تلك القيمة True أو False في حالة الفرع، لكن يختلف تعريف هاتين القيمتين من لغة لأخرى، فأغلب اللغات تساوي بين القيمة False وبين الصفر أو القيمة غير الموجودة أو غير المعرفة والتي تدعى NULL أو Nil أو None، وبناءً على ذلك تقيَّم القائمة الفارغة أو السلسلة النصية الفارغة إلى false في السياق البولياني وتعتمد بايثون هذا السلوك، مما يعني أننا نستطيع استخدام حلقة while لمعالجة القائمة إلى أن تصبح فارغةً، بالشكل التالي: while aList: # افعل شيئًا هنا أو يمكن استخدام تعليمة if لننظر هل القائمة فارغة أم لا، دون اللجوء إلى دالة len()‎ كما يلي: if aList: # افعل شيئًا هنا يمكن جمع عدة تعابير بوليانية باستخدام عوامل بوليانية كذلك، والتي تقلل من عدد تعليمات if التي علينا كتابتها، كما في المثال التالي: if value > maximum: print( "Value is out of range!" ) else if value < minimum: print( "Value is out of range!" ) لاحظ أن كتلة الشيفرة التي يجب تنفيذها متطابقة في شرطي المثال أعلاه، ويمكن أن نوفر على أنفسنا بعض الكتابة وعلى الحاسوب بعض العمل، بأن نجمع الاختبارين في اختبار واحد كما يلي: if (value < minimum) or (value > maximum): print( "Value is out of range!" ) لاحظ كيف جمعنا الاختبارين باستخدام عامل or البولياني، وبما أن بايثون تقيِّم مجموعة الاختبارات المجمعة تلك إلى نتيجة واحدة؛ فنستطيع القول أن هذين التعبيرين إنما هما تعبير واحد، ونستطيع استيعاب هذا الأسلوب إذا عرفنا أننا نقيّم المجموعة الأولى من الأقواس أولًا، ثم نقيّم المجموعة الثانية، ثم نجمع القيمتين الناتجتين لنشكل قيمةً نهائيةً وحيدةً تكون إما True أو False. تستخدم بايثون أسلوبًا أكثر كفاءةً من هذا يُعرف بالتقييم المقصور أو تقييم الدارة المقصورة short-circuit evaluation، وإذا تأملنا في هذه الاختبارات، فسنجد أننا نفكر فيها بالمنطق اللغوي البشري الذي يستخدم حروف العطف مثل ("و" "and") و("أو" "or") و("النفي" "not")، مما يتيح لنا كتابة اختبار واحد مجمَّع بدلًا من عدة اختبارات منفصلة، كما سنرى فيما يلي. تعليمات if المتسلسلة يمكن سَلسَلة تعليمات "if..then..else" معًا بجعلها متشعبةً، بحيث تتداخل كل واحدة مع الأخرى، لننظر مثالًا على ذلك في بايثون: # افترض أن السعر قد حُدد مسبقًا... price = int(input("What price? ")) if price == 100: print( "I'll take it!" ) else: if price > 500: print( "No way!" ) else: if price > 200: print( "How about throwing in a free mouse mat?" ) else: print( "price is an unexpected value!" ) لاحظ أننا استخدمنا == المزدوجة لاختبار التساوي في تعليمة if الأولى، بينما استخدمنا علامة = مفردةً لإسناد القيم إلى المتغيرات، وهذا الخطأ شائع جدًا في الكتابة بلغة بايثون، لأنه يعارض المنطق الرياضي الذي تعودنا عليه، وبايثون تحذرك من أن هذا خطأ لغوي syntax error، وعليك النظر والبحث لإيجاده. ننفذ اختبار "أكبر من" بدءًا من القيمة العظمى إلى الصغرى، فإذا عكسنا هذا المنطق، أي بدأنا من price > 200 فستتحقق التعليمة دومًا ولن ننتقل إلى اختبار ‎> 500، وبالمثل يجب أن يبدأ استخدام تسلسل اختبارات "أقل من" من القيمة الصغرى ثم ننتقل إلى العظمى، وهذا أيضًا أحد الأخطاء الشائعة في البرمجة ببايثون. جافاسكربت وVBScript يمكن أن نسلسل تعليمات if في جافاسكربت وVBScript أيضًا، لكننا لن نشرح إلا VBScript لأن المثال واضح: <script type="text/vbscript"> DIM Price price = InputBox("What's the price?") price = CInt(price) If price = 100 Then MsgBox "I'll take it!" Else If price > 500 Then MsgBox "No way Jose!" Else If price > 200 Then MsgBox "How about throwing in a free mouse mat too?" Else MsgBox "price is an unexpected value!" End If End If End If </script> يجب ملاحظة وجود تعليمة End If مطابقة لكل تعليمة If، واستخدامنا لدالة التحويل CInt الخاصة بلغة VBScript لتحويل الدخل من سلسلة نصية إلى عدد صحيح. تعليمات الحالة Switch/Case تتسبب إزاحة الشيفرات بملء الصفحة بسرعة، وهو أحد مساوئ سلسلة تعليمات if/else أو تشعبها، لكن شيوع هذا التسلسل المتشعب في البرمجة جعل كثيرًا من اللغات توفر نوعًا آخر من التفريع خاصًا بها، ويشار إليه عادةً باسم تعليمة Case أو Switch، التي تبدو في جافاسكربت كما يلي: <script type="text/javascript"> function doArea(){ var shape, breadth, length, area; shape = document.forms["area"].shape.value; breadth = parseInt(document.forms["area"].breadth.value); len = parseInt(document.forms["area"].len.value); switch (shape){ case 'Square': area = len * len; alert("Area of " + shape + " = " + area); break; case 'Rectangle': area = len * breadth; alert("Area of " + shape + " = " + area); break; case 'Triangle': area = len * breadth / 2; alert("Area of " + shape + " = " + area); break; default: alert("No shape matching: " + shape) }; } </script> <form name="area"> <label>Length: <input type="text" name="len"></label&lgt; <label>Breadth: <input type="text" name="breadth"></label> <label>Shape: <select name="shape" size=1 onChange="doArea()"> <option value="Square">Square <option value="Rectangle">Rectangle <option value="Triangle">Triangle </select> </label> </form> لا تقلق من حجم الشيفرة أعلاه، فما هي إلا امتداد لما شرحناه في المقالات السابقة وإن زاد حجمه قليلًا. تحتوي استمارة HTML التي في آخر الشيفرة على حقلين نصيين لإدخال الطول length و العرض breadth، أما حقل الإدخال الثالث فهو قائمة منسدلة من القيم التي ألحقناها بسمة onChange التي تستدعي دالةً ما، وكل تلك الحقول لديها عناوين labels مرتبطة. تسمح شيفرة الاستمارة في HTML بالتقاط التفاصيل والبيانات، ثم تستدعي دالة جافاسكربت حين يختار المستخدم أحد الأشكال، وبما أننا لم نشرح الدوال بعد، فيكفي أن تعلم الآن أن الدالة هي برنامج صغير تستدعيه البرامج الأخرى، وفي حالتنا هذه عرَّفنا تلك الدالة في أول الشيفرة. تنشئ الأسطر الأولى بعض المتغيرات المحلية، وتحوِّل سلاسل الإدخال النصية إلى أعداد صحيحة عند الحاجة، وما نريده هو تعليمة switch، التي تختار الإجراء المناسب وفقًا لقيمة الشكل. لاحظ أن الأقواس التي حول shape ضرورية، ولا تُحدَّد كتل الشيفرة التي داخل بنية case باستخدام الأقواس المعقوصة كما هو متوقع، فإذا أردنا إنهاءها، فسنستخدم تعليمة break؛ أما مجموعة تعليمات case الخاصة بـ switch فهي مرتبطة معًا مثل كتلة واحدة بين قوسين معقوصين. يلتقط الشرط الأخير default أي شيء لم تلتقطه تعليمات case السابقة. جرب توسيع المثال السابق ليشمل الدوائر، وتذكر أن تضيف خيارًا جديدًا إلى القائمة المنسدلة في استمارة HTML وتعليمة case جديدة إلى switch. بنية Case الاختيارية في VBScript تحتوي لغة VBscript على بنية case كما يلي: <script type="text/vbscript"> Dim shape, length, breadth, SQUARE, RECTANGLE, TRIANGLE SQUARE = 0 RECTANGLE = 1 TRIANGLE = 2 shape = CInt(InputBox("Square(0),Rectangle(1) or Triangle(2)?")) length = CDbl(InputBox("Length?")) breadth = CDbl(InputBox("Breadth?")) Select Case shape Case SQUARE area = length * length MsgBox "Area = " & area Case RECTANGLE area = length * breadth MsgBox "Area = " & area Case TRIANGLE area = length * breadth / 2 MsgBox "Area = " & area Case Else MsgBox "Shape not recognized" End Select </script> تجمع الأسطر الأولى البيانات من المستخدم وتحولها إلى النوع المناسب، تمامًا مثلما يحدث في جافاسكربت، وتظهر تعليمة select بنية case الخاصة بلغة VBScript، حيث تنهي كل تعليمة Case الكتلة التي سبقتها، كذلك لدينا فقرة Case Else التي تلتقط أي شيء لم تلتقطه تعليمات Case التي سبقتها، كما في حالة default في جافاسكربت. وكما تعودنا في أسلوب VBScript في التنسيق، فإن الشيفرة تغلَق بتعليمة End select. ربما تجب الإشارة إلى استخدام الثوابت الرمزية بدلًا من الأعداد، أي استخدام المتغيرات SQUARE وRECTANGLE وTRIANGLE، لأنها تجعل الشيفرة أسهل في القراءة، كما أن استخدام الأحرف الكبيرة هو اصطلاح لبيان كونها قيمًا ثابتةً وليست متغيرات، مع أن VBScript تسمح بأي أسماء نريدها للمتغيرات. الاختيار المتعدد في بايثون لا توفر بايثون بنية case صراحةً، وإنما تعوضنا عن ذلك بتوفير صيغة مضغوطة من if/else-if/else: menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle """ shape = int(input(menu)) if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width/2 ) else: print( "Not a valid shape, try again" ) لاحظ استخدام elif، وعدم تغير الإزاحة على عكس مثال تعليمة if المتشعبة، وتجدر الإشارة إلى أنه لا فرق بين استخدام if المتشعبة أو elif، فكلاهما صالح، كما أنهما تؤديان نفس الغرض، غير أن elif أيسر في القراءة إذا كان لدينا عدة اختبارات. أما الشرط الأخير فهو else التي تلتقط أي شيء لم تلتقطه الاختبارات السابقة، كما في default في جافاسكربت وCase Else في VBScript. توفر VBScript نسخةً معقدةً من هذه التقنية هي ElseIf...Then التي تُستخدم بنفس طريقة elif في بايثون، لكنها غير شائعة بما أن Select Case أسهل استخدامًا. إيقاف الحلقة التكرارية يغطي هذا الجزء استخدامًا خاصًا للتفريع كنا نريد شرحه في مقال الحلقات التكرارية، لكن اضطررنا إلى الانتظار حتى شرح تعليمات if، لذا نعود الآن إلى موضوع الحلقات التكرارية لنرى كيف يمكن أن يحل التفريع مشكلةً شائعةً فيها، فقد نريد الخروج من حلقة تكرارية قبل أن تنتهي. توفر أغلب اللغات آليةً لإيقاف تنفيذ الحلقة، وفي بايثون تكون تلك الآلية هي كلمة break، ويمكن استخدامها في حلقتي for وwhile. تُستخدم هذه الكلمة غالبًا عند البحث في قائمة عن قيمة ما وإيجادها، عندها لا نريد متابعة البحث إلى نهاية الحلقة، كما تُستخدم إذا اكتشفنا خللًا في البيانات، أو إذا قابلنا شرط خطأ error condition؛ أما أكثر الاستخدامات شيوعًا خاصةً في بايثون التي اعتُمد فيها هذا السلوك لكثرة استخدامه، فهو عند قراءة الدخل باستخدام حلقة while. في مثالنا التالي سنستخدم كلمة break للخروج من الحلقة عندما نقابل أول قيمة صفرية في قائمة من الأعداد: nums = [1,4,7,3,0,5,8] for num in nums: print( num ) if num == 0: break # اخرج من الحلقة فورًا print("We finished the loop") في المثال السابق نستطيع رؤية كيفية اختبار شرط الخروج في تعليمة if، ثم استخدام break للقفز خارج الحلقة. تحتوي جافاسكربت على الكلمة المفتاحية break لإيقاف الحلقات التكرارية، وتُستخدم بنفس الطريقة المستخدمة في بايثون؛ أما VBScript، فتستخدم الكلمات Exit For أو Exit Do للخروج من حلقاتها التكرارية. الجمع بين الشروط والحلقات التكرارية بما أن الأمثلة التي أوردناها سابقًا كانت نظريةً وتجريديةً، فسننظر الآن في مثال يستخدم كل ما تعلمناه سابقًا لنشرح تقنيةً شائعةً في البرمجة، وهي عرض القوائم للتحكم في مدخلات المستخدم، لنرى الشيفرة أولًا ثم نشرحها: menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle 4) Quit """ shape = int(input(menu)) while shape != 4: if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width / 2 ) else: print( "Not a valid shape, try again" ) shape = int(input(menu)) لقد زدنا ثلاثة أسطر على مثال بايثون السابق، وهي: 4) Quit while shape != 4: shape = int(input(menu)) لكن هذه الأسطر الثلاثة جعلت البرنامج أكثر سهولةً، فقد مكنّا المستخدم من استمرار حساب أحجام الأشكال المختلفة إلى أن يجمع كل المعلومات التي يريدها، وذلك بإضافة الخيار Quit إلى القائمة وحلقة while، كما لا نحتاج الآن إلى إعادة تشغيل البرنامج يدويًا في كل مرة. أما السطر الثالث الذي أضفناه فقد كان لتكرار عملية اختيار الشكل input(menu)‎ ليتمكن المستخدم من تغيير الشكل والخروج من البرنامج إذا أراد. يوهم هذا البرنامج المستخدم بأنه يعرف ما يرغب به وينفذه له، ويختلف سلوك البرنامج في كل مرة باختلاف مدخلات المستخدم، مما يجعل المستخدم يبدو وكأنه هو المتحكم بينما يكون المتحكم الحقيقي هو المبرمج، لأنه توقع جميع المدخلات الصالحة وجعل البرنامج يتفاعل معها، فتكون العبقرية الحقيقية هنا للمبرمج وليس للبرنامج أو الحاسوب، فالحواسيب غبية كما ذكرنا من قبل. تتضح الآن سهولة توسعة وظائف برنامجنا بمجرد إضافة بعض الأسطر ودمج تسلسلات -الكتل البرمجية التي تحسب مساحات الأشكال-، والحلقات التكرارية -حلقة while-، والتعليمات الشرطية -بنية if / elif-، وبهذا نكون قد أنهينا الوحدات الثلاث الأساسية التي تتكون منها البرمجة وفقًا لديكسترا، ونستطيع الآن برمجة أي شيء، من الناحية النظرية، بما أننا تعلمنا هذه الوحدات، غير أننا لا زلنا بحاجة إلى تقنيات أخرى لنتعرف على كيفية تسهيل كتابة البرامج على أنفسنا. مبدأ DRY: لا تكرر نفسك إحدى المزايا التي نريد الإشارة إليها في هذا البرنامج هو أننا اضطررنا إلى تكرار سطر input()‎ مرةً قبل الحلقة ومرةً داخلها؟ ولا يفضَّل تكرار الشيفرة البرمجية نفسها أكثر من مرة، لأننا سنضطر إلى تذكر تغيير كلا السطرين إذا احتجنا إلى تعديلها أو تغييرها، مما يفسح مجالًا للخطأ والنسيان، وهنا يمكن استخدام حيلة مبنية على خاصية break التي تحدثنا عنها في مقال الحلقات التكرارية في البرمجة، حيث نجعل في هذه الحيلة حلقة while حلقةً لا نهائية، ثم نختبر شرط الخروج، ونستخدم break للخروج منها، انظر إلى المثال التالي: menu = """ Pick a shape(1-3): 1) Square 2) Rectangle 3) Triangle 4) Quit """ while True: shape = int(input(menu)) if shape == 4: break if shape == 1: length = float(input("Length: ")) print( "Area of square = ", length ** 2 ) elif shape == 2: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of rectangle = ", length * width ) elif shape == 3: length = float(input("Length: ")) width = float(input("Width: ")) print( "Area of triangle = ", length * width / 2 ) else: print( "Not a valid shape, try again" ) يسمى تقليل التكرار هذا، والذي يبدو بدهيًا في أوساط المبرمجين، باسم مبدأ DRY، وهو اختصار لـ: "لا تكرر نفسك Dont Repeat Yourself". التعابير الشرطية توجد صورة أخرى من التفريع شائعة جدًا في البرمجة، عندما نريد إسناد قيمة مختلفة إلى متغير وفقًا لشرط ما، ويمكن فعل هذا بسهولة باستخدام شرط if/else كما يلي: if someCondition: value = 'foo' else: value = 'bar' إلا أن لغات البرمجة توفر اختصارًا لذلك، وهو ما يسمى ببنية التعبير الشرطي، ويبدو في بايثون كما يلي، وهو مطابق تمامًا في وظيفته للشيفرة أعلاه: value = 'foo' if شرط ما else 'bar' لا تحتوي VBScript على مثل هذه البنية، وتوفر جافاسكربت شيئًا شبيهًا بها، لكن البنية اللغوية له مبهمة قليلًا: <script type="text/javascript"> var someCondition = true; var s; s = (someCondition ? "foo" : "bar"); document.write(s); </script> لاحظ البنية الغريبة للشرط بين القوسين ()، الذي له نفس وظيفة الأمثلة السابقة في بايثون، إلا أنه يستخدم مجموعةً مختصرةً من الرموز، وهو يقول: "إن تحقق التعبير الذي يسبق علامة الاستفهام وكان true، فأعد القيمة التي بعد علامة الاستفهام، وإلا فأعد القيمة التي بعد النقطتين الرأسيتين". لا يُعَد القوسان ضروريين في هذا المثال رغم استخدامنا لهما، لأنهما يوضحان للقارئ ما يحدث في الشيفرة، ويُنصح باستخدامهما حتى في التعبيرات الشرطية في بايثون. إن مثل هذه الاختصارات تبدو جماليةً مريحةً في استخدامها، لكن كثيرًا من المبرمجين ينأون عنها ويرونها غير عملية، لذا يجب استخدمها متى كان وجودها ضروريًا ومتى دعت الحاجة إليها، ويُفضل تجنبها إذا جعلت الشيفرة تبدو معقدةً أكثر من اللازم. تعديل التجميعات من داخل الحلقات التكرارية لقد ذكرنا في مقال الحلقات التكرارية في البرمجة أن تعديل التجميعة collection من داخل حلقة تكرارية أمر صعب، لكن لم نشرح كيفية تعديلها وقتها، إذ أردنا الانتظار حتى نشرح التفريع أولًا، وقد أتى وقت بيان ذلك، يمكن استخدام حلقة while لتنفيذ التعديلات أثناء التكرار على التجميعة نفسها، وهذا ممكن لأننا نستطيع التحكم الصريح في الفهرس داخل بنية while على عكس حلقة for التي يحدَّث الفهرس فيها تلقائيًا. لننظر الآن كيف نحذف جميع الأصفار من قائمة ما: myList = [1,2,3,0,4,5,0] index = 0 while index < len(myList): if myList[index] == 0: del(myList[index]) else: index += 1 print( myList ) تجدر الإشارة هنا إلى أننا لا نزيد الفهرس عند حذف عنصر، بل تحرك عملية الحذف باقي العناصر للأعلى كي يشير الفهرس القديم إلى العنصر التالي في التجميعة. سنستخدم فرع if/else لنتحكم في وقت زيادة الفهرس، ويسهل هنا ارتكاب خطأ في تنفيذ مثل هذا التعديل، لذا احرص على اختبار شيفرتك جيدًا، هناك مجموعة أخرى من دوال بايثون مصممة خصيصًا لتعديل محتويات القائمة، وسننظر فيها في مقال لاحق. خاتمة في نهاية هذا المقال نريد التذكير بما يلي: استخدم if/else لتفريع مسار البرنامج. استخدام else أمر اختياري يعود إليك. يمكن تمثيل القرارات المتعددة باستخدام بنية Case أو if/elif. تعيد التعابير البوليانية القيمة True أو False، ويمكن دمجها باستخدام and أو or. دمج القوائم باستخدام البنية Case يسمح لنا ببناء تطبيقات يتحكم فيها المستخدم. ترجمة -بتصرف- للفصل العاشر: Decisions, Decisions من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: البرمجة باستخدام الوحدات المقال السابق: كيفية قراءة البرامج لمدخلات المستخدم تعلم البرمجة المدخل الشامل لتعلم علوم الحاسوب العمليات الشرطية في مايكروسوفت إكسل باستخدام VBA أسهل لغات البرمجة
  17. إن العنصر الرابع من عناصر البرمجة هو الوحدات، ومع أنك تستطيع كتابة بعض البرامج الرائعة بما تعلمته من بداية هذه الدروس إلى الآن دون تعلم الوحدات، إلا أن تتبع ما يحدث في البرامج -مع زيادة حجمها- يصبح صعبًا جدًا، وسنحتاج إلى طريقة لاستخلاص بعض التفاصيل لنستطيع التفكير في المشكلات التي تواجهنا ونريد حلها، بدلًا من صرف الجهد والوقت في التفاصيل الدقيقة المتعلقة بكيفية عمل الحاسوب. توفر بايثون وجافاسكربت وVBScript ذلك إلى حد ما بما فيها من إمكانيات مضمّنة تلقائيًا، فهي تجنبنا التعامل مع عتاد الحواسيب والنظر في كيفية قراءة كل مفتاح على لوحة المفاتيح على حدة، وغير ذلك من الأمور التي تستنزف موارد المبرمجين. وتعتمد فكرة البرمجة باستخدام الوحدات على السماح للمبرمج بتوسيع الإمكانيات الموجودة في لغة البرمجة، عبر تجميع أجزاء من البرنامج في وحدات يمكن توصيلها ببرامجنا، وقد كانت الصورة الأولى للوحدات هي البرامج الفرعية subroutines التي تمثل كتلةً من الشيفرة نستطيع القفز إليها، بدلًا من استخدام GOTO التي ذكرناها في المقال السابق، لكنها تقفز عند تمام الكتلة عائدةً إلى المكان الذي استدعيت منه، ويُعرف هذا الأسلوب من الوحدات بالإجراء procedure أو الدالة function، بل إن مفهوم الوحدة module نفسه يتغير في بعض اللغات مثل بايثون، ليأخذ معنىً أكثر دقة. استخدام الدوال لننظر أولًا في كيفية استخدام الدوال functions الكثيرة التي تأتي في أي لغة برمجة، حيث تسمى مجموعة الدوال القياسية المضمّنة في اللغة باسم المكتبة القياسية، وقد رأينا استخدام بعض الدوال، وذكرناه في قسم العوامل في مقال البيانات وأنواعها؛ أما الآن فسننظر في الأمور المشتركة بينها، وكيف يمكن أن نستخدمها في برامجنا. للدالة الهيكل الأساسي التالي: aValue = someFunction ( anArgument, another, etc... ) يأخذ المتغير aValue القيمة التي نحصل عليها باستدعاء الدالة someFunction، والتي تقبل عدة وسطاء arguments بين القوسين -وقد لا يوجد أي وسيط-، وتعاملها على أنها متغيرات داخلية، وتستطيع الدوال أن تستدعي دوالًا أخرى داخلها. تفرض بعض اللغات وضع القوسين للدالة عند استدعائها حتى لو لم يكن لها وسطاء، وقد ذكرنا أنه يفضل تعويد النفس على استخدام الأقواس حتى في لغات مثل VBScript التي لا تشترط استخدامها حتى مع وجود الوسطاء. لننظر الآن في بعض الأمثلة في لغاتنا الثلاث، ولنرى الدوال عمليًا: الدالة Mid في VBScript تعيد الدالة Mid(aString, start, length)‎ مجموعة المحارف من aString بدءًا من start وبعدد محارف length، حيث ستعرض الشيفرة التالية "Good EVENING" مثلًا. <script type="text/vbscript"> Dim time time = "MORNING EVENING AFTERNOON" MsgBox "Good" & Mid(time, 8, 8) </script> نلاحظ أن VBScript لا تتطلب أقواسًا لجمع وسطاء الدالة بل تكتفي بالمسافات كما كنا نفعل مع MsgBox، لكن عند جمعنا دالتين -كما فعلنا هنا- فيجب أن تستخدم الدالة الداخلية أقواسًا، والنصيحة العامة هي استخدام الأقواس عندما نشك هل يجب استخدامها أم لا. الدالة Date في VBScript تعيد الشيفرة التالية التاريخ الحالي للنظام: <script type="text/vbscript"> MsgBox Date </script> بما أن المثال بسيط فلا يوجد ما يمكن شرحه هنا، لكن تجدر الإشارة إلى وجود مجموعة كاملة من دوال التاريخ الأخرى التي تستخرج اليوم والأسبوع والساعة. الدالة startString.replace في جافاسكربت تعيد دالة startString.replace(searchString, newString)‎ سلسلةً نصيةً جديدةً مع وضع newString بدلًا من searchString‎ في startString. <script type="text/javascript"> var r,s = "A long and winding road"; document.write("Original = " + s + "<BR>"); r = s.replace("long", "short"); document.write("Result = " + r); </script> لاحظ أن الدوال في جافاسكربت ما هي إلا مثال لنوع خاص يسمى بالتابع method، وهو دالة ترتبط بكائن، كما شرحنا في مقال البيانات وأنواعها المذكور أعلاه، وكما سنشرح لاحقًا. وما نريد قوله، هو أن الدالة ترتبط بالسلسلة النصية s بواسطة عامل النقطة .، وهذا يعني أن s هي السلسلة التي سننفذ عليها الاستبدال، وهذا أمر عرضناه من قبل باستخدام التابع write()‎ الخاص بالكائن document الذي استخدمناه لعرض الخرج من برامج جافاسكربت باستخدام document.write()‎، لكننا لم نشرح السبب وراء صيغة الاسم المزدوجة حتى الآن. الدالة Math.pow في جافاسكربت نستخدم الدالة pow(x,y)‎ في وحدة Math -التي ذكرناها في مقال الخامس: البيانات وأنواعها- لرفع x إلى الأس y: <script type="text/javascript"> document.write( Math.pow(2,3) ); </script> الدالة pow في بايثون تستخدم بايثون دالة pow(x,y)‎ لرفع x إلى الأس y: >>> x = 2 # سنستخدم 2 كرقم قاعدة >>> for y in range(0,11): ... print( pow(x,y) ) # y ارفع 2 إلى الأس # أي من 0-10 نولد هنا قيم y من 0 إلى 10، ونستدعي الدالة المضمنة pow()‎ لتمرير وسيطين هما x وy، ونستبدل القيم الحالية لكل منهما في استدعاء pow()‎ في كل مرة، ثم نطبع النتيجة. الدالة dir في بايثون إحدى الدوال المفيدة المضمنة في بايثون هي دالة dir، والتي تعرض جميع الأسماء المصدَّرة داخل وحدة ما إذا مررنا اسم الوحدة إليها، بما في ذلك جميع المتغيرات والدوال التي يمكن استخدامها، وعلى الرغم من أننا لم نشرح إلا بضع وحدات في بايثون، إلا أنها تأتي بوحدات كثيرة. تعيد الدالة dir قائمةً من الأسماء الصالحة في الوحدة، والتي تكون دوالًا في الغالب. لنجرب هذه الدالة على بعض الدوال المضمنة: >>> print( dir(__builtins__) ) لاحظ أن builtins هي إحدى الكلمات السحرية في بايثون، وعلى ذلك يجب إحاطتها بزوج من شرطتين سفليتين على كل جانب. وإذا أردنا استخدام dir()‎ على أي وحدة، فسنحتاج إلى استيرادها أولًا باستخدام import، وإلا فستخبرنا بايثون أنها لا تتعرف عليها. >>> import sys >>> dir(sys) لقد استوردنا وحدة sys في المثال أعلاه، وهي الوحدة التي ذكرناها أول مرة في مقال التسلسلات البسيطة، ونستطيع أن نرى كلًا من exit وargv وstdin وstdout في الخرج الأخير لدالة dir، بين الأشياء الأخرى الموجودة في وحدة sys. لننظر الآن في وحدات بايثون بقليل من التفصيل قبل أن ننتقل إلى ما بعدها. استخدام الوحدات في بايثون تتميز لغة بايثون بقابليتها الكبيرة للتوسع، حيث نستطيع إضافة وحدات جديدة باستيرادها بواسطة import، وفيما يلي بعض الوحدات التي تأتي افتراضيًا مع بايثون. الوحدة sys رأينا sys سابقًا عند الخروج من بايثون، وهي تحتوي على مجموعة من الدوال المفيدة كدالة dir التي سبق شرحها، ويجب أن نستورد وحدة sys أولًا لنصل إلى تلك الدوال: import sys # نجعل الدوال متاحة print( sys.path ) # نرى أين تبحث بايثون عن الدوال sys.exit() # 'sys' أسبقها بـ وإذا علمنا أننا سنستخدم الدوال بكثرة وأنها لن تحمل نفس أسماء الدوال التي استوردناها أو أنشأناها؛ فعندئذ نستطيع فعل ما يلي: from sys import * # sys استورد جميع الأسماء في print( path ) # يمكن استخدامها دون تحديد السابقة 'sys' exit() يتمثل خطر هذا النهج في إمكانية وجود دوال بنفس الاسم في وحدتين مختلفتين، وبالتالي لن نستطيع الوصول إلا إلى الدوال التي استوردناها ثانيًا، لأننا بهذه الطريقة سنلغي الدالة التي استوردناها أولًا، فإذا أردنا أن نستخدم بعض العناصر فقط، فيفضل أن ننفذ ذلك كما يلي: from sys import path, exit # استورد الدوال التي تحتاجها فقط exit() # استخدم دون تحديد السابقة 'sys' لاحظ أن الأسماء التي نحددها لا تحتوي على أقواسًا تليها، ففي تلك الحالة سنحاول تنفيذ الدوال بدلًا من استيرادها، ولا يُعطى هنا إلا اسم الدالة فقط. نريد الآن أن نشرح طريقةً مختصرةً توفر علينا القليل من الكتابة، وهي أننا نستطيع إعادة تسمية الوحدة عند استيرادها إذا كان لها اسم طويل جدًا، مثلًا: import SimpleXMLRPCServer as s s.SimpleXMLRPCRequestHandler() لاحظ كيف أخبرنا بايثون أن تعُد s اختصارًا لـ SimpleXMLRPCServer، ولن نحتاج بعد ذلك إلا إلى كتابة s كي نستخدم دوال الوحدة، مما قلل من الكتابة. وحدات بايثون الأخرى يمكن استيراد أي وحدة من وحدات بايثون واستخدامها بالطريقة السابقة، وهذا يشمل الوحدات التي ننشئها بأنفسنا، لنلق الآن نظرةً على بعض الوحدات القياسية في بايثون، وما توفره من وظائف: وحدة sys: تسمح بالتفاعل مع نظام بايثون: exit()‎: للخروج. argv: للوصول إلى وسطاء سطر الأوامر. path: للوصول إلى مسار البحث الخاص بوحدة النظام. ps1: لتغيير محث بايثون ‎>>>‎. وحدة os: تسمح بالتفاعل مع نظام التشغيل: name: تعطينا اسم نظام التشغيل الحالي، وهي مفيدة في البرامج المحمولة التي لا تحتاج إلى تثبيت. system()‎: تنفذ أمرًا من أوامر نظام التشغيل. mkdir()‎: تنشئ مجلدًا. getcwd()‎: تعطينا مجلد العمل الحالي. وحدة re: تسمح هذه الوحدة بتعديل السلاسل النصية باستخدام التعابير النمطية regular expressions لنظام يونكس: search()‎: تبحث عن النمط في أي موضع في السلسلة النصية. match()‎: تبحث في البداية فقط. findall()‎: تبحث عن جميع مرات الورود في سلسلة نصية. split()‎: تقسيم السلسلة النصية إلى حقول مفصولة بالنمط. ()sub وsubn()‎: استبدال السلاسل النصية. وحدة math: تسمح بالوصول إلى العديد من الدوال الرياضية. ()sin وcos()‎: دوال حساب المثلثات. log(), log10()‎: اللوغاريتمات الطبيعية والعشرية. ()ceil وfloor()‎: دالتا الجزء الصحيح floor والمتمم الصحيح الأعلى ceiling. pi وe: الثوابت الطبيعية. وحدة time: دوال التاريخ والوقت. time()‎: تحصل على الوقت الحالي بالثواني. gmtime()‎: تحول الوقت بالثواني إلى التوقيت العالمي UTC (أو GMT). localtime()‎: التحويل إلى التوقيت المحلي. mktime()‎: معكوس التوقيت المحلي. strftime()‎: تنسيق السلسلة النصية للوقت، مثل YYYYMMDD أو DDMMYYYY. sleep()‎: إيقاف البرنامج مؤقتًا لمدة n ثانية. وحدة random: تولد أرقامًا عشوائية، وهي مفيدة في برمجة الألعاب. randint()‎: تولد عددًا صحيحًا عشوائيًا بين نقطتين تضمَّنان في التوليد. sample()‎: تولد قائمةً فرعيةً عشوائيًا من قائمة أكبر. seed()‎: إعادة ضبط مفتاح توليد الأعداد. هذه الوحدات على كثرتها ليست إلا شيئًا يسيرًا من الوحدات التي توفرها بايثون، والتي تزيد على مئة واحدة وأكثر يمكن تحميلها. تذكر أننا نستطيع استخدام dir()‎ وhelp()‎ للحصول على معلومات عن كيفية استخدام الدوال المختلفة، وأن المكتبة القياسية موثقة جيدًا في فهرس وحدات بايثون، ومن المصادر الجيدة للوحدات الإضافية فهرس حزم بايثون، الذي ضم عند كتابتنا لهذا المقال أكثر من مئة ألف حزمة، وكذلك مشروع SciPy الذي يستضيف مئات وحدات المعالجة العلمية والعددية، ولا غنى عنه لمن يعمل على مشاريع تحليل علمية، وأفضل وسيلة للوصول إلى تلك الحزم هو تثبيت إحدى إصدارات بايثون التي تحتوي على SciPy كإضافة قياسية فيها، مثل موقع anaconda.org، كما يحتوي sourceforge ومواقع التطوير مفتوح المصدر الأخرى على عدة مشاريع لبايثون فيها وحدات نافعة، ويمكنك الاستعانة بمحرك البحث نظرًا لتعدد المصادر، وتستطيع تصفحها وغيرها إذا أضفت كلمة python في بحثك، ولا تنس قراءة توثيق بايثون للمزيد من المعلومات عن البرمجة للإنترنت والرسوميات وبناء قواعد البيانات وغيرها. والمهم هنا إدراك أن أغلب لغات البرمجة تحوي هذه الدوال، والوظائف الأساسية إما مضمّنة فيها أو تكون جزءًا من مكتبتها القياسية، فابحث أولًا في توثيقك قبل كتابة دالة ما، فربما تكون موجودةً ولا تحتاج إلى كتابتها. تعريف الدوال الخاصة بنا يمكن إنشاء دوال خاصة بنا من خلال تعريفها، أي بكتابة تعليمة تخبر المفسر أننا نعرِّف كتلةً من الشيفرة، ويجب عليه تنفيذها عندما نطلبها في أي مكان في البرنامج. VBScript سننشئ الآن دالةً تطبع مثال جدول الضرب الخاص بنا لأي قيمة نعطيها إليها كوسيط، ;ستبدو هذه الدالة في VBScript كما يلي: <script type="text/vbscript"> Sub Times(N) Dim I For I = 1 To 12 MsgBox I & " x " & N & " = " & I * N Next End Sub </script> sنبدأ هنا في هذا المثال بالكلمة المفتاحية Sub -وهي اختصار برنامج فرعي Subroutine-، التي تلي محدد VBScript لكتل الشيفرات مباشرةً في السطر الثاني، ثم نعطيها قائمةً من المعامِلات بين قوسين. أما الشيفرة التي داخل الكتلة المعرَّفة فهي شيفرة VBScript عادية مع استثناء أنها تعامل المعامِلات على أنها متغيرات محلية، لذا تسمى الدالة في المثال أعلاه Times، وتأخذ معامِلًا واحدًا هو N، كما تعرِّف المتغير المحلي I، ثم تنفذ حلقةً تكراريةً تعرض جدول الضرب الخاص بالعدد N باستخدام المتغيرين N و I، نستدعي هذه الدالة الجديدة كما يلي: <script type="text/vbscript"> MsgBox "Here is the 7 times table..." Times 7 </script> لاحظ أننا عرّفنا معاملًا اسمه N ومررنا إليه الوسيط 7، وقد أخذ المعامل أو المتغير المحلي N داخل الدالة القيمة 7 عندما استدعيناه، ويمكن تعريف أي عدد نريده من المعامِلات في تعريف الدالة، وعلى البرامج المستدعية أن توفر قيمةً لكل معامِل. تسمح بعض لغات البرمجة بتعريف قيم افتراضية للمعامل في حالة عدم توفير قيمة، لتستخدم الدالة تلك القيمة الافتراضية. كذلك فقد غلفنا المعامل N بقوسين أثناء تعريف الدالة، لكن هذا غير ضروري في VBScript عند استدعاء الدالة، كما قلنا من قبل. لا تعيد هذه الدالة أي قيمة، وهو ما نسميه بالإجراء في البرمجة، وما هو إلا دالة لا تعيد قيمةً، وتفرّق لغة VBScript بين الدوال والإجراءات باستخدام أسماء مختلفة لتعريفاتهما، فمثلًا: تعيد الدالة التالية في VBScript جدول الضرب الخاص بنا في سلسلة نصية طويلة واحدة: <script type="text/vbscript"> Function TimesTable (N) Dim I, S S = N & " times table" & vbNewLine For I = 1 to 12 S = S & I & " x " & N & " = " & I*N & vbNewLine Next TimesTable = S End Function Dim Multiplier Multiplier = InputBox("Which table would you like?") MsgBox TimesTable (Multiplier) </script> تكاد صيغة هذه الشيفرة أن تطابق صيغة Sub، مع استثناء أننا استخدمنا الكلمة Function بدلًا من Sub السابقة، ويجب أن نسند النتيجة إلى اسم الدالة داخل التعريف، لهذا ستعيد الدالة أي قيمة يحتويها اسمها عند خروجها: ... TimesTable = S End Function فإذا لم نسند قيمةً لاسم الدالة بشكل صريح، فستعيد الدالة القيمة الافتراضية، والتي تكون في الغالب صفرًا أو سلسلةً نصيةً فارغةً. لاحظ أننا وضعنا أقواسًا حول الوسيط في سطر MsgBox، لأن MsgBox لن يعرف -لولا هذه الأقواس- هل يجب أن يُطبع Multiplier أم يُمرّره إلى الوسيط الأول والذي هو TimesTable، فلما وضعناه داخل الأقواس فهم المفسر أن القيمة هي وسيط للدالة TimesTable بدلًا من MsgBox. بايثون ستكون دالة جدول الضرب في بايثون كما يلي: def times(n): for i in range(1,13): print( "%d x %d = %d" % (i, n, i*n) ) وتُستدعى كما يلي: print( "Here is the 9 times table..." ) times(9) لاحظ أن الإجراءات في بايثون لا تميَّز عن الدوال، ويُستخدم def لتعريفهما، والفرق الوحيد هو أن الدالة التي تعيد قيمةً تستخدم تعليمة return، كما يلي: def timesTable(n): s = "" for i in range(1,13): s = s + "%d x %d = %d\n" % (i,n,n*i) return s الأمر بسيط، إذ تعيد الدالة النتيجة باستخدام تعليمة return، أما إذا لم يكن لدينا تعليمة return صريحة فستعيد بايثون تلقائيًا قيمةً افتراضيةً تسمى None، والتي نتجاهلها في العادة. نستطيع الآن طباعة نتيجة الدالة كما يلي: print( timesTable(7) ) يفضل عدم وضع تعليمات print داخل الدوال، وإنما جعل الدالة تعيد النتيجة باستخدام return، ثم طباعتها من خارج الدالة، ورغم أننا لم نتبع هذا الأسلوب في أمثلتنا، إلا أن هذا يجعل الدوال قابلةً لإعادة الاستخدام في نطاق أوسع من الحالات. يبقى أمر مهم للغاية يجب أن نذكره حول تعليمة return، وهو أنها لا تعيد قيمةً من الدالة فحسب، بل تعيد التحكم إلى الشيفرة التي استدعت الدالة، وتكمن أهمية ذلك في أن الإعادة لا يجب أن تكون آخر سطر في الدالة، فقد تكون هناك تعليمات أكثر، وقد لا تنفَّذ أبدًا، كما يمكن أن يحتوي متن الدالة الواحدة على عدة تعليمات return. تُنهي التعليمة التي نصل إليها أولًا الدالة وتعيد القيمة إلى الشيفرة المستدعية، سنعرض مثالًا عن دالة لها عدة تعليمات return، وهي تعيد أول عدد زوجي تجده في القائمة المزودة بها أو None إذا لم تجد أي عدد زوجي: def firstEven(aList): for num in aList: if num % 2 == 0: # تحقق من كونه زوجيًا return num # اخرج من الدالة فورًا return None # لا نصل إليها إلا إذا لم نجد عددًا زوجيًا ملاحظة بشأن المعاملات قد يصعب على المبتدئين فهم دور المعامِلات في تعريف الدالة، فهل يجب تعريف الدالة كما يلي: def f(x): # داخل الدالة x يمكن استخدام... أم تعريفها بالشكل: x = 42 def f(): # داخل الدالة x يمكن استخدام... يعرِّف المثال الأول هنا المعامِل x ويستخدمه داخل الدالة، بينما يستخدم المثال الثاني متغيرًا معرَّفًا من خارج الدالة مباشرةً، وبما أن المثال الثاني صالح ويعمل دون مشاكل، فلم نتكبد عناء تعريف المعامل؟، والجواب هو أن المعامِلات تتصرف مثل متغيرات محلية، أي مثل المتغيرات التي لا تُستخدم إلا داخل الدالة، وقلنا إن مستخدم الدالة يستطيع أن يمرر وسطاءً إلى هذه المعامِلات، وعلى ذلك تتصرف قائمة المعامِلات مثل بوابة للبيانات التي تتحرك بين البرنامج الرئيسي والدالة. تستطيع الدالة أن ترى بعض البيانات خارجها، لكن إذا أردنا للدالة أن تكون قابلةً لإعادة الاستخدام في أكثر من برنامج، فيجب أن نقلل اعتمادها على البيانات الخارجية، بل يجب أن تُمرَّر البيانات المطلوبة لأداء وظيفة الدالة بكفاءة إليها من خلال معامِلاتها، فإذا عُرِّفت الدالة داخل ملف وحدة، فيجب أن تكون لها صلاحية قراءة البيانات المعرَّفة داخل نفس الوحدة، لكن هذه الخاصية ستقلل من مرونة الدالة التي نعرِّفها. نريد أن نقلل عدد المعامِلات المطلوبة لتشغيل الدالة إلى حد يمكن السيطرة عليه وإدارته، وهذا يراعى في حالة البيانات الكثيرة التي تحتاج إلى معامِلات أكثر، وذلك من خلال استخدام تجميعات البيانات مثل القوائم وصفوف tuples والقواميس وغيرها، كما نستطيع تقليل عدد قيم المعامِلات الفعلية التي يجب أن نوفرها، باستخدام ما يسمى بالوسيط الافتراضي. الوسيط الافتراضي يشير هذا المصطلح إلى طريقة لتعريف معامِلات الدالة التي تأخذ قيمًا افتراضيةً إذا لم تمرَّر كوسطاء صراحةً، وأحد استخدامات هذا الوسيط المنطقية في دالة تعيد يوم الأسبوع، فإذا استدعيناها بدون قيمة فيكون قصدنا اليوم الحالي، وإلا فإننا نوفر رقم اليوم كوسيط، كما يلي: import time # None قيمة اليوم هي def dayOfWeek(DayNum = None): # طابق ترتيب اليوم مع قيم إعادة بايثون days = ['Saturday','Sunday', 'Monday','Tuesday', 'Wednesday', 'Thursday', 'Friday'] # تحقق من القيمة الافتراضية if DayNum == None: theTime = time.localtime(time.time()) DayNum = theTime[6] # استخرج قيمة اليوم return days[DayNum] لا نحتاج إلى استخدام وحدة الوقت إلا إذا كانت قيمة المعامِل الافتراضي مطلوبةً، وبناءً عليه نستطيع تأجيل عملية الاستيراد إلى أن نحتاج إليها، وسيحسن هذا من الأداء تحسينًا طفيفًا إذا لم نضطر إلى استخدام خاصية القيمة الافتراضية للدالة، لكن هذا التحسن يُعَد طفيفًا كما ذكرنا، ويلغي اصطلاح الاستيراد الذي ذكرناه أعلاه، لذا لا يستحق هذا التشوش. نستطيع الآن أن نستدعي ذلك كما يلي: print( "Today is: %s" % dayOfWeek() ) Saturday. print( "The third day is %s" % dayOfWeek(2) ) تذكر أننا نبدأ العد من الصفر في عالم الحواسيب، وأننا افترضنا أن اليوم الأول في الأسبوع هو السبت. عد الكلمات أحد الأمثلة الأخرى على دالة تعيد قيمةً، هو الدالة التي تَعُد الكلمات في سلسلة نصية، ويمكن استخدامها لحساب الكلمات في ملف ما بجمع كلمات كل سطر، وتكون شيفرة هذه الدالة كما يلي: def numwords(s): s = s.strip() # أزل المحارف الزائدة list = s.split() # قائمة كل عنصر فيها يمثل كلمة return len(list) # عدد كلمات القائمة هو عدد كلمات s لقد عرَّفنا الدالة في المثال أعلاه مستفيدين من بعض توابع السلاسل النصية المضمَّنة التي ذكرناها في مقال البيانات وأنواعها، ويمكن استخدام الدالة الآن كما يلي: for line in file: total = total + numwords(line) # راكم مجموع كل سطر print( "File had %d words" % total ) إذا حاولنا كتابة ذلك فلن تنجح الشيفرة، لأن مثل هذه الشيفرة تُعرف باسم الشيفرة الوهمية pseudocode، وهي تقنية تصميم شائعة للشيفرات لتوضيح الفكرة العامة لها، وليست مثالًا لشيفرة حقيقية صحيحة التركيب، وتُعرف أحيانًا باسم لغة وصف البرامج Program Description Language. يتضح لنا سبب أفضلية إعادة قيمة من دالة وطباعة النتيجة خارج الدالة بدلًا من داخلها، فإذا طبعت الدالة الطول بدلًا من إعادته فلم نكن لنستخدمها في عدّ إجمالي الكلمات في الملف، بل كنا سنحصل على قائمة طويلة فيها طول كل سطر، لكننا بإعادة القيمة نستطيع الاختيار بين استخدام القيمة كما هي، أو تخزينها في متغير بهدف المعالجة اللاحقة كما فعلنا هنا من أجل أخذ العدد الإجمالي، وهذه نقطة في غاية الأهمية من ناحية التصميم لفصل عرض البيانات من خلال الطباعة عن معالجها داخل الدالة. هناك ميزة أخرى وهي أننا إذا طبعنا الخرج فلن يكون مفيدًا إلا في بيئة سطر أوامر، أما بإعادة القيمة فنستطيع عرضها في صفحة ويب أو واجهة رسومية، فلفصل عرض البيانات عن معالجتها فائدة كبيرة، لذا اجتهد في إعادة القيم من الدوال بدلًا من طباعتها ما استطعت، وليس ثمة استثناء لهذه القاعدة إلا عند إنشاء دالة مخصصة لطباعة بعض البيانات، ففي تلك الحالة يجب توضيح هذا باستخدام كلمة print أو عرض اسم الدالة. دوال جافاسكربت يمكن إنشاء دوال داخل جافاسكربت باستخدام أمر function، كما يلي: <script type="text/javascript"> var i, values; function times(m) { var results = new Array(); for (i = 1; i <= 12; i++) { results[i] = i * m; } return results; } // استخدم الدالة values = times(8); for (i=1;i<=12;i++){ document.write(values[i] + "<br />"); } </script> لن نستطيع الاستفادة كثيرًا من هذه الدالة بتلك الحالة، لكن هذا المثال يوضح كيف يشبه الهيكل الأساسي لإنشاء الدالة هنا تعريفات الدوال في بايثون وVBSCript، وسننظر في دوال أكثر تعقيدًا في جافاسكربت لاحقًا، لأنها تستخدم الدوال لتعريف الكائنات والدوال أيضًا، وهو الأمر الذي يبدو مربكًا للقارئ أو لمستخدم اللغة. تنبيه تنبع قوة الدوال من سماحها بتوسيع نطاق الوظائف والمهام التي تستطيع اللغة تنفيذها، كما أنها تتيح لنا إمكانية تغيير اللغة من خلال تعريف معنىً جديد لدالة موجودة مسبقًا -لا يُسمح بهذا في بعض اللغات-، ولكن هذا أمر غير محمود العاقبة، إلا إذا تحكمنا فيه بحذر شديد، لأن تغيير السلوك القياسي للغة يجعل قراءة الشيفرة وفهمها يُعَد صعبًا للغاية على غيرك، بل عليك أنت نفسك فيما بعد، وبما أن القارئ يتوقع من الدالة أن تنفذ سلوكًا معينًا لكنك غيرت هذا السلوك إلى شيء آخر، لذا يفضل عدم تغيير السلوك الافتراضي للدوال المضمّنة في اللغة. يمكن التغلب على هذا التقييد للإبقاء على السلوك المضمّن للغة مع الاستمرار في استخدام أسماء ذات معنىً لدوالنا، من خلال وضع الدوال داخل كائن أو وحدة توفر سياقها المحلي. إنشاء الوحدات الخاصة رأينا كيف ننشئ دوالًا خاصةً بنا وكيف نستدعيها من أجزاء أخرى من البرنامج، وهذا أمر جيد لأنه يوفر علينا كثيرًا من الكتابة المتكررة، ويجعل برامجنا سهلة الفهم، لأننا ننسى بعض التفاصيل بعد إنشاء دالة تخفيها، وهو مبدأ متبع في البرمجة عند الحاجة إلى إخفاء بعض التفاصيل، ويسمى إخفاء المعلومات، حيث تغلَّف المعلومات والتفاصيل في دالة ننشئها لها، لكن كيف نستخدم هذه الدوال في البرامج الأخرى؟ الإجابة على هذا هي إنشاء وحدة module لهذا الغرض. وحدات بايثون الوحدة في بايثون ما هي إلا ملف نصي بسيط فيه تعليمات برمجية مكتوبة بلغة بايثون، وتكون تلك التعليمات عادةً تعريفات دوال، فمثلًا عند كتابة: import sys فإننا نخبر مفسر بايثون أن يقرأ هذه الوحدة وينفذ الشيفرة الموجودة فيها، ويتيح لنا الأسماء التي تولدها في ملفنا، ويبدو هذا كأننا ننشئ نسخةً من محتويات sys.py في برنامجنا، على أن بعض الوحدات مثل sys في البرمجة العملية ليس لها ملف sys.py أصلًا، لكننا سنتجاهل هذا الآن، وتوجد لغات برمجة مثل C و++C، التي ينسخ فيها المترجم أو المصرِّف ملفات الوحدة إلى البرنامج الحالي حسب الطلب. ننشئ الوحدة بإنشاء ملف بايثون يحتوي الدوال التي نريد إعادة استخدامها في برامج أخرى، ثم نستورد الوحدة كما نستورد الوحدات القياسية، ولتنفيذ هذا عمليًا، انسخ الدالة التالية إلى ملف، واحفظه باسم timestab.py. يمكنك فعل هذا باستخدام IDLE أو Notepad، أو أي محرر آخر يحفظ الملفات النصية العادية، لكن لا تستخدم برامج معالجة نصوص مثل مايكروسوفت وورد، لأن تلك البرامج تدخل شيفرات تنسيق كثيرةً لن تفهمها بايثون. def print_table(multiplier): print( "--- Printing the %d times table ---" % multiplier ) for n in range(1,13): print( "%d x %d = %d" % (n, multiplier, n*multiplier) ) ثم اكتب في محث بايثون: >>> import timestab >>> timestab.print_table(12) وهكذا تكون قد أنشأت وحدةً واستوردتها واستخدمت الدالة المعرَّفة فيها. لاحظ أنك إن لم تبدأ بايثون من نفس المجلد الذي خزنت فيه ملف timestab.py، فلن تستطيع بايثون أن تجد الملف وستعطيك خطأً، وعندها يمكن إنشاء متغير بيئة اسمه PYTHONPATH يحمل قائمةً من المجلدات الصالحة للبحث فيها عن وحدات، إضافةً إلى الوحدات القياسية التي تأتي مع بايثون، ويفضل تعريف مجلد داخل PYTHONPATH وتخزين جميع ملفات الوحدات القابلة لإعادة الاستخدام داخله، ولا تنسى اختبار الوحدات جيدًا قبل نقلها إليه. يجب التأكد من عدم استخدام اسم تحمله وحدة قياسية في بايثون، لئلا تجعل بايثون تستورد ملفك أنت بدلًا من القياسي، مما سينتج عنه سلوك غريب جدًا كما ذكرنا من قبل في شأن التلاعب في لغة البرمجة. ولا تستخدم اسم إحدى الوحدات التي تحاول استيرادها إلى نفس الملف، فهذا سيؤدي أيضًا إلى حدوث مشاكل. الوحدات في جافاسكربت وVBScript يُعَد إنشاء الوحدات في VBScript أكثر تعقيدًا من بايثون، فلم يكن مفهوم الوحدات موجودًا في هذه اللغة ولا في اللغات التي بنفس عمرها، بل كانت تعتمد على إنشاء الكائنات لإعادة استخدام الشيفرة بين المشاريع، وسننظر الآن في كيفية النسخ من المشاريع السابقة واللصق في مشروعنا الحالي باستخدام المحرر النصي. أما جافاسكربت فتوفر آليةً لإنشاء وحدات من ملفات الشيفرة القابلة لإعادة الاستخدام، لكنها آلية معقدة وتستخدم صيغةً غامضةً تخرج عن نطاق عملنا في هذه المرحلة، غير أن لدينا حلًا أسهل، وهو استخدام وحدات كتبها أشخاص آخرون، باستخدام الصيغة التالية: <script type=text/JavaScript src="mymodule.js"></script> نستطيع الوصول إلى جميع تعريفات الدوال الموجودة في ملف mymodule.js بمجرد إدراج السطر السابق داخل قسم <head> في صفحة الويب الخاصة بنا، وتوجد وحدات عديدة من الطرف الثالث متاحة لمبرمجي الويب ويمكن استيرادها بهذه الطريقة، ولعل أشهرها هي وحدة JQuery؛ أما في المواضع التي تُستخدم فيها جافاسكربت خارج المتصفحات -انظر قسم Windows Script Host اللاحق- فهناك آليات أخرى متاحة، ويُرجع في ذلك إلى التوثيق. تقنية Windows Script Host نظرنا حتى الآن إلى جافاسكربت وVBScript على أنهما لغات للبرمجة داخل الويب، ولكن توجد طريقة أخرى لاستخدامهما داخل بيئة ويندوز، وهو تقنية مضيف سكربت ويندوز Windows Script Host أو WSH اختصارًا، وهي تقنية أتاحتها مايكروسوفت لتمكين المستخدمين من برمجة حواسيبهم بنفس الطريقة التي استخدم بها مستخدمو نظام DOS قديمًا ملفات باتش Batch Files، فهي توفر آليات لقراءة الملفات والسجل والوصول إلى الحواسيب والطابعات التي في الشبكة وغيرها. في الإصدار الثاني من WSH إمكانية تضمين ملف WSH آخر، ومن ثم توفير وحدات قابلة لإعادة الاستخدام، وذلك بإنشاء ملف وحدة أولًا اسمه SomeModule.vbs يحتوي على ما يلي: Function SubtractTwo(N) SubtractTwo = N - 2 End function ننشئ الآن ملف سكربت WSH اسمه testModule.wsf مثلًا، كما يلي: <?xml version="1.0" encoding="UTF-8"?> <job> <script type="text/vbscript" src="SomeModule.vbs" /> <script type="text/vbscript"> Dim value, result WScript.Echo "Type a number" value = WScript.StdIn.ReadLine result = SubtractTwo(CInt(value)) WScript.Echo "The result was " & CStr(result) </script> </job> يمكن تشغيل هذا في ويندوز ببدء جلسة DOS وكتابة ما يلي: C:\> cscript testModule.wsf تسمى الطريقة التي تمت هيكلة ملف (wsf.) بها باسم XML، ويتواجد البرنامج داخل زوج من وسوم <job></job> بدلًا من وسم <html></html> الذي رأيناه في لغة HTML من قبل. يشير أول وسم سكربت في الداخل إلى ملف وحدة اسمه SomeModule.vbs، أما وسم السكربت الثاني فيحتوي على برنامجنا الذي يصل إلى SubtractTwo داخل ملف SomeModule.vbs؛ بينما ملف ‎.vbs فيحتوي على شيفرة VBScript عادية ليس فيها وسوم XML أو HTML. لاحظ أن علينا تهريب محرف & من أجل ضم السلاسل النصية لتعليمة WScript.Echo، لأن التعليمة جزء من ملف XML، وهذا المحرف مستخدم في لغة XML كرمز محدِّد. نستخدم WScript.Stdin لقراءة مدخلات المستخدم، وهو تطبيق لما تحدثنا عنه في مقال قراءة البيانات من المستخدم. تصلح هذه التقنية مع جافاسكربت أيضًا، أو لنكون أدق، مع نسخة مايكروسوفت من جافاسكربت التي تسمى JScript، وذلك بتغيير سمة type=‎، بل يمكن دمج اللغات في WSH بأن نستورد وحدةً مكتوبةً بجافاسكربت ونستخدمها في شيفرة VBScript أو العكس. فيما يلي سكربت WSH مكافئ لما سبق، حيث تُستخدم جافاسكربت للوصول إلى وحدة من VBScript: <?xml version="1.0" encoding="UTF-8"?> <job> <script type="text/vbscript" src="SomeModule.vbs" /> <script type="text/javascript"> var value, result; WScript.Echo("Type a number"); value = WScript.StdIn.ReadLine(); result = SubtractTwo(parseInt(value)); WScript.Echo("The result was " + result); </script> </job> نستطيع رؤية مدى تقارب هاتين النسختين، فإذا استثنينا بعض الأقواس الزائدة فسيمكننا القول أنهما متشابهتان للغاية؛ أما أغلب الأمور الفنية فتجري من خلال كائنات WScript. لن نستخدم WSH كثيرًا، لكن قد ننظر فيها بين الحين والآخر إذا رأينا أنها توفر لنا مزايا لا يمكن شرحها باستخدام بيئة المتصفح الأكثر تقييدًا، فعلى سبيل المثال، سنستخدم WSH في المقال التالي لبيان كيف يمكن تعديل الملفات باستخدام جافاسكربت وVBScript، وتوجد بعض الكتب التي تتحدث عن WSH إذا كنت مهتمًا بتعلم المزيد عنها، ويحتوي موقع مايكروسوفت على قسم خاص بها مع أمثلة لبرامج وأدوات تطوير وغير ذلك. خاتمة نأمل أن تخرج من هذا المقال وقد تعلمت: الدوال التي هي شكل من أشكال الوحدات. تعيد الدوال قيمًا، أما الإجراءات فلا تعيد شيئًا. تتكون الوحدات في بايثون في العادة من تعريفات للدوال داخل ملف. يمكن إنشاء دوال جديدة في بايثون باستخدام الكلمة المفتاحية def. استخدام Sub أوFunction في VBScript، وfunction في جافاسكربت. ترجمة -بتصرف- للفصل الحادي عشر: Programming with Modules من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: التعامل مع الملفات في البرمجة المقال السابق: مقدمة في البرمجة الشرطية تعلم البرمجة المدخل الشامل لتعلم علوم الحاسوب
  18. يمكن القول إنك لن تحتاج لأكثر من اتصال بالإنترنت لتتعلم البرمجة من هذه السلسلة، ومع أن هذا يكفي من الناحية التقنية إلا أنه غير كافٍ لتعلم البرمجة، إذ يجب التنويه إلى أسلوب التفكير الذي ستتبعه في البرمجة، فلابد أن تتمتع بفضول للتعلم مع أسلوب منطقي لتفكير، وهما أمران لازمان لأي مبرمج ناجح. تبرز أهمية الفضول في البحث عن إجابات للمشاكل، وفي قدرتك على التجربة والتنقيب في الملفات بحثًا عن الأفكار والمعلومات المطلوبة لتنفيذ مهمة معينة، كما أن التفكير المنطقي مهم لأن الحواسيب آلات غبية بطبيعتها، ولا تستطيع فعل أي شيء سوى إضافة أرقام مفردة إلى جانب بعضها البعض، وتحريك بايتات من مكان لآخر. لقد كتب كثير من المبرمجين المهرة -لحسن الحظ- برمجيات تُخفي غباء الحواسيب هذا، لكنك بصفتك مبرمجًا ستتعرض لمواقف تواجه فيها ذلك الغباء الذي لم يعالجه أو يتعامل معه أحد قبلك، وهنا يجب أن تضع نفسك مكان الحاسوب وتفكر بدلًا عنه، وأن تعرف تحديدًا ما يجب عمله ببياناتك وزمن ذلك أيضًا. قد يكون هذا سردًا فلسفيًا لأمر يبدو تقنيًا وإلكترونيًا محضًا، غير أنك تحتاج إلى مثل تلك الفلسفة لتفهم هذا الشرح فهمًا جيدًا. بعد ذلك يأتي الجزء الخاص بالتدريب العملي الذي ستحتاج فيه إلى كتابة الأمثلة بيدك، أو نسخها من الكتاب إلى المحرر النصي عندك، ثم تشغيلها ورؤية النتائج، وستحتاج هنا إلى تثبيت بايثون Python على حاسوبك، وإلى متصفح قادر على تشغيل لغتي VBScript وJScript، مع الإشارة إلى أن أي متصفح حديث قادر على تشغيل جافاسكربت. بايثون Python يُعَد أحدث إصدار من لغة بايثون وقت كتابة هذه الكلمات -بلغتها الأصلية- هو 3.9، وحجم ملف تحميله من ActiveState يقارب 29 ميجا بايت لنسخة إصدار ويندوز (لا زالت ActiveState في الإصدار 3.8)، غير أنها تشمل كامل التوثيق والكثير من الأدوات التي سننظر في بعضها لاحقًا في هذه السلسلة، لذا تأكد من اختيار النسخة الموافقة لنظام تشغيلك. أما بالنسبة لنظام لينكس أو الأنظمة الشبيهة بيونكس عمومًا، فاطلب من مدير نظامك تثبيت النسخة المصدرية لبايثون على حاسوبك، لكن قد لا تحتاج إلى ذلك لأنها تأتي مدمجةً مسبقًا، ومثبتةً تلقائيًا في أغلب توزيعات لينكس، كما ستجدها في الإصدارات بتحزيمات موجهة للتوزيعات المشهورة مثل ريدهات Red Hat وديبيان Debian وأوبنتو Ubuntu وغيرها، بل قد تجد أن أغلب أدوات إدارة النظام في لينكس مكتوبة بلغة بايثون، ولا تقلق إذا كان إصدارك أقل من 3.6، فأي إصدار بعد 3.4 سيكون مناسبًا. تستطيع النظر في نسخ التحميل المختلفة لاختيار ما يناسبك من موقع التحميل الرئيسي لبايثون، أما مستخدمو ويندوز وماك فقد يفضلون نسخة ActiveState.com التي تأتي غالبًا مع بعض الأدوات الإضافية المدمجة في البرنامج نفسه، وقد تكون ActiveState متأخرةً قليلًا في إصدار نسخها الجديدة بسبب برنامجهم الخاص في التحزيم والاختبار، غير أنها تستحق الانتظار. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن VBScript وجافاسكربت لقد سبق وأن قلنا إن أغلب المتصفحات تستطيع تشغيل جافاسكربت دون مشاكل، لكن VBScript عكس ذلك، فهي لن تعمل إلا في متصفح إنترنت إكسبلورر من مايكروسوفت، ولن تحتاج إلى تثبيت أي شيء إضافي لهاتين اللغتين، فإما أن تكونا لديك معًا إذا كنت تستخدم ويندوز، أو لن تكون لديك VBScript إذا كنت تستخدم ماك أو لينكس، والأمر الوحيد الذي عليك الانتباه إليه هنا هو أن بعض مديري الأنظمة القلقين بشأن الأمان قد يغلقون خاصية تشغيل السكربتات scripts في المتصفح لدواع أمنية، لكن هذا نادر الآن لأن أغلب المتصفحات تشغّل جافاسكربت. برمجة الحواسيب هي فن نجعل فيه الحاسوب ينفذ ما نرغب فيه بالضبط، وهي تتكون في أبسط صورها من سلسلة أوامر نعطيها للحاسوب لينفذها من أجل تحقيق هدف ما، وقد كان المستخدمون قديمًا أيام نظام دوس الخاص بويندوز، ينشئون ملفات نصيةً تحوي قوائم من تلك الأوامر، تُسمى ملفات الرُّقع أو باتش batch files (تدعى غالبًا سكربتات أو سكربت باتش)، وسبب تسميتها بذلك هو أنها تنفذ الأوامر مثل مجموعة أو رقعة واحدة، وكان امتدادها هو ‎.BAT، لذا أُطلق عليها اسم ملفات بات BAT، ولا يزال بإمكاننا كتابة مثل تلك الملفات في بيئات ويندوز هذه الأيام رغم ندرة استخدامها، فمثلًا إذا كنت تكتب مستند HTML مكوَّن من ملفات كثيرة مثل الدليل الذي تقرؤه الآن، فسينشئ برنامج معالجة النصوص الذي تستخدمه نسخًا احتياطيةً من كل ملف كلما حفظ نسخةً جديدةً منه. فإذا رغبت في أن تضع النسخة الحالية من المستند -وهي الإصدارات الأخيرة من جميع ملفاته- في مجلد نسخ احتياطي backup في آخر كل يوم ثم حذف النسخ الاحتياطية التي لدى معالج النصوص؛ فيمكن كتابة ملف BAT بسيط لتنفيذ لك، وسيكون كما يلي: COPY *.HTM BACKUP DEL *.BAK إذا كان اسم الملف هو SAVE.BAT فسنكتب SAVE في محث DOS (يطلق على المحث أيضًا موجه أوامر) في نهاية اليوم بعد انتهاء العمل، وستُحفظ الملفات وتُحذف النسخ الاحتياطية تلقائيًا، وهكذا تكون قد رأيت مثالًا عمليًا لبرنامج بسيط. لاحظ أن مستخدمي نظام لينكس وغيره، بل حتى مستخدمي الإصدارات الحديثة من ويندوز، لديهم نسختهم الخاصة بهم من أمثلة تلك الملفات، والتي تُعرف عادةً باسم سكربتات الصدفة shell scripts، وهي أقوى بكثير من ملفات BAT الخاصة بنظام دوس، وتدعم أغلب التقنيات البرمجية التي سنتحدث عنها في هذا المقال. دورة تطوير التطبيقات باستخدام لغة JavaScript تعلم البرمجة بلغة جافا سكريبت انطلاقًا من أبسط المفاهيم وحتى بناء تطبيقات حقيقية. اشترك الآن تعريف البرنامج مرة أخرى لقد ذكرنا أعلاه مثالًا عن برنامج، لنبين بساطة مفهوم البرمجة في حد ذاته، لكن إذا خشيت عدم فهم البرمجة، فاعلم أن البرنامج ما هو إلا مجموعةً من التعليمات التي تخبر الحاسوب كيف ينفذ مهمةً ما، وهو يشبه وصفة الطعام التي تتكون من مجموعة من التعليمات التي تخبر الطاهي كيف يصنع طبقًا ما، فهي تصف مقادير المكونات (البيانات) وترتيب خطوات التنفيذ (العملية) المطلوبة لتحويل تلك المكونات إلى كعكة أو غيرها، فالبرنامج يشبهها كثيرًا في هذا. نظرة تاريخية نحن نستخدم لغةً للحديث مع الحواسيب، كما نستخدم لغات بيننا نحن البشر، غير أن اللغة الوحيدة التي يتحدثها الحاسوب تسمى اللغة الثنائية binary والتي توجد عدة نسخ منها، لهذا لا يعمل برنامج موجه لنظام ماك على ويندوز والعكس. ويُعَد تعلّم هذه اللغة صعبًا جدًا بالنسبة للبشر، سواءً قراءتها أو كتابة برامج بها، لذلك يجب أن نستخدم لغةً وسيطةً ثم نترجمها إلى اللغة الثنائية، تمامًا مثل شخصين من دولتين مختلفتين يتحدثان معًا وبينهما مترجم وسيط يفسر كلام كل منهما للآخر، فقد يتحدث أحدهما العربية والآخر الإنجليزية، فيترجم المترجم الكلام العربي إلى الإنجليزية وينقله إلى متحدث الإنجليزية، ثم يعكس العملية إذا تحدث الإنجليزي مخاطبًا الشخص العربي، وما سنستخدمه ليترجم لغتنا البرمجية إلى الحاسوب يسمى مترجمًا أو مفسرًا interpreter. وكما نحتاج مفسرًا لكل لغة من لغات البشر، فإننا نحتاج مفسرًا لكل لغة برمجية ليترجمها إلى لغة الحاسوب، فنحتاج مفسرًا من بايثون إلى لغة الآلة الثنائية binary، وآخر من VBScript إلى لغة الآلة كذلك، غير أن المبرمجين الأوائل كانوا مضطرين إلى كتابة الشيفرات الثنائية تلك بأنفسهم، أي بلغة الآلة التي ذكرناها قبل قليل وهي صعبة الكتابة والتعلم. بعد ذلك أتت المرحلة التالية التي أُنشئ فيها مفسر يحول كلمات مكتوبةً بأحرف بشرية إلى ما يقابلها من اللغة الثنائية، فبدلًا من تذكر أن الرمز ‎001273 05 04‎ يعني جمع 4 إلى 5، نستطيع الآن أن نكتب شيئًا مثل ADD 5 4، وقد سهلت تلك النقلة البسيطة الكثير من عمل البرمجة والتطوير، حيث كانت تلك الأنظمة البسيطة من الشيفرات هي لغات البرمجة الأولى التي كانت تختلف باختلاف نوع الحاسوب، وتسمى باسم اللغات المجمِّعة Assembler Languages، ولا زالت البرمجة بلغة التجميع مستخدَمةً هذه الأيام في بعض المهام المتخصصة، لكن هذا التطور كان بدائيًا في أسلوب إخبار الحاسوب بما يجب فعله، مثل نقل البيانات من هذا الموضع من الذاكرة إلى ذلك الموضع، وإضافة هذا البايت إلى ذلك البايت وغيرها من العمليات. البايت Byte هو وحدة بيانات تتكون من ثمانية بتّات bits أصغر منه ومجموعة فيه، وتلك البتات تكون إما 1 أو 0، وقد استُخدم البايت في البداية لتمثيل محارف النصوص، بحيث يمثل كل بايت حرفًا واحدًا. وبما أن هذا النمط من البرمجة لا زال صعبًا في تعلمه والعمل به لإنجاز أبسط المهام، فقد طور علماء الحوسبة مع الوقت لغات تسهل عملية البرمجة، وكأن ذلك جاء في وقته إذ تطورت المشاكل التي يواجهها المستخدمون في ذلك الوقت بسبب تطور المهام في أعمالهم اليومية، وهم يريدون للحواسيب أن تحل لهم تلك المشاكل. ولا زال هذا التنافس قائمًا، كما لا زالت لغات البرمجة الجديدة تظهر على الساحة. هذا ومع جعل البرمجة أمرًا مثيرًا يتغير كل يوم، إلا أنه يجعلك كونك مبرمجًا في حاجة إلى استيعاب المفاهيم البرمجية وطرق تنفيذها وتطبيقها في لغة واحدة بعينها، وسنناقش بعض تلك المفاهيم فيما يلي، لكن يجب أن تجعلها حاضرةً عندك تعود إليها دائمًا أثناء قراءتك للسلسلة. المزايا المشتركة لجميع البرامج خرج إدزجر ديكسترا Edsger Dijkstra قبل زمن بمفهوم اسمه البرمجة الهيكلية Structured Programming، يتحدث فيه عن إمكانية هيكلة جميع البرامج بأربعة طرق، هي الآتية: سلاسل من التعليمات: يتحرك فيها البرنامج من خطوة لأخرى في تسلسل صارم. الفروع Branches: هنا يصل البرنامج إلى نقطة اتخاذ قرار، فإذا تحققت نتيجة الاختبار -أي كانت القيمة true-، فإن البرنامج سينفذ التعليمات التي في المسار 1، وإذا كانت false فسينفذ الإجراءات التي في المسار 2، ويُعرف هذا بالبنية الشرطية لأن سير البرنامج يتوقف على نتيجة اختبار شرطي. الحلقات التكرارية Loops: تُكرَّر خطوات البرنامج في هذه الطريقة إلى أن نصل إلى اختبار شرطي ما، ينتقل تحكم البرنامج بعدها من الحلقة التكرارية إلى الجزء التالي من منطق البرنامج. الوحدات Modules: هنا ينفذ البرنامج تسلسلًا متطابقًا من الخطوات عدة مرات، فتُجمع تلك الإجراءات في وحدة واحدة، وهي برنامج صغير الحجم يمكن تنفيذه من داخل البرنامج الرئيسي، وقد تُسمى الوحدات بأسماء أخرى مثل الدوال functions أو الإجراءات procedures أو البرامج الفرعية sub-routines. احتاجت البرامج إلى بعض المزايا الأخرى، إضافةً إلى ما سبق كي تكون مفيدة: البيانات العمليات: مثل الجمع والطرح والموازنة وغيرها. إمكانية الإدخال والإخراج: مثل عرض النتائج على شاشة مثلًا. وبمجرد أن تستطيع استيعاب المفاهيم أعلاه، والتعرُّف على كيفة تنفيذ اللغة البرمجية التي تستخدمها لها، فستكون قادرًا على كتابة برامج بتلك اللغة. توضيح بعض المصطلحات إذا قلنا إن البرمجة هي الفن الذي نجعل فيه الحواسيب تنفذ ما نريده منها، فما هو البرنامج إذًا؟ في الواقع لدينا مفهومان مختلفان عن البرنامج، أولهما من منظور المستخدم، وهو ملف تنفيذي يثبَّت على الحاسوب ثم يمكن تشغيله لتنفيذ مهمة ما، فمثلًا يقول المستخدم أنه "يشغِّل" برنامج معالجة النصوص؛ أما المفهوم الثاني فهو من منظور المبرمج، وهو هنا مجموعة من التعليمات النصية الموجهة إلى الحاسوب المكتوبة بلغة برمجة ما، ويمكن ترجمتها إلى ملف تنفيذي. لهذا يجب أن تكون مدركًا عن أي المفهومين تتحدث حين تستخدم كلمة برنامج. يكتب المبرمجون برامجهم عادةً بلغة برمجة عالية المستوى تفسَّر إلى بايتات يفهمها الحاسوب، أي يكتب المبرمج شيفرةً مصدريةً source code؛ أما المفسر فيولد تعليمات مُصرَّفة object code، وقد يطلق على هذه التعليمات الناتجة عن التصريف أسماء أخرى مثل ملف تنفيذي أو شيفرة تنفيذية أو محمولة P-Code أو بايت كود Byte Code أو شيفرة ثنائية binary code، أو شيفرة الآلة machine code. كما يطلق على المترجم الذي يترجم لغة البرمجة العالية إلى لغة الآلة عدة أسماء، فقد يسمى بالمفسر interpreter أحيانًا، وبالمصرِّف compiler أحيانًا أخرى، وتشير هذه المصطلحات إلى نوعين من التقنيات المستخدمة في توليد الشيفرات الكائنية من الشيفرة المصدرية، فالمصرِّفات تنتج شيفرةً كائنيةً يمكن تشغيلها مستقلةً بذاتها دون الحاجة إلى المصرِّف في كل مرة يعمل فيها البرنامج، ويكون البرنامج في صورة ملف تنفيذي executable file؛ أما المفسِّرات فيجب أن تكون حاضرةً لتشغيل برامجها أثناء تنفيذها. لكن الفرق بين هذين المصطلحين صار ضبابيًا هذه الأيام بما أن بعض المصرفات تحتاج إلى مفسرات تكون حاضرةً لتنفيذ التحويل النهائي، كما تصرِّف بعض المفسرات شيفرتها المصدرية إلى شيفرة كائنية مؤقتة وتنفذها؛ أما من منظور المبرمجين فليس هناك فرق حقيقي، إذ تُكتب الشيفرة المصدرية وتُستخدَم أداة تسمح للحاسوب بقراءة الشيفرة وترجمتها وتنفيذها. هيكل البرنامج يعتمد الهيكل الدقيق للبرنامج على لغة البرمجة والبيئة التي يعمل فيها، لكن توجد بعض المبادئ الأساسية عمومًا: المحمِّل Loader: يحتاج كل برنامج أن يُحمّله نظام التشغيل إلى الذاكرة، وهذه وظيفة المحمل الذي يُنشأ عادةً بواسطة المفسر. تعريفات البيانات: تعمل أغلب البرامج بناءً على بيانات، وسنحتاج في مرحلة ما في شيفرتنا المصدرية إلى تعريف نوع البيانات الذي نعمل معه تعريفًا دقيقًا، وهذا يختلف من لغة برمجة لأخرى. التعليمات statements: وهي صلب البرامج، وهي تعدّل البيانات التي نعرّفها وتنفذ الحسابات وتطبع الخرج لنا.. تتبع أغلب البرامج إحدى الهيكلين التاليين: برامج باتش Batch Programs تُبدأ تلك البرامج عادةً من سطر الأوامر أو بواسطة أداة جدولة، وتتبع النمط التالي في الغالب. يبدأ البرنامج بتعيين حالته الداخلية كأن يعين الإجماليات totals إلى صفر، ويفتح الملفات المطلوبة، وبمجرد أن يكون جاهزًا للعمل، فإنه يقرأ البيانات من المستخدم بعرض موجهات الأوامر أو المحثات على الشاشة أو من ملف بيانات، أو بالطريقتين معًا، حيث يعطي المستخدم اسم ملف البيانات ثم تُقرأ البيانات الفعلية من الملف، بعد ذلك يعالج البرنامج البيانات معالجةً تتضمن عمليات رياضيةً أو تحويلات للبيانات أو غير ذلك، أخيرًا، تُخرج النتائج إلى شاشة عرض أو تُكتب إلى ملف، وستكون جميع البرامج التي نكتبها في الأجزاء الأولى من السلسلة من هذا النوع، أي برامج باتش أو رُقع. البرامج الحدثية Event driven programs تُعَد أغلب الأنظمة ذات الواجهة الرسومية مثل ويندوز أو أندرويد، وأنظمة التحكم المدمجة Embedded control systems مثل جهاز المايكروويف لديك أو الكاميرا أو غيرهما، من البرامج الحدَثية، أي يتوقف سيرها على وقوع أحداث معينة، بحيث يرسِل نظام التشغيل أحداثًا إلى البرنامج فيستجيب لها وفقًا لوصولها إليه، وقد تكون تلك الأحداث أمورًا يفعلها المستخدم مثل نقر زر الفأرة أو ضغط زر ما، أو أمورًا يفعلها النظام نفسه مثل تعديل الساعة أو تحديث الشاشة، وتبدو البرامج الحدثية في الغالب كما يلي: يبدأ البرنامج هنا بتعيين حالته الداخلية، ثم ينتقل التحكم إلى بيئة التشغيل (تسمى أحيانًا وقت التشغيل runtime)، ويوفر نظام التشغيل تلك البيئة في الغالب، كما ينتظر البرنامج حلقة الحدث لتلتقط تفاعل المستخدم الذي يترجَم إلى أحداث بعدها، ثم ترسَل تلك الأحداث إلى البرنامج كي يتعامل معها حدثًا حدثًا، وينفذ المستخدِم الإجراء النهائي الذي ينهي البرنامج، فيُنشَأ حدث خروج ويُرسَل إلى البرنامج. خاتمة ذكرنا في هذا المقال أنك تحتاج إلى التفكير المنطقي والفضول من أجل تعلم البرمجة، ويمكن الرجوع في هذا إلى مقال الدليل الشامل في تعلم البرمجة من أكاديمية حسوب، ومقال حل المشكلات وأهميتها في احتراف البرمجة من الأكاديمية أيضًا، كما يجب أن نذكر أن كل لغات البرمجة المذكورة أعلاه متاحة للتحميل مجانًا، وبهذا لا يبقى سوى أن تأتي بذهن حاضر، مع قليل من حس الدعابة والمرح لنبدأ البرمجة، إذ تسمح لنا لغات البرمجة بالتحدث مع الحواسيب بلغة قريبة من لغات البشر المنطوقة، لكنها تختلف عن الطريقة التي تتحدث الحواسيب أو تفكر بها، وقد قلنا إن البرامج تعمل وفقًا للبيانات، وأنها إما برامج رُقع batch programs أو برامج حدثية Event driven تتصرف وفقًا للأحداث التي تُرسل إليها. ترجمة -بتصرف- للفصلين ?What do I need و?What is Programming من كتاب Learning to Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: بداية رحلة تعلم البرمجة تعلم البرمجة أسهل لغات البرمجة ما هي البرمجة ولماذا تصبح مبرمجا
  19. رغم أن الأفكار التي كانت وراء البرمجة الكائنية التوجه طُورت في ستينيات القرن الماضي إلا أنها لم تشتهر في الوسط البرمجي إلا بعد ذلك بعقدين، أي في الثمانينيات، بعد إطلاق Smalltalk-80 ومجموعة متنوعة من تطبيقات لغة Lisp، ولم تكن وقتها اتجاهًا سائدًا في البرمجة وإنما كانت تثير الفضول فقط، ثم تغير ذلك عندما انتشرت الواجهات الرسومية في الحواسيب الشخصية على حواسيب أبل أولًا، ثم على الحواسيب العاملة بنظام ويندوز ونظام نوافذ X في يونكس، إلى أن اقتربنا من نهاية الألفية السابقة، حيث صارت البرمجة الكائنية التوجه Object Oriented Programming -والتي تعرف اختصارًا OOP- التقنية الأبرز لتطوير البرمجيات. وتتجسد مفاهيم البرمجة الكائنية التوجه في لغات مثل جافا وC++‎ وبايثون بحيث لا تكاد تفعل شيئًا فيها إلا وتقابل كائنًا في مكان ما، ونريد في هذا المقال أن نتعرف على هذه التقنية وننظر في المفاهيم الأساسية لها، مثل تعريف الكائن والصنف وتعددية الأشكال polymorphism والوراثة inheritance، وكيفية إنشاء الكائنات وتخزينها واستخدامها، والبرمجة الكائنية التوجه موضوع كبير قد كُتبت فيه كتب، فإذا أردت التعمق فيه أكثر مما هو مذكور في هذا المقال فانظر هذه الكتب باللغة الإنجليزية: كتاب Object Oriented Analysis لبيتر كود Peter Coad وإد يوردون Ed Yourdon. كتاب Object Oriented Analysis and Design with Applications لجريدي بوش Grady Booch (الطبعة الأولى أو الثالثة). كتاب Object Oriented Software Construction لبرتراند ماير Berterand Meyer (الطبعة الثانية). تختلف هذه الكتب عن بعضها في العمق والحجم والدقة الأكاديمية بالترتيب، فالكتاب الأول مناسب للأغراض العامة التي هي خارج نطاق العمل البرمجي، والحق أنها كلها ليست كتبًا في البرمجة، بل كتب تحليل وتصميم برمجي، لأن أفضل تطبيق للبرمجة الكائنية التوجه يكون بتطبيق المبادئ خلال دورة حياة المشروع، وهذه طريقة مختلفة لحل المشاكل عن الطريقة العادية للبرمجة. أما في هذا المقال فسنتحدث باختصار عن مفاهيم البرمجة الكائنية التوجه التي ذكرناها، ولا مشكلة إذا لم تستوعبها في البداية، فلا تزال تستطيع استخدام الكائنات بدون أن تستوعب المفهوم الذي بُنيت عليه، ثم ستتضح الأمور بالتدريج مع التدرب والوقت،كما يمكن استخدام تصميم كائني التوجه في لغة غير كائنية من خلال الاصطلاحات البرمجية، لكن لا يُنصح بهذا الأسلوب، وإنما يستخدَم ملاذًا أخيرًا عندما لا نجد حلًا آخر، حيث تُستخدم التقنيات الكائنية التوجه إذا كانت المشكلة توافقها وتُحل بها، ويُفضل أن تُستخدم لغة كائنية التوجه أيضًا عندها، وتدعم أغلب اللغات الحديثة البرمجة الكائنية التوجه جيدًا، بما فيها اللغات الثلاثة التي نتدرب عليها، لكننا سنستخدم بايثون في الأمثلة الواردة هنا، ثم سنعرض المفاهيم الأساسية فقط في جافاسكربت وVBScript. جمع البيانات والدوال الكائنات هي تجميعات من البيانات والدوال التي تنفذ مهامًا على تلك البيانات، وتوضعان معًا بحيث يمكن تمرير كائن من جزء ما في البرنامج كي نحصل تلقائيًا على وصول إلى العمليات المتاحة وسمات البيانات، وهذا الجمع بين البيانات والدوال هو أصل البرمجة الكائنية التوجه، ويُعرف باسم التغليف encapsulation، لأن بعض لغات البرمجة تخفي البيانات عن مستخدمي الكائن، وبناءً عليه تتطلب توابع الكائن للوصول إليها، وتسمى هذه التقنية باسم إخفاء البيانات، ويطلق عليها التغليف أحيانًا، وكمثال على التغليف، قد يخزن كائن سلسلة نصية سلسلة محارف، لكنه يوفر كذلك توابع للعمل على هذه السلسلة؛ لتنفيذ أمور مثل البحث وتغيير حالة الأحرف وحساب الطول وغير ذلك، وتستخدم الكائنات مجازًا تمرير الرسالة message passing، حيث يمرر كائنٌ رسالةً إلى كائن آخر، ويرد الكائن المستقبل بتنفيذ تابع -وهو إحدى عملياته-، وهكذا يُستدعى التابع عند استقبال الرسالة الموافقة له بواسطة الكائن المالك، ويمكن تمثيل ذلك بصيغ مختلفة، وأكثرها شيوعًا الصيغة النقطية . التي تحاكي الوصول إلى العناصر التي في الوحدات، فبالنسبة إلى صنف widget وهمي: w = Widget() # widget جديدة من w أنشئ نسخة w.paint() # paint أرسل إليها الرسالة ستستدعي هذه التعليمات التابع paint الخاص بكائن widget. تعريف الأصناف يمكن للكائنات أن تحتوي على أنواع مختلفة، كما أن للبيانات أنواعًا مختلفةً، وتُعرَّف تجميعات الكائنات التي لها صفات متطابقة باسم الأصناف classes، ونستطيع تعريف هذه الأصناف وإنشاء نسخ منها، حيث تكون تلك النسخ هي الكائنات الفعلية، كما يمكن تخزين مراجع إلى تلك الكائنات في المتغيرات داخل برامجنا، لننظر الآن في مثال حقيقي لنرى إن كنا نستطيع تفسيره وشرحه، حيث سننشئ صنف رسالة يحتوي على سلسلة نصية -تمثل نص الرسالة- وتابع لطباعة الرسالة. class Message: def __init__(self, aString): self.text = aString def printIt(self): print( self.text ) الملاحظة الأولى: يسمى أحد توابع هذا الصنف باسم __init__، وهو تابع خاص يسمى الباني constructor، وسبب هذا الاسم أنه يُستدعى عند إنشاء أو بناء نسخة جديدة من كائن ما، وستكون المتغيرات المسندة داخل هذا التابع -والتي أنشئت داخل بايثون- متغيرات فريدة للنسخة الجديدة، وتوجد عدة توابع خاصة مثل هذا التابع في بايثون، وجميعها مميزة بصيغة التسمية التي فيها شرطتان سفليتان عن يمينها وشمالها __xxx__، ويطلق عليها مستخدمو بايثون أحيانًا اسم التوابع السحرية magic methods أو التوابع المحاطة بشرطين سفليتين dunder methods (إذ dunder اختصار إلى double under)؛ أما وقت استدعاء الباني الدقيق فيختلف بين اللغات، حيث يُستدعى التابع init في بايثون بعد إنشاء النسخة في الذاكرة، لكنه في لغات أخرى يعيد النسخة نفسها، والفرق في هذا بين اللغات طفيف ولا يستحق الانتباه له. الملاحظة الثانية: يحتوي كلا التابعين المعرفين على معامل أول هو self، والاسم مجرد اصطلاح يشير إلى نسخة الكائن، وسنرى قريبًا أن هذا المعامِل لا يملؤه المبرمج، بل يُملأ بواسطة المفسر في وقت التشغيل، وعلى هذا يُستدعى printIt على نسخة للصنف -انظر أدناه-، بدون وسطاء بالشكل m.printIt()‎. الملاحظة الثالثة: لقد استدعينا الصنف Message بحرف M كبير كما نرى، وهذا للسهولة فقط، لكن هذا الاصطلاح يُستخدم بكثرة في لغات البرمجة الكائنية التوجه، وليس في بايثون وحدها، ويوجد اصطلاح قريب من هذا يقتضي أن تبدأ أسماء التوابع بحرف صغير ثم تبدأ الكلمات التالية في الاسم بحرف كبير، فإذا كان لدينا تابع اسمه calculate current balance، فسيُكتب بالشكل calculateCurrentBalance. ننصحك عند هذه النقطة بالعودة إلى مقال البيانات وأنواعها، لقراءة قسم الأنواع المعرَّفة من قِبل المستخدم، حيث ستفهم مثال دليل جهات الاتصال في بايثون فهمًا أفضل بعد هذا الشرح هنا، فالنوع الوحيد الذي يعرّفه المستخدم في بايثون هو الصنف، والصنف الذي له سمات attributes وليس له توابع -ما عدا __init__- يكافئ الباني المسمى record أو struct في بعض لغات البرمجة. الصيغة الرسومية تبنّى مجتمع هندسة البرمجيات صيغةً مرئيةً لوصف الأصناف والكائنات وعلاقاتها بعضها ببعض، وتسمى هذه الصيغة باسم لغة النمذجة الموحدة Unified Modelling Language أو UML اختصارًا، وهي أداة تصميم قوية وتحتوي على العديد من المخططات والأيقونات، وسننظر في بعضها هنا بما يعيننا على فهم المبادئ التي نريد شرحها فقط، وأول أيقونة سنقابلها في UML هي وصف الصنف، وهي أهم الأيقونات، وتتكون من صندوق من ثلاثة أجزاء، يحتوي الجزء العلوي على اسم الصنف، والأوسط على سماته أو البيانات فيه، أما الجزء السفلي فيحتوي على توابع الصنف أو دواله، وبناءً عليه سيبدو صنف Message المعرَّف أعلاه كما يلي: سنرى في هذا المقال أيقونات UML أخرى، ونتعرض لمفاهيم جديدة تدعمها هذه الصيغة. استخدام الأصناف بما أننا عرّفنا الصنف Message فنستطيع إنشاء نسخ منه الآن والعمل عليها: m1 = Message("Hello world") m2 = Message("So long, it was short but sweet") notes = [m1, m2] # ضع الكائنات في قائمة for msg in notes: msg.printIt() # اطبع الرسائل متتابعة وبهذا نعامل الصنف كما لو كان نوع بيانات قياسيًا في بايثون، وهو الغرض من التدريب ابتداءً. كما توجد أيقونة للكائن أو النسخة في UML، وهي مثل أيقونة الصنف إلا أننا نترك الجزئين السفليين في الصندوق فارغين، ويتكون الاسم من اسم الكائن أو النسخة متبوعًا بنقطتين رأسيتين ثم اسم الصنف، وعليه فإن m1:Message تخبرنا أن m1 ما هي إلا نسخة من الصنف Message، ويمكن رسم مثال الرسالة الخاص بنا الآن كما يلي: نلاحظ أن الصنف List يمثل نوع القائمة القياسي في بايثون، كما هو موضح من وضع كلمة builtin بين أقواس حادة، وهي بنية معروفة في UML باسم القالب النمطي stereotype، وتشير الخطوط ذوات الرؤوس الماسية في الصورة إلى القائمة التي تحتوي على كائنات Message، وبالمثل فإن كائن MyProg يُنمَّط stereotyped على أنه صنف مساعد utility class، مما يعني في هذه الحالة أنه غير موجود مثل صنف داخل البرنامج، لكنه منتج من منتجات البيئة نفسها، وتُظهَر أدوات نظام التشغيل عادةً بهذه الطريقة، مثل مكتبات لدوال. أما الخطوط المستقيمة التي تخرج من myProg إلى Message فتوضح أن الكائن myProg يرتبط بـكائنات Message أو يشير إليها، وتشير الأسهم المرافقة لتلك الخطوط أن كائن myProg يرسل رسالة printIt إلى كل كائن من كائنات Message، وتُنقل رسائل الكائنات من خلال ارتباطات associations. المعامل self يطرح من يبدأ حديثًا في البرمجة الكائنية التوجه ببايثون سؤالًا هو: ما هو المعامل self؟ لأن تعريف أي تابع في صنف ما في بايثون يبدأ به، ويجب أن نبين أن الاسم نفسه مجرد اصطلاح، ولم يتغير إلى الآن لأن الثبات أمر محمود في الاصطلاحات البرمجية، فلغة جافاسكربت مثلًا لديها مفهوم مشابه لكنها تستخدم اسم this بدلًا من self. أما self نفسه فهو مرجع إلى النسخة الحالية، فحين ننشئ نسخةً من الصنف فإنها تحتوي على بياناتها الخاصة كما أنشأها الباني، لكنها لا تحوي التوابع، لذا عندما نرسل رسالةً إلى نسخة وتستدعي التابع الموافق؛ فإنها تستدعيه إلى الصنف من خلال مرجع داخلي، فتمرر مرجعًا إلى نفسها self إلى التابع لتعرف شيفرة الصنف أي نسخة يجب أن تستخدمها. لننظر الآن في مثال مألوف، فإذا كان لدينا تطبيق رسومي فيه كائنات أزرار كثيرة، فسيُفعَّل التابع المرتبط بكل زر عندما يضغطه المستخدم، ويعرف تابع الزر أي زر ضغِط بالإشارة إلى قيمة self التي ستكون مرجعًا إلى نسخة الزر الحقيقي الذي ضُغط، وسنرى ذلك عمليًا في مقال لاحق. وعند إرسال رسالة إلى كائن يحدث ما يلي: تستدعي شيفرة العميل النسخة، أي ترسل الرسالة إذا أردنا الحديث باصطلاح البرمجة الكائنية التوجه. تستدعي النسخة تابع الصنف، وتمرر مرجعًا إلى نفسها self. يستخدم تابع الصنف بعدها المرجع الممرَّر ليأخذ بيانات النسخة للكائن المستقبِل. يمكن رؤية تلك النقاط عمليًا في تسلسل الشيفرة التالي، ونلاحظ أننا نستطيع استدعاء تابع الصنف صراحةً كما فعلنا في السطر الأخير: >>> class C: ... def __init__(self, val): self.val = val ... def f(self): print ("hello, my value is:", self.val) ... >>> # create two instances >>> a = C(27) >>> b = C(42) >>> # first try sending messages to the instances >>> a.f() hello, my value is 27 >>> b.f() hello, my value is 42 >>> # now call the method explicitly via the class >>> C.f(a) hello, my value is 27 نستطيع استدعاء التوابع كما نرى في المثال أعلاه من خلال النسخة، وتملأ بايثون معامِل self في تلك الحالة لنا، أو من خلال الصنف صراحةً، وفي تلك الحالة نحتاج إلى تمرير قيمة self صراحةً. لدينا سؤال يطرح نفسه الآن، فإذا كانت بايثون تستطيع توفير مرجع بين النسخة وصنفها، ألا تستطيع أن تملًا self بنفسها أيضًا؟ ربما يكون هذا سؤالًا منطقيًا لكن الإجابة عليه هي أن Guido Van Rossum -منشئ اللغة- صممها هكذا. لكن مع هذا فإن العديد من لغات البرمجة الكائنية التوجه تخفي معامِل self، لكن بايثون تعتمد الصراحة explicity وتفضلها على الضمنية implicity، ويتعود المبرمج على هذا المبدأ مع كثرة العمل. تعددية الأشكال polymorphism لدينا الآن القدرة على تعريف أصنافنا الخاصة وإنشاء نسخ منها وإسنادها إلى متغيرات، ثم تمرير رسائل إلى تلك الكائنات تؤدي إلى تشغيل التوابع التي عرفناها، لكن هناك عنصر أخير يتعلق بالبرمجة الكائنية التوجه هنا، وهو الأهم فيها من نواحٍ عدة، فإذا كان لدينا كائنان من صنفين مختلفين لكنهما يدعمان نفس مجموعة الرسائل، لكن مع التوابع الموافقة لها، فنستطيع عندئذ أن نجمع تلك الكائنات معًا ونعاملها معاملةً واحدةً في برنامجنا، لكنها ستتصرف تصرفًا مختلفًا، وتُعرف تلك القدرة على التصرف المختلف لنفس رسائل الدخل باسم تعددية الأشكال، تُستخدم هذه الخاصية عادةً لجعل عدد من الكائنات الرسومية المختلفة ترسم نفسها عند استلام رسالة paint، فترسم الدائرة شكلًا مختلفًا تمامًا عن المثلث، لكن بما أن لهما نفس تابع paint فنستطيع -نحن المبرمجين- أن نتجاهل الاختلافات ونراهما على أنهما مجرد أشكال، لننظر الآن في مثال نحسب فيه مساحة الأشكال بدلًا من رسمها: ننشئ أولًا الصنفين Square وCircle: class Square: def __init__(self, side): self.side = side def calculateArea(self): return self.side**2 class Circle: def __init__(self, radius): self.radius = radius def calculateArea(self): import math return math.pi*(self.radius**2) نستطيع الآن أن ننشئ قائمةً من الأشكال -دوائر أو مربعات- ثم نطبع مساحاتها: shapes = [Circle(5),Circle(7),Square(9),Circle(3),Square(12)] for item in shapes: print "The area is: ", item.calculateArea() إذا جمعنا هذه الأفكار مع وحدات modules فسنحصل على آلية بالغة القوة لإعادة استخدام الشيفرة، حيث نضع تعريفات الصنف في وحدة ولتكن shapes.py مثلًا، ثم نستورد تلك الوحدة حين نرغب في التعديل على الأشكال، وهذا بالضبط ما حصل مع العديد من وحدات بايثون القياسية، وهو السبب الذي يجعل الوصول إلى توابع كائن ما يشبه استخدام الدوال في وحدة. نرى في الصورة أعلاه مخطط كائن أكثر تعقيدًا، ونلاحظ أن الكائنات التي داخل القائمة في هذه الحالة ليس لها أسماء لأننا لم ننشئ متغيرات لها صراحةً، ففي تلك الحالة نعرض مسافةً فارغةً قبل النقطين الرأسيتين واسم الصنف، لكن هذا يجعل المخطط مزدحمًا، لذا لا نرسم مخططات الكائنات إلا عند الضرورة لتوضيح بعض المزايا غير المألوفة للتصميم، أما في الأحوال العادية فنستخدم خصائص معقدةً أكثر من مخططات الأصناف لعرض العلاقات التي لدينا، كما سنرى في الأمثلة التالية. الوراثة inheritence تُستخدم الوراثة (أو الاكتساب) عادةً لتنفيذ تعددية الأشكال واستخدامها، وقد تكون هي الآلية الوحيدة لذلك في العديد من لغات البرمجة الكائنية، ويمكن للصنف أن يرث السمات والعمليات من صنف أب parent class أو صنف رئيسي super class، وهذا يعني أن الصنف الجديد المطابق لصنف آخر في أغلب جوانبه لا يجب أن يعيد تنفيذ جميع التوابع التي في الصنف الأول، بل يمكن أن يرث تلك الإمكانيات ثم يغيرها لتنفيذ أمور مختلفة، كما في تابع calculateArea أعلاه، وسنستخدم للتوضيح مثالًا فيه هرمية أصناف حسابات بنكية، حيث نستطيع إيداع المال والحصول على الرصيد والقيام بعمليات سحب، ولبعض الحسابات نسبة ربوية (فائدة) سنفترض أنها تُحسب عند كل إيداع، إضافةً إلى بعض الرسوم الأخرى لعمليات السحب. الصنف BankAccount لنرى الآن كيف سيبدو هذا المثال، سننظر في السمات والعمليات الخاصة بالحساب البنكي في أكثر مستوىً عام له، ومن الأفضل هنا أن ننظر في العمليات أولًا، ثم نوفر السمات حسب الحاجة لدعم تلك العمليات، فمع الحساب المصرفي نستطيع القيام بما يلي: إيداع المال. سحب المال. التحقق من الرصيد الحالي. تحويل الأموال إلى حساب آخر. وسنحتاج إلى معرِّف الحساب المصرفي ID للحساب الآخر والرصيد الحالي، بالنسبة للمعرِّف فسنستخدم المتغير الذي نسند الكائن إليه، لكن إذا كنا في مشروع حقيقي فيجب إنشاء سمة خاصة بالمعرِّف تخزن مرجعًا فريدًا، كما سنحتاج إلى تخزين الرصيد، وعند تمثيل ذلك بلغة النمذجة الموحدة UML فسيبدو كما يلي: نستطيع الآن أن ننشئ صنفًا يدعم ذلك: # ‫ننشئ صنف اعتراض Exception مخصص class BalanceError(Exception): value = "Sorry you only have $%6.2f in your account" class BankAccount: def __init__(self, initialAmount): self.balance = initialAmount print( "Account created with balance %5.2f" % self.balance ) def deposit(self, amount): self.balance = self.balance + amount def withdraw(self, amount): if self.balance >= amount: self.balance = self.balance - amount else: raise BalanceError() def checkBalance(self): return self.balance def transfer(self, amount, account): try: self.withdraw(amount) account.deposit(amount) except BalanceError: print( BalanceError.value % self.balance ) الملاحظة الأولى: نتحقق من الرصيد قبل السحب، ونستخدم اعتراضًا لمعالجة الأخطاء، وبما أنه لا يوجد خطأ من النوع BalanceError في بايثون فسنحتاج إلى إنشاء واحد، وهو صنف فرعي من الصنف Exception مع قيمة نصية، وتُعرَّف قيمة السلسلة value سمةً لصنف الاعتراض لمجرد الاصطلاح فقط، وهي تضمن أننا نولد رسائل خطأ في كل مرة نرفع فيها اعتراضًا، ونلاحظ هنا أننا لم نستخدم self عند تعريف القيمة في BalanceError لأن value سمة مشتركة بين كل النسخ، وهي معرَّفة على مستوى الصنف وتُعرف بمتغير الصنف، ونصل إليها باستخدام اسم الصنف متبوعًا بنقطة BalanceError.value كما رأينا أعلاه، فعندما يولّد خطأ التعقب العكسي traceback -أي مسار مكان وقوع الخطأ ورجوعًا ضمن سلسلة الاستدعاءات- فسينتهي بطباعة سلسلة الخطأ المصاغة مع عرض الرصيد الحالي. الملاحظة الثانية: يستخدم التابع transfer الدالة التابعة withdraw/deposit الخاصة بالصنف BankAccount أو توابعه لتنفيذ عملية التحويل، وهذا أمر شائع في البرمجة الكائنية التوجه ويُعرف بالمراسلة الذاتية self messaging، ويعني أن الأصناف المشتقة تستطيع تنفيذ نسخها الخاصة من deposit/withdraw لكن يظل التابع transfer كما هو لجميع أنواع الحسابات. بما أننا عرّفنا BankAccount صنفًا قاعديًا فنستطيع أن نعود إلى الوراثة التي كنا نشرحها، ولننظر في أول صنف فرعي لنا فيما يلي. الصنف InterestAccount نستخدم الوراثة الآن لتوفير حساب يضيف نسبة ربوية -سنفترض أنها ‎3%- عند كل عملية إيداع، وستكون مطابقةً لصنف BankAccount القياسي عدا تابع الإيداع وبدء معدل النسبة، لذا نعيد كتابة تنفيذ هذه التوابع كما يلي: class InterestAccount(BankAccount): def __init__(self, initialAmount, interest=0.03): super().__init__(initialAmount) self.interest = interest def deposit(self, amount): super().deposit(amount) self.balance = self.balance * (1 + self.interest) الملاحظة الأولى: نمرر الصنف الرئيسي (أو الأب) معامِلًا في تعريف الصنف، ويكون هذا الصنف الأب في حالتنا هو BankAccount. الملاحظة الثانية: نستدعي super().__init__()‎ في بداية التابع ‎__init__()‎، والدالة super()‎ هي دالة خاصة وظيفتها معرفة الصنف الرئيسي، ويفيدنا ذلك عند وراثة أكثر من صنف رئيسي واحد فيما يسمى بالوراثة المتعددة، حيث نتجنب بعض المشاكل الغريبة التي قد تظهر إذا حاولنا استدعاء الصنف الرئيسي باسمه، لذلك يُفضل استخدام super()‎. ونبدأ الصنف الموروث باستدعاء التابع __init__ الخاص بالصنف الرئيسي، ولا نحتاج هنا إلا إلى بدء السمة interest التي قدمناها هنا، وبالمثل في استخدام super()‎ في تابع الإيداع، إذ يستدعي التابع deposit الخاص بالصنف الأب فلا نحتاج إلا إلى إضافة المزايا الجديدة للصنف InterestAccount. وهكذا نرى قوة البرمجة الكائنية التوجه وإمكانياتها، فبما أننا وضعنا BankAccount داخل الأقواس بعد اسم الصنف فقد صارت جميع التوابع موروثةً من BankAccount، ونلاحظ أن deposit تستدعي التابع deposit الخاص بالصنف الرئيسي بدلًا من نسخ الشيفرة، وسيحصل الصنف الفرعي على تلك التعديلات تلقائيًا إذا عدّلنا deposit الخاص بالصنف BankAccount بحيث يحوي تحققًا من بعض الأخطاء. الصنف ChargingAccount هذا الصنف مطابق للصنف BankAccount عدا أنه يطلب رسومًا افتراضية مقدارها ‎3$ لكل عملية سحب، وبالنسبة لـ InterestAccount فيمكن إنشاء صنف يرث من BankAccount ويعدّل التابعين init و withdraw: class ChargingAccount(BankAccount): def __init__(self, initialAmount, fee=3): super().__init__(initialAmount) self.fee = fee def withdraw(self, amount): super().withdraw(amount+self.fee) الملاحظة الأولى: نخزن الرسوم مثل متغير نسخة intance variable لنستطيع تغييره لاحقًا عند الحاجة، ونلاحظ أننا نستدعي __init__ مرةً أخرى مثل أي تابع آخر. الملاحظة الثانية: نضيف الرسوم إلى عملية السحب المطلوبة في استدعاء التابع الموروث withdraw الذي ينجز العمل الفعلي. الملاحظة الثالثة: نضيف أثرًا جانبيًا هنا حيث تُفرض رسوم تلقائيًا على عمليات التحويل، لكن هذا مطلوب على الأرجح لذا لا بأس به، وتجدر الإشارة هنا إلى أن إعادة الاستخدام هذه تحمل في طياتها احتمالية الآثار الجانبية غير المتوقعة التي يجب الحذر منها. ونمثل هذه الوراثة في UML بسهم مصمت من الصنف الفرعي إلى الصنف الرئيسي، فتُمثَّل هرمية الحساب البنكي الآن كما يلي: نلاحظ أننا سردنا التوابع والسمات التي تغيرت فقط أو أضيفت إلى الأصناف الفرعية. اختبار النظام للتحقق من عمل الهرمية السابقة بكفاءة، جرب تنفيذ الشيفرة التالية في محث بايثون أو بإنشاء ملف اختبار منفصل: from bankaccount import * # الحساب البنكي العادي a = BankAccount(500) b = BankAccount(200) a.withdraw(100) # a.withdraw(1000) a.transfer(100,b) print( "A = ", a.checkBalance() ) print( "B = ", b.checkBalance() ) # حساب للنسبة الربوية c = InterestAccount(1000) c.deposit(100) print( "C = ", c.checkBalance() ) # حساب للرسوم المفروضة d = ChargingAccount(300) d.deposit(200) print( "D = ", d.checkBalance() ) d.withdraw(50) print( "D = ", d.checkBalance() ) d.transfer(100,a) print( "A = ", a.checkBalance() ) print( "D = ", d.checkBalance() ) # حوّل من حساب الرسوم إلى حساب النسبة الربوية # حساب الرسوم سيطلب رسومًا، وحساب النسبة الربوية # يضيف نسبة ربوية print( "C = ", c.checkBalance() ) print( "D = ", d.checkBalance() ) d.transfer(20,c) print( "C = ", c.checkBalance() ) print( "D = ", d.checkBalance() ) أزل علامة التعليق الآن من السطر (a.withdraw(1000 لترى الاعتراض عمليًا. وبهذا نكون أتممنا مثالًا بسيطًا يظهر كيفية استخدام الوراثة لتوسيع إطار بسيط وإضافة مزايا قوية إليه، وقد رأينا كيف يبنى المثال على مراحل ويوضع برنامج اختبار للتحقق من نجاحه، مع أن اختباراتنا لم تكن كاملةً لأننا لم نغطِّ كل الحالات الممكنة، وكان من الممكن إدراج المزيد من الاختبارات، كما في حالة إنشاء حساب برصيد سالب. تجميعات الكائنات إحدى المشاكل التي قد تواجهها هي كيفية التعامل مع كائنات كثيرة، أو كيفية التعامل مع كائنات تنشئها في وقت التشغيل، فمن السهل إنشاء حسابات بنكية ثابتة كما فعلنا أعلاه: acc1 = BankAccount(...) acc2 = BankAccount(...) acc3 = BankAccount(...) etc... لكن في العالم الحقيقي لا تكون لدينا بيانات عن عدد الحسابات التي يجب إنشاؤها، فكيف نحل هذه المشكلة؟ لننظر فيها بتفصيل أكبر: نريد شكلًا ما من قواعد البيانات التي تسمح لنا بإيجاد أي حساب بنكي باسم مالكه أو رقم حسابه -بما أنه قد يكون للشخص الواحد عدة حسابات-، والعكس صحيح، ولكن ألا يشبه البحث عن شيء له معرّف خاص به القاموس؟ لنجرب استخدام قاموس في بايثون للاحتفاظ بكائنات منشأة ديناميكيًا: from bankaccount import BankAccount import time # أنشئ دالة جديدة لتوليد أرقام معرّفات فريدة def getNextID(): ok = input("Create account[y/n]? ") if ok[0] in 'yY': # check valid input id = time.time() # use current time as basis of ID id = int(id) % 10000 # حول إلى عدد صحيح وقلله إلى 4 أرقام else: id = -1 # وذلك سيوقف الحلقة التكرارية return id # أنشئ بعض الحسابات وخزنها في القاموس accountData = {} # قاموس جديد while True: # كرر حلقيًا بلا نهاية id = getNextID() if id == -1: break # تخرج إجباريًا من الحلقة التكرارية bal = float(input("Opening Balance? ")) # حول السلسلة إلى عدد ذي فاصلة عائمة accountData[id] = BankAccount(bal) # استخدم المعرِّف لإنشاء إدخال جديد في القاموس print( "New account created, Number: %04d, Balance %0.2f" % (id, bal) ) # دعنا نصل الآن إلى بعض الحسابات for id in accountData.keys(): print( "%04d\t%0.2f" % (id, accountData[id].checkBalance()) ) # ونبحث عن واحد فيها # أدخل محرفًا غير رقمي لرفع اعتراض وإنهاء البرنامج while True: id = int(input("Which account number? ")) if id in accountData: print( "Balance = %0.2d" % accountData[id].checkBalance() ) else: print( "Invalid ID" ) لا شك أن المفتاح الذي نستخدمه للقاموس قد يكون أي شيء يعرّف الكائن تعريفًا فريدًا، فقد يكون أحد سماته -مثل الرصيد balance- لكن الرصيد قد يتشابه بين الحسابات، ويتغير بالزيادة والنقص، وهكذا نفكر في الخيارات المتاحة إلى أن نصل إلى معرّف لا يتكرر، وهنا يمكن الرجوع إلى مقال البيانات وأنواعها، لقراءة القسم الخاص بالقاموس مرةً أخرى. يمثَّل هذا مرئيًا في UML باستخدام مخطط الصنف، ويُعرض القاموس مثل صنف له علاقة مع العديد من الحسابات البنكية، ونرى ذلك موضحًا بمحرف النجمة على الخط الموصل بين الأصناف، ونستخدم محرف النجمة هنا لأنه الرمز المستخدم في التعابير النمطية للإشارة إلى عدد من العناصر مقداره صفر أو أكثر، وهذا يُعرف بعدد عناصر العلاقة cardinality of the relationship، ويمكن رؤيته بعد طرق، لكن المجالات العددية للتعابير النمطية هي المستخدمة بكثرة لثرائها ومرونتها. نلاحظ استخدام القالب النمطي stereotype على القاموس Dictionary لإظهار أنه صنف مضمَّن، كما نلاحظ وجود الصندوق الملحق بالارتباط، والذي يوضح أن المفتاح هو قيمة المعرّف ID، فإذا كنا نستخدم قائمةً بسيطةً فلن يكون لدينا الصندوق ولكان الخط وصل بين الصنفين مباشرةً، وبهذا يتضح أننا نتجنب الحاجة إلى مخططات الكائنات الكبيرة والمعقدة باستخدام علاقات الأصناف وعدد العناصر في المجموعة cardinality، حيث نركز على العلاقات المجردة بين الأصناف بدلًا من التعامل مع عدد كبير من العلاقات الحقيقية بين النسخ المفردة. حفظ الكائنات إن فقد البيانات عند انتهاء المخطط هو أحد مشاكل السلوك السابق، لذا نريد طريقةً لحفظ الكائنات، ويمكن فعل ذلك باستخدام قواعد البيانات لكنه أسلوب متقدم، أما الآن فسنستخدم ملفًا نصيًا بسيطًا لحفظ الكائنات واسترجاعها، ورغم أن بايثون تحتوي على وحدتين لتنفيذ ذلك بكفاءة، وهما pickle وshelve، إلا أننا سنشرح الطريقة العامة التي تصلح لأي لغة، والطريقة العامة التي نقصدها هي إنشاء التابعين save وrestore في الكائن ذي المستوى الأعلى، ثم إعادة كتابتهما في كل صنف ليستدعيا النسخة الموروثة ثم يضيفا السمات المعرفة محليًا، وبالمناسبة يُستخدم مصطلح الثبات Persistence للإشارة إلى القدرة على حفظ الأشياء واستعادتها. class A: def __init__(self,x,y): self.x = x self.y = y self.f = None def save(self,fn): f = open(fn,"w") f.write(str(self.x)+ '\n') # convert to a string and add newline f.write(str(self.y)+'\n') return f # for child objects to use def restore(self, fn): f = open(fn) self.x = int(f.readline()) # convert back to original type self.y = int(f.readline()) return f class B(A): def __init__(self,x,y,z): super().__init__(x,y) self.z = z def save(self,fn): f = super().save(fn) # call parent save f.write(str(self.z)+'\n') return f # in case further children exist def restore(self, fn): f = super().restore(fn) self.z = int(f.readline()) return f # أنشئ النُسخ a = A(1,2) b = B(3,4,5) # احفظ النُسخ a.save('a.txt').close() # تذكر أن تغلق الملف b.save('b.txt').close() # اجلب النسخ newA = A(5,6) newA.restore('a.txt').close() # تذكر أن تغلق الملف newB = B(7,8,9) newB.restore('b.txt').close() print( "A: ",newA.x,newA.y ) print( "B: ",newB.x,newB.y,newB.z ) نلاحظ أن القيم المطبوعة هي القيم المسترجعة، وليست القيم التي استخدمناها لإنشاء النسخ. والمهم هنا هو إعادة كتابة التابع save والتابع restore في كل صنف واستدعاء التابع الرئيسي في خطوة أولى، ثم لا نتعامل في الصنف الفرعي إلا مع سمات ذلك الفرعي فقط، ومن البديهي أن تحويل السمة إلى سلسلة نصية وحفظها أمر متروك لك كونك مبرمجًا، لكن يجب إخراجها على سطر واحد، أما عند الاستعادة فببساطة يمكن عكس عملية التخزين، لكن تظهر هنا عقبة كبيرة في هذا الأسلوب، وهي أننا نحتاج إلى إنشاء ملف منفصل لكل كائن، وهذا قد يعني آلاف الملفات الصغيرة إذا كنا في بيئة برمجية لسوق حقيقي، حيث سيتعقد العمل بوتيرة متسارعة، وسنحتاج إلى استخدام قاعدة بيانات لحفظ الكائنات، وسنبحث في ذلك في مقال لاحق، أما الآن فيكفي أن تعلم أن المفاهيم الأساسية ستظل كما هي. دمج الأصناف والوحدات توفر الأصناف والوحدات آليات للتحكم في تعقيد البرنامج، ومن المنطقي مع ازدياد حجم البرنامج ازدياد الحاجة إلى دمج المزايا بوضع أصناف داخل وحدات، وتنصح بعض الهيئات بوضع كل صنف في وحدة منفصلة، لكن هذا يؤدي إلى وحدات كثيرة جدًا ويزيد التعقيد بدلًا من تقليله، والبديل الذي لدينا هو تجميع الأصناف معًا، ووضع المجموعة في وحدة، وإذا عدنا إلى مثالنا أعلاه فسنضع كل تعريفات أصناف الحساب المصرفي في وحدة واحدة هي bankaccount مثلًا، ثم ننشئ وحدةً منفصلةً لشيفرة التطبيق التي تستخدم الوحدة. يمكن تمثيل ذلك مرئيًا بواسطة UML بطريقتين، حيث يمكن تمثيل الجمع المنطقي للأصناف باستخدام حزمة، أو نستطيع تمثيل الملف الحقيقي مثل مكوّن: والهدف هنا أن تبدو أيقونة الحزمة مثل مجلد في أي برنامج مدير ملفات، أما الأيقونة الصغيرة التي في أعلى اليمين في أيقونة المكون فهي رمز المكون القديم في UML، وبما أن رسمها صعب في المخططات عند رسم الخطوط التي تظهر العلاقات بين المكونات فقد صغِّر شكلها في UML 2.0. هذا ما سنغطيه حول UML في هذه السللسلة، ويمكن الرجوع لمحركات البحث والويب للاستزادة من المراجع والتدريبات وأدوات رسم UML، رغم أن الأشكال سهلة الرسم في أي برنامج رسم متجهي. إذا أردنا تمثيلًا بسيطًا لذلك التصميم فسيكون كما يلي: # File: bankaccount.py # # Implements a set of bank account classes ################### class BankAccount: .... class InterestAccount: ... class ChargingAccount: ... ثم إذا أردنا استخدامه: import bankaccount newAccount = bankaccount.BankAccount(50) newChrgAcct = bankaccount.ChargingAccount(200) # هنا يمكن تنفيذ المهام التي تريدها لكن ماذا لو أراد صنفان في وحدتين الوصول إلى بيانات بعضهما بعضًا؟ إن أبسط حل لهذا هو استيراد كلتا الوحدتين وإنشاء نُسخ للأصناف التي نريدها، وتمرير نُسخ أحد الصنفين إلى توابع النسخة الأخرى، وتمرير الكائنات كاملةً من مكان لآخر ما هو إلا برمجة كائنية التوجه، وهنا ندرك أحد أسباب التسمية لهذا النوع من البرمجة، فلا نحتاج إلى استخراج سمات كائن وتمريرها إلى كائن آخر، بل نمرر الكائن كله، وإذا كان الكائن يستخدم رسالةً متعددة الأشكال للوصول إلى المعلومات التي يحتاج إليها فسيصلح التابع مع أي نوع من الكائنات التي تدعم الرسالة. لننظر في مثال واقعي لتوضيح ذلك، حيث ننشئ وحدةً قصيرةً نسميها logger تحتوي صنفين، هما Logger الذي يسجل النشاط داخل ملف، ويحتوي هذا الصنف على تابع واحد هو log()‎ الذي يأخذ معاملًا كائنًا قابلًا للتسجيل، أما الصنف الآخر فهو Loggable الذي تستطيع الأصناف الأخرى أن ترثه لتعمل مع logger: # File: logger.py # # Create Loggable and Logger classes for logging activities # of objects ############ class Loggable: def activity(self): return "This needs to be overridden locally" class Logger: def __init__(self, logfilename = "logger.dat"): self._log = open(logfilename,"a") def log(self, loggedObj): self._log.write(loggedObj.activity() + '\n') def __del__(self): self._log.close() نلاحظ أننا وفرنا تابع تدمير destructor هو __del__ لإغلاق الملف عند حذف كائن التسجيل أو كنسه garbage collected، وهو أحد التوابع السحرية الموجودة في بايثون كما نرى من الشرطتين السفليتين حوله، واللتين تشبهان ‎__init__()‎، مع فرق أن init يُستدعى عند إنشاء نسخة ما، أما del فيستدعى عندما يحذف كانس المخلفات النسخة، وقد لا يُستدعى إذا خرجت بايثون خروجًا غير متوقع، حيث سيكون لدينا في هذه الحالة مشاكل أكبر من استدعاء del أو عدم استدعائه. كما استدعينا سمة السجل ‎_log مع شرطة سفلية قبلها، وهو اصطلاح للتسمية في بايثون، كما في استخدام الكلمات ذات الأحرف الكبيرة لأسماء الأصناف، فالشرطة السفلية المفردة تعني أن السمة ليست مصممةً لنصل إليها مباشرةً، بل من خلال توابع الصنف. سننشئ الآن وحدةً جديدةً تعرِّف النسخ القابلة للتسجيل لأصناف حساباتنا المصرفية السابقة، لنستطيع استخدام وحدتنا: # File: loggablebankaccount.py # # Extend Bank account classes to work with logger module. ############################### import bankaccount, logger class LoggableBankAccount(bankaccount.BankAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableInterestAccount(bankaccount.InterestAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableChargingAccount(bankaccount.ChargingAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() استخدمنا الوراثة المتعددة في المثال أعلاه، حيث ورثنا صنفين رئيسيين وليس صنفًا واحدًا، وهذا غير ضروري في بايثون بما أننا نستطيع إضافة التابع activity()‎ إلى أصنافنا الأصلية ونحقق نفس الأثر، أما في لغات برمجة كائنية التوجه ثابتة مثل جافا أو C++‎ فسيكون هذا ضروريًا، لذا سنشرح التقنية هنا، قد تلاحظ أن التابع activity()‎ متطابق في الأصناف الثلاثة، وهذا يعني أننا نستطيع توفير بعض الكتابة على أنفسنا بإنشاء نوع وسيط من صنف حساب قابل للتسجيل يرث Loggable وله تابع activity فقط، ثم ننشئ ثلاثة أنواع حسابات قابلة للتسجيل بوراثتها من ذلك الصنف الجديد ومن صنف Loggable، كما يلي: class LoggableAccount(logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableBankAccount(bankaccount.BankAccount, LoggableAccount): pass class LoggableInterestAccount(bankaccount.InterestAccount, LoggableAccount): pass class LoggableChargingAccount(bankaccount.ChargingAccount, LoggableAccount): pass لا يوفر هذا علينا الكثير من الكتابة، لكنه يعني أن علينا اختبار تعريف تابع واحد فقط والاحتفاظ به بدلًا من ثلاثة توابع متطابقة، وهذا النوع من البرمجة الذي يكون فيه لصنف رئيسي وظيفةً مشتركةً يسمى بالبرمجة الخليطة mixin programming، ويسمى الصنف الأدنى بالصنف الخليط mixin class، والناتج المتوقع من ذلك الأسلوب أن يكون لتعريفات الصنف النهائي متن صغير أو ليس لها متن أصلًا، لكنها تحوي قائمةً طويلةً من الأصناف الموروثة كما رأينا هنا. ومن الشائع أيضًا أن الأصناف المختلطة لا ترث من أي شيء بنفسها، رغم أننا فعلنا هذا هنا، فما هي إلا طريقة لإضافة تابع مشترك أو مجموعة من التوابع إلى صنف أو مجموعة أصناف باستخدام الوراثة، ويأتي مصطلح المختلطة mixin، من مجال صناعة المثلجات، حيث تضاف نكهات مختلفة إلى الفانيليا لإنتاج نكهة جديدة، وكانت أول لغة تدعم هذا الأسلوب هي لغة Flavors، والتي كانت إحدى لغات Lisp المشهورة وقتها. نأتي الآن إلى النقطة التي نُظهر فيها شيفرة التطبيق الخاص بنا بإنشاء كائن مسجل logger وبعض الحسابات المصرفية، ثم تمرير الحسابات إلى المسجل، رغم أنها معرّفة في وحدات مختلفة: # Test logging and loggable bank accounts. ############# import logger import loggablebankaccount as lba log = logger.Logger() ba = lba.LoggableBankAccount(100) ba.deposit(700) log.log(ba) intacc = lba.LoggableInterestAccount(200) intacc.deposit(500) log.log(intacc) نلاحظ هنا كلمة as المفتاحية التي تُستخدم لإنشاء اسم مختصر عند استدعاء loggablebankaccount. لا نحتاج إلى استخدام سابقة الوحدة module prefix بعد إنشاء النسخ المحلية، وبما أنه لا يوجد وصول مباشر من كائن إلى آخر بل من خلال الرسائل، فلا حاجة أن تشير وحدتا تعريف الصنف إلى بعضهما البعض مباشرةً، كما يعمل المسجل مع نسخ كل من LoggableBankAccount وLoggableInterestAccount لأنهما يدعمان واجهة Loggable، فالتوافق بين واجهات الكائنات من خلال تعددية الأشكال هو الأساس الذي تبنى عليه جميع البرامج الكائنية التوجه. يوجد نظام تسجيل أكثر تعقيدًا في وحدة المكتبة القياسية logging، لإظهار بعض التقنيات فقط، ونذكره هنا لتكون هذه المكتبة أول خيار نبحث فيه عند الحاجة إلى أدوات تسجيل في البرامج التي نكتبها. نأمل أن يكون هذا الشرح كافيًا لفهم البرمجة كائنية التوجه، مع الاستزادة من المصادر الموجودة في الويب أو قراءة أحد الكتب المذكورة في بداية المقال، أما الآن فسننظر في كيفية تنفيذ البرمجة كائنية التوجه في جافاسكربت وVBScript. البرمجة الكائنية في VBScript تدعم VBScript مفهوم الكائنات وتسمح بتعريف الأصناف وإنشاء نسخ منها، لكنها لا تدعم مفهوم الوراثة ولا تعددية الأشكال، وعلى هذا تكون لغة VBScript لغةً كائنية الأساس object based وليست كائنية التوجه، لكن مفهوم دمج البيانات والدوال في كائن واحد لا يزال صالحًا هنا، ويمكن تنفيذ صورة محدودة من الوراثة باستخدام تقنية تسمى التفويض delegation. تعريف الأصناف يُعرَّف الصنف في VBScript باستخدام تعليمة Class كما يلي: <script type=text/VBScript> Class MyClass Private anAttribute Public Sub aMethodWithNoReturnValue() MsgBox "MyClass.aMethodWithNoReturnValue" End Sub Public Function aMethodWithReturnValue() MsgBox "MyClass.aMethodWithReturnValue" aMethodWithReturnValue = 42 End Function End Class </script> وهذا يعرِّف صنفًا جديدًا اسمه MyClass مع سمة تسمى anAttribute تكون مرئيةً فقط للتوابع التي في الصنف، كما نرى من كلمة Private المفتاحية، ومن المتعارف عليه أن نصرح عن سمات البيانات بأنها Private، وعن أغلب التوابع بأنها Public، ويُعرف هذا باسم إخفاء البيانات، وميزته أنه يسمح لنا بالتحكم في الوصول إلى البيانات بإجبار استخدام التوابع التي تتحقق من جودة البيانات على القيم التي تمرَّر إلى داخل وخارج الكائن، وتوفر بايثون آليةً خاصةً بها لتنفيذ هذا لكنها خارج نطاق شرحنا. إنشاء النسخ ننشئ النسخ في VBScript بدمج الكلمتين المفتاحيتين Set وNew، ويجب أن يكون المتغير الذي أُسندت إليه النسخة الجديدة قد صرِّح عنه باستخدام كلمة Dim كما هو متبع في VBScript: <script type=text/VBScript> Dim anInstance Set anInstance = New MyClass </script> يؤدي هذا إلى إنشاء نسخة من الصنف مصرح عنها في القسم السابق وإسنادها إلى متغير anInstance، لاحظ أننا يجب أن نسبق اسم المتغير بـ Set، وأننا نستخدم كلمة New لإنشاء الكائن. إرسال الرسائل تُرسَل الرسائل إلى النسخ باستخدام نفس الصيغة النقطية . التي تستخدمها بايثون: <script type=text/VBScript> Dim aValue anInstance.aMethodWithNoReturnValue() aValue = anInstance.aMethodWithReturnValue() MsgBox "aValue = " & aValue </script> يُستدعى التابعان المصرح عنهما في تعريف الصنف، ولا توجد في الحالة الأولى قيمة معادة، أما في الحالة الثانية فسنسند القيمة المعادة إلى المتغير aValue، ولا يوجد شيء غير اعتيادي هنا باستثناء أن البرنامج الفرعي subroutine والدالة مسبوقان باسم النسخة. الوراثة وتعددية الأشكال لا تدعم VBScript أي آلية للوراثة أو تعددية الأشكال، لكن نستطيع محاكاة ذلك إلى حد ما باستخدام تقنية تسمى التفويض، وهذا يعني أننا نعرف سمةً للصنف الفرعي ليكون نسخةً من الصنف الرئيسي المفترض، ثم نعرف تابعًا لجميع التوابع الموروثة التي تستدعي تابع النسخة الرئيسية أو تفوض إليه، لننشئ صنفًا فرعيًا من MyClass كما هو معرَّف أعلاه: <script type=text/VBScript> Class SubClass Private parent Private Sub Class_Initialize() Set parent = New MyClass End Sub Public Sub aMethodWithNoReturnValue() parent.aMethodWithNoREturnVAlue End Sub Public Function aMethodWithReturnValue() aMethodWithReturnValue = parent.aMethodWithReturnValue End Function Public Sub aNewMethod MsgBox "This is unique to the sub class" End Sub End Class Dim inst,aValue Set inst = New SubClass inst.aMethodWithNoReturnVAlue aValue = inst.aMethodWithReturnValue inst.aNewMethod MsgBox "aValue = " & CStr(aValue) </script> نلاحظ هنا استخدام السمة الخاصة parent والتابع الخاص المميز Class_Initialise، فالأولى هي سمة تفويض الصنف الأب، والثاني هو المكافئ للتابع __init__ في بايثون لبدء النسخ عند إنشائها، أي أنه الباني في لغة VBScript. البرمجة الكائنية في جافاسكربت تدعم جافاسكربت الكائنات باستخدام تقنية تسمى النمذجة الأولية prototyping، وهذا يعني عدم وجود بنية صنف صريحة في جافاسكربت، بل نستطيع تعريف الصنف بمجموعة من الدوال أو مثل مفهوم شبيه بالقاموس يُعرف بالمهيئ initializer. تعريف الأصناف من أكثر الطرق شيوعًا لتعريف الأصناف في جافاسكربت هي إنشاء دالة بنفس اسم الصنف، ويكون هو الباني، لكنه لا يُحتوى داخل أي بنية أخرى: <script type=text/JavaScript> function MyClass(theAttribute) { this.anAttribute = theAttribute; }; </script> ربما تلاحظ كلمة this التي تُستخدم بنفس طريقة استخدام self في بايثون مثل مرجع نائب placeholder reference إلى النسخة الحالية، رغم أننا لا نحتاج في الغالب إلى إدراج this صراحةً في قائمة المعامِلات لتوابع الصنف، ونستطيع إضافة سمات جديدة إلى الصنف لاحقًا باستخدام السمة prototype المضمَّنة كما يلي: <script type=text/JavaScript> MyClass.prototype.newAttribute = null; </script> ويعرِّف هذا سمةً جديدةً لـ MyClass اسمها newAttribute، وتضاف التوابع من خلال تعريف دالة عادية؛ ثم إسناد اسم الدالة إلى سمة جديدة مع اسم التابع، ويكون للتابع والدالة نفس الاسم عادةً، لكن لا مانع من تغيير اسم التابع إلى شيء مختلف، كما يلي: <script type=text/JavaScript> function oneMethod(){ return this.anAttribute; } MyClass.prototype.getAttribute = oneMethod; function printIt(){ document.write(this.anAttribute + "<BR>"); }; MyClass.prototype.printIt = printIt; </script> ولا شك أن الأسهل تعريف الدوال ثم الباني، ثم إسناد التوابع داخل الباني، وهذا هو الأسلوب الافتراضي، لذا سيبدو تعريف الصنف كاملًا كما يلي: <script type=text/JavaScript> function oneMethod(){ return this.anAttribute; }; function printIt(){ document.write(this.anAttribute + "<BR>"); }; function MyClass(theAttribute) { this.anAttribute = theAttribute; this.getAttribute = oneMethod; this.printIt = printIt; }; </script> لكن ثمة طريقة أخرى في جافاسكربت، باستخدام صيغة مختلفة قليلًا لإنشاء دوال التابع، حيث تسمح جافاسكربت بتعريف الدالة كما يلي: square = function(x){ return x*x;} ثم نستدعي ذلك كما يلي: document.write("The square of 5 is: " + square(5)) فإذا طبقناه على تعريف الصنف الخاص بنا نحصل على: <script type=text/JavaScript> function MyClass(theAttribute) { this.anAttribute = theAttribute; this.getAttribute = function(){ return this.anAttribute; }; this.printIt = function printIt(){ document.write(this.anAttribute + "<BR>"); }; }; </script> يفضل بعض المبرمجين هذا الأسلوب لأنه يبقي تعريفات التابع داخل الصنف دون تلويث فضاء الاسم الخارجي، بينما يرى آخرون أن هذا أسلوب فوضوي وأصعب في القراءة، وأنت حر في اختيار أي الأسلوبين تفضل. إنشاء النسخ تُنشأ نسخ الأصناف باستخدام كلمة new المفتاحية كما يلي: <script type=text/JavaScript> var anInstance = new MyClass(42); </script> مما ينشئ نسخةً جديدةً اسمها anInstance. إرسال الرسائل لا يختلف إرسال الرسائل في جافاسكربت عن اللغات الأخرى، إذ نستخدم الصيغة النقطية: <script type=text/JavaScript> document.write("The attribute of anInstance is: <BR>"); anInstance.printIt(); </script> الوراثة وتعددية الأشكال يمكن استخدام آلية النمذجة الأولية في جافاسكربت للوراثة من صنف آخر -على عكس VBScript-، مع أنها أعقد من تقنية بايثون لكن يمكن التعامل معها وضبطها، لكنها ليست منتشرةً بين مبرمجي جافاسكربت، إن أساس الوراثة في جافاسكربت هو الكلمة المفتاحية prototype التي استخدمناها في التمرير في الشيفرة أعلاه، حيث يمكن إضافة مزايا إلى كائن ما بعد تعريفه، كما يلي: <script type="text/javascript"> function Message(text){ this.text = text; this.say = function(){ document.write(this.text + '<br>'); }; }; msg1 = new Message('This is the first'); msg1.say(); Message.prototype.shout = function(){ alert(this.text); }; msg2 = new Message('This gets the new feature'); msg2.shout(); /* msg1 وبالمثل بالنسبة لـ ...*/ msg1.shout(); </script> الملاحظة الأولى: أضفنا تابع alert جديد باستخدام prototype بعد إنشاء نسخة msg1 للصنف، غير أن الخاصية كانت متاحةً للنسخة الحالية ونسخة msg2 التي أنشئت بعد الإضافة، أي أن الخاصية الجديدة تضاف إلى جميع نسخ Message الحالية والجديدة، وتؤدي خاصية النمذجة الأولية هذه إلى إمكانية تغيير سلوك كائنات جافاسكربت المضمَّنة، بإضافة مزايا جديدة أو تغيير الطريقة التي تتصرف بها المزايا الحالية، لذا استخدمها بحرص إذا لم ترد أن تضيع وقتك مع زلات برمجية يصعب تعقبها. ومع ذلك لاستخدام prototype آليةً لإضافة وظائف إلى الأصناف الحالية عيوبه، التي منها تغيير سلوك النسخة الحالية، وتغيير تعريف الصنف الأصلي. ويوجد أسلوب تقليدي أكثر من الوراثة يمكن استخدامه، كما يلي: <script type="text/javascript"> function Parent(){ this.name = 'Parent'; this.basemethod = function(){ alert('This is the parent'); }; }; function Child(){ this.parent = Parent; this.parent(); this.submethod = function(){ alert('This from the child'); }; }; var aParent = new Parent(); var aChild = new Child(); aParent.basemethod(); aChild.submethod(); aChild.basemethod(); </script> يجب أن نلاحظ أن كائن child هنا له وصول إلى basemethod، دون أن يُعطى ذلك الوصول صراحةً، وإنما يرثه من الصنف الرئيسي بحكم أسطر الإسناد/الاستدعاء داخل تعريف الصنف Child: this.parent = Parent; this.parent(); وبهذا نكون ورثنا basemethod من الصنف الرئيسي Parent. يمكن استخدام نفس حيلة التفويض التي استخدمناها في VBScript، كما يلي: <script type=text/JavaScript> function noReturn(){ this.parent.printIt(); }; function returnValue(){ return this.parent.getAttribute(); }; function newMethod(){ document.write("This is unique to the sub class<BR>"); }; function SubClass(){ this.parent = new MyClass(27); this.aMethodWithNoReturnValue = noReturn; this.aMethodWithReturnValue = returnValue; this.aNewMethod = newMethod; }; var inst, aValue; inst = new SubClass(); // عرِّف الصنف الرئيسي document.write("The sub class value is:<BR>"); inst.aMethodWithNoReturnValue(); aValue = inst.aMethodWithReturnValue(); inst.aNewMethod(); document.write("aValue = " + aValue); </script> سنرى استخدام الكائنات والأصناف في دراسات الحالات والفصول التالية، ورغم أنه من الصعب أن يرى المبرمج المبتدئ كيف أن هذه البنية المعقدة تسهل كتابة وفهم البرامج، إلا أننا نأمل أن يتضح هذا المفهوم إذا رأيت استخدام الأصناف في البرامج الحقيقية، على أن ذلك ليس له فائدة كبيرة في البرامج الصغيرة، وإنما سيجعلها أعقد وأطول، لكن كلما زاد حجم البرنامج -أكثر من 100 سطر مثلًا-، فستعين الأصناف والكائنات على تنظيمه وتقليل كمية الشيفرات المكتوبة، ومن المهم أن تعلم أنه من الممكن تعلم البرمجة وكتابة برامج دون الحاجة إلى مفهوم البرمجة الكائنية التوجه أصلًا، فكم من مبرمج كتب برامج دون إنشاء صنف واحد طيلة حياته، لكن إذا استطعت استيعابها فإن فيها مزايا وتقنيات قويةً ومفيدةً. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: تغلِّف الأصناف البيانات والدوال في كيان واحد. تشبه الأصناف قاطعات البسكويت، حيث تُستخدم لإنشاء النسخ أو الكائنات. تتواصل الكائنات من خلال إرسال رسائل إلى بعضها البعض. عندما يستقبل كائن ما رسالةً فإنه ينفذ تابعًا موافقًا لها. التوابع هي دوال تُخزَّن مثل سمات للصنف. تستطيع الأصناف أن ترث التوابع والبيانات من أصناف أخرى، مما يسهل توسيع إمكانيات الصنف دون تغيير الصنف الأصلي. تعددية الأشكال هي القدرة على إرسال نفس الرسالة إلى عدة أنواع مختلفة من الكائنات، وسيستجيب كل منها بطريقته الخاصة. التغليف وتعددية الأشكال والوراثة كلها خصائص للغات البرمجة كائنية التوجه. تسمى لغة VBScript لغةً كائنية الأساس، لأنها لا تدعم الوراثة وتعددية الأشكال دعمًا كاملًا، رغم دعمها للتغليف. ترجمة -بتصرف- للفصل السابع عشر: Object Oriented Programming من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: البرمجة الحدثية Event Driven Programming المساقة بالأحداث المقال السابق: التعابير النمطية في البرمجة التوابع السحرية (Magic Methods) في PHP البرمجة كائنية التوجه (Object Oriented Programming) في PHP البرمجة كائنية التوجه (Object Oriented Programming) في لغة سي شارب #C تطبيق البرمجة كائنية التوجه في لغة سي شارب #C - الجزء الثالث
  20. استخدام بايثون سنفترض أنك قد ثبّتّ إحدى إصدارات بايثون على حاسوبك، فإذا لم تفعل فاذهب إلى موقع بايثون واجلب النسخة الأحدث منها واتبع إرشادات التثبيت على حاسوبك، لاحظ أن بايثون متاحة لأغلب أنواع الحواسيب المتوفرة في السوق، وستجد ملفات تثبيت لنسختي 64 بت و 32 بت من ويندوز، وكذلك نظام MacOS؛ أما لينكس فستجدها من خلال مدير الحزم في توزيعتك، فإذا لم تكن تعلم معمارية حاسوبك فاختر نسخة 32 بت، وانتبه عند التثبيت إلى خيار إضافة بايثون إلى Path، وهو متغير بيئة سنحتاج أن نضيف بايثون إليه كي يراها ويندوز في سطر الأوامر، بالشكل التالي: أما إذا لم تفعل ذلك أو نسيته أو لم تكن نسخة التثبيت تحتوي على ذلك الخيار، فاتبع الإرشادات التي نذكرها في الفقرة التالية. سطر أوامر ويندوز لقد بدا منذ كتابة هذه السلسلة -بنسخته الأجنبية لأصلية- أن العديد من مستخدمي ويندوز ليسوا معتادين على التعامل مع سطر أوامر MS Dos، لذا سنشرح كيف يمكن الوصول إلى تلك الأداة دون الاستغراق في التفاصيل غير الضرورية. توجد عدة طرق للوصول إلى سطر الأوامر أبسطها الضغط باستمرار على زر ويندوز وحرف R من أجل فتح نافذة Run، ثم كتابة cmd في مربع الحوار الذي سيظهر لك ثم الضغط على OK، وهنا يجب أن ترى نافذةً سوداء فيها نص أبيض مثل هذا: C:\WINDOWS> يشير السطر أعلاه إلى المجلد الذي نحن فيه، فإذا كتبنا DIR وضغطنا على زر الإدخال Enter؛ فستعرَض لنا قائمة بجميع الملفات التي في ذلك المجلد؛ أما إذا كتبنا python فيجب أن نرى المحث ‎‎>>>‎ الخاص ببايثون. قد لا تستطيع CMD العثور على بايثون بسبب بعض إصداراته الأخيرة التي لم تأتي بتلك الإعدادات، ولهذا فإنا لم تستطع إيجادها فستحتاج إلى ضبط متغير بيئة اسمه Path، وذلك بفتح مدير الملفات في ويندوز إما بالطريقة العادية، أو بضغط زر ويندوز مع حرف E (لفتح المتصفح)، ثم الذهاب إلى قسم This PC، والنقر بالزر الأيمن لاختيار Properties التي ستفتح نافذة About الخاصة بحاسوبك، والتي تحوي المعلومات الأساسية عنه. ستجد في تلك الصفحة خيار Advaned System Settings، اضغط عليه لتفتح لك نافذة أخرى ثم اختر تبويب Advanced. سترى زر Environment Variables في أسفل النافذة، اضغط عليه لتذهب إلى نافذة جديدة، وسترى أن Path معرَّف بالفعل كمتغير للنظام. اختره ثم انقر على زر Edit في يمين النافذة. انتبه في هذه الخطوة لئلا تحذف المسار الموجود بالخطأ، فإذا مسحت شيئًا من غير قصد فاضغط زر Esc في لوحة المفاتيح، أو استخدم زر Cancel في النافذة المفتوحة لتخرج منها وتعيد المحاولة. اذهب إلى نهاية الحقل Variable Value وأضف فاصلةً منقوطة ;، ثم المسار الكامل لمجلد بايثون التنفيذي لديك، بعد ذلك اضغط زر الإدخال Enter لتكتمل العملية، فإذا لم تعرف المسار الكامل إلى بايثون فابحث في مدير الملفات عن الملف python3.exe، وستكون محتويات العمود In Folder الذي في شاشة البحث هي المسار الكامل، وقد تضطر إلى إعادة التشغيل كي يعتمد نظام التشغيل الإعدادات الجديدة. اكتب python في سطر الأوامر لنظام تشغيلك من أي مجلد شئت وسترى المحث الثلاثي لبايثون، ونستطيع من هنا كتابة CD إلى المجلد الحامل للسكربت الخاص بنا لننتقل إليه -حيث تشير CD إلى Change Directory-، كما ستجد قائمةً من الأوامر المتاحة التي يمكن كتابتها في سطر الأوامر في نظام المساعدة المدمج في CMD نفسها، من خلال كتابة help في سطر الأوامر؛ أما إذا أردت معرفة المزيد من العلومات عن أحد الأوامر، فاكتب اسم الأمر متبوعًا بـ ‎/?‎، فإذا أردنا مثلًا عرض صفحة المساعدة الخاصة بالأمر DIR فسنكتب ما يلي: C:\WINDOWS> DIR /? أخيرًا يمكن إنشاء اختصار على سطح المكتب بالنقر بالزر الأيمن على سطح المكتب، ثم اختيار جديد New، ثم اختصار Short-cut، واكتب cmd في صندوق الموقع location داخل صندوق الحوار الذي يظهر لك، ثم انقر على التالي Next، ثم غير الاسم إلى شيء مثل Command Prompt أو نحوها. حين تنتهي انقر على Finish لتظهر أيقونة جديدة على سطح المكتب مثل اختصار إلى سطر الأوامر. خذ وقتك في استعراض هذه الأداة، فرغم أنها قد تبدو بدائيةً إلا أنها أقوى مما تتخيل، وخاصةً في إنجاز المهام المتكررة، على عكس الأدوات ذات الواجهة الرسومية مثل مدير الملفات، حيث يمكنك قراءة المزيد عنها في Computer Hope للبدء في تعلمها. عودة إلى بايثون بما أن مستخدمي ويندوز قد ثبتوا بايثون باتباع الخطوات السابقة، فسنفترض أن مستخدمي لينكس متعودون على استخدام الطرفية، أما مستخدمي نظام ماك فيمكنهم تشغيل برنامج الطرفية بالنقر على الأيقونة كالمعتاد، وهنا يجب أن يظهر محث بايثون كما يلي: Python 3.6.2 (default, Jul 29 2017, 00:00:00) [GCC 4.8.4] on linux Type "copyright", "credits" or "license()" for more information. >>> وفي خيار بديل لسطر الأوامر ذاك؛ قد تجد اختصارًا إلى شيء اسمه IDLE، أو Python GUI في قائمة ابدأ لديك، وهو بيئة برمجة مخصصة لبايثون، وتوفر كثيرًا من الأدوات والأوامر المفيدة للمبرمجين، فإذا شغلته بدلًا من سطر الأوامر فستحصل على نافذة مستقلة لسطر الأوامر مع بعض الألوان المميزة للخطوط، وقد كتب Danny Yoo دليلًا مفصلًا لهذه البيئة يمكنك قراءته والاطلاع عليه إذا أردت استخدامه بدلًا من سطر الأوامر العادي، وهو يكرر بعض المعلومات التي ذكرناها من قبل، لكن تكرار التعليم لا يضر، كما تستطيع الاطلاع على التوثيق الرسمي لبيئة IDLE كذلك إن شئت. أما إذا كنت تفضل التدريب المرئي بالفيديو، فهناك الكثير من الفيديوهات المتعلقة بالبرمجة على يوتيوب، ويُرى أن تعلم المفاهيم واستخدام الأدوات من الفيديو أمر ممكن، شرط أن توقِف الفيديو مع كل سطر أوامر يُكتَب كي تتابع الشرح جيدًا، كما يوصى بكتابة الشيفرة وتشغيلها بنفسك لتتذكر ما تتعلمه، لذا فإن أردت مشاهدة الفيديو لفهم المبدأ فلا بأس، لكن عد إلى هنا مرةً أخرى واقرأ حول ذلك المفهوم واكتب الشيفرة وجربها بنفسك، ثم عدل فيها وجرب إلى أن تصل إلى توقع التغييرات التي ستحدث، وتلك هي الطريقة الوحيدة لتعلم البرمجة في رأيي. المثير في بيئة IDLE أنها برنامج مكتوب ببايثون، فهي تبين لك قوة اللغة بمثال حي، وتوضح ما يمكن تنفيذه بها؛ أما إذا حصلت على بايثون من ActiveState أو كنت قد حمّلت نسخًا مخصصةً لويندوز -مثل حزمة PyWin32-؛ فيمكنك الوصول إلى بيئة برمجة رسومية أخرى تشبه IDLE لكنها أكثر أناقةً منها تسمى Pythonwin. لا شك أن كلا البيئتين تسهلان البرمجة أكثر من سطر الأوامر العادي، لكننا نفضل استخدام الأدوات البسيطة في بداية التعلم لإدراك المفاهيم التي نشرحها إدراكًا أعمق. كلمة حول رسائل الخطأ سترى أثناء كتابة التعليمات البرمجية ببايثون رسائل خطأ لا محالةً، وستبدو مثل هذه: >>> print( 'fred' + 7 ) Traceback (most recent call last): File "<input>", line 1, in ? TypeError: cannot concatenate 'str' and 'int' objects لا تشغل بالك بالمعنى الدقيق لهذه الرسالة الآن، وإنما نريدك أن تنظر إلى هيكلها، فسطر ‎'>>> print ...'‎ مثلًا هو السطر الخاطئ، أما السطران التاليان فيصفان مكان الخطأ، وقد تتكون رسالة الخطأ من عدة أسطر في البرامج المعقدة، فقد تقترح كلمة Traceback مثلًا أن الرسالة تتضمّن أثرًا أو سجلًا لكل ما كان البرنامج يفعله عند وقوع الخطأ، وقد يكون هذا مربكًا للمبتدئين، لكن ثق أنك مع الخبرة ستسعد بوجود رسالة الخطأ تلك، وستعلم أن الأسلوب الأمثل لقراءتها حينئذ سيكون من الأسفل، وتصعد لأعلى بقدر حاجتك من الرسالة. نعود إلى رسالة الخطأ السابقة حيث يشير ‎'line 1 in ?'‎ إلى السطر رقم 1 في التعليمة التي نكتبها، فلو كان برنامجًا أطول وكان مخزّنًا في ملف مصدري فسيحل اسم الملف الحقيقي محل <input>، بينما يخبرنا السطر ‎'TypeError...'‎ بالخطأ الذي يراه المفسر، وقد يوجد أحيانًا محرف إقحام ^ يشير إلى الجزء الذي تراه بايثون خطأً، لكن هذا التقرير يكون غير صحيح في العادة، فقد يكون الخطأ الحقيقي في مكان سابق للموضع الذي أشارت إليه بايثون، أو حتى قبله بسطر أو سطرين، فالحواسيب آلات غبية بأي حال كما قلنا من قبل. تُستخدم بيانات الأخطاء تلك لمعرفة ما يحدث في الشيفرة التي بين أيدينا، وقد يكون سبب الخطأ البرمجي بشريًا في الغالب، فرغم أن الحواسيب آلات غبية، إلا أنها آلات غاية في الدقة، فلعلنا أخطأنا في كتابة كلمة أو تعليمة أو نسينا علامة اقتباس أو فاصلةً منقوطةً مثلًا، ولدينا عمومًا ثلاثة أنواع من الخطأ التي سنواجهها: الخطأ اللغوي syntax error، وهو يعني أن بايثون لا ترى أن ما أُدخل إليها صالح، وقد يكون سببه نسيان علامة ترقيم أو خطأً في هجاء كلمة. خطأ وقت التشغيل runtime error، وذلك حين يكون البرنامج صالحًا لكن لا يمكن تنفيذه لسبب ما، كما في محاولة تنفيذ عملية غير مسموح بها أو غير صالحة، مثل طلب قراءة ملف غير موجود. خطأ دلالي semantic، حيث يعمل البرنامج ولا تظهر أي رسالة خطأ، لكنه يخرج لنا مخرجات خاطئةً غير التي يفترض به إخراجها، فإذا كتبنا مثلًا برنامجًا ليخبرنا بعدد كلمات الملف الذي تقرؤه الآن، وأخرج لنا أنه يحوي خمس كلمات فقط، فستكون هذه النتيجة خاطئةً قولًا واحدًا، فهنا يكون خطأ البرنامج دلاليًا. ستكون أغلب الأخطاء التي تتعرض لها في البداية أخطاءً لغويةً أو أخطاء وقت تشغيل إلى أن تبدأ بتصميم برامجك الخاصة، فحينها سترتكب أخطاء دلالية، وتسمى تلك العملية حينئذ بالتنقيح debugging، وتُسمى الأخطاء التي سترتكبها آنذاك بالزلات البرمجية bugs، لكن الترجمة الحرفية لاسمها الأجنبي bug هي عثة، وهي حشرة صغيرة سميت الأخطاء البرمجية باسمها لأسباب تاريخية، فقد كانت أولى الأخطاء التي حدثت في الحواسيب الأولى بسبب عثة علقت داخل الحاسوب وتسببت في حرق بعض داراته الكهربائية، وعلى الرغم أن الكلمة نفسها قد استُخدمت للدلالة على الأخطاء البرمجية قبل هذا بعدة عقود، لكنها لم تثبت إلا مع تلك الحادثة، لكننا سنستخدم اصطلاح الزلات البرمجية لقربها من المفهوم العربي للفعل ذاته. وبالعودة إلى الخطأ الذي ارتكبناه في المثال السابق والذي تسبب في إخراج رسالة الخطأ لنا، فقد كان محاولة إضافة عدد إلى سلسلة محارف، وهو خطأ دلالي، لكنه ينتج لنا خطأ وقت تشغيل أيضًا، فليس هذا مسموحًا لك في بايثون، لذا كانت رسالة الخطأ تمثل اعتراضًا من اللغة على ما فعلناه، فأخبرتنا أن هناك TypeError، وسنتحدث عن هذه الأنواع في مقال لاحق من هذه السلسلة. وبغض النظر عن الأداة التي تريد استخدامها سواء كانت سطر الأوامر أو بيئة IDLE أو Pythonwin، فنحن الآن جمعنا عدتنا وجاهزون للبدء في إنشاء بعض البرامج البسيطة باستخدام بايثون. جافاسكربت إذا أردنا إنشاء برامج جافاسكربت في متصفح، فسنحتاج إلى مزيد من الإجراءات التي علينا تنفيذها، حيث سنحتاج مثلًا إلى إنشاء ملف HTML نستطيع تحميله إلى متصفح، وهذا الملف لا يحوي إلا نصًا مجردًا نستطيع إنشاءه في محرر نصي بسيط مثل Notepad أو أي محرر نصي آخر، ثم حفظه بالامتداد ‎.htm أو ‎.html، وسيبدو بالشكل الآتي: <html> <body> <script type="text/javascript"> document.write('Hello World\n'); </script> </body> </html> سيكون الجزء الواقع بين بداية الوسم <script> ونهايته هو برنامجنا، ولن تعرض جميع وسوم HTML في كل مرة أثناء شرحنا في هذه السلسلة، لذا عليك أن تنسخ هذا الملف في كل مرة مثل قالب ثم تستبدل الشيفرة التي تريد تجربتها بما هو موجود بين الوسمين <script> و‎</script>‎، ثم افتح ملف HTML ذاك في متصفح ويب عن طريق النقر عليه في مدير ملفاتك، يجب أن يشغّل نظامك عندئذ برنامج المتصفح ويحمّل الملف الذي سيتسبب بالتبعية في تنفيذ برنامجنا. VBScript يمكن القول أن VBScript هي نفسها جافاسكربت لكن مع استبدال الاسم "vbscript" الذي في type=‎ بالنص القديم الموجود "javascript"، كما يلي: <html> <body> <script type="text/vbscript"> MsgBox "Hello World" </script> </body> </html> لاحظ أن متصفح إنترنت إكسبلورر الخاص بمايكروسوفت هو الوحيد القادر على تشغيل VBScript، أما المتصفحات الأخرى فلا تدعم إلا جافاسكربت بما في ذلك متصفح Edge الخاص بويندوز، والذي استبدلت إنترنت إكسبلورر به، لذا يبدو أن أيام VBScript صارت معدودةً. أخطاء VBScript وجافاسكربت سنحصل على صندوق حوار في كل من جافاسكربت وVBScript يخبرنا برقم السطر الذي فيه الخطأ، كما سيكون لدينا عدة أخطاء غامضة غير معروفة، ويجب معاملة رقم السطر المذكور بأنه قد لا يكون دقيقًا في الغالب كما فعلنا مع بايثون، وسنحتاج بعد إصلاح الخطأ إلى إعادة تحميل الصفحة التي هو فيها. توجد في المتصفحات أدوات تنقيح متقدمة وموجهة للمطورين المحترفين، لكنها مخبأة داخل المتصفحات ولا تناسب احتياجاتنا الحالية بعد. خاتمة بغض النظر عن اللغة التي ستستخدمها في متابعة الشرح في هذه السلسلة، فنرجو أن تخرج من هذا المقال وأنت تعلم أنك تستطيع بدء بايثون بكتابة python في سطر الأوامر، وألا تخشى رسائل الخطأ، بل اقرأها بعناية، فهي تعطينا عادة المفاتيح التي نحتاجها لإصلاح الخطأ الواقع في البرنامج، غير أنها لا زالت مجرد مفاتيح، فإذا شككت في دقتها فانظر إلى الأسطر السابقة للسطر الذي تخبرك أن الخطأ فيه. ترجمة -بتصرف- للفصل الثالث من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: التسلسلات البسيطة في البرمجة المقال السابق: ما هي البرمجة؟ تعلم البرمجة ما هي البرمجة ولماذا تصبح مبرمجًا
  21. سنغطي في هذا المقال من سلسلة تعلم البرمجة: تاريخ موجز للويب. أساسيات بروتوكول HTTP. معماريات الويب وأطر العمل فيه. دور كل من HTML و CSS وجافاسكربت وبايثون. تاريخ موجز للويب ابتكر تِم برنرز-لي Tim Berners-Lee الشبكة العالمية -الوب- لحل مشكلة واجهته هو وزملاؤه في CERN، وهي مشكلة مشاركة المستندات فيما بينهم، فقد كان لديهم مستندات كثيرة في مواقع مختلفة وبصيغ مختلفة، ويحتاج كل منها إلى مفاهيم أو مواد موجودة في مستندات أخرى بعيدة، وكان الكثير من تلك المستندات مشاريع جاريةً يعمل عليها عدة أشخاص معًا. أدرك برنرز-لي أن هذه المشكلة قد تُحل باستخدام تقنية موجودة آنذاك اسمها النصوص الفائقة أو المتشعبة Hypertext، وهي تقنية قديمة يعود تاريخها إلى ما قبل الحواسيب الحديثة!، فعكف يدرس المشكلة وينظر في حلول النصوص الفائقة الممكنة، فوجدها غالية ومغلقة المصدر، أو لا تستطيع العمل إلا على حاسوب واحد، فكانت المساهمة التي قدمها لحل هذه المشكلة هي أخذ فكرة النصوص الفائقة وتطويرها لتعمل عبر شبكة، مما مكّن العاملين من التعاون على مشروع واحد في نفس الوقت، والوصول إلى نفس المستندات من أماكن متفرقة، من خلال السماح للمستخدم من الوصول إلى أي حاسوب متصل بالشبكة، فصارت المكتبة الكبيرة مثل مستند عملاق تتصل فيه جميع الملفات ببعضها وتتكامل فيما بينها، مثل شبكة عنكبوتية كبيرة من المعلومات. النصوص المتشعبة ولغة HTML والمحتوى الثابت بنى برنرز-لي شكلًا من أشكال نظم النصوص المتشعبة، وقد كانت لديه في نفس الوقت خبرة بالإنترنت الموجود آنذاك والمفاهيم التي بني عليها، لذا كانت الخطوة المنطقية التالية هي دمج الفكرتين معًا، فابتكر عدة أجزاء تشكل في مجموعها الويب الذي نعرفه اليوم. واحتاج مفهوم النص المتشعب إلى آلية لربط المستندات معًا، فابتكر لي صيغةً نصيةً أو لغةً توصيفيةً سماها لغة توصيف النصوص الفائقة Hypertext Markup Language أو HTML اختصارًا، مبنيةً على معيار موجود من قبل اسمه لغة التوصيف المعيارية العامة Standard Generalised Markup Language أو SGML اختصارًا، وتُكتب صفحات الويب الحالية في أبسط صورها بلغة HTML أو XHTML -وهي صورة أخرى تتوافق مع HTML-، يدويًا أو بواسطة برنامج حاسوبي، وتعرض المتصفحات صفحاتها من خلال تفسير وسوم HTML تلك وإخراج المحتوى المنسَّق بها على شاشة المستخدم، ويمكن الرجوع إلى توثيق موسوعة حسوب للغة HTML للمزيد عن هذه اللغة. استطاع لي بعد كتابة هذه اللغة أن ينشئ مستندات فائقةً -أو تشعبيةً وهو مصطلح آخر لوصف مستندات HTML- وإن كانت بسيطةً نسبةً إلى الموجود الآن، أتاحت تنسيق الصفحات، وإدراج الصور والروابط إلى مستندات أخرى، لاحظ أننا لم نتعرض حتى الآن لمفهوم الشبكات، فكانت الخطوة التالية هي تمكين الوصول إلى تلك المستندات من حواسيب أخرى عبر الشبكة، وقد تطلب ذلك تعريف صيغة قياسية لعناوين تلك المستندات وذلك المحتوى، وهو ما صار يُعرف فيما بعد باسم المحدد الموحد للموارد Uniform Resource Locator أو URL اختصارًا، يشير أول جزء منه إلى البروتوكول المستخدم، والذي يكون عادةً http أو https في حالة الويب، أما الجزء التالي فيستخدم تسميةً قياسيةً في الإنترنت لتحديد الخادم -ومنفذًا اختياريًا هو عادةً المنفذ 80 كما شرحنا في المقال السابق-، ثم يأتي الجزء الأخير وهو الموقع المنطقي logical للمحتوى على الخادم، ونستخدم كلمة المنطقي هنا لأن هذا الموقع قد لا يكون حقيقيًا أصلًا، وإنما متعلق بموقع ثابت ما يعرفه الخادم، وإن كان يبدو مثل مسار مطلق لمجلد في نظام يونكس، وقد يترجم الخادم الموقع إلى استدعاء تطبيق أو صورة أخرى من مصادر البيانات، لذا إذا نظرنا إلى الرابط الكامل للصفحة http://www.alan-g.me.uk/l2p2/tutweb.htm مثلًا، فسنجد أنه يتكون مما يلي: table { width: 100%; } thead { vertical-align: middle; text-align: center; } td, th { border: 1px solid #dddddd; text-align: right; padding: 8px; text-align: inherit; } tr:nth-child(even) { background-color: #dddddd; } البروتوكول عنوان IP المنفذ الموقع http://‎ www.alan-g.me.uk ‎:80 ‎/l2p2/tutweb.htm لكن المشكلة التي تأتي مع النصوص التشعبية الثابتة هي أن نمط تنسيق الصفحات هذا كان للقراءة فقط، فلا يمكن التعديل عليه أو التفاعل معه، وقد أراد لي طريقةً للتفاعل الديناميكي مع المحتوى. الصفحات الديناميكية وواجهة البوابة المشتركة CGI حُلّت مشكلة توفير المحتوى الديناميكي بإلحاق البيانات بنهاية الرابط فيما يعرف بالسلسلة المرمَّزة encoded string، أو السلسلة المهرَّبة escaped string، وهي تلك السلاسل الطويلة من الأحرف والأرقام ومحارف النسبة المئوية التي تكون في شريط عنوان المتصفح بعد الرابط، وتبدو للوهلة الأولى بلا معنى، وسندرسها بالتفصيل لأننا نحتاج إليها للاتصال بالمواقع الديناميكية. وتعطينا إمكانية التفاعل مع المحتوى هذه عدة مزايا، لعل أهمها توفير وصول آمن للصفحات من خلال مطالبة المستخدم بإدخال اسم مستخدم وكلمة مرور، أو الطلب من المستخدمين تسجيل الاهتمام بالصفحات قبل منحهم صلاحية الوصول إليها، وتُستخدم نفس المزية في التقاط أسماء المستخدمين، كما تُستخدم لاستلام بيانات بطاقات الائتمان والاختيار من قوائم المنتجات، وقد مهدت هذه المزايا الطريق لمجال التجارة الإلكترونية والتسوق عبر الإنترنت. أما التقنية المستخدمة في إنشاء المحتوى الديناميكي للويب فتسمى واجهة البوابة المشتركة CGI، وتمتاز بسهولة تنفيذها وحياديتها اللغوية بحيث لا تتعلق بلغة بعينها، فقد كُتبت تطبيقات الويب الأولى المبنية على CGI بلغات مثل C و C++‎ وملفات باتش لنظام DOS -أو batch files- وسكربتات صدفة يونكس، إلا أنها لم تلبث أن صارت تُكتب بلغة Perl وحدها بسبب القدرة الكبيرة لهذه اللغة على معالجة النصوص، ووجود وحدة CGI library لمعالجة طلبات الويب، وتحتوي بايثون أيضًا على وحدة cgi التي تُستخدم لبناء تطبيقات ويب ديناميكية، وإن كانت بسيطة، وسندرس ذلك في مقال لاحق. كل هذا العمل يضع إمكانيات التفاعل مع المستخدمين على عاتق الخادم، لذا صار جليًا أننا نحتاج إلى نوع من البرمجة داخل المتصفح، لأننا نريد سرعة الاستجابة في هذا التفاعل، وقد وفر متصفح Netscape ذلك في صورة جافاسكربت -و VBScript في متصفح إنترنت إكسبلورر-. وبهذه البرمجة النصية scripting languages -التي لا تحتاج إلى تصريف compiling قبل تشغيلها- صار المتصفح ينشئ نموذجًا برمجيًا للمستند داخل ذاكرته، فيما يسمى بنموذج كائن المستند Document Object Model أو DOM اختصارًا -وقد شاعت هذه التقنية إلى أن صارت معيارًا موحدًا على مستوى المتصفحات- ثم تستطيع اللغات النصية scripting languages أن تبحث في ذلك النموذج عن مكونات المستند، مثل الفقرات أو الجداول، وتعدلها، بتغيير لونها مثلًا أو موضعها في الصفحة، وقد كان ذلك مفيدًا في التحقق من صحة مدخَلات المستخدم مثلًا قبل إرسال البيانات إلى الخادم. غير أننا نواجه مشكلةً في البرمجة القياسية لواجهة البوابة المشتركة CGI، وهي إنشاء خادم الويب لعملية جديدة لكل طلب، مما يبطئ التنفيذ ويستهلك الموارد، خاصةً على الحواسيب التي تعمل بنظام تشغيل ويندوز، وكان من الطبيعي ظهور آليات أكثر تطورًا تستغل بروتوكول CGI، مع تمكينها لخوادم الويب من معالجة الطلبات بكفاءة أكبر في نفس الوقت. من النادر كتابة تطبيقات الويب باستخدام هذا البروتوكول حاليًا، وقد فقدت Perl موقعها في كونها لغةً مفضلةً للويب في ظل وجود تقنيات مثل صفحات الخوادم النشطة Active Server Pages أو ASP اختصارًا، وصفحات جافا للخوادم Java Server Pages أو JSP، وكذلك PHP وغيرها، وسنلقي نظرةً على تقنية من تلك التقنيات المبنية على بايثون في مقال لاحق. أما الآن فنسنلقي نظرةً على الهيكل العام لتطبيقات الويب، والتقنيات المستخدمة في كل مرحلة، قبل أن نكتب تطبيقات ويب على الخادم، وسنبدأ بإلقاء نظرة على البروتوكول الأساسي للشبكة، والذي طوره برنرز-لي لتمكين عملاء النصوص الفائقة من التواصل مع خوادم المستندات. بروتوكول النصوص التشعبية HTTP يجب أن نفهم آلية عمل الويب قبل أن نكتب برامج له، وبالتالي لا بد أن نعرف ما هو برتوكول النصوص الفائقة أو التشعبية، وهو بروتوكول ذو أساس نصي يتصل من خلال مقابس، بنفس الطريقة التي رأيناها في مقال برمجة الشبكات من قبل، ويوفر عدة رسائل: GET: لقراءة المستند من الخادم. POST: لإرسال البيانات إلى الخادم. PUT: لإنشاء مستند جديد على الخادم، أو بديل له. DELETE: لحذف المستند من الخادم. توجد رسائل أخرى غير التي ذكرناها، لكننا ذكرنا الرسائل الأساسية المستخدمة في بناء التطبيقات، ولعل أكثرها استخدامًا GET و POST، غير أننا نستطيع أن نرى أن لدينا أساسًا من نمط CRUD التقليدي هنا، والذي يعني إنشاء Create وقراءة Read وتعديل Update وحذف Delete. فإذا تتبعنا رابط http أعلاه فسنجد أننا نحتاج إلى تعلم الكثير لنكون خبراء في هذا البروتوكول، لكن لحسن الحظ فإن مستوى المعرفة المطلوب لاستخدامه بسيط، لأن وحدات المكتبات تنفذ أغلب العمل المبني عليه، إذ يرسل عميل الويب طلب http GET، ثم يرد الخادم برسالة خطأ فيها رمز من بضعة رموز قياسية لكل منها معنىً محدد، أو بمستند HTML. ورغم إمكانية تنفيذ كل ذلك يدويًا باستخدام المقابس و السلاسل المنسقة، إلا أن الأسهل استخدام حزمة urllib الموجودة في مكتبة بايثون القياسية، وتحديدًا وحدة urlliv.requests التي تعالج إرسال الطلبات إلى الخادم. استخدام الوحدة urllib.requests لجلب صفحة ويب بسيطة نستورد urllib.request، ثم نفتح رابطًا لقراءة النتيجة، كما يلي: >>> import urllib.request as url >>> site = url.urlopen('http://www.alan-g.me.uk/l2p2/index.htm') >>> page = site.read() >>> print( page ) هذا هو كل ما نحتاج إليه، فلدينا الآن سلسلة نصية تحتوي على شيفرة HTML للصفحة الرئيسية للنسخة الإنجليزية من هذه السلسلة، ونستطيع موازنتها إن شئنا مع نتيجة استخدام View>Source في المتصفح، حيث سنرى أن لهما نفس المحتوى تقريبًا، باستثناء أن المتصفح ينسق HTML لجعلها أسهل في القراءة. يبقى أن نسأل أنفسنا ماذا نفعل بالمحتوى الذي لدينا؟ والجواب أننا بلا شك نريد استخراج معلومات منه من خلال تحليله، ويتضمن هذا التحليل في أبسط صوره البحث عن سلسلة أو تعبير نمطي ما، إذ نستطيع أن نبحث في جميع وسوم الصور مثلًا في الصفحة من خلال البحث عن السلسلة ‎'<img'‎، أو ‎'<IMG'‎، أو التعبير النمطي ‎'<img'‎ مع تعيين الراية re.IGNORECASE. غير أننا سنواجه عقبات أخرى في الممارسة العملية كما سنرى في المقال التالي، لكن قبل أن نتعرف على تحليل ملفات HTML يجب أن ننظر إلى الصورة الكبيرة للكيفية التي تُبنى بها تطبيقات الويب، حيث توجد عدة طبقات تستخدم كل منها مجموعةً من التقنيات، وهذه أبرز الخصائص اللازمة لمن يكتب برامج للويب، وهي الحاجة إلى تعلم لغات كثيرة إذا أراد أن يبني تطبيقات تصلح للسوق، وتمثل بايثون هنا جزءًا واحدًا فقط من تلك اللغات. هيكل تطبيق الويب يبدأ تطبيق الويب التقليدي بمتصفح ويب يعمل على حاسوب عميل، يرسل طلبًا عبر الشبكة إلى خادم في مكان ما، ويشغّل الخادم جزءًا من البرنامج يسمى خادم الويب -أو مستمع الويب أحيانًا- ليلتقط الطلبات، ويرسلها -إذا كانت صالحةً- إلى خادم تطبيقات application server قد يكون -أو لا يكون- جزءًا من حزمة خادم الويب، بل قد يكون على حاسوب منفصل داخل مركز بيانات كبير، يفسر خادم التطبيقات الرسالة التي استلمها، ويعيد ملف HTML ساكنًا من نظام ملفاته، أو يعالج البيانات المستلَمة، ويولّد مستند HTML جديدًا حسب الطلب، بمساعدة البيانات المخزنة في قاعدة بيانات أحيانًا، وترسَل HTML في كلا الحالتين إلى المتصفح الذي يستقبلها، ويفسرها، ثم يعرضها على شاشة المستخدم في صورة صفحة ويب منسقة. تختلف التقنيات المستخدمة في كل مرحلة عن الأخرى، وسننظر الآن في تلك الوحدات بالترتيب. متصفح الويب Web Browser المتصفح غالبًا هو أحد المتصفحات الشهيرة، مثل كروم أو سفاري أو فاير فوكس، وسيحتوي على البرمجية اللازمة لتفسير HTML وجافاسكربت وعرض صفحة الويب على الشاشة، كما سيرسل طلبات http إلى خادم الويب، ويستلم الردود عليها. مستمع الويب Web Listener حزمة قياسية -مثل خادم Apache المعروف-، رغم وجود عدة حزم أخرى، ولا تحتوي هذه الحزمة على أي مزايا يمكن للمستخدم برمجتها، باستثناء بعض الإعدادات. خادم التطبيق Application Server تكون هذه الحزمة غالبًا حزمة خادم قياسيةً، إما متكاملةً مع مستمع الويب، أو مستقلةً بذاتها، كما في حالة حاوية Tomcat Java Server Container، أو قد تكون إطار عمل برمجي، مثل جانغو Django للغة بايثون، أو إطار فلاسك Flask الذي سندرسه لاحقًا. وخادم التطبيق -في كل من الحالات السابقة- هو المكان الذي سيكون فيه منطق التطبيق وشيفرته، ويمكن كتابته بأي لغة تقريبًا، لكننا سنكتبه ببايثون في شرحنا، وهو أيضًا المكان الذي ستخزَّن فيه موارد الويب الأخرى، مثل الصور وملفات الوسائط. ملفات HTML ملفات HTML هي ملفات نصية قياسية تُخزَّن على الخادم، وتُكتب بمزيج من لغات HTML وCSS وجافاسكربت، وربما VBScript إذا كانت في بيئة ويندوز، وسبب استخدام هذه اللغات الثلاثة مجموعةً؛ هو أن كلًا منها يؤدي دورًا مستقلًا في بناء الصفحة وجعلها قابلة للتعديل اللاحق، فتحدد لغة HTML بنية المستند، مثل العناوين والجداول والفقرات والصور وغيرها، وتوفر أوراق الأنماط المتتالية -أو التنسيقات الموروثة- CSS المظاهر الجمالية، مثل الألوان والمواضع على الصفحة والخطوط، وتتحكم في طريقة عرض عناصر HTML على الصفحة، بينما تتحكم جافاسكربت في السلوك الديناميكي للعناصر، مثل القوائم المنسدلة والعناصر القابلة للطي وغيرها، وقد استُخدمت في البداية للتحقق من البيانات، غير أن خيارات التحقق التي أتت في HTML5 حلت محلها في هذه الوظيفة. قاعدة البيانات حزمة قاعدة البيانات في الغالب حزمة قياسية مثل التي شرحناها في مقال العمل مع قواعد البيانات، وتتكون من جداول SQL واستعلاماتها وبعض الإجراءات المخزنة في أي لغة تدعمها قاعدة البيانات، ويكون الوصول إلى تلك البيانات غالبًا باستخدام واجهة برمجة التطبيقات API من شيفرة خادم التطبيق، كما رأينا في مقال قواعد البيانات سالف الذكر. ويتبين مما سبق أننا نحتاج إلى أن نتعلم HTML وCSS وجافاسكربت وبايثون وSQL أيضًا إذا أردنا بناء تطبيق ويب كامل، وكذلك كيفية إعداد الخوادم المختلفة وإدارتها، إلا أن مطوري الويب يتخصصون غالبًا إما في تطوير الواجهات الأمامية فقط، فيتعلمون اللغات التي تبني ما يراه المستخدم النهائي، مثل HTML و CSS وجافاسكربت ونحوها، أو تطوير الواجهات الخلفية فقط، فيتعلمون بايثون أو أي لغة تطوير أخرى مثل جافا و PHP وروبي Ruby وSQL (انظر مصادر التعلم وخارطة الطريق في مقال المدخل الشامل لتعلم تطوير الويب). وقد وُضعت آليات مختلفة لقولبة مهام التخصصات لتوضيح الفروق بينها، حيث يستطيع مصمم الواجهات مثلًا أن يصمم صفحات الويب، ويترك علامات markers في الشيفرة يستطيع مطور الواجهة الأمامية، وكذلك مطور الواجهة الخلفية، استخدامها لوضع بياناتهم فيها، ويفيد هذا التخصص في المهام أن مصممي الواجهات ليس عليهم تعلم التقنيات البرمجية، وبالمثل فليس على المطورين أن يشغلوا أنفسهم بأمور التصميم المرئية. سندرس في المقالين التاليين جانبًا من برمجة الويب من جانب العميل client side وجانب الخادم server side، فسنرى كيف نعالج HTML كما لو كانت في متصفح، وهذا ضروري إذا أردنا بناء قاعدة بيانات من المعلومات التي نحصل عليها من الويب، فقد نحصل على البيانات من موقعي ويب مختلفين، ونريد جمعهما معًا لتحليل الظواهر الشائعة trends، وهو ما يُعرف ببرمجة جانب العميل client side programming. أما برمجة جانب الخادم server side programming فهي التي ننشئ فيها موقع ويب فيه محتوىً ديناميكي، وسندرس تنفيذ ذلك باستخدام CGI التقليدية، إذ من الضروري فهم التقنيات الأساسية وراء هذه المهام عند العمل مع أطر العمل المتقدمة لاحقًا. ثم سندرس أحد أطر العمل الحديثة، وهو إطار فلاسك Flask، وهو إطار عمل خفيف ويسهل تعلمه، لكنه قوي بما يكفي لبناء تطبيقات عملية للبيئات التجارية، ثم نختم بنقل تطبيق دليل جهات الاتصال الذي نطوره ليكون تطبيق ويب هذه المرة. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: تُرسل الطلبات إلى خوادم الويب باستخدام طلبات http GET. يرد خادم الويب بمستند HTML. نحتاج إلى تحليل HTML لاستخراج البيانات التي نريدها. التعابير النمطية ليست أفضل أداة لتحليل HTML. توفر بايثون حزم browser وurllib وhtml لاستخدامها في برمجة جانب العميل. توفر بايثون كذلك عدة وحدات للتحليل، لعل أبرزها ElementTree. يُفضل التحكم في سلوك المتصفح من داخل صفحة الويب باستخدام جافاسكربت. ترجمة -بتصرف- للفصل الثامن والعشرين: Working With the Web من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: برمجة عملاء ويب باستخدام بايثون المقال السابق: تواصل البرامج والعمليات البرمجية عبر الشبكة المدخل الشامل لتعلم تطوير الويب المدخل الشامل لتعلم علوم الحاسوب دليلك الشامل إلى تعلم البرمجة كيف تستخدم أدوات المطوِّر في المتصفحات الحديثة كيف تستخدم أدوات المطوِّر في المتصفحات الحديثة - جافاسكربت - أكاديمية حسوب (hsoub.com)
  22. سنغطي في هذا المقال من سلسلة تعلم البرمجة ما يلي: أساسيات أطر عمل الويب. استخدام إطار Flask في مثال Hello World. بناء برنامج دليل جهات الاتصال في تطبيق ويب. أطر عمل الويب Web Frameworks تُعد البرامج التي تعتمد على الواجهة CGI التي تحدثنا عنها في المقال السابق وسيلةً فعالةً لبناء مواقع ويب تفاعلية، إلا أن لها عدة مشاكل لا يمكن تجاهلها، لعل أخطرها بدء الخادم عمليةً جديدةً في كل طلب، مما يسبب بطءً واستهلاكًا للموارد، لذا لا يمكن استخدامها في التطبيقات ذات العمليات الكثيرة المتزامنة، والمشكلة الثانية وجود الشيفرة وتعليمات HTML والبيانات في ملف واحد، مما يصعّب عملية الصيانة ويعرّضها للأخطاء، فقد يتسبب تعديل بسيط في HTML بأخطاء تركيبية في شيفرة بايثون، وقد جُربت عدة أساليب مختلفة للتعامل مع هذه المشاكل، إلا أن الأسلوب الذي استمر والذي سننظر فيه هو إطار عمل الويب web framework، وأشهر هذه الأطر: صفحات خوادم مايكروسوفت النشطة Active Server Pages: واختصارًا ASP، يعمل هذا الإطار جنبًا إلى جنب مع خادم ويب مايكروسوفت IIS وبيئة "‎.NET" الخاصة بها، وهذا يعني إمكانية استخدام أي لغة مبنية على "‎".NET -بما في ذلك نسخة بايثون الخاصة بها- في إطار ASP. صفحات خوادم جافا Java Server Pages: واختصارًا JSP، هي إطار عمل جافا الخاص بتطوير الويب، و هي تقنية لتوليد تطبيقات الخوادم المصغرة Servlets، التي هي عمليات خفيفة تشبه برامج CGI، لكنها أسهل في التعامل معها. إطار عمل Ruby on Rails: يشبه إطار العمل ريلز rails الخاص بلغة روبي إطار عمل Flask الخاص ببايثون، والذي سندرسه قريبًا. إطار عمل جانغو Django: يُعد جانغو أكثر أطر عمل بايثون شهرةً، خاصةً في بناء المواقع الكبيرة، وله شروحات كثيرة في كتب وتوثيقات إلكترونية، وهو غني بوحدات الإضافات plug-in modules المتاحة لتوسيعه، إلا أنه صعب التعلم موازنةً بإطار Flask. إطار العمل Flask: وهو ما سندرسه في هذا المقال، إذ يوفر جميع العناصر الأساسية الموجودة في أطر العمل، وهو سهل التعلم نسبيًا، ويمكن استخدامه ببساطة دون كثير من التعقيد الذي يشتت الانتباه عن الأفكار الرئيسية. تتمثل الفكرة الأساسية في جميع أطر عمل الويب في أنها تقلل الحمل على الخادم، باستخدام تقنيات البرمجة المتزامنة، والتي سندرسها في المقال التالي، كما تمقال المنطق logic عن شيفرة العرض presentation code، لتسهيل صيانة الموقع، حيث تسعى أحدث المعايير الصادرة عن w3c في كل من HTML5 و CSS3 إلى تحقيق هذا المقال، إذ يجب أن تُستخدم HTML حصرًا في هيكلة بناء المستند، بينما تُستخدم التنسيقات المورَّثة CSS للمظهر، من خطوط وألوان ومواضع وتحكم في رؤية العناصر أو إخفائها وغير ذلك، وبهذا تصبح برمجة الويب عملًا منظمًا يمكن صيانته، من خلال الجمع بين تلك الممارسات في كل من CSS وHTML مع أطر عمل الويب، وذلك من خلال تقنيتين رئيسيتين: توجيه نقطة النهاية endpoint routing للروابط، والتي يشار إليها أحيانًا بالربط mapping، حيث يوجَّه الجزء الأخير من الرابط من ملف إلى دالة أو تابع في إطار العمل. توفر قوالب المستندات طريقةً لإنشاء ملفات HTML ساكنة، فيها محددات للمواضع place-markers لإدراج البيانات فيها، ويمكن لدوال إطار عمل الويب أن تجهز البيانات ثم تمررها إلى محرك القالب، الذي يجلب القالب المناسب، ويدرج البيانات في محددات مواضعها لتوليد خرج HTML النهائي الذي يُعاد إلى متصفح المستخدم. سنرى استخدام كلا التقنيتين في Flask، ولأطر عمل الويب غالبًا نفس المفاهيم، رغم اختلاف تفاصيل بنائها اللغوي syntax، واصطلاحات الاستدعاء المتبعة. تثبيت Flask لا يوجد إطار عمل Flask في مكتبة بايثون القياسية، لذا يجب تثبيته إما باستخدام أداة pip التي تأتي مع بايثون، أو استخدام حزمة تنفيذية خاصة، وهو ما يُنصح به مستخدمو لينكس، خاصةً عندما يُثبت على النظام أكثر من إصدار بايثون. عند استخدام pip نفتح طرفية النظام (وقد نضطر إلى تشغيل أمر pip بصلاحيات مدير النظام، خاصةً عند تثبيت بايثون لجميع المستخدمين على الحاسوب) ونكتب فيها ما يلي: $ pip install flask يمكن التحقق منها بتشغيل بايثون، واستيراد Flask بالأمر import flask، فإذا لم نحصل على أخطاء نكون قد نجحنا. استخدام Flask في مثال Hello World يوفر إطار عمل Flask وحدة خادم ويب بسيطةً، يمكن استخدامها للاختبار والتطوير قبل نقل الشيفرة إلى منصة استضافة ويب في شبكة تابعة لشركة أو على الإنترنت، وسندرس الآن كيفية تشغيله وتوفير صفحة ويب بسيطة. صفحة ويب بسيطة لن نحتاج هنا إلى إنشاء ملف HTML كما فعلنا في حالة CGI في المقال السابق، بل سنعيد شيفرة HTML من دالة Flask، كما يلي: import flask helloapp = flask.Flask(__name__) @helloapp.route("/") def index(): return """ <html><head><title>Hello</title></head> <body> <h1>Hello from Flask!</h1> </body></html>""" if __name__ == "__main__": helloapp.run() يجب أن نشير هنا إلى بضعة أمور، حيث يُسند أول سطر بعد import flask نسخةً من كائن تطبيق Flask إلى متغير helloapp، وهو اسم عشوائي رغم أنه نفس اسم تطبيقنا، ثم نمرر المتغير الخاص __name__، الذي رأيناه في فصول سابقة، إلى التطبيق الذي يستخدمه ليعرّف الموقع الرئيسي (الجذر) لموقع الويب. أما الأمر التالي فهو الدالة التي تعالج طلب http GET، والتي تسمى index اصطلاحًا لتوافق تسمية ملف index.htm، غير أن المثير للاهتمام هنا هو المزخرِف ‎@helloapp.route("/")‎ الذي يسبقها، والذي يخبر إطار Flask أن أي طلب إلى جذر الموقع / يجب توجيهه إلى التابع التالي المسمى index في حالتنا هذه، ويمكن توجيه عدة نقاط نهاية end points إلى نفس التابع بتكديس المزخرفات decorators فوق بعضها البعض، وقد ذكرنا من قبل أن توجيه نقاط النهاية هو إحدى التقنيات المستخدمة في أطر عمل الويب، وهذه هي طريقة إطار عمل Flask لتوجيهها. تشغيل خادم ويب Flask نبدأ تشغيل شيفرة Flask التي صارت جاهزةً الآن بالطريقة المعتادة، باستدعاء ما يلي من المجلد الذي يحوي التطبيق: $ python hello.py ينبغي أن نرى رسالةً تخبرنا أن الخادم يعمل وينتظر الطلبات: * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) نستطيع الآن العودة إلى المتصفح لندخل العنوان الموجود في الرسالة: http://127.0.0.1:5000/ ستظهر رسالة "Welcome from Flask"، وبهذا نكون قد بنينا أول تطبيق ويب بإطار عمل Flask. مقدمة في القوالب تتعامل شيفرة إطار Flask التي رأيناها حتى الآن مع مشاكل توسع التطبيقات، وزيادة حجمها، وبعض الفوضى التي تسببها برمجة CGI، إلا أنها لا تستطيع مقال الشيفرة عن HTML، فلا زلنا نكتب سلاسل HTML داخل شيفرة البرنامج، ولمعالجة تلك المشكلة نستخدم قوالب Flask. والقوالب في إطار Flask ما هي إلا ملفات HTML ساكنة فيها محددات markers أو مواضع خاصة لاستقبال البيانات من التطبيق، وهي تشبه سلاسل التنسيق format strings التي في بايثون، فمثلًا نريد قالبًا يستطيع استقبال رسالة الترحيب في سلسلة، ثم يدرجها في قالب، سيكون هذا القالب كما يلي: <!doctype html> <head><title>Hello from Flask</title></head> <body> <h1>{{message}}</h1> </body> </html> إذا نظرنا إلى {{message}} فسنجد المواضع التي ذكرناها، فتلك الأقواس المزدوجة هي مواضع استقبال البيانات، والمتغير message هو اسم المتغير الذي سيدخله محرك القالب إلى HTML. نحفظ المثال السابق في ملف باسم hello.htm داخل مجلد باسم templates في مجلد المشروع، واسم القالب مهم هنا لأنه المكان الذي يتوقع إطار Flask أن يجد فيه ملفات القوالب، يتبقى الآن بعض التعديلات على شيفرة بايثون الخاصة بنا لربطها بمحرك القوالب، وسنغير الشيفرة السابقة لتكون كما يلي: from flask import Flask, render_template helloapp = Flask(__name__) @helloapp.route("/") def index(): return render_template("hello.htm", message="Hello again from Flask") if __name__ == "__main__": helloapp.run() الاختلاف الأول في تعليمة import، حيث غيرنا النمط لنستطيع استيراد الأسماء التي نحتاجها مباشرةً. نلاحظ الآن اختفاء شيفرة HTML من ملف بايثون الخاص بنا، ونمرر الرسالة مثل سلسلة عادية إلى الدالة render_template مع اسم القالب، ونترك الباقي لإطار Flask، لكننا نريد أن نضمن مطابقة الوسائط المسماة في استدعاء هذه الدالة للأسماء التي في مواضع القالب، ثم نعرف كيف نقرأ البيانات الواردة من طلبات http لنستطيع تكرار نسخة CGI التي نفذناها من تطبيق "hello user". استخدام Flask في مثال Hello User نريد الآن تعديل التطبيق ليعمل مع استمارة HTML التي استخدمناها من قبل، فنبدأ بتحويل HTML إلى قالب نرسله عند تحديد المستخدم لنقطة نهاية "hello"، ولا نحتاج إلى إضافة أية محددات خاصة إلى HTML لأننا لا ندرج أي بيانات، لكن يجب تغيير الخاصية method للاستمارة إلى "POST"، وكذلك الخاصية action لتعكس منفذ إطار Flask -الذي هو 5000- ونقطة النهاية المطلوبة للرابط، والتي هي sayhello، ثم نحفظ ذلك في مجلد templates باسم helloform.htm ليستطيع إطار Flask العثور عليه، وسيبدو بعد تلك التعديلات كما يلي: <!doctype html> <html> <head> <title>Hello user page</title> </head> <body> <h1>Hello, welcome to our website!</h1>8000 <form name="hello" method="POST" action="http://localhost:5000/sayhello"> <p>Please tell us your name:</p> <input type="text" id="username" name="username" size="30" required autofocus/> <input type="submit" value="Submit" /> </form> </body> كتابة شيفرة Flask نحتاج الآن لإضافة تابعين جديدين إلى تطبيقنا، يعرض الأول منهما قالب helloform.htm، بينما يرد الثاني على طلب إرسال الاستمارة، ونلاحظ أن الدالة الثانية ستستخدم قالب hello.htm الأصلي، ولم نضف شيئًا سوى كتابة سلسلة رسالة جديدة: from flask import Flask, render_template, request helloapp = Flask(__name__) @helloapp.route("/") def index(): return render_template("hello.htm", message="Hello again from Flask") @helloapp.route("/hello") def hello(): return render_template("helloform.htm") @helloapp.route("/sayhello", methods=['POST']) def sayhello(): name=request.form['username'] return render_template("hello.htm", message="Hello %s" % name) if __name__ == "__main__": helloapp.run() لاحظ أننا اضطررنا إلى إضافة request إلى قائمة العناصر المستورَدة لأننا نستخدمه للوصول إلى بيانات طلب http، كما عدلنا مزخرف معالج sayhello ليشير إلى أنه يستطيع معالجة طلبات النوع POST -وقد كان الافتراضي طلبات GET- حيث نستخرج بيانات username داخل الدالة من الاستمارة، وندخلها في السلسلة التي نعيدها إلى قالب hello.htm. أما معالج hello فهو أبسط من ذلك، إذ يرسل قالب helloform.htm إلى المستخدم. إذا شغّلنا الشيفرة الآن فسيعمل الخادم، وإذا كتبنا العنوان التالي: http://localhost:5000/hello فسنرى نفس الاستمارة التي كانت لدينا في مثال CGI من قبل (لاحظ أن كلمة localhost هي اسم بديل لـ 127.0.0.1، ويمكن تذكرها بسهولة أكثر)، فإذا ملأنا الاستمارة وضغطنا زر Submit؛ فستظهر لنا رسالة ترحيبية. وبهذا نكون ألغينا الحاجة إلى بدء عملية منمقالة، وبالتالي جعلنا التطبيق قابلًا للتوسيع وزيادة الحجم، كما أزلنا أي أثر لتعليمات HTML من شيفرة البرنامج لتسهيل صيانته وتعديله، وهذا غيض من فيض إمكانيات Flask، إذ يحوي الكثير من المزايا التي لم نرها بعد، فمثلًا يستطيع الاتصال تلقائيًا بقاعدة بيانات عند بدئه، وإغلاقها عندما ينتهي، كما يستطيع التحقق من أن المستخدمين سجلوا الدخول قبل تنفيذ أي تغييرات على البيانات، وهناك العديد من مصطلحات الترميز التي لم نستخدمها، والتي تعيننا في صيانة وتشغيل موقع ويب كبير، وخاصةً في نظام القولبة الذي يحوي بدوره بعض المزايا الأخرى، وسننظر في بعضها إذ سننتقل الآن إلى إنشاء واجهة ويب أمامية لقاعدة بيانات دليل جهات الاتصال الخاص بنا. دليل جهات الاتصال كتبنا في مقال العمل مع قواعد البيانات في البرمجة تطبيقًا لدليل جهات اتصال يعمل من سطر الأوامر، وسنعيد استخدام قاعدة البيانات تلك لبناء نسخة ويب مبنية على إطار Flask، وسنضيف بعض عناصر برمجة الويب الأخرى أثناء ذلك، وسيكون تطبيق ويب بسيط رغم تلك العمليات التي سننفذها، غير أنه سيوفر أساسًا كافيًا لبناء تطبيقات ويب وفهم التوثيقات والتدريبات الأخرى. إعداد المشروع لمشاريع إطار Flask عادةً بنية محددة، فهي تأخذ صورة هرمية مجلد، حيث يكون اسم المشروع في الأعلى ، متبوعًا بمجلد static للملفات الساكنة مثل الصور وملفات CSS، ومجلد templates للقوالب، وحزمة بايثون اسمها في الغالب هو اسم المشروع، والتي هي مجلد يحوي ملفًا اسمه ‎__init__.py يتحكم في ما تصدره الحزمة، كما تحتوي عادةً على ملف setup.py يُستخدم لتثبيت الحزمة إذا كانت موزَّعةً من فهرس حزم بايثون Python Package Index أو PyPI اختصارًا، وتسهل هذه الهرمية توزيع التطبيق باستخدام أدوات بايثون القياسية مثل pip. لكننا لن نوزع التطبيق في حالة دليل جهات الاتصال، لذا سنكتفي بترتيب بسيط مبني على المجلدات القياسية الثلاثة، إضافةً إلى مجلد رابع لملف قاعدة البيانات: addressbook static templates db سننسخ ملف قاعدة البيانات من المقال السابق إلى مجلد db هنا. إنشاء قالب HTML سيكون لدينا صفحة ويب واحدة تتكون من استمارة بسيطة لإدخال البيانات، فيها ثلاثة أزرار هي Create وFind وList all، حيث سيستخدم زر Create البيانات التي في الاستمارة لإضافة مدخل جديد إلى قاعدة البيانات، ويعرض زر Find قائمةً بجميع العناوين المطابقة للبيانات التي في الاستمارة، بينما يعرض زر List all القائمة الكاملة للعناوين. سنستخدم مزيةً جديدةً لمحرك القوالب، وهي القدرة على تكرار صفوف HTML وفقًا لمجموعة بيانات الدخل، وسيُدمج هذا مع عنصر HTML جديد هو وسم الجدول <table> وعائلته التي سنستخدمها لعرض قائمة العناوين. وسيبدو القالب كما يلي: <!doctype html> <html> <head> <title>Flask Address Book</title> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> h1 {text-align: center;} label { width: 20em; text-align: left; margin-top: 2px; margin-right: 2em; float: left;} input { margin-left: 1em; float: right; width: 12em;} input.button {width: 6em; text-align: center; float: left;} br {clear: all;} div.buttons {float: left; width:100%; padding: 1em;} </style> </head> <body> <header> <h1>Address Book Website</h1> </header> <div class="content"> <form name="hello" method="POST" action="http://localhost:5000/display"> <fieldset><legend>Address</legend> <label>First name: <input type="text" id="First" name="First" required autofocus/> </label> <label>Second Name: <input type="text" id="Last" name="Last" required /> </label> <br /> <label>House Number: <input type="text" id="House" name="House" /> </label> <label>Street: <input type="text" id="Street" name="Street" required /> </label> <br /> <label>District: <input type="text" id="District" name="District" /> </label> <label>Town: <input type="text" id="Town" name="Town" required /> </label> <br /> <label>Postcode: <input type="text" id="Postcode" name="Postcode" required /> </label> <label>Phone: <input type="text" id="Phone" name="Phone" /> </label> </fieldset> <div class="buttons"> <input class="button" type="submit" value="List All" /> <input class="button" type="submit" name="Filter" value="Filter" /> <input class="button" type="submit" name="Add" value="Add" /> <input class="button" type="reset" value="Clear" /> </div> </form> <br /> <div class="data"> <table id="addresses"> <tr> <th>First</th> <th>Second</th> <th>House#</th> <th>Street</th> <th>District</th> <th>Town</th> <th>Postcode</th> <th>Phone</th> </tr> {% for row in book %} <tr> <td>{{row.First}}</td> <td>{{row.Last}}</td> <td>{{row.House}}</td> <td>{{row.Street}}</td> <td>{{row.District}}</td> <td>{{row.Town}}</td> <td>{{row.PostCode}}</td> <td>{{row.Phone}}</td> </tr> {% endfor %} </table> </div> </div> </body> </html> يوجد عدد كبير من العناصر الجديدة هنا، بما في ذلك قسم <style> الذي يتحكم في تخطيط الاستمارة، ويمكن الرجوع إلى أي شرح للغة CSS -مثل توثيق CSS في موسوعة حسوب- لمعرفة ما تفعله الشيفرة هنا إذ لا يتسع المقام لشرحها بسبب بعدها عن الغرض من المقال. كما توجد بعض مزايا HTML الجديدة: يوضع ترميز المحارف في وسم meta داخل وسم head، وتجب إضافة هذا الوسم في صفحات الويب الحديثة خاصةً إذا كنا نستخدم محارف غير قياسية، وإلا فسيكون لدينا في الصفحة أجزاء غير قابلة للقراءة. الوسم meta هو منفذ للعرض viewport، وهو مصمم لتحسين عرض الصفحة على الأجهزة المحمولة، ويُفضل إضافة هذا الوسم إلى الصفحة. استخدمنا عددًا من وسوم div، وهي مجرد أدوات تنظيمية لا تظهر على الشاشة إلا إذا تعمدنا إظهارها باستخدام CSS، وهي تشبه ودجات Frame التي استخدمناها في برامج Tkinter الرسومية، وتفيدنا في التحكم في نطاق الأوامر لكل من CSS وجافاسكربت. تحتوي الاستمارة form على ثلاثة عناصر جديدة، يساهم كل منها في تحسين مظهرها، هي العنصر fieldset الذي يجمع عدة حقول داخل إطار مرئي يُدرج فيه العنصر legend، والعنصر label الذي يغلف حقول input ليجعلها معًا على الشاشة. نختم الاستمارة بثلاثة أزرار من النوع submit لها الخاصية name التي تُرسَل إلى الخادم، ونستطيع استخدام تلك البيانات لتحديد الدالة التي يجب تنفيذها، أما الزر الأخير فيكون من النوع reset، وهو يمسح حقول الاستمارة ولا يرسل شيئًا إلى الخادم. قسم <table> الذي يبدأ بصف من الترويسات <th> و<tr>. يوفر الجزء التالي ميزةً جديدةً لمحرك القوالب، وهي القدرة على تنفيذ حلقات تكرارية واستبدال عدة أجزاء من البيانات، وهي الحقول التي في كل صف في حالتنا، وتُحدَّد بنى التحكم هذه بمحارف {%...%}، ويدعم المحرك عدة بنىً مختلفة إضافةً إلى الحلقة الموضحة هنا. كتابة شيفرة إطار Flask لا نحتاج إلى إضافة الكثير من الشيفرات الجديدة في هذا المشروع، فعناصر إطار Flask مجرد توسيع طفيف من المثال السابق لتحديد أي زر من أزرار submit الثلاثة قد ضُغط، وبمجرد أن ننفذ ذلك نستدعي دوال بايثون العادية التي تعدل قاعدة البيانات باستخدام وحدة sqlite3 كما شرحنا في مقال قواعد البيانات، وتعيد تلك الدوال قائمةً من عناصر القواميس، بمقدار عنصر واحد لكل صف في قاعدة البيانات، وتمرَّر تلك القائمة إلى محرك عرض القوالب template rendering engine الذي ينفذ مهمة إدخال HTML إلى الصفحة التي أنشئت، وستبدو الشيفرة كما يلي: from flask import Flask, render_template, request, g import sqlite3, os addBook = Flask(__name__) addBook.config.update(dict( DATABASE=os.path.join(addBook.root_path,'static','address.db'), )) @addBook.route("/") def index(): data = findAddresses() return render_template("address.htm", book=data) @addBook.route("/display", methods=['POST']) def handleForm(): if 'Filter' in request.form: query= buildQueryString(request.form) return render_template('address.htm', book=findAddresses(query)) elif 'Add' in request.form: addAddress(request.form) # add a new entry return render_template("address.htm", book=findAddresses()) # Note: flask.g is the "global context" object # that lives for the life of the application. def get_db(): if not hasattr(g, 'sqlite_db'): try: file = addBook.config['DATABASE'] db = sqlite3.connect(file) db.row_factory = sqlite3.Row # return dicts instead of tuples except: print("failed to initialise sqlite") g.sqlite_db = db return g.sqlite_db @addBook.teardown_appcontext def close_db(error): if hasattr(g, 'sqlite_db'): db = g.sqlite_db db.commit() db.close def buildQueryString(aForm): base = "WHERE" test = " %s LIKE '%s' " fltr = '' for name in ('First','Last', 'House','Street', 'District','Town', 'PostCode','Phone'): field = aForm.get(name, '') if field: if not fltr: fltr = base + test % (name, field) else: fltr = fltr + ' AND ' + test % (name, field) return fltr def findAddresses(filter=None): base = """ SELECT First,Last,House,Street,District,Town,PostCode,Phone FROM address %s ORDER BY First;""" db = get_db() if not filter: filter = "" # empty -> get all query = base % filter cursor = db.execute(query) data = cursor.fetchall() return data def addAddress(aForm): db = get_db() cursor = db.cursor() first = aForm.get('First','') last = aForm.get('Last','') house = aForm.get('House','') street = aForm.get('Street','') district= aForm.get('District','') town = aForm.get('Town','') code = aForm.get('PostCode','') phone = aForm.get('Phone','') query = '''INSERT INTO Address (First,Last,House,Street,District,Town,PostCode,Phone) Values ("%s","%s","%s","%s","%s","%s","%s","%s;");''' %\ (first, last, house, street, district, town, code, phone) cursor.execute(query) if __name__ == "__main__": addBook.run() نلاحظ بعض النقاط المهمة هنا: نستورد الاسم g من إطار Flask، وهو كائن خاص يوفره Flask ليحمل قيم مستويات التطبيق، ونستفيد من المبدأ الذي يقوم عليه، رغم غرابة اسمه، وهو يشبه المعامِل self في البرمجة الكائنية لكنه ينطبق هنا على تعاملات الويب بدلًا من الكائن. نعِدّ موقع قاعدة البيانات في البنية الخاصة addbook.config، وهناك عدة عناصر أخرى يجب إعدادها هنا في الموقع الكامل، بما في ذلك اسم المستخدم وكلمة المرور للمدير admin، وتخزَّن هذه الأمور عادةً في ملف config، ويُستخدم أمر خاص لتحميلها. كما يجب الانتباه إلى خيار DEBUG الذي يؤدي لطبع معلومات كثيرة إلى الطرفية عند ضبطه على القيمة True، لأن هذه المعلومات مفيدة للغاية في حال حدوث المشاكل أثناء التطوير. تتحقق الدالة get_db من كون الخاصية sqlite_db مضبوطةً أو لا قبل أن تضبطها، وهذا يضمن وجود اتصال واحد فقط لقاعدة البيانات. كما تضبط هذه الدالة row_factory من sqlite3.Row، وفائدته أنه يجعل Sqlite تعيد قائمةً من كائنات Row بدلًا من صفوف tuple تحتوي على قيم، وتُعامَل كائنات Row تلك على أنها قواميس، وهو ما يبحث عنه Flask تحديدًا في محرك القوالب الخاص به، لذا يوفر سطر الشيفرة ذاك علينا كثيرًا من تنسيق البيانات. ينبغي أن توجد معالجات أخطاء try/except حول الكثير من التعليمات البرمجية، خاصةً أقسام قواعد البيانات، لكننا لم نشأ الإطالة أكثر من اللازم، وسنرى مثالًا في دالة get_db يوضح أننا نستطيع استخدام تعليمات print لعرض خرج التنقيح debug output في الطرفية. يُستخدم هنا مزخرِف جديد هو ‎@addBook.teardown_appcontext لرفع راية إلى إطار Flask بأنه يجب تشغيل الدالة close_db عند إغلاق التطبيق. تساعد الدالة buildQueryString في بناء شرط WHERE الخاص باستعلامنا ديناميكيًا، وقد تبدو معقدةً إلا أنها مجرد تعديل بسيط على سلسلة نصية، ويسمح لنا هذا الأسلوب باستخدام دالة واحدة لإيجاد جميع العناوين عند عدم استخدام مرشحات filters، أو العناوين المطلوبة فقط. تكون عمليات البحث أكثر مرونةً باستخدام عامل LIKE الخاص بـ SQL، بدلًا من اختبار التكافؤ equality test، بما في ذلك القدرة على استخدام علامة % محرف بدل في SQL. نستخدم تابع القاموس get لجلب القيم من الاستمارة، وهذا يضمن حصولنا على قيمة افتراضية عند عدم وجود المفتاح لسبب ما، وهي سلسلة فارغة في حالتنا. تشغيل دليل جهات الاتصال سنغير مجلد التطبيق ونشغل الملف address.py، ثم نستخدم المتصفح لزيارة localhost:5000، وبهذا تطابق عملية التشغيل هذه عملية التشغيل السابقة، ويجب أن نرى نفس الأسماء والعناوين التي أنشأناها في مقال قواعد البيانات في المتصفح. كما ينبغي أن نستطيع الآن إدخال القيم في الاستمارة، وترشيح النتائج لمطابقة كلمات البحث -نستخدم % محرف بدل wildcard- وكذلك نستطيع إضافة إدخالات جديدة، وبما أنه لا يوجد تحقق من الحقول أو الاستمارة فيجب أن نراعي إدخال قيم منطقية مناسبة، أو نتلافى أي أخطاء يدويًا باستخدام محث sqlite3. ينبغي أن يقدم هذا المقال فكرةً عن متطلبات إنشاء تطبيق ويب، وهناك المزيد لتعلمه بما في ذلك تقنيات برمجة المتصفحات، وأمور الأمان في جانب الخادم، وملفات تعريف الارتباط cookies، وإطلاق الموقع الحي في صورته النهائية على الإنترنت، وكل هذا خارج عن سياق شرحنا، لذا يُرجع فيه إلى تطوير التطبيقات باستخدام لغة Python من أكاديمية حسوب، أو دورة تطبيقات الويب باستخدام PHP، وغيرها من مقالات البرمجة والكتب البرمجية في الأكاديمية كما توفر شركات استضافة الويب توثيقات ممقالةً عن تحقيق الاستفادة القصوى من المواقع التي ننشئها. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: تحسّن أطر عمل الويب إمكانية توسيع المواقع وصيانتها. توجه أطر عمل الويب نقاط النهاية إلى الدوال. توجد عدة إطارات عمل للويب في السوق الآن. إطار Flask يمثل حلًا وسطًا بين البساطة والإمكانيات. يستخدم Flask مزخرفات decorators لتوجيه نقاط النهاية. كما يستخدم نظام قوالب لتمرير البيانات إلى صفحات الويب. ترجمة -بتصرف- للمقال الحادي والثلاثين: Using Web Apllication Frameworks من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: البرمجة المتزامنة وفائدتها في برمجة التطبيقات المقال السابق: كيفية كتابة تطبيقات الويب برمجة عملاء ويب باستخدام بايثون كيفية كتابة تطبيقات الويب كيفية التعامل مع الويب تواصل البرامج والعمليات البرمجية عبر الشبكة
  23. سنغطي في هذا المقال من سلسلة تعلم البرمجة: تاريخ موجز لخوادم الويب. أساسيات CGI: واجهة البوابة المشتركة. مقدمة في برمجة خوادم الويب في بدايات الإنترنت كنا نطلب صفحات HTML من خوادم الويب فتعطينا صفحات ثابتةً أو ساكنةً، ليس للمستخدمين أي يد في تعديل محتواها أو التفاعل معها، باستثناء بعض عمليات باتش batch processes التي استخدمتها بعض المواقع لإنشاء صفحات HTML من مصادر البيانات، لضمان تحديث معلومات تلك الصفحات، وفي هذه الحالة أيضًا لم يكن للمستخدمين دور في ما يظهر أمامهم على صفحة الويب. ثم صرنا ندمج البرامج في خوادم الويب لتوليد الصفحات ديناميكيًا كلما طلبها المستخدم، وسميت الآلية المستخدمة في ذلك واجهة البوابة المشتركة Common Gateway Interface أو CGI اختصارًا، ولا يزال أثر تلك التقنية باقيًا في مواقع الويب التي نتصفحها حاليًا. ومع استغلال المبرمجين إمكانيات واجهة CGI -مع وسم <form> في HTML- صارت المواقع التي يبنونها أكثر تطورًا وتعقيدًا، وصار من الممكن بناء مواقع التسوق الإلكتروني، والألعاب، والدعم الفني، وغيرها من الخدمات التي صارت اليوم بدهيات. تُبنى واجهة CGI على مفهوم بسيط، هو أن بيانات الإدخال تُرسَل مثل جزء من رسالة http GET أو http POST، ويشير الرابط إلى مجلد خاص في خادم الويب، الذي يعرف أن عليه تنفيذ المورد resource بدلًا من إعادته، وهذا المورد هو برنامج يرسل الخرج الخاص به إلى مجرى الخرج القياسي stdout في صفحة HTML، فيقرأ الخادم مجرى الخرج القياسي، ويوجهه إلى العميل الذي طلب الصفحة. سندرس الآن جزءًا من تلك المرحلة المبكرة في تطور خوادم الويب، بأن ننشئ خادم ويب بسيط على حاسوبنا المحلي، ليعطينا صفحة HTML ثابتةً، ثم نوسّع الصفحة لتشمل استمارةً تلتقط اسم المستخدم وترسله إلى الخادم، ونختم بإنشاء برنامج CGI يقرأ اسم المستخدم ذاك، ويعيد رسالة ترحيب مخصصةً باسمه من الخادم. إنشاء صفحة ترحيب باستخدام واجهة CGI توفر بايثون وحدة خادم ويب بسيطةً نستطيع استخدامها للاختبار والتطوير، قبل نقل الشيفرة إلى منصة استضافة ويب حقيقية في شبكة ما أو على الإنترنت، وسنبدأ بالنظر في كيفية تشغيلها لإرسال صفحات ويب ساكنة static web pages. صفحة ويب بسيطة أول ما علينا فعله هو إنشاء صفحة الويب التي نريد إرسالها، ولن نشرح كيفية كتابة شيفرة HTML بالتفصيل هنا، وإنما سنشرح ما يكفي لتشغيل الأمثلة التي نكتبها، وستبدو صفحة "Hello World" بسيطةً كما يلي: <!doctype html> <html> <head> <title>Hello world web page</title> </head> <body> <h1>Hello World</h1> </body> </html> تتكون HTML من وسوم، وهي أسماء محددة مسبقًا في توصيف اللغة نفسها، تحيط بها علامتا < و>، وتأتي أغلب الوسوم في أزواج يكون وسم الإغلاق فيها مسبوقًا بشرطة مائلة /، كما قد تحتوي الوسوم على بيانات تُعرف بالخاصيات attributes، غير أن المثال أعلاه ليس فيه أي منها لأننا بدأنا به بسيطًا، لكننا سنراها لاحقًا. تجدر الإشارة هنا إلى أن بعض العناصر إجبارية في HTML، فيجب أن تحتوي كل صفحة HTML عليها على الأقل لتكون صالحةً، رغم أن أغلب المتصفحات الحالية ستعرض الصفحة حتى لو لم تكن هذه العناصر موجودةً، وتلك العناصر هي: التصريح doctype: يشير إلى أن هذا المستند هو مستند HTML، وقد كان هذا التصريح طويلًا ومفصلًا سابقًا، لكن -ومنذ صارت HTML5 قياسيةً ومعتمدةً- نكتفي بكتابة html في ذلك التصريح. لاحظ أن تنسيق الوسم في doctype مختلف عن وسوم HTML العادية، إذ توجد علامة تعجب مباشرةً بعد علامة ‎<‎. الوسم html: نستخدم زوجًا من الوسم <html> لتحديد بداية متن المستند نفسه ثم وسم إغلاق له، ويشكل هذا الوسم جذر المستند، وتمثَّل صفحات HTML في ذاكرة المتصفح في هيكل شجري، تكون قمته الوسم <html>. وتعدِّل شيفرة جافاسكربت التي في المتصفح ذلك الهيكل، لذا تؤثر طريقة كتابة HTML كثيرًا في كيفية كتابة شيفرة جافاسكربت، وكذلك في قراءة عملاء الويب web clients -مثل تلك التي كتبناها في المقال السابق- لتلك الصفحة. الوسم head: يحدد الوسم <head> جزءًا من الصفحة يحوي معلومات عن الصفحة نفسها، لكن المتصفح لا يعرضها، فمثلًا تعرَّف فيه بيانات أوراق الأنماط المتتالية أو التنسيقات الموروثة CSS، وقد يُستورد ملف CSS عند وجود عدة أنماط في الصفحة، كما تستورد ملفات جافاسكربت المستخدَمة في الصفحة. نلاحظ أننا أزحنا الوسوم في المثال أعلاه، لكن ذلك لا يؤثر على تنفيذ الشيفرة، وهو لتحسين قراءة الشيفرة وإظهار الهيكل الشجري المتشعب للمستند لا أكثر، ولا فرق بالنسبة للمتصفح سواء أزيحت الشيفرة أم لا، وقسم head غير إلزامي عند كتابة مستندات HTML نظريًا، لكن وجوده يرجع إلى حاجة أغلب المتصفحات الحديثة للمعلومات التي فيه. الوسم title: يحتوي هذا الوسم على عنوان الصفحة الذي سيعرضه المتصفح، وهو الجزء الوحيد المعروض من قسم الترويسة، رغم تأثير الأنماط وجافاسكربت في المظهر العام لمحتوى الصفحة الرئيسية. الوسم body: يغلف هذا الوسم المحتوى الأساسي للصفحة، والذي نراه في نافذة المتصفح. هذه هي العناصر الأساسية لصفحة الويب، وقد استخدمنا الوسم <h1> الذي يحتوي رسالة "Hello World"، وهو جزء من مجموعة عناصر h -التي تشير إلى كلمة ترويسة header- وتُرقَّم من 1 إلى 6 لتوضح ترتيب عناوين الفقرات، ويصغر حجم الخط المستخدم ومظهره كلما اقتربنا من العنوان السادس، رغم إمكانية تعديل ذلك باستخدام CSS. نحفظ شيفرة HTML في مستند باسم index.htm في مجلد باسم hello، ونتحقق من عمله بتحميله في متصفح ويب، فإذا عرض المتصفح الصفحة كما نريدها فنكون قد نجحنا في هذه المهمة البسيطة، وننتقل الآن إلى توفيره من خلال خادم الويب الخاص بنا. تشغيل خادم الويب يوجد خادم الويب الخاص ببايثون في وحدة http.server، ويمكن تشغيله دون أي تعديلات من خلال سطر أوامر نظام التشغيل، بتغيير المجلد العامل إلى مجلد hello الذي أنشأناه قبل قليل، كما يلي: $ python -m http.server --cgi 8000 يحدد الخيار ‎-m في الشيفرة أعلاه الوحدة التي يجب أن تشغلها بايثون، أما الراية ‎--cgi فتفعّل عمليات واجهة CGI التي سنحتاج إليها لاحقًا، ويشير العدد 8000 إلى منفذ الشبكة الذي ستستخدمه. تحميل صفحة الويب نستطيع الآن الوصول إلى الخادم من خلال تحميل الرابط التالي في شريط عنوان المتصفح: http://localhost:8000 إذا كان الخادم يعمل فستحمَّل تلك الصفحة وتُعرض كما فعلنا من قبل، إلا أنها الآن تُرسَل من قبل الخادم، كما يتضح من شريط العنوان في المتصفح، وبهذا نكون قد أرسلنا أول صفحة ويب لنا! والسبب الذي يجعل هذه العملية ناجحةً دون تحديد اسم الملف هو أن خوادم الويب تبحث عن ملف باسم index.htm تلقائيًا، فإذا كان موجودًا ولم نحدّد ملفًا مسبقًا فسيُعرض index.htm. كما يمكن إعداد الخادم ليبحث عن ملفات افتراضية أخرى، مثل index.html أو index.php. استخدام واجهة CGI لعرض رسالة ترحيب بالمستخدم نريد الآن أن نوسع صفحة الويب السابقة لتلتقط اسم المستخدم وترسله إلى الخادم، الذي يرد بإرسال رسالة ترحيب مخصصة باسم المستخدم. إنشاء استمارة HTML الخطوة الأولى لذلك هي تعديل ملف HTML ليتضمن حقل إدخال لاسم المستخدم، كما يلي: <!doctype html> <html> <head> <title>Hello user page</title> </head> <body> <h1>Hello, welcome to our website!</h1> <form name="hello" method="get" action="http://localhost:8000/cgi-bin/sayhello.py"> <p>Please tell us your name:</p> <input type="text" id="username" name="username" size="30" required autofocus/> <input type="submit" value="Submit" /> </form> </body> </html> نلاحظ هنا أن عناصر <form> تحتوي على خاصيات في وسومها، حيث تشكل الخاصية name جزءًا من البيانات المرسَلة إلى الخادم مع القيمة التي في صندوق الإدخال النصي، وتخبر الخاصية method الخاصة بوسم form المتصفح نوع رسالة http التي يجب إرسالها -وهي GET في هذه الحالة-، كما تخبره الخاصية action بالمكان الذي يجب أن يرسلها إليه. تخبر خاصيتا العنصر input الأخيرتان المتصفح ألا يرسل الاستمارة إلا إذا احتوى الحقل النصي على قيمة، وأن يضع المؤشر في ذلك الحقل ليكون مستعدًا لاستقبال الإدخال، كما تخبر القيمة submit الموجودة في نوع الإدخال type المتصفح أن يعرض هذا العنصر مثل زر تظهر عليه الكلمة الموجودة في قيمة الخاصية value -والتي هي submit أيضًا-، وسيرسل ذلك الزر الاستمارة عند الضغط عليه إلى الخاصية action الخاصة بالاستمارة. نحفظ هذا في نفس المجلد كما فعلنا من قبل، لكن نستدعي hello.htm في هذه المرة، ونتحقق من صحة عملها بكتابة ما يلي في شريط العنوان: http://localhost:8000/hello.htm ينبغي أن نرى رسالةً فيها حقل إدخال نصي يطلب منا إدخال الاسم مع زر تحته، إلا أنه لن يحدث شيء عند ضغطنا على الزر لأننا لم نكتب أي شيفرة تعالج تلك النقرة على الخادم، لذا نحتاج إلى إنشاء برنامج CGI يُستدعى عند إرسال الاستمارة إلى الخادم بالضغط على الزر. كتابة شيفرة CGI يشبه برنامج CGI برامج بايثون التي كتبناها من قبل، باستثناء أمرين هما: برنامج CGI يستورد وحدة CGI. يوجد في مجلد باسم cgi-bin، في جذر خادم الويب، ويكون هذا البرنامج تنفيذيًا executable، لنحقق الأمر الثاني ننشئ مجلد cgi-bin داخل مجلد html، ثم ننشئ ملفًا داخل ذلك المجلد الجديد ونسميه sayhello.py يحتوي على الشيفرة التالية: #!/usr/bin/env python3 import cgi # استخرج حقول البيانات data = cgi.FieldStorage() username = data["username"].value # \n\n الإجبارية مع اللاحقة http أرسل ترويسة: print("ContentType: text/html\n\n") # HTML والآن، أرسل محتوى print("<!doctype html>\n<html><head>") print("<title>Hello %s</title></head>" % username) print(''' <body> <h1>Welcome %s</h1> </body> </html>''' % username) تنفَّذ العمليات الخاصة بالبيانات داخل استدعاء FieldStorage، حيث تجمع وحدة cgi جميع البيانات من طلب http، وتضعها في قاموس لنستطيع الوصول إليها بسهولة باستخدام مفاتيح نصية هي خاصيات name من الاستمارة الخاصة بنا. نلاحظ كيف تمكننا علامات الاقتباس الثلاثية الخاصة ببايثون من هيكلة الخرج في HTML بصورة يمكن قراءتها -انظر قسم head و body. بعد أن نحفظ الصفحة، نتأكد من تغيير الصلاحيات ليكون الملف قابلًا للتنفيذ من جميع المستخدمين، فإذا أعدنا تحميل صفحة hello.htm، وملأنا الاستمارة فسنحصل على رسالة ترحيب من الخادم عند الضغط على الزر. تصلح هذه التقنية لمثل هذه التطبيقات البسيطة، وتمتاز بشفافية الخطوات، ومن ثم سهولة تصحيحها، غير أنه مع زيادة حجم المواقع وتعقيد البيانات لا تكون واجهة CGI مناسبةً للعمل معها، وهنا يأتي دور أطر عمل الويب frameworks، والتي سننظر فيها في المقال التالي. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: تُنشأ الطلبات إلى خوادم الويب باستخدام طلبات http GET. يرد خادم الويب بمستند HTML. تُمرَّر البيانات في رابط الطلب أو متغيرات البيئة. تعالج وحدة CGI البروتوكول الأساسي. تُجلب بيانات الاستمارة من خلال قاموس FieldStorage. واجهة CGI مناسبة لاستمارات الويب البسيطة، مثل شاشات تسجيل الدخول، إلا أنها لا تناسب التطبيقات الكبيرة. ترجمة -بتصرف- للفصل الثلاثين: Writing Web Applications من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: استخدام أطر العمل في برمجة تطبيقات الويب: فلاسك نموذجا المقال السابق: برمجة عملاء ويب باستخدام بايثون أساسيات بناء تطبيقات الويب في ريآكت كيف تكتب أول برنامج لك في بايثون 3 البرمجة بلغة بايثون
  24. سنغطي في هذا المقال من سلسلة تعلم البرمجة ما يلي: آلية ووقت استخدام التزامن concurrency والخيوط threads. مثال على تقسيم الحمل بين العمليات. الوصول إلى البيانات المشتركة باستخدام الخيوط. بعض الاحتمالات والمحاذير الأخرى. رأينا إضافة هذا المقال إلى شرحنا بعد تفكير طويل نظرًا لأهمية موضوعه، وسبب ترددنا في ذلك أن التزامن عمومًا -والخيوط على وجه الخصوص- موضوع يصعب فهمه، رغم مسارعة الكثيرين إليه ظنًا منهم أنه يحل مشاكلهم، لكنهم يزيدونها سوءًا لضعف فهمهم لمفاهيم التزامن والخيوط، واللتان هما أداتان قويتان عند استعمالهما في المواضع المناسبة عن فهم وإدراك، لكن نرى أن يكونا الملاذ الأخير، نلجأ إليهما بعد فشل جميع الحلول الأخرى، وقد عملنا -يقصد المؤلف نفسه- على عدة مشاريع تستخدم التزامن بصورة أو بأخرى في الأعوام الأربعين الماضية، لكننا لم نستخدمها في مشاريع شخصية من قبل، وربما يعطي هذا تصورًا عن توقيت استخدام هذه التقنية، ونوعية المشاريع التي تُستخدم فيها. مفهوم البرمجة التزامنية وتوقيت استخدامها تشير البرمجة التزامنية Concurrent programming ببساطة إلى برنامج يحوي عناصر تعمل على التوازي في نفس الوقت، وهو ما نطبقه على حواسيبنا كل يوم، لكننا نترك أمر إدارة تلك البرامج لنظام التشغيل، ليجدولها لتعمل بالترتيب، ويوزع حمل التشغيل على المعالجات والنوى kernels الموجودة فيها، فمفهوم تقسيم المهمة إلى عدة أجزاء والعمل على كل جزء على حدة ليس جديدًا، وهو يشبه إنشاء فرق مختلفة للتعامل مع مشكلة كبيرة تُقسم إلى عدة أجزاء، ليعمل كل فريق على جزء منها. وقد اتبعنا تلك الأساليب في علم الحواسيب على مدار العقود الماضية، خاصةً في الخوادم، فمثلًا يستقبل خادم الويب طلبات ويعالجها، لكن إذا كان الموقع كبيرًا وطلباته كثيرة ومتلاحقة، وكان الخادم يُعالج كل طلب قبل بدء الطلب الذي يليه؛ فستطفح قائمة انتظار المدخلات للخادم، لذلك يقرأ الخادم الطلب من قائمة الانتظار، فإذا كان الطلب ملف html بسيطًا فيعيده، أما إن كان أعقد من هذا فيشتق الخادم عمليةً فرعيةً للتعامل معه، ويعود هو لقراءة الطلب التالي. وقد رأينا من قبل كيفية إنشاء عمليات من شيفرة بايثون الخاصة بنا في مقال التواصل مع نظام التشغيل باستخدام وحدة subprocess، ورأينا منظورًا مختلفًا في مقال التواصل بين العمليات، حيث استخدمنا fork لإنشاء عملية فرعية تكون نسخةً من العملية الأصلية، وتعمل كلا التقنيتين بسلاسة إذا كنا نرغب في عمليات قليلة منمقالة تمامًا عن بعضها، لكنهما لا تناسبان الحالة التي نحتاج فيها إلى عمليات كثيرة، كما في حالة معالجة خادم الويب لآلاف الطلبات كل دقيقة، وإحدى المشاكل التي قد تحدث عند استخدامهما لحالة الطلبات الكثيرة هو ما ينتج عن بطء إنشاء العملية الجديدة -بمقياس سرعة الحواسيب-، كما تكلف كل عملية الكثير من الأحمال الزائدة من استهلاك الذاكرة وغيرها، وهنا يبرز دور الخيوط therads، وهي تشبه العمليات الدقيقة التي تعمل داخل العملية الأصل، فتتشارك جميعها نفس مساحة الذاكرة ونفس الشيفرة، وتأتي تسمية الخيوط من فكرة أن الشيفرة الخاصة بنا تعمل من الأعلى إلى الأسفل -مع قفزات وحلقات تكرارية في طريقها-، فهي مثل بكرة من القطن أمسكنا طرف خيطها وتركناها تسقط، فكل خيط جديد يشبَّه بكرة قطن جديدة نسقطها بالتوازي مع الخيط الأول، وكل خيط له مسار تنفيذ خاص به في نفس الشيفرة. لقد أشرنا أن التزامنية تتعلق بشكل ما بالأداء، خاصةً في حالة الأحمال الكبيرة من البيانات، والحق أن هذا هو السبب الوحيد لاستخدامها، فإذا واجهنا مشكلة عند زيادة البيانات ونكون قد بذلنا كل ما نستطيع من تعديلات على الأداء الأساسي -لعملية تبادل أو وحدة بيانات واحدة-، فحينئذ قد نحتاج إلى إعادة التفكير في شأن تقسيم الأحمال. اختيار أسلوب التزامن بعد أن أثبتنا فائدة التزامن في تحسين الأداء في حالة الأحمال الكبير، كيف نقرر التقنية التي سنستخدمها لمعالجة مهمة ما؟ أيهما أفضل لمهمتنا العمليات المتعددة أم الخيوط المتعددة؟ والجواب أننا ننظر في عدة عوامل، حيث: نستخدم الخيوط إذا كان في المهمة انتظار لنشاط الإدخال والإخراج، مثل رسائل الشبكة أو نتائج استعلامات قواعد البيانات. نستخدم الخيوط إذا تطلبت المهمة مشاركة البيانات بين عدة "خيوط"، لكن يجب تذكر قفل lock البيانات المشارَكة أثناء التحديثات. نستخدم العمليات الفرعية إذا كان في المهمة معالجة خالصة للبيانات data crunching، وقد صممت الوحدة multiprocessing في بايثون خصيصًا لهذه الحالة. إذا كانت المهمة الفرعية تعمل لوقت طويل، أو لا تُستدعى إلا لوقت قصير، فننشئ عملية خادم طويلة التشغيل long running server process، كما فعلنا في مقال التواصل بين العمليات، لنرسل البيانات إليها عند الحاجة. البدء بالبرمجة المتزامنة بما أننا قررنا استخدام التزامن فلننظر في الشيفرة المطلوبة لها، لدينا وحدتان في المكتبة القياسية تتعلقان بالخيوط، هما Thread وthreading، والوحدة الأخيرة هي وحدة عالية المستوى بُنيت فوق وحدة Thread، ولا نحتاج إلا إلى النظر فيها، أما في حالة العمليات المتعددة فنستخدم وحدة multiprocessing التي تعمل تقريبًا بنفس طريقة threading. تحديد المشكلة لننظر في مشروع بسيط نريد فيه حساب مضروب أول N عدد من مجموعة ما من الأعداد، فنكتب دالةً لحساب المضروب ثم نضعها في حلقة تكرارية ونخزن النتائج، وستبدو كما يلي: import time, sys factorials = [] def fact(n): if n < 2: return 1 result = 1.0 for x in range(2,n+1): result *= x return result def do_it(f,lo,hi): global factorials for n in range(lo,hi): factorials.append(f(n)) if __name__ == "__main__": hi = int(sys.argv[1]) + 1 start = time.time() do_it(fact, 1, hi) print('Time for %s: %s' % (hi, time.time() - start)) نلاحظ أننا أنشأنا دالة do_it التي تغلف الحلقة التكرارية الخارجية واستدعاءات المضروب، وهي ليست ضروريةً لكننا سنرى نفعها لاحقًا عندما ننظر في التزامن، وقد جعلنا عدد مرات التكرار وسيطًا في سطر الأوامر، وأضفنا مؤقتًا لإظهار الزمن الذي تستغرقه. احفظ ذلك في ملف باسم no_threads.py وشغله لأول 100 عدد كما يلي: $ python3 no_threads.py 100 إذا شغلنا هذا الأمر فسنجد أن الوقت المستغرق أقل من ثانية، نظرًا لسرعة الحواسيب هذه الأيام، لكن جرب ذلك مع أول ألف عدد مثلًا وانظر الوقت المستغرق، وقد جربناها لكل من أول 100 عدد، وأول 1000، وأول 10000، وخرجنا بالنتائج التالية: $ python3 no_threads.py 100 Time for 100: 0.0006973743438720703 $ python3 no_threads.py 1000 Time for 1000: 0.06539225578308105 $ python3 no_threads.py 10000 Time for 10000: 6.800917863845825 نلاحظ أن السرعة جيدة إلى أن نصل إلى الألف عدد، لكنها تسوء فجأةً مع زيادة العدد عن ذلك، ونريد تحسين هذا الأداء لتلك الأعداد الكبيرة، وهنا يأتي دور التزامن. إضافة التزامن إلى العملية باتباع الإرشادات التي شرحناها أعلاه، سنختار multiprocessing بدلًا من threading لهذه المهمة، ونريد أن نعرف مقدار العدد المُدخَل أولًا، فإذا كان أكثر من 1000، فسنقسم العملية إلى عدة فروع، وسيكون ذلك أبطأ في الأعداد الكبيرة، لذلك بدلًا من تقسيم البيانات بالتساوي بين العمليات سنقسمها عند 75% -عشوائيًا-. ستكون الشيفرة كما يلي: import time, sys import multiprocessing factorials = [] def fact(n): if n < 2: return 1 result = 1.0 for x in range(2,n+1): result *= x return result def do_it(f,lo,hi): global factorials for n in range(lo,hi): factorials.append(f(n)) if __name__ == "__main__": hi = int(sys.argv[1]) + 1 start = time.time() if hi > 1000: hi_1 = int(hi * 0.75) p1 = multiprocessing.Process(target=do_it, args=(fact,1,hi_1)) p2 = multiprocessing.Process(target=do_it, args=(fact,hi_1,hi+1)) p1.start() p2.start() p1.join() p2.join() else: do_it(fact, 1, hi) print('Time for %s: %s' % (hi, time.time() - start)) نلاحظ أننا أنشأنا كائنيْ Process، ومررنا الدالة التي نريد تشغيلها -وهي do_it- إضافةً إلى الوسائط اللازمة في صف tuple، ثم استدعينا start لتشغيل العمليات، أخيرًا استخدمنا التابع join لجعل البرنامج الرئيسي ينتظر انتهاء العمليات. $ python3 processes.py 100 Time for 100: 0.0006771087646484375 $ python3 processes.py 1000 Time for 1000: 0.06577491760253906 $ python3 processes.py 10000 Time for 10000: 3.690302610397339 نلاحظ أن الوقت المستغرق للعملية الكبيرة قد انخفض إلى النصف تقريبًا، لكن ما نفذناه لم يكن بسيطًا أو مباشرًا، فلم نقسم البيانات بالتساوي، فإذا جربت تقسيمها عند 50% فستجد أن الوقت المستغرق زاد مرةً أخرى. يبدو أن التزامن يعطينا تحسنًا كبيرًا في الأداء، لكن في الواقع لدينا خلل كبير في برنامجنا، فإذا طبعنا factorials -وهي قائمة النتائج- فسنجدها فارغةً! والسبب في هذا أن كل عملية فرعية هي نسخة من العملية الأصل، وبالتالي لها نسختها الخاصة من قائمة factorials، والتي نفقد بياناتها عند انتهاء العملية، لذلك نحتاج إلى طريقة لتمرير البيانات إلى العملية الأصل، مما يعني الكتابة إلى ذاكرة مشتركة -انظر وحدة mmap- أو إلى قاعدة بيانات أو إلى ملف. نستخدم في تلك الحالات كلها عمليات الإدخال والإخراج، لذا فلم لا نستخدم الخيوط بما أنها تتشارك الذاكرة! فنكون قد أنشأنا نسختنا الخاصة من معضلة Catch-22)! لكن لحسن الحظ نادرًا ما يكون لدينا عمليات نحتاج إلى تقسيمها بالتوازي دون أن يكون فيها عمليات إدخال وإخراج، لذا فإن الخيوط هنا حل يمكن تنفيذه، وسننظر في مثال "مفتعل" إلى حد ما لمجرد موازنة هيكل الشيفرة مع مثال تعدد العمليات السابق. استخدام الوحدة threading سننشئ في هذا المثال خيطًا مساعِدًا لتحديث المتغير theTime في كل ثانية، وسيتكرر البرنامج الرئيسي بلا نهاية ليطبع المتغير في كل مرة يتغير فيها، ولضمان تشغيل الخيوط بسلاسة سنضيف تأخيرًا زمنيًا باستخدام time.sleep، التي يعاملها المفسر على أنها عملية إدخال/إخراج. import time, threading theTime = 0 def getTime(): global theTime while True: theTime = time.time() time.sleep(1) def main(): global theTime current = theTime thrd = threading.Thread(target=getTime) thrd.start() while True: if current != theTime: current = theTime print(time.asctime(time.localtime(current))) time.sleep(0.01) if __name == "__main__": main() لقد أنشأنا في المثال أعلاه دالةً تغلف مهمة الخيوط، لضمان وجود عملية time.sleep فيها -أو أي دالة I/O أخرى-، ثم أنشأنا خيطًا نسند فيه دالتنا على أنها الهدف، كما فعلنا في العمليات أعلاه، ونبدأ تشغيل الخيط في الخلفية ثم ننتقل إلى الحلقة الأساسية التي تتحقق من المتغير في كل جزء من مئة من الثانية. عند الحاجة إلى إنهاء البرنامج نكتب Ctrl+C أو نستخدم مدير المهام في نظام التشغيل لإنهاء هذه العملية. إذا شغلنا الشيفرة السابقة فستكون النتيجة شبيهةً بما يلي: $ python3 clock.py Sat Dec 30 11:30:33 2017 Sat Dec 30 11:30:34 2017 Sat Dec 30 11:30:35 2017 Sat Dec 30 11:30:36 2017 ... كان من الممكن تحقيق ذلك بسهولة دون استخدام الخيوط، لكنها تعطينا فكرةً عما تبدو عليه أبسط شيفرة تحوي خيوطًا، فإذا وازنّاها مع شيفرة العمليات المتعددة فسنجد أنهما متطابقتان تقريبًا في بنيتيهما، والفرق بينهما أن شيفرة الخيوط تستطيع تحديث متغير getTime العام الذي تستطيع الدالة الرئيسية الموجودة في العملية الأصل أن تراه، نستطيع الآن أن نعود ونستبدل العمليات بالخيوط في المثال السابق ونوازن بين النتائج، وسنجد أن نسخة الخيوط لم تقدم مزيةً زمنيةً على نسخة العمليات. سنكتفي بهذا القدر من شرح التزامن لأنه موضوع معقد فيه الكثير من الفخاخ الدقيقة، وننصح بعدم استخدامه إلا عند الضرورة، وحتى في تلك الضرورة فالشرح الموجود هنا يمثل نقطة بداية فقط، يمكن الانتقال بعدها إلى شروح أكثر تفصيلًا وعمقًا. للمزيد من المعلومات، ننصحك بالإطلاع على دورة تطوير التطبيقات باستخدام لغة Python التي تشرح الكثير من المفاهيم الأساسية لبناء التطبيقات في بايثون. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: يُستخدم التزامن لتحسين الأداء. يُنفَّذ التزامن بتشغيل عمليات أو خيوط إضافية. تعمل العمليات بشكل مستقل عن بعضها، وتتواصل مع العملية الأصل باستخدام الأنابيب pipes. تعمل الخيوط افتراضيًا داخل العملية الأصل، وتتشارك الموارد -مثل الذاكرة وغيرها- فيما بينها. يجب إقفال الموارد المشتركة قبل تغيير الحالة لتجنب حدوث تعارضات. توجد طرق أخرى للتزامن، كما في وحدة asyncio في بايثون التي تستخدم منظورًا مختلفًا. ترجمة -بتصرف- للمقال الثاني والثلاثين: Concurrent Programming من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال السابق: استخدام أطر العمل في برمجة تطبيقات الويب: فلاسك نموذجا برمجة عملاء ويب باستخدام بايثون كيفية كتابة تطبيقات الويب كيفية التعامل مع الويب استخدام أطر العمل في برمجة تطبيقات الويب: فلاسك نموذجًا
  25. نظرنا حتى الآن في سلسلة تعلم البرمجة في نظام التشغيل وقدرته على إدارة العمليات، وفي كيفية جعل السكربتات تنفذ برامج موجودةً من قبل، وكذلك استنساخ البرامج والتواصل بين تلك النسخ باستخدام الأنابيب pipes، وسندرس في هذا المقال الاتصال بالعمليات التي تعمل على حاسوب آخر عبر شبكة ما، أو بعمليات قد تكون جاريةً على نفس الحاسوب، حيث ستكون الشبكة هنا شبكةً منطقيةً logical network، وهذا النوع هو المثال الأول الذي سننظر فيه. وعلى ذلك سنشرح في هذا المقال ما يلي: مقدمةً بسيطةً عن الشبكات. أساسيات المقابس sockets. إنشاء عملية الخادم server process. إنشاء عملية العميل client process. التواصل من خلال المقابس. مقدمة في الشبكات يعمل خادم الويب web server على حاسوب في مكان ما في الشبكة، ونستطيع الوصول إليه من حاسوبنا إذا كان لدينا عنوان الويب Uniform Resource Locator واختصارًا URL، والذي هو نوع من عناوين الشبكات يحوي معلومات حول العنوان في الشبكة، واللغة التي يتحدث بها -أو البروتوكول protocol-، وكذلك مكانه على خادم الملفات التي نريد جلبها، وسنفترض أن للقارئ خلفيةً أساسيةً عن الإنترنت، ويعرف أن للحواسيب المتصلة بها عناوين. لكن كيف تتصل تلك الحواسيب ببعضها؟ طبعًا لا يتسع المقام هنا لشرح مفصل حول الشبكات، لذا يُرجع في هذا إلى أكاديمية حسوب التي فيها شرح ماتع في أساسيات الشبكات يمكن النظر فيه، وكذلك في هذا المصدر بالإنجليزية، وخلاصة ما نريد قوله في الشبكات هو أنه عند حاجة حاسوبين على شبكة ما للاتصال ببعضهما فإنها يتصلان من خلال إرسال حزمة بيانات من حاسوب لآخر، وتشبه تلك الحزمة إلى حد كبير مظروفًا يُرسل في طرد عبر البريد مع ورقة بداخله، حيث تمثل تلك الورقة البيانات، ويمثل المظروف ترويسة الطرد packet header التي تحوي عناوين المرسل والمستقبل، ويحدد جهاز التوجيه router أو المحول switch موقع الحاسوب المستقبِل على الشبكة، ثم يوجه الحزمة إلى جهاز توجيه أو راوتر في تلك المنطقة، وتصل الحزمة في النهاية إلى نفس الجزء من الشبكة الذي يحوي الحاسوب الهدف، ويتعرف الحاسوب الهدف على عنوانه ويفتح الطرد أو الحزمة، ثم يرسل حزمة تأكيد مرةً أخرى إلى المرسل ليخبره أن الرسالة قد وصلت. وللحزم قيمة عظمى لا تتعداها، فيما يتعلق بحجم البيانات التي ترسلها، خلافًا للخدمات البريدية التقليدية، ويمكن تشبيه ذلك بخدمة لإرسال خطاب يتكون من ورقة واحدة فقط، أما الرسائل الطويلة فنحتاج إلى إرسالها في عدة خطابات يحوي كل منها ورقةً واحدةً فقط، ويجب على الطرف المستقبل أن يجمع تلك الأجزاء بالترتيب، حيث يضاف رقم متسلسل إلى الورقة -مثل ترقيم الصفحات-، وذلك لتُرسَل رسالة خطأ من المستقبل إلى المرسل إذا لم تصل صفحة ما أو لم تظهر في الوقت المحدد لها، وعلى الرغم من انتفاء الحاجة إلى ذلك غالبًا، لأن الحاسوب يتكفل به وكذلك نظام التشغيل وبرمجيات الشبكات، لكن هذه الأمور تستحق أن نعلمها على أي حال، نظرًا لتعذر الاعتماد على موثوقية نقل البيانات أو استمراريته عند استخدام شبكة ما، إذ تقع الأخطاء العرضية بلا شك، ويجب أن نكون مستعدين لفقدان البيانات أو تلفها. الاتصال بالشبكة لنترك الكلام المجرد ولندرس التفاصيل العملية لكيفية كتابة تطبيق متصل بالشبكة، حيث نحتاج إلى إنشاء برنامج يعمل مثل خادم server ويكون على حاسوب ما، وبرنامج للعميل client على حاسوب أو عدة حواسيب أخرى متصلة بالشبكة التي يتصل بها الخادم، كما نحتاج إلى آلية تتيح التواصل بين البرنامجين وتعمل في كامل الشبكة، وقد رأينا أن لكل حاسوب عنوانًا، يتكون من عنوان IP الذي يحوي أربعة أرقام تفصل بينها نقاط، لا شك أننا رأيناها من قبل في عناوين الويب، ويضيف التطبيق المتصل بالشبكة عنصرًا آخر إلى ذلك العنوان، يُعرف باسم المنفذ port. المنافذ والبروتوكولات يُحدَّد المنفذ بنقطتين رأسيتين : متبوعتين برقم المنفذ، ويضاف ذلك إلى عنوان IP العادي، فنصل مثلًا إلى المنفذ 80 في العنوان 127.0.0.1 بالشكل 127.0.0.1:80، وتُحفظ بعض أرقام المنافذ لأغراض خاصة تكون في الغالب لبروتوكولات تطبيقات الإنترنت المختلفة، والبروتوكول -أو الميثاق- هو مجموعة من القواعد وتعريفات الرسائل التي تحدد كيفية عمل الخدمة، فالمنفذ 80 هو المنفذ القياسي المستخدم في خوادم الويب لطلبات http، أما المنفذ 25 فيُستخدم لبريد SMTP، وبناء عليه يتصرف الحاسوب مثل خادم لبعض الخدمات في نفس الوقت، بعرض تلك الخدمات من خلال منافذها المختلفة، ويمكن توضيح هذا بسهولة بإضافة رقم المنفذ 80 إلى عنوان خادم الويب مثل http://www.google.com:80، حيث ينبغي أن تفتح الصفحة بلا مشاكل لأن المتصفح يتصل بالمنفذ 80 افتراضيًا إن لم يتوفر منفذ آخر، لهذا يكثر استخدام المنفذ 8080 مثل منفذ اختبار للإصدارات الجديدة من مواقع الويب قبل إطلاقها. ورغم قلة عدد تلك المنافذ المحجوزة إلا أننا نستطيع استخدام أرقام المنافذ التي بين 1000 و60000 للتطبيقات المخصصة bespoke applications دون تعارض، لكن يفضل جعل رقم المنفذ قابلًا للإعداد من خلال متغير لبيئة النظام مثلًا، أو ملف إعدادات config file، أو بواسطة معامل سطر أوامر، نظرًا لوجود احتمال -ولو ضئيل- أن يختار برنامج آخر نفس المنفذ على الحاسوب، ولن نشرح ذلك هنا لكن يجب الانتباه إلى أنه وارد في التطبيقات الحقيقية، حين لا يكون لدينا تحكم كامل بحاسوب الخادم، لذا يجب اتخاذ مثل تلك الاحتياطات. بعد أن عرفنا الآلية، فإن السؤال التالي هو: كيف نصل الشيفرة بأحد تلك المنافذ؟ المقابس Sockets المقابس هي أبسط آلية اتصال يمكن استخدامها بين الشبكات، وفيها يُقدَّم المقبس للشبكة على أنه منفذ في عنوان IP، وتُنشأ المقابس في بايثون وتُستخدم من خلال استيراد وحدة socket، ويجب أن نكتب خادمًا لينشئ المقبس، ويربطه مع منفذ، لنتمكن بعدها من استخدامه، ونراقب ذلك المقبس منتظرين الطلبات الواردة إليه، ثم نكتب عميلًا ليتصل بالمقبس على ذلك المنفذ، ثم يتصل العميل بالمنفذ ويقبل الخادم ذلك الاتصال، ثم ينشئ الخادم منفذًا مؤقتًا جديدًا يُستخدم لعملية التواصل -أي عمليات الإرسال والاستقبال send/recv الفعلية- مع الخادم أثناء عملية النقل، مما يحرر المنفذ لمزيد من طلبات الاتصال. يمكن توضيح ما سبق في الصورة التالية: تظهر هنا مشكلة اختبار مثل تلك التطبيقات، إذ لا نستطيع أن نعرف إن كان الخادم يعمل أم لا بدون العميل، كذلك فإن العميل لا يستطيع فعل شيء دون الخادم، لذا ينبغي أن يكون لدينا كل من العميل والخادم. غير أنه يمكن إنشاء أي عدد من العملاء الآخرين بمجرد كتابة الخادم، شرط أن يتصلوا بمقبسه من خلال بروتوكول الرسائل المناسب، ونرى أمثلة ذلك في متصفحات الويب المختلفة التي تستطيع جميعها أن تتصل بأي خادم http، ويمكن بطريقة مماثلة كتابة العديد من الخوادم المختلفة بمجرد نشر البروتوكول، وينبغي هنا ألا توجد مشكلة في عمل أي عميل وأي خادم معًا، وهذا السلوك هو أحد أسباب انتشار تلك التطبيقات، فهو يشكل بيئةً مفتوحةً وقابلةً للتوسع، تكون فيها إحدى نهايات أي زوج من أزواج العميل/الخادم قابلةً للتحسين دون تعطيل النهاية الأخرى. إنشاء الخادم سننشئ خادمًا بسيطًا يستجيب للطلبات بأن يعيد رسالة ترحيب وعدد الطلبات التي عالجها من قبل. import socket # STREAMing و InterNET أنشئ مقبس # TCP/IP المعروف باسم serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # والمنفذ 2007 localhost استخدم serversocket.bind(('localhost', 2007)) # استعد لاستقبال الطلبات serversocket.listen(5) connections = 0 while True: # عالج الاتصالات من العملاء (clientSocket, address) = serversocket.accept() connections += 1 print( "Connection %d using port %d" % (connections, address[1]) ) # clientSocket افعل شيئًا باستخدام while True: req = clientSocket.recv(100) if not req: break # client closed connection message = 'Thankyou!, processed connection number %d' % connections clientSocket.send(message) clientSocket.close() نلاحظ هنا عدة أمور: يشير هذا المزيج من AF_INET وSOCK_STREAM إلى أننا سنستخدم بروتوكول TCP/IP، وكل بروتوكولات عناوين IP الأخرى متاحة من خلال استخدام تجميعات ثوابت أخرى، لكن TCP/IP هو الأشهر منها وهو ما سنستخدمه. مررنا القيمة 5 إلى listen()‎، وهي تمثل العدد الأقصى للاتصالات التي يمكن أن تنتظر في طابور المنفذ، لأننا نُعالج الطلب قبل أن تتجمع طلبات كثيرة في قائمة الانتظار تلك، ونشتق عمليةً مستقلةً لتنفيذ المعالجة الحقيقية إذا أردنا تحسين كفاءتها -انظر الملاحظة الخامسة أدناه-، مما يسمح للخادم أن يسحب الرسائل من قائمة الانتظار في أسرع وقت ممكن، ولا نحتاج زيادة عدد الاتصالات المسموح لها بالانتظار عن 5 اتصالات إلا في حالة الخوادم شديدة الزحام. ينشئ العملاء اتصالًا جديدًا لكل عملية تبادل بيانات، ولا تكون لدينا بيانات متاحة إذا انتهت عملية التبادل، وحينئذ ننهي حلقة while الداخلية ونعود إلى انتظار اتصال جديد. عالجنا طلب العميل في شيفرة الخادم، ولا بأس بهذا لأنها معالجة طفيفة، لكنها قد تستغرق وقتًا كبيرًا إذا كانت في أحد التطبيقات التجارية الكبيرة، عندها نشتق عمليةً أخرى في تلك الحالة لمعالجة تلك العملية خاصةً -ربما باستخدام وحدة subprocess التي ذكرناها في مقال نظم التشغيل-، ونترك الخادم يعود لسحب الطلبات من قائمة انتظاره. لا توجد طريقةً لإنهاء عملية الخادم، فهي تعمل بلا نهاية إلا إذا حدث خطأ، فإذا أردنا إنهاءها فسنستخدم أداةً من نظام التشغيل نفسه، من خلال برنامج TaskManager في ويندوز مثلًا، أو kill في يونكس. ينبغي أن يكون الخادم جاهزًا للعمل الآن وينتظر طلبات العملاء، لكن ليس لدينا عميل ليرسل تلك الطلبات، لذا سننشئه الآن. إنشاء العميل إنشاء العميل client هي عملية سهلة بقدر سهولة إنشاء الخادم، إذ يرسل طلبات متكررةً إلى الخادم بفواصل زمنية قدرها ثانية واحدة، ويطبع استجابة الخادم: import socket,time # أنشئ المقبس serverAddress = ('localhost',2007) # أرسل بعض الطلبات for n in range(5): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(serverAddress) try: sock.send('dummy request\n') data = sock.recv(100) if not data: break # لا توجد بيانات من الخادم print( data ) time.sleep(1) finally: # نرتب الآن ما سبق sock.close() لدينا بعض الملاحظات هنا: نستخدم connect للوصول إلى المقبس، ثم نستخدم نفس واجهة send/recv التي يستخدمها الخادم، لكن يكون التسلسل معكوسًا لأن العميل هو الذي يبدأ عملية تبادل البيانات. كان من الممكن إرسال أو استقبال بيانات أكثر في عملية واحدة، لكننا اخترنا هذه الطريقة ببساطة لإبراز أرقام الاتصال المختلفة القادمة من الخادم، فالعميل هو الذي يقرر متى ينهي عملية التبادل وليس الخادم، إلا إذا حدث خطأ ما. لاحظ استخدام try/finally لضمان إغلاق المقبس حتى في حالة رفع استثناء exception، وهذا مفيد لتقليل المراجعة والتصحيح لاحقًا، لأن بعض أنظمة التشغيل تترك المقابس مفتوحةً لفترة طويلة، مما يعني أنها ستستهلك موارد النظام. تشغيل البرامج نريد أن نتأكد أن الخادم يعمل أولًا قبل أن نستطيع تشغيل البرامج، ثم نبدأ برنامج عميل واحد أو أكثر ليتصل به، ولا نستطيع تشغيل هذه البرامج عبر الشبكة لأننا جعلنا الخادم على الحاسوب المحلي فقط localhost، لذا نحتاج إلى بدء عدد من جلسات الطرفية على حاسوبنا. توضح الصورة التالية الخادم وهو يعمل على يمين الصورة، واثنين من العملاء على يسارها: لاحظ أن خرج كلا العميلين يُظهر تسلسل الرسائل التي استلمت من الخادم، وتُظهر رسائل الخادم الاتصالات وأرقام المنافذ المؤقتة المسندة إلى الخادم. دليل جهات الاتصال الشبكي بنينا في المقال السابق: التواصل بين العمليات نسخةً تعمل على خادم من دليل جهات الاتصال الذي نطوره، وسميناها address_srv.py، وسنستخدمها في هذا المقال لبناء نسخة مبنية على المقابس، وسيكون الاختلاف الواضح بين نسخة IPC السابقة وبين هذه النسخة هو إمكانية وجود أكثر من عميل واحد يستطيع الوصول إلى دليل جهات الاتصال، وسيكون العملاء على حواسيب مختلفة قطعًا. وكانت الدوال التي المتاحة في address_srv هي: ‎readBook(filename)‎ ‎saveBook(book,filename)‎ ‎addEntry(book, name, data)‎ ‎removeEntry(book, name)‎ ‎findEntry(book, name)‎ برنامج الخادم لا زلنا بحاجة إلى كتابة برنامج خادم يعالج الطلبات الواردة من العملاء ويستدعي الدالة المناسبة، رغم أننا حولنا البرنامج إلى دوال مخدمات server style functions في المرة السابقة، وتسمى مثل تلك الآلية ببعث الرسائل dispatching messages، وستكون الشيفرة شبيهةً للغاية بالأمثلة البسيطة السابقة. سيكون البرنامج الرئيسي كما يلي: import socket, address_srv addresses = address_srv.readBook() # أعد المقبس serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.bind(('localhost', 2007)) serversocket.listen(5) print( 'Server started and listening on port 2007...' ) # عالج الاتصالات من العملاء while True: (clientSocket, address) = serversocket.accept() # عالج أوامر دليل جهات الاتصال while True: s = clientSocket.recv(1024) try: cmd,data = s.split(':') except ValueError: break print( 'received request: ', cmd ) if cmd == "add": details = data.split(',') name = details[0] entry = ','.join(details[1:]) s = address_srv.addEntry(addresses, name, entry) address_srv.saveBook(addresses) elif cmd == "rem": s = address_srv.removeEntry(addresses, data) address_srv.saveBook(addresses) elif cmd == "fnd": s = address_srv.findEntry(addresses, data) else: s = "ERROR: Unrecognised command: " + cmd clientSocket.send(s) clientSocket.close() نلاحظ هنا أن شيفرة المعالجة الرئيسية للمقبس هي نفسها الشيفرة السابقة، بينما وضعنا معالجة بيانات الطلب في بنية try/except لالتقاط البيانات غير المكتملة من العميل، أما غير ذلك فإن هذه النسخة تكاد تطابق نسخة IPC في المقال السابق. برنامج العميل صار لدينا الآن خادم يعمل في الخلفية، ونريد كتابة برنامج عميل يتحدث إليه، وسيكون مشابهًا لنسخة IPC أيضًا، لكنه سيوجد في سكربت خاصة به، وسنتمكن من تشغيل أكثر من نسخة في نفس الوقت: import socket serverAddress = ('localhost', 2007) menu = ''' 1) Add Entry 2) Delete Entry 3) Find Entry 4) Quit ''' # اتصل بالخادم sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(serverAddress) while True: print( menu ) try: choice = int(input('Choose an option[1-4] ')) except: continue if choice == 1: name = input('Enter the name: ') num = input('Enter the House number: ') street= input('Enter the Street name: ') town = input('Enter the Town: ') phone = input('Enter the Phone number: ') data = "%s,%s %s, %s, %s" % (name,num,street,town,phone) cmd = "add:%s" % data elif choice == 2: name = input('Enter the name: ') cmd = 'rem:%s' % name elif choice == 3: name = input('Enter the name: ') cmd = 'fnd:%s' % name elif choice == 4: break else: print( "Invalid choice, must be between 1 and 4." ) continue # تحدث إلى الخادم try: sock.send(cmd) data = sock.recv(250) if not data: break # no data from server print( data ) finally: sock.close() نلاحظ هنا أن عملية معالجة القائمة هي نفسها في المثال السابق، وأن أوامر الاتصالات مجموعة في بضعة أسطر في الأسفل، وهذا أيضًا مشابه لمثال العميل الذي تقدم شرحه. الانتقال إلى الشبكة كانت مقابسنا إلى الآن على حاسوب محلي، ونريد أن ننقلها إلى شبكة حقيقية ويكون لدينا عمليات عميل/خادم حقيقية أيضًا، ويسهل تنفيذ ذلك بتغيير العناوين المستخدمة في استدعاء bind()‎ في الخادم واستدعاء connect()‎ في العميل، واستبدال عنوان IP -سواءً النسخة الرقمية أو الاسمية منه- للحاسوب الذي يعمل عليه الخادم بالمرجع المشير إلى 'localhost'، ويمكن تشغيل عدة نسخ من العميل على كل حاسوب في نفس الوقت إذا كان لدينا عدة أجهزة على نفس الشبكة، وسيعالج الخادم الطلبات من تلك النسخ. أما في الحياة العملية فقد نبذل مزيدًا من الجهد في التعامل مع تحليل أسماء DNS مثلًا، ونضيف اختبارات تتحقق من الأخطاء وآليات المهل الزمنية timeouts لكي لا يُعلِّق الخادم ويتأثر، لأن الشبكات الحقيقية أقل موثوقيةً وأكثر عرضةً للأخطاء، غير أننا لن نتحدث عن تلك الآليات والمهام، وإنما نذكرها فقط لوجوب حسابها عند حل مثل تلك المشكلات. المزيد من المعلومات كُتبت الكثير من الشروحات في برمجة المقابس، لعل أبرزها Socket How-To الذي كتبه جوردُن ماكمِلان Gordon McMillan، وهو يشرح كثيرًا من عيوب برمجة المقابس ويقدم الحلول المقترحة للتعامل معها، إضافةً إلى توثيق وحدة socket في بايثون، والذي لا غنى عن قراءته. كما تحتوي العديد من الكتب على أقسام عن البرمجة باستخدام المقابس، ونخص بالذكر منها كتاب Python Network Programming الذي كتبه جون جورزن John Goerzen، ويدور حول برمجة الشبكات مغطيًا كثيرًا من جوانب برمجة المقابس. والجميل في الأمر أنه يمكن تنفيذ أغلب مهام برمجة الشبكات بمستوىً أعلى إذا كنا نستخدم أحد بروتوكولات الإنترنت القياسية، مثل http و smtp و telnet وغيرها، ففي بايثون مثلًا وحدات تنفذ تلك البروتوكولات في طبقة المقابس لئلا نضطر نحن إلى ذلك، وسندرس في المقالات القادمة كيف نبسط برمجة الويب باستخدام http، من خلال وحدات المستوى الأعلى تلك، أما عند اختيار العمل في برمجة الشبكات ليكون تخصصًا مهنيًا فتُستخدم لغة rebol لأنها تولي أهميةً لخصوصية المهام، وفيها دعم للعديد من مهام الشبكة. وإن أردت التعمق أكثر في الشبكات، فقد ترجمت أكاديمية حسوب كتابًا مهمًا ونشرت مقالاته تحت وسم "أساسيات الشبكات " يمكنك الرجوع إليه. خاتمة نرجو في نهاية هذا المقال أن تكون تعلمت ما يلي: تمثَّل اتصالات شبكات الحواسيب بعناوين IP ومنافذ ports. تتصل المقابس بالمنافذ. تراقب مقابس الخوادم الاتصالات وتستمع لها عبر listen، وتقبلها إذا التقطتها بواسطة accept، وهذا يحدد منفذًا جديدًا ليستخدمه العميل الجديد. يجب أن تستقبل الخوادم رسائل العملاء على المنفذ الجديد من خلال recv، وترسل send الردود إلى العملاء. يتصل عملاء المقابس بمقبس الخادم من خلال connect، ويرسلون البيانات إليه من خلال send، ثم يستقبلون البيانات مرةً أخرى عبر recv في صورة ردود. يغلق العميل المقبس باستخدام close عند انتهاء عملية تبادل البيانات. ترجمة -بتصرف- للفصل السابع والعشرين: Network Communications من كتاب Learn To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: كيفية التعامل مع الويب المقال السابق: التواصل بين العمليات في البرمجة المدخل الشامل لتعلم علوم الحاسوب مدخل إلى شبكات الحواسيب: مصطلحات وفهم طبقات الشبكة البرمجيات المستخدمة في بناء الشبكات الحاسوبية معمارية الشبكة الحاسوبية وشبكة الإنترنت (Network Architecture)
×
×
  • أضف...