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

لوحة المتصدرين

  1. محمد الخضور

    محمد الخضور

    الأعضاء


    • نقاط

      3

    • المساهمات

      21


  2. أحمد عصام9

    أحمد عصام9

    الأعضاء


    • نقاط

      2

    • المساهمات

      3


  3. سجى الحاج

    سجى الحاج

    الأعضاء


    • نقاط

      1

    • المساهمات

      13


  4. Ola Abbas

    Ola Abbas

    الأعضاء


    • نقاط

      1

    • المساهمات

      189


المحتوى الأكثر حصولًا على سمعة جيدة

عرض المحتوى الحاصل على سمعة أكبر منذ 08/29/25 in مقالات البرمجة

  1. سنبدأ في هذا المقال من سلسلة برمجة الذكاء الاصطناعي في تعلم أساسيات لغة بايثون، وهي من أهم لغات البرمجة على الإطلاق المستخدمة في مجال الذكاء الاصطناعي، ولكنها ليست لذلك فقط؛ إذ تُستعمَل لغة بايثون في كثير من المجالات الأخرى مثل برمجة المواقع وبرامج سطح المكتب وأنظمة التشغيل وغيرها. قبل البدء في أساسيات لغة بايثون: ما هي لغة البرمجة بايثون؟ تعني بايثون في اللغة الإنجليزية نوعًا من الثعابين الكبيرة، لكنها لم تُسمى لذلك بل سُمِّيَت بهذا الاسم تيمنًا ببرنامج ترفيهي قدَّمته قناة BBC يحمل اسم Monty Python’s Flying Circus، وذلك بعد ما شاهده مخترع اللغة. وتُعَدّ بايثون لغةً برمجيةً عامةً، أي تستطيع استخدامها في مجالات عدة على عكس بعض اللغات الأخرى التي تتخصص في مجال ما دونًا عن الآخر، كما تُعَدّ لغةً بسيطةً ومتطورةً للغاية، بالإضافة إلى أنها تدعم البرمجة كائنية التوجه Object Oriented Programming أو OOP اختصارًا. صُنِعت بايثون بواسطة الهولندي جايدو فان روسم Guido van Rossum، وأُصدِرت في شهر 11 من عام 1994م بعدما عُمِل عليها في معهد الأبحاث القومي للرياضيات وعلوم الحاسوب في هولندا، في حين نُشر الإصدار الثاني من بايثون في عام 2000م؛ أما الإصدار الثالث، فقد نُشِر في عام 2008م وهو الإصدار المستخدم حاليًا من بايثون لأن الإصدار الثاني السابق قد توقف دعمه وتطويره. خصائص لغة بايثون تُعَدّ لغة بايثون لغةً مفتوحة المصدر تجد شيفرتها المصدرية على موقع GitHub، وبالتالي يستطيع أيّ مبرمج المشاركة في تطوير اللغة. وبحسب موقع جيت هاب GitHub، فقد شارك أكثر من 1200 شخص حول العالم في تطويرها، كما تُعرَف بايثون بسهولة تراكيب الجمل فيها Syntax التي تشبه تركيب اللغة الإنجليزية بنسبة كبيرة، وهي لغة مهمة جدًا للطلبة والباحثين والمهنيين على حد سواء في الكثير من النطاقات العلمية والعملية. وتتميز بايثون بالميزات التالية: لغة برمجة مفسرة Interpreted تدعم البرمجة الكائنية مناسبة للمبتدئين مدعومة بالكثير من المكتبات لغة مجانية ومفتوحة المصدر تستخدم في العديد من التخصصات لغة برمجة مفسرة Interpreted أي أنها تُنفَّذ مباشرةً مثل لغة PHP ولغة Perl، ولا تحتاج إلى تصريف كامل الشيفرة أولًا ثم تنفيذها مثل لغة C، فلا يتطلب الأمر تحويل الشيفرة الخاصة بك إلى شيفرة ثنائية تفهمها الآلة أولًا لتبدأ عملية التنفيذ، وهذا قد يميز شيفرات بايثون في سرعة تنفيذها أثناء البرمجة. وفي تلك النقطة بالتحديد قد يختلف بعض المبرمجين، فالبرغم من تصنيف بايثون أنها لغة مفسَّرة، إلا أنّ الشيفرة تُصرَّف compiled أولًا ليستطيع المُفسِّر فهمها قبل تنفيذها، لذلك قد تجد بعض النقاشات المتباينة حول بايثون لمحاولة تصنيفها تصنيفًا دقيقًا. يذهب بعض المبرمجين إلى القول بأنّ لغة بايثون لها طريقتها الخاصة في تلك النقطة، فالأمر معقَّد ولا نريد الخوض فيه. تدعم البرمجة الكائنية تدعم بايثون نمطًا يُدعى الكائنية في البرمجة Object-oriented programming (أو تدعى الشيئية أحيانًا)، وهو نمط شهير ومهم، إذ تُكتَب الشيفرة ويُتعامَل مع أجزاء التطبيق على أساس الكائنات Objects، وهو نمط غير مدعوم في بعض اللغات القديمة مثل لغة C، كما أنها تدعم البرمجة الوظيفية Functional والهيكلية Structured وغيرها. أساسيات لغة بايثون مناسبة للمبتدئين تُعَد بايثون مناسبةً جدًا للمبتدئين، حيث أنَّ صياغة الجمل فيها بسيطة للغاية، ولا يتطلب الأمر الدخول في تفاصيل كثيرة عند كتابتها؛ لذلك فهي سهلة التعلم والقراءة. مدعومة بالكثير من المكتبات يمكنك في بايثون إيجاد مكتبات بسيطة الاستخدام تستطيع بها برمجة تطبيقات معقدة جدًا، فهي لغة لديها أرشيف واسع من المكتبات في كافة المجالات تقريبًا. لغة مجانية ومفتوحة المصدر توجد بعض لغات البرمجة غير المجانية، أي أنك مُطالَب بدفع الأموال لشركة ما، كي تستطيع استخدام تلك اللغة، كما أنَه لا يمكنك ولا يمكن لأيّ شخص آخر إصلاح مشكلة ما في اللغة أو أن يطوِّر ميزةً أو خاصيةً جديدةً في اللغة، فالشيفرة المصدرية في تلك الحالة تقع تحت أيدي الشركة المصنعة فقط، وهي الوحيدة التي يحق لها تطوير اللغة أو إصلاح مشاكلها أو إصدار نسخ جديدة منها. أما في بايثون والعديد من اللغات المجانية المفتوحة المصدر، فالأمر مختلف إذ عمِل على على لغة بايثون أكثر من 1200 شخص حول العالم، فالشيفرة المصدرية للغة موجودة ومتاحة على موقع GitHub، ويمكن لأيّ شخص له الخبرة والمعرفة الكافية أن يطوِّر أو يعدِّل ميزةً ما، كما يستطيع مجتمع مبرمِجي بايثون على الإنترنت من المشاركة بآرائهم في تطوير اللغة، فالأمر بالجميع وللجميع، وهي لغة مجانية بالكامل تستطيع استخدامها في أيّ مشروع خيري أو تجاري، بدون أية مشاكل قانونية على الإطلاق. تستخدم في العديد من التخصصات لا يقتصر الأمر أبدًا على برمجة الذكاء الاصطناعي وتعلّم الآلة، ولا يقتصر على برمجة مواقع الويب أيضًا، إذ تُعَدّ بايثون من أكثر لغات البرمجة انتشارًا وتوغلًا في العديد من المجالات في حياتنا اليومية، وفي التخصصات العلمية والأبحاث ومعامل ومختبرات الجامعات حول العالم، لذلك بتعلُُّمك للغة بايثون فإنّ الأمر لا يقتصر على فرصة عمل في مجال الذكاء الاصطناعي فحسب، وإنما تستطيع استخدام معرفتك وخبرتك في بايثون في مجالات أخرى تفتح عليك أبواب دخل إضافية. تُشتهر بايثون أيضًا في استخدامها في برمجة المواقع وتطبيقات سطح المكتب وبرمجة برامج تجارية عبر بايثون مثل أودوو Odoo الذي يُعَدّ أشهرها وله متخصصين وشركات تجارية تعتمد كليةً على استخدامه. كما أنَّ لغة بايثون كما أوردنا تدخل في الكثير من مجالات البحث العلمي، فهي من أكثر اللغات التي تحتوي على مكتبات تهدف إلى خدمة مجالات البحث العلمي والرياضيات من الذكاء الاصطناعي حتى التغير المناخي وتُعَد دراسة لغة بايثون أمرًا أساسيًا بالنسبة لمبرمجي الذكاء الاصطناعي، لذلك سنبدأ الآن في دراسة أساسيات اللغة حتى نكون على قدر من المعرفة المطلوبة لنبدأ في دراسة وتطبيق الخوارزميات الأساسية في تعلُّم الآلة. لذلك فإن السهل البدء بتعلم أساسيات بايثون والبدء في عالم البرمجة بسهولة. تثبيت لغة بايثون أول ما نبدأ به في تعلم أساسيات لغة Python ولكي تستطيع العمل بلغة بايثون، يجب عليك أولًا تثبيت البرنامج الذي يفهم اللغة ثم ينفذها، وذلك لكي يستطيع حاسوبك التعرف على الأوامر التي تكتبها لتعمل عليه بصورة صحيحة، لذلك من الضروري أن تكون أول خطوة نقوم بها هي تثبيت لغة بايثون على حاسوبك. يختلف أمر تثبيت اللغة باختلاف نظام التشغيل، فإذا كان حاسوبك مثلًا يعمل على نظام لينكس Linux، فعلى الأرجح أنّ حاسوبك مثبَّت عليه بالفعل لغة بايثون، وللتأكد من ذلك يمكنك فتح الطرفية Terminal ثم كتابة الأمر الآتي: >> python --version أول الأمر التالي بالنسبة للإصدار الثالث: >> python3 --version إذا كانت بايثون مثبتةً بالفعل على حاسوبك، فسيظهر لك رقم الإصدار المثبَّت، والجدير بالذكر أنه يجب أن يكون الإصدار المثبت لديك هو الإصدار الثالث، وبالتالي يجب بدء رقم الإصدار بالرقم 3؛ أما إذا لم تكن اللغة مثبتةً على حاسوبك، فيمكنك ذلك عبر تنفيذ الأمر الآتي في الطرفية Terminal على لينكس. >> sudo apt-get install python3.6 أما إذا كنت مستخدِمًا لنظام التشغيل ماك macOS بمختلف إصداراته، فعلى الأغلب أيضًا أنّ لغة بايثون مثبتة بالفعل على حاسوبك، وتستطيع اختبار ذلك عبر الأمر السابق ذكره بخصوص نظام لينكس، فإذا لم تكن اللغة مثبتةً، فيمكنك ببساطة تثبيتها مثل أيّ برنامج أخر عن طريق الموقع الرسمي للغة /Python. بعد تثبيت اللغة بالطرق الموضحة أعلاه في نظامي لينكس وماكينتوش، فمن المحتمل ألا يعمل أمر التحقق من الإصدار وألا يكون جاهزًا للعمل بعد، إذ أنه قد لا يُتعرَّف على برنامج بايثون عندما تُنفِّذ الأمر التالي: >> python --version ولحل ذلك يجب تنفيذ الأمر التالي في الطرفية Terminal: >> export PYTHONPATH=/usr/local/bin/python3.6 مع تغيير كلمة python3.6 لأنها قد تختلف حسب الإصدار الذي ثبَّته؛ لذلك يجب التحقق من ذلك المسار على حاسوبك أولًا لترى أيّ الإصدارات يجب استدعاؤها في الأمر السابق. أما في حالة مستخدمي نظام الويندوز، فالأمر بسيط للغاية، إذ تستطيع تنزيل برنامج اللغة من الموقع الرسمي السالف ذكره، ثم تثبيته مثل أيّ برنامج آخر على حاسوبك دون تعقيدات قد لا يعمل كذلك أمر التحقق من إصدار اللغة بصورة تلقائية بعد التثبيت، ولحل ذلك ببساطة يمكنك فتح موجِّه الأوامر Command Prompt في ويندوز ثم تنفيذ الأمر الآتي: >> %path%;C:\Python مع الأخذ في الحسبان إمكانية تغيير النص C:\Python إذا كنت قد تثبَّت اللغة في مسار آخر على حاسوبك أثناء عملية التثبيت. استعمال بايثون مع خدمة Google Colab ضمن أساسيات لغة بايثون وبالرغم من سهولة عملية تثبيت بايثون على حاسوبك، فإنه ليس من الضروري فعلًا فعل تلك الخطوات السالف ذكرها، فقد أصدرت شركة جوجل مؤخرًا ما يُدعى Google Colaboratory عبر موقع الأبحاث الخاص بها \colab.research، وبالتالي تستطيع ببساطة استخدام تلك الخاصية بإنشاء ذلك النوع من الملفات على خدمة Google Drive الموجودة مجانيًا لأي عنوان بريد إلكتروني مُسجَّل على Gmail، بعدها يمكنك البدء في كتابة وتنفيذ شيفرة البايثون الخاصة بك عبر الإنترنت دون الحاجة إلى الدخول في الكثير من التعقيدات والمشاكل التقنية أثناء تعلمك، أو حتى أثناء عملك في برمجة الذكاء الاصطناعي. كما تحتوى تلك الخدمة تلقائيًا على معظم وأهم مكتبات بايثون المستخدَمة في مجال الذكاء الاصطناعي عامةً ومجال تعلّم الآلة خاصةً، فنجد مثلًا تلقائيًا في تلك الخدمة أنّ مكتبات متخصصة في الرياضيات مثل Numpy، ومكتبات متخصصة في رسم البيانات مثل Matplotlib ومكتبات متخصصة في خوارزميات تعلّم الآلة مثل Keras، ومكتبات متخصصة في التعلّم العميق والشبكات العصبية مثل Tensorflow …إلخ مثبتة ومتاحة للاستخدام مباشرةً. أُصدِرت الخدمة أساسًا للتسهيل على العاملين في مجال برمجة الذكاء الاصطناعي، وبالأخص تعلُّم الآلة ليستطيع المبرمج مشاركة الشيفرة المصدرية الخاصة به مع نتائج هذه الشيفرة والملاحظات مع شركائه في العمل أو أي شخص آخر، وهي خدمة سحابية بالكامل، أي أنها تعمل عبر الإنترنت ولا تحتاج إلى أي متطلبات أو إمكانيات في حاسوبك، فكل ما تحتاجه لاستخدام الخدمة هي وصلة الإنترنت وعنوان بريد إلكتروني من Gmail. أفضِّل شخصيًا استخدام تلك الخدمة أثناء التعلم لأنها بسيطة وسهلة، وتحتوي تلقائيًا على الكثير من مكتبات بايثون الخاصة بالذكاء الاصطناعي التي قد يكون تثبيت بعضها عملًا شاقًا إذا حدث خطأ ما أثناء التثبيت والسبب الآخر الذي يدفعني إلى التوصية باستخدام تلك الخدمة بشدة، هو عدم امتلاك بعض أجهزة الحاسوب للإمكانيات اللازمة لتشغيل نماذج تعلّم الآلة، إذ تحتاج بعض الخوارزميات إلى ذاكرة عشوائية RAM كبيرة ليُدرَّب النموذج تدريبًا صحيحًا، وذلك اعتمادًا على حجم البيانات المتدفقة إلى النموذج. ولمزيد من التفاصيل، ارجع إلى مقال دليل استخدام Google Colab. برنامجك الأول في لغة بايثون من أساسيات لغة بايثون أنك تستطيع البدء في كتابة برنامجك الأول بعدة من الطرق، أولها عبر كتابة الشيفرة مباشرةً في الطرفية Terminal في لينكس وماك وموجِّه الأوامر Command Prompt في ويندوز؛ وثانيها، كتابة البرنامج في ملف أو عدة ملفات منفصلة، ثم تشغيلها عبر البرامج السابق ذكرها؛ أما ثالثها فتكون عن طريق خدمة Google Colab التي ذكرناها سابقًا. أما كتابة الشيفرة مباشرة في الطرفية وموجه الأوامر، فالخطوات لذلك بسيطة، وكل ما عليك فعله بعد فتح أحد تلك البرامج حسب نظام التشغيل الخاص بحاسوبك هو تنفيذ الأمر الآتي: >> python أو الأمر التالي بالنسبة للإصدار 3 من بايثون: >> python3 تستطيع بعد ذلك كتابة أوامر بايثون مباشرةً وتنفيذها، كما يمكنك الخروج من هذه الشاشة بعد ذلك عبر كتابة الأمر الآتي: >> quit() وأما كتابة الشيفرة في ملف منفصل، فتستطيع إنشاء ملف جديد في أيّ مكان في حاسوبك وتسميته بأيّ اسم تريده، كما يفضَّل أن يكون الاسم معبِّرًا، فالتسمية البسيطة والمعبِّرة من الأمور المهمة. احفظ بعد ذلك الملف بصيغة py -وهي صيغة اختصارية لكلمة Python-، فإذا كان مثلًا اسم الملف Program، فستكون التسمية الكاملة للملف Program.py، ثم اذهب إلى المكان المخزن فيه الملف غبر الطرفية أو موجِّه الأوامر، وبعدها نفِّذ الأمر التالي: >> python Program.py والطريقة الثالثة، تستطيع ببساطة استخدام Google Colab من خدمة Google Drive ومن ثم إنشاء ملف جديد من نوع Google Colaboratory، ثم البدء في إضافة الفقرات، فيمكنك إضافة شيفرات بايثون في ذلك الملف بجانب نصوص عادية وبذلك تستطيع كتابة ملاحظات وتعليقات بين أسطر الشيفرات ويمكنك في الوقت نفسه تنفيذ الشيفرات ككل أو أجزاء محددة. سنبدأ بأمر الطباعة لكتابة أول برنامج بايثون خاص بك، فوظيفة أمر الطباعة في بايثون وفي كثير من اللغات الأخرى، هي طباعة نص على شاشة المستخدِم عند تشغيل البرنامج، وقد ذكرنا ذلك الأمر سابقًا عند الحديث عن الخوارزميات في البرمجة، فعند كتابة الأمر print والذي يعني اطبع بالإنجليزية، فيجب إلحاقه بقوسين، ومن ثم فتح علامات تنصيص بداخل القوسين تحتوى على الجملة التي نريد طباعتها. print ("Hello World") قد يُستخدَم الأمر print لطباعة النصوص على الشاشة أو لطباعة الأرقام، فالأمر سيان في حالة الطباعة، ولكن لا يجب إضافة علامات تنصيص في حالة طباعة الأعداد. print (3) >> 3 كما أنه من الممكن طباعة نتيجة عملية رياضية بسيطة مثل عمليات الجمع والطرح كما في الأمثلة الآتية: print (3+3) >> 6 print (6-4) >> 2 يمكن أيضًا طباعة عمليات الضرب والقسمة وباقي القسمة، إذ يمكنك عبر كتابة الشيفرة التالية طباعة حاصل ضرب عددين مثلًا: print (6*6) >> 36 والأمر بسيط كذلك لطباعة حاصل قسمة عددين: print (49/7) >> 7.0 أما حالة طباعة باقي القسمة، فسنستخدِم رمز النسبة المئوية %: print (50%7) >> 1 كما يمكنك طباعة أيّ عدد من النصوص باستخدام علامة الزائد + كما في المثال الآتي: print ("Hello " + "World!") >> Hello World! إذا أردنا تضمين قيمة عددية داخل نص، فيجب فيجب تحويل العدد إلى نص لأنّ الأعداد في بايثون وفي عدد من اللغات الأخرى عمومًا هي نوع من أنواع البيانات، لذلك يجب استخدام دالة str في هذه الحالة لتحويل العدد إلى نص لتستطيع لغة بايثون التعامل معها على أساس نص. print ("Hello "+str(2)+"nd "+"World!") >> Hello 2nd World! نستطيع الاستغناء عن دالة str إذا أدرجنا الأعداد داخل علامات التنصيص، إذ ستَعُدّ بايثون الأعداد داخل علامات التنصيص نصًا عاديًا، كما سنتعرف على الدوال بصورة أكبر في الصفحات القادمة. print ("Hello " + "2nd " + "World!") >> Hello 2nd World! المعرفات في بايثون تعد المعرِّفات Identifiers من أساسيات البايثون وهي الكلمات التي تستطيع من خلالها تعريف اسم متغير Variable أو ثابت Constant أو دالة Function أو صنف Class أو وحدة Module، ونختصر ذلك كله الآن بكلمة المعرِّفات فقط للدلالة على أيّ منهم، فتلك المتغيرات والثوابت والدوال والأصناف والوحدات، كلها مواضيع وسنتعرف عليها بالتفصيل في هذا الكتاب. تخضع تسمية المعرفات إلى قواعد محدَّدة لا يُمكن الخروج عنها في بايثون؛ لأنه عند الخروج عن إحدى القواعد سيطبع مفسر بايثون رسالة خطأ عند محاولتك تشغيل البرنامج، وتلك القواعد كما يلي: يجب أن تبدأ بحرف إنجليزي أو شَرطة سفلية Underscore _ ولا يُمكنها البدء برقم أبدًا. لا يمكنها احتواء رموز مثل % أو $ أو & …إلخ، ولكن يمكنها احتواء الأرقام. ألا تكون مطابقةً لأيّ كلمة من الكلمات المفتاحية في بايثون. الكلمات المفتاحية في بايثون هي كلمات تُستخدَم في أصل اللغة، بمعنى أنّ تلك الكلمات يقرؤها مفسر لغة بايثون لإجراء مهمة ما، فكلمة مثل print كما علمنا من قبل تؤدي مهمة طباعة نص أو عدد على الشاشة، لذلك لا نستطيع تعريف متغير أو ثابت أو دالة بهذا الاسم، وتكون جميع الكلمات المفتاحية في لغة بايثون كما يلي: 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; } and exec not as finally or assert for Pass break from print class global raise continue if return def import try del in while elif is with else lambda yield except والجدير بالذكر أنّ جميع تلك الكلمات المفتاحية لا تحتوي على أي حرف كبير، وبما أنّ لغة بايثون لغة حساسة لحالة الأحرف، فمن تسمية أيّ معرِّف بتلك الكلمات في حالة تغيير حالة الأحرف، بمعنى أنه لا يُمكنك تسمية متغير باسم print، لكن يمكنك تسمية متغير باسم Print أو PRINT لأنه بالنسبة لبايثون، تكون الكلمات الثلاثة السابقة مختلفةً تمامًا عن بعضها، وبناءً على ذلك، فإذا أردت تسمية متغير أو دالة أو صنف في بايثون، فيجب عليك اتباع القواعد السابقة. كما أنّ هناك أيضًا في بايثون بعض التوصيات أثناء التسمية، وهي ليست قواعدًا يجب اتباعها بل هي أقرب إلى العُرف، ولكن من الأفضل اتباعها حتى تكون الشيفرة المصدرية في أفضل صورة ممكنة، وتلك التوصيات هي كما يلي: اسم الصنف من المفضل أن يبدأ بحرف كبير مثل Mouse وليس mouse. جميع المعرِّفات الأخرى مثل المتغيرات والدوال من الأفضل أن تبدأ بحرف صغير. إذا عرَّفت متغيرًا ما خاصًا، ولا تريد أن يُستخدَم في أيّ مكان آخر في البرنامج، فمن المفضل بدء اسم المتغير بشرطة سفلية واحدة أو شرطتين إذا كان المتغير خاصًا جدًا. السطور والمسافات لدى بايثون نوعًا فريدًا من القواعد عندما يتعلق الأمر بالأسطر والمسافات وتنظيم الشيفرة، إذ تستخدِم معظم لغات البرمجة الأخرى الأقواس المعقوصة { } لكتابة كتلة من الشيفرات، لكن الأمر في بايثون مختلف قليلًا، إذ تُنظَّم كتل الشيفرات باستخدام المسافات، وهي عادةً مسافة جدولة Tab، أو فراغين أو أربعة فراغات spaces، فنكتب كتلةً من الشيفرات لتُنفَّذ عند تحقق شرط معين بالشكل التالي: if something_happens: do_this() else: do_that() نقول للمفسر في المثال السابق الوهمي إذا حدث هذا الأمر، افعل هذا؛ وإذ لم يحدث، افعل ذاك، فالأمر بسيط للغاية، المهم دقق بالمسافات وكيف أن do_this تدخل ضمن الشرط if أما do_that فتدخل ضمن else. وبالمثل، عند كتابة كتلة من الشيفرة داخل أيّ قاعدة شرطية أو غيرها من القواعد، يجب عليك البدء في كتابة أسطر الشيفرة الخاصة بالكتلة بعد مسافة تفصل بينها وبين أول السطر، أو بمعنى أدق تفصل بينها وبين كتلة الشيفرة التي تسبقها، انظر مثلًا: count = 10 if count >= 10: if count <= 20: print ("Count is between 10 and 20") else: print ("Count is larger than 20") else: print ("Count is less than 10") وإليك المثال التالي لموازنة طريقة بايثون تلك مع اللغات الأخرى مثل لغة جافاسكربت: let count = 10; if (count <= 20) { if (count <= 20) { console.log("Count is between 10 and 20"); } else { console.log("Count is larger than 20"); } } else { console.log("Count is less than 10"); } تضمَّن كتل الشيفرة في هذا المثال بداخل القواعد الشرطية داخل أقواس معقوصة بغض النظر عن المسافة بين كل سطر وبدايته، المثال السابق يكافئ: let count = 10; if (count <= 20) { if (count <= 20) { console.log("Count is between 10 and 20"); } else { console.log("Count is larger than 20"); } } else { console.log("Count is less than 10"); } المثالان السابقان متطابقان تمامًا ويعملان بلا مشكلة؛ أما في بايثون، فتخضع الشيفرة إلى قاعدة مسافات الأسطر تلك، ولا يُمكن كسر تلك القاعدة، كما أنّ كافة مبرمجي بايثون يحبون قاعدة المسافات لأنها تُجبِر المبرمجين على كتابة شيفرة بسيطة ومنظمة وسهلة القراءة. ومن أساسيات البايثون وأهم القواعد الخاصة بالأسطر في بايثون، نجد قاعدة استكمال الأسطر، فإذا كنت تكتب سطرًا ما وكان هذا السطر طويلًا للغاية وتريد تقسيمه إلى سطرين، فستستطيع في بايثون تحقيق ذلك عبر استخدام الرمز \، فإذا كتبت سطرًا يجمع رقمَين مثلًا ثم يقسم أحدهما على الآخر، وكنت تريد تجزئة هذا السطر إلى سطرين مختلفين، فيمكنك فعل ذلك كما في المثال التالي: 30 + 6 / 6 >> 31.0 30 + 6 \ / 6 >> 31.0 كتبنا في السطر الأول عملية الجمع مع عملية القسمة في سطر واحد مباشرةً وأنتج ذلك العدد 31، أما في المثال الثاني كتبنا عملية الجمع في السطر الأول فقط، ثم ألحقنا عملية الجمع بالرمز \، واستكملنا السطر التالي العمليات بكتابة عملية القسمة مباشرةً، وأنتج ذلك في النهاية العدد نفسه، لكن توجد مع ذلك حالة خاصة لأيّ سطر في بايثون يحتوي على إحدى الأقواس بمختلف أنواعها، مثل [] أو {} أو ()، إذ يمكن كتابة تلك الأسطر على سطرين أو أكثر دون استخدام الرمز السابق ذكره، فالسطر التالي مثلًا يعمل بدون مشكلة حتى مع عدم استخدامنا للرمز. items = ['item_1', 'item_2', 'item_3', 'item_4', 'item_5', 'item_6'] علامات التنصيص توجد اختلافات بسيطة بين علامات التنصيص في لغة بايثون مثل أي لغة برمجة أخرى، إذ يمكنك في بايثون تضمين أيّ نص بين علامتَي تنصيص مُفرَدة ' أو علامتي تنصيص مزدوجة " أو علامتي تنصيص ثلاثية """ أو ''' لكن من أهم قواعد استخدام علامات التنصيص في بايثون هي إنهاء النص بعلامة التنصيص نفسها المُستخدَمة في البداية، فلا يُمكن استخدام علامة تنصيص مُفرَدة في بداية النص ثم استخدام علامة تنصيص مزدوجة في نهايته، وإنما يجب تطابق العلامة في البداية والنهاية للنص الواحد، وإليك أمثلةً على ذلك في أوامر الطباعة: print ("Hello World!") print ('Hello World!') print ("""Hello World!""") أما بالنسبة لعلامات التنصيص الثلاثية، فتُستخدَم في الغالب لامتلاكها ميزةً غير موجودة في العلامات المفرَدة والمزدوجة، إذ تُعَدّ قادرةً على معالجة النصوص التي تتكون من أكثر من سطر، في حين أنّ علامات التنصيص المُفردة والمزدوجة يجب احتوائها على نص مكوَّن من سطر واحد لا أكثر، فلا يمكنك مثلًا طباعة سطرين متتالين عبر علامات التنصيص المزدوجة، أي لا يمكنك تنفيذ المثال التالي في بايثون بصورة صحيحة: print ("Hello World!") لكن يمكنك تنفيذ ذلك الأمر عند استخدام علامات التنصيص الثلاثية كما يلي: print ("""Hello World!""") >> Hello World! التعليقات في أساسيات لغة بايثون ستحتاج في كثير من الأوقات أثناء كتابتك أو عملك على برنامج ما، إلى كتابة بعض الملاحظات على بعض الأسطر، فقد تكون تلك الملاحظات موجهةً لتذكيرك بكيفية عمل هذه الكتلة من الشيفرة، أو لتذكيرك بأمر ما تريد استكماله في هذه الأسطر في وقت لاحق، وتوفر بايثون مثلها مثل بقية لغات البرمجة إمكانية كتابة التعليقات عبر استعمال الرمز # والذي سيؤدي إلى تجاهل ما يليه حتى آخر السطر، انظر مثلًا الشيفرة التالية: # هذا تعليق print ("Hello, Python!") # تعليق آخر >> Hello, Python! كما ترى، فإنّ المثال السابق يعمل عملًا عاديًا وكأنه مكتوب بالشكل التالي دون تعليقات: print ("Hello, Python!") >> Hello, Python! فإذا كتبت أيّ سطر برمجي بعد رمز # فسيتجاهله مفسر بايثون تمامًا كما لو أنه غير موجود؛ وذلك لأن التعليقات هي في الأساس جمل من اللغة الطبيعية البشرية التي يستخدمها المبرمج للتعليق وكتابة الملاحظات بين تعليمات البرنامج. كما أنه في بايثون توجد طريقة أخرى لكتابة التعليقات في أسطر عدة، وذلك باستخدام علامات التنصيص الثلاثية، ومن مميزات هذه الطريقة أنها قد تُستخدم في توثيق الدوال وغير ذلك، كما أن هنالك أدوات تستخلص تلك التعليقات لتوليد توثيق لشيفرة البرنامج ووظائفه. """This is a multi line comment. It's wonderful how easy is Python language!""" print ("Hello World!") تُستخدَم التعليقات استخدامًا كبيرًا أثناء برمجة التطبيقات المعقَّدة، فغير أنها تُستخدَم للتعليق على الشيفرة، فإنها قد تكون مفيدةً بصورة كبيرة في تعطيل وتفعيل بعض الأسطر في الشيفرة أثناء عملك على حل مشكلة ما، مثل نسخ سطر ما ووضعه بداخل التعليق حتى يتجاهله البرنامج، ولكي أحتفظ بذلك السطر لاستخدامه لاحقًا. تعليمات متعددة في سطر واحد تنتهي التعليمة البرمجية في السطر في معظم لغات البرمجة مثل لغة PHP أو جافاسكربت JavaScript عن طريق كتابة رمز الفاصلة المنقوطة ; مما يسمح بكتابة أكثر من تعليمة برمجية في سطر واحد؛ أما في بايثون، فينتهي السطر عن طريق بداية سطر جديد، ولكن مع ذلك تدعم بايثون تلك الميزة أيضًا، إذ يمكنك إنهاء التعليمة البرمجية عبر الرمز ; وهو بالإنجليزية Semicolon، وهو أمر اختياري وليس إجباريًا كما في اللغات الأخرى، وبذلك تستطيع كتابة أكثر من تعليمة برمجية في سطر واحد مثل اللغات الأخرى. print ("Hello"); print("World") >> Hello >> World اقرأ أيضًا المقال السابق: البرمجة والخوارزميات والذكاء الاصطناعي المرجع الشامل إلى تعلم لغة بايثون النسخة العربية الكاملة من كتاب البرمجة بلغة بايثون
    2 نقاط
  2. يتضمن مجال تطوير الويب قسمين أساسين هما تطوير الواجهة الأمامية 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 أو ما يعرف بتطوير واجهة المستخدم وتعرفنا على أهم اللغات وأطر العمل والأدوات التي تحتاجها كمطور واجهة أمامية لتنجز الجزء المرئي من الموقع الذي يتفاعل المستخدمون من خلاله مع التطبيقات والمواقع، كما شرحنا في ختامة أهم خطوات تعلم تطوير الواجهة الأمامية ومصادر تعلمها باللغة العربية. وفي حال كان لديك أي سؤال يتعلق بتطوير الويب وتحديدًا تطوير الواجهات الأمامية للويب فلا تتردد في كتابته في قسم التعليقات أسفل المقال، أو طرحه في قسم الأسئلة والأجوبة في أكاديمية حسوب ليجيبك عليه مبرمجون خبراء. اقرأ أيضًا المدخل الشامل لتعلم تطوير الويب وبرمجة المواقع برمجة مواقع الويب: دليلك المختصر ما الفرق بين تصميم المواقع الإلكترونية وتطوير المواقع الإلكترونية؟ عالم الويب ومعاييره ما هي صفحات الويب؟
    1 نقطة
  3. يمكن أن تكون أدوات تطوير الويب من طرف العميل غير مفهومة بالنسبة لكثير من المطورين، لذلك سنوضّح من خلال سلسلة من المقالات الغرض من بعض أدوات تطوير الويب الأكثر شيوعًا من طرف العميل، وسنشرح أيضًا الأدوات التي يمكنك ربطها مع بعضها بعضًا، وكيفية تثبيتها باستخدام مدير الحزم، والتحكم فيها باستخدام سطر الأوامر، وسنقّدّم مثالًا كاملًا عن سلسلة أدوات يوضح كيفية زيادة الإنتاجية، ولكن في البداية وقبل محاولة استخدام هذه الأدوات يجب أن تتعلم أساسيات لغات HTML وCSS وجافاسكربت JavaScript. وفّرنا من خلال موسوعة حسوب مرجعًا لكل من لغات HTML وCSS وJavaScript يمكنك البدء منه. سنوضح في هذه السلسلة من المقالات المواضيع التالية لفهم أدوات تطوير الويب من طرف العميل: نظرة عامة على أدوات تطوير الويب من طرف العميل: نقدّم في هذا المقال نظرة عامة على أدوات الويب الحديثة، وأنواع الأدوات المتاحة وأين ستصادفها في دورة حياة تطوير تطبيقات الويب، وكيفية العثور على المساعدة باستخدام هذه الأدوات. دورة مكثفة لفهم سطر الأوامر: سيُطلب منك بلا شك تشغيل بعض الأوامر في الطرفية Terminal أو في سطر الأوامر خلال عملية التطوير، حيث يقدم هذا المقال مقدمة إلى الطرفية والأوامر الأساسية التي ستحتاج إلى إدخالها، وكيفية ربط الأوامر مع بعضها بعضًا، وكيفية إضافة أدوات واجهة سطر الأوامر Command Line Interface -أو CLI اختصارًا. أساسيات إدارة الحزم: سنلقي نظرة على مدراء الحزم بشيء من التفصيل لفهم كيفية استخدامها في مشاريعك لتثبيت اعتماديات Dependencies أدوات المشروع وتحديثها وغير ذلك. سلسلة أدوات كاملة: سنعمل في المقالين الأخيرين من السلسلة على ترسيخ معرفتك بالأدوات من خلال إرشادك خلال عملية بناء نموذج لسلسلة أدوات عن طريق إعداد بيئة تطوير ووضع أدوات التحويل في مكانها لنشر تطبيقك فعليًا على Netlify. كما سنقدم دراسة حالة مع إعداد بيئة التطوير الخاصة بنا وإعداد أدوات تحويل شيفرتنا. نشر التطبيق: سنأخذ في المقال الأخير من هذه السلسلة مثالًا عن سلسلة الأدوات التي أنشأناها في المقال السابق ونضيفها لنتمكن من نشر التطبيق، إذ سنرفع الشيفرة البرمجية للمشروع على موقع مشاركة الشيفرات جيت هب GitHub، وننشرها باستخدام نيتليفاي Netlify، وسنوضّح كيفية إضافة اختبار بسيط لهذه العملية. لنبدأ بمقالنا الأول من هذه السلسلة من خلال إلقاء نظرة سريعة على أدوات تطوير الويب من طرف العميل. المتطلبات الأساسية: الإلمام بمفاهيم لغات HTML و CSS وجافاسكربت الأساسية. الهدف: فهم أنواع الأدوات من طرف العميل وكيفية العثور عليها والحصول على المساعدة بشأنها. استخدام الأدوات الحديثة أصبحت كتابة برمجيات الويب أكثر تعقيدًا بمرور الوقت، وبالرغم من ذلك لا يزال كتابة برمجيات الويب يدويًا بلغة HTML و CSS وجافاسكربت أمرًا ممكنًا إلا أنه يوجد الآن مجموعة كبيرة من الأدوات التي يمكن للمطورين استخدامها لتسريع عملية إنشاء موقع ويب أو تطبيق. توجد بعض الأدوات المستقرة التي أصبحت أسماء مألوفة وشائعة في مجتمع تطوير الويب، بالإضافة إلى الأدوات الجديدة التي نراها تصدر كل يوم لحل مشكلات معينة، فيمكن أن تكتب برنامجًا للمساعدة في عملية التطوير الخاصة بك ولحل مشكلة معينة لا يمكن أن تحلها الأدوات الحالية. يمكنك استخدام عدد هائل من الأدوات وتضمينها في مشروع واحد، كما يمكنك استخدام أداة واحدة مثل Webpack وإعداد ملف تكوينها من مئات الأسطر، وغالبًا ما ينظر المبرمجين المبتدئين لهذه الشيفرة وكأنها تعويذات تؤدي المهمة بطريقة سحرية ولن يفهمها إلا المهندسون الخبراء. إلا أنه في الواقع غالبية الخبراء يواجهون مشاكلًا في استخدام الأدوات من وقت لآخر، إذ يمكن إضاعة ساعات في محاولة تشغيل مسار أدوات قبل لمس سطر واحد من شيفرة التطبيق. لذلك لا داعي للقلق، فأنت لست وحدك. سنزودك من خلال هذا المقال بنقطة بداية مفيدة لفهم أساسيات استخدام أدوات الويب، إذ يُفضَّل أن تبدأ على نطاق صغير، ثم تشق طريقك تدريجيًا إلى الاستخدامات أكثر تقدمًا. نظام أدوات المطورين الحديث يعدّ النظام البيئي Ecosystem الحديث لأدوات المطورين في يومنا الحالي ضخم نسبيًا، لذا يجب من الأفضل تكوين فكرة عامة عن المشاكل الرئيسية التي تحلها هذه الأدوات. إذا انتقلت إلى محرك البحث المفضل لديك وبحثت عن "أدوات مطور الواجهة الأمامية"، فستصل لمجموعة كبيرة من النتائج تتراوح من محرّرات النصوص والمتصفحات وحتى نوع الأقلام التي يمكنك استخدامها لتدوين الملاحظات. وبالرغم من أن اختيارك لمحرّر الشيفرة هو بالتأكيد جزء من خيارات الأدوات، ولكن في هذه السلسلة من المقالات سنتجاوز ذلك من خلال التركيز على أدوات المطور التي تساعدك على إنتاج شيفرة ويب ذات كفاءة عالية. يمكنك تصنيف الأدوات من طرف العميل ضمن الفئات الثلاث التالية: شبكة الأمان Safety Net: أدوات مفيدة أثناء تطوير شيفرتك. التحويل Transformation: الأدوات التي تحول الشيفرة بطريقة ما مثل تحويل لغة وسيطة إلى لغة جافاسكربت التي يمكن أن يفهمها المتصفح. أدوات ما بعد التطوير Post-development: الأدوات المفيدة بعد كتابة شيفرتك مثل أدوات الاختبار والنشر. لنلقِ نظرة على كل واحدة من هذه الفئات بمزيد من التفصيل. شبكة الأمان هي الأدوات التي تحسّن شيفرتك البرمجية التي تكتبها، ويجب أن تكون هذه الأدوات خاصةً ببيئة التطوير الخاصة بك، بالرغم من ذلك من غير المألوف أن يكون لدى الشركات سياسة أو إعدادات جاهزة للتثبيت لكي تضمن أن يستخدم جميع مطوري هذه الشركات العمليات نفسها. تتضمن هذه الأدوات أيّ شيء يسهّل عملية التطوير فيما يتعلق بإنشاء شيفرة مستقرة وموثوقة. كما يجب أن تساعدك أدوات شبكة الأمان في منع حدوث الأخطاء أو تصحيحها تلقائيًا دون الحاجة إلى إنشاء شيفرة من نقطة الصفر في كل مرة. سنوضّح فيما يلي بعض أنواع أدوات شبكة الأمان الشائعة التي يستخدمها المطورون. منقحات الصياغة Linters منقحات الصياغة هي أدوات تتحقق من شيفرتك وتخبرك بوجود أخطاء وبأنواعها وسطور الشيفرة التي توجد فيها. يمكن ضبط منقحات الصياغة للإبلاغ عن الأخطاء، وللإبلاغ عن أيّ انتهاكات لدليل النمط المحدَّد الذي يستخدمه فريقك مثل الشيفرة التي تستخدم عددًا خاطئًا من المسافات البادئة، أو استخدام صياغة قالب Template Literals بدلًا من صياغة سلسلة نصية عادية String Literals. يعدّ Eslint منقّح أخطاء معياري خاص بلغة جافاسكربت ويمكن ضبط هذه الأداة لاكتشاف أخطاء الصياغة المحتملة وتشجيعك لاستخدام أفضل الممارسات ضمن شيفرتك البرمجية. شاركت بعض الشركات والمشاريع إعدادات Eslint الخاصة بها، ويمكنك العثور على أدوات اكتشاف أخطاء للغات أخرى مثل Csslint. كما يمكنك استخدام Webhint وهو منقح أخطاء مفتوح المصدر يمكن ضبطه للويب، ويعرض أفضل الممارسات لاستخدامها بما في ذلك أساليب الوصول والأداء والتوافق مع المتصفحات باستخدام بيانات توافق متصفح MDN والأمان واختبار تطبيقات الويب ذات الصفحة الواحدة PWA وغير ذلك. كما يتوفر كأداة سطر أوامر Node.js وكامتداد VS Code. التحكم بالشيفرة البرمجية يُعرَف أيضًا باسم أنظمة التحكم بالإصدارات Version Control Systems أو VCS اختصارًا، ويُعَد التحكم بالشيفرة البرمجية ضروريًا لدعم العمل الفردي أو ضمن فريق. يتضمن نظام VCS إصدارًا محليًا من الشيفرة التي تجري تغييرات عليها، ثم ترفع التغييرات إلى إصدار رئيسي من الشيفرة داخل مستودع بعيد مُخزَّن على خادم في مكان ما. هناك عادةً طريقة للتحكم في التعديلات التي تُطبَّق على النسخة الرئيسية من الشيفرة وتنسيقها ومتى تطبَّق، وبالتالي لا يكتب فريق المطورين فوق عمل بعضهم بعضًا. يعد نظام جيت هاب Git من أشهر نظم التحكم بالشيفرة البرمجية الذي يستخدمه معظم المطورين حاليًا، إذ يمكن الوصول إليه عبر سطر الأوامر أو عبر واجهات سهلة الاستخدام. كما يمكنك رفع نسخة من المشروع إلى الخادم الخاص بك باستخدام شيفرتك في مستودع جيت، أو يمكنك استخدام موقع ويب مستضاف للتحكم بالشيفرة المصدرية مثل جيت هب GitHub أو جيت لاب GitLab أو بيت باكيت BitBucket، ولكن سنستخدم GitHub في مثالنا. مُنسِّقات الشيفرة Code Formatters ترتبط مُنسِّقات الشيفرة إلى حد ما بمنقّحات الصياغة، باستثناء أنه بدلًا من الإشارة إلى الأخطاء في شيفرتك، فإنها عادةً ما تميل إلى التأكد من تنسيق شيفرتك الصحيح وفقًا لقواعد النمط الخاصة بك، وتعمل تلقائيًا على إصلاح الأخطاء التي تعثر عليها. أحد الأمثلة الشائعة لمنسقات الشيفرة البرمجية هو Prettier، والذي سنستخدمه لاحقًا في مثالنا. الحزم Bundlers أو Packagers هي الأدوات التي تجعل شيفرتك جاهزةً لعملية الإنتاج عن طريق تقنية هز الشجرة Tree-Shaking مثلًا للتأكّد من إدراج أجزاء مكتبات الشيفرة التي تستخدمها فعليًا فقط في شيفرة الإنتاج النهائي، أو التصغير Minifying لإزالة كل مسافة فارغة في شيفرة الإنتاج، مما يصغّرها قدر الإمكان قبل رفعها إلى الخادم. تعد أداة Parcel من الأدوات الذكية التي يمكنها تطبيق المهام المذكورة السابقة، كما أنها تساعد أيضًا في حزم الملفات أو الملحقات assets مثل HTML وCSS وملفات الصور ضمن حزم ملائمة يمكنك نشرها لاحقًا، وتضيف اعتماديات تلقائيًا كلما حاولت استخدامها. كما يمكن لهذه الأداة التعامل مع بعض مهام تحويل الشيفرة نيابة عنك. يذكر أن أداة ويب باك Webpack هي أشهر أداة حزم تطبّق مهامًا مماثلة. التحويل Transformation تتيح هذه المرحلة من دورة حياة تطبيق الويب كتابة شيفرة برمجية إما في شيفرة مستقبلية مثل تحويل الشيفرة البرمجية لأحدث ميزات لغة CSS أو جافاسكربت التي يمكن ألّا تدعمها بعض المتصفحات حتى الآن، أو إنشاء شيفرة برمجية مكافئة لشيفرة برمجية مكتوبة بلغة معينة مثل لغة TypeScript، لتتوافق الشيفرة التي أنشأتها الأداة المطلوبة مع المتصفح لاستخدامها في عملية الإنتاج. يُنظَر إلى تطوير الويب على أنه مؤلَّف من ثلاث لغات هي HTML وCSS وجافاسكربت، وهناك أدوات تحويل لجميع هذه اللغات. يقدّم التحويل فائدتين رئيسيتين هما: القدرة على كتابة شيفرة برمجية باستخدام أحدث ميزات اللغة وتحويلها إلى شيفرة تعمل على جميع الأجهزة، فيمكن أن ترغب مثلًا في كتابة شيفرة بلغة جافاسكربت باستخدام ميزات لغة جديدة متطورة، ولكن لا يزال لديك شيفرة الإنتاج النهائي التي تعمل على المتصفحات القديمة التي لا تدعم هذه الميزات. تشمل الأمثلة التالية: Babel: مصرّف جافاسكربت JavaScript الذي يسمح للمطورين بكتابة شيفرة باستخدام أحدث إصدارات جافاسكربت، والتي يأخذها Babel ويحوّلها إلى إصدار جافاسكربت قديم يمكن لمزيد من المتصفحات فهمه. كما يمكن للمطورين كتابة ونشر إضافات Babel. PostCSS: تطبّق هذه الأداة الشيء نفسه الذي يطبّقه Babel، ولكن مع ميزات CSS المتطورة. إذا لم تكن هناك طريقة مكافئة لتطبيق شيء ما باستخدام ميزات CSS القديمة، فسيثبّت PostCSS تعويض نقص دعم المتصفحات Polyfill بلغة جافاسكربت لمحاكاة تأثير CSS الذي تريده. خيار كتابة الشيفرة بلغة مختلفة تمامًا وتحويلها إلى لغة متوافقة مع الويب مثل: Sass / SCSS: يتيح لك هذا الامتداد من لغة CSS استخدام المتغيرات والقواعد المتداخلة والمزج والدوال والعديد من الميزات الأخرى، إذ يُعَد بعضها متاحًا في لغة CSS الأصلية مثل المتغيرات، وبعضها ليس كذلك. TypeScript: هي مجموعة شاملة من لغة جافاسكربت التي تقدم مجموعة من الميزات الإضافية. يحوّل مصرّف TypeScript شيفرة TypeScript إلى جافاسكربت عند البناء بهدف الإنتاج. توفّر أطر العمل مثل React وEmber وVue الكثير من الوظائف مجانًا وتسمح لك باستخدامها عبر صيغة مخصَّصة مبنية على لغة جافاسكربت الصرفة Vanilla JavaScript. تعمل شيفرة جافاسكربت الخاصة بإطار العمل في الخلفية لتفسير هذه البنية المخصَّصة وتقديمها بوصفها تطبيق ويب نهائي. أدوات ما بعد التطوير Post Development تضمن أدوات ما بعد التطوير أن يصل برنامجك إلى الويب ويستمر في عمله، إذ تتضمن مرحلة ما بعد التطوير عمليات النشر وأطر عمل الاختبار وأدوات التدقيق وغير ذلك. تُعَد هذه المرحلة بأنها المرحلة التي تحتاج أقل قدر من التفاعل النشط بحيث تُشغَّل تلقائيًا بمجرد تهيئتها، وتخبرك بحدوث خطأ ما. أدوات الاختبار Testing Tools تأخذ هذه الأدوات شكل أداة تختبر تلقائيًا شيفرت البرمجية للتأكد من صحتها قبل المضي قدمًا مثل رفع تعديلات إلى مستودع جيب هب GitHub Repo. يمكن أن يشمل ذلك الكشف عن الأخطاء Linting، ويشمل إجراءات أكثر تعقيدًا مثل اختبارات الوحدة إذ تشغّل جزءًا من شيفرتك، مع التأكد من أنها تتصرف كما ينبغي. تشمل أطر عمل اختبارات الكتابة Jest وMocha وJasmine. تتضمن أنظمة التشغيل والاختبارات الآلية Travis CI وJenkins وCircle CI وغيرها. أدوات النشر Deployment Tools تسمح أنظمة النشر بنشر موقع الويب الخاص بك، وهي متاحة لكل من المواقع الثابتة والديناميكية، وتميل للعمل جنبًا إلى جنب مع أنظمة الاختبار، إذ ستنتظرك سلسلة الأدوات إلى أن ترفع التغييرات إلى المستودع البعيد، وتجري بعض الاختبارات لمعرفة ما إذا كانت التغييرات مناسبة، وإذا نجحت الاختبارات، فستنشر تطبيقك تلقائيًا على موقع إنتاج. تعد Netlify واحدة من أكثر أدوات النشر شيوعًا في الوقت الحالي، ولكن هناك أدوات أخرى مثل Vercel وGithub Pages. أدوات ما بعد التطوير الأخرى هناك عدد من أنواع الأدوات الأخرى المتاحة للاستخدام في مرحلة ما بعد التطوير، بما في ذلك Code Climate لجمع مقاييس جودة الشيفرة، وامتداد متصفح Webhint لإجراء تحليل وقت التشغيل للتوافق مع المتصفحات وعمليات التحقق الأخرى، وGithub bots لتوفير المزيد من ميزات GitHub القوية، وUpdown لتوفير مراقبة وقت تشغيل التطبيق وغير ذلك الكثير. أنواع الأدوات تُطبَّق أنواع الأدوات المختلفة في دورة حياة التطوير وفق ترتيب معين، ولكن كن مطمئنًا أنك لست مضطرًا إلى أن يكون لديك كل هذه الأدوات لإصدار موقع ويب، فلن لا تحتاج لأيٍّ منها. لكن سيؤدي تضمين بعض هذه الأدوات في عملياتك إلى تحسين تجربة التطوير، ويُحتمَل أن يؤدي إلى تحسين جودة شيفرتك الإجمالية. يستغرق استقرار أدوات المطور الجديدة بعض الوقت حسب تعقيدها. تشتهر إحدى أشهر الأدوات وهي Webpack بكونها معقدة للغاية للتعامل معها، ولكن كان هناك ضغط كبير لتبسيط الاستخدام في أحدث إصدار رئيسي، لذا قُلٍّل الإعداد المطلوب إلى الحد الأدنى. ليس هناك حل سحري يضمن النجاح باستخدام الأدوات، ولكن ستجد تدفقات عمل تناسبك أو تناسب فريقك ومشاريعك مع زيادة خبرتك، ويجب أن تكون سلسلة الأدوات شيئًا يمكنك نسيانه وأن تركّز على العمل فقط، بمجرد تسوية جميع مكامن الخلل في العملية. كيفية اختيار أداة معينة والحصول عليها تميل معظم الأدوات إلى كتابتها وإصدارها بصورة منفصلة، لذلك لا تتوفر أبدًا في المكان أو التنسيق نفسه، على الرغم من وجود مساعدة شبه مؤكدة، فيمكن أن يكون العثور على مساعدة في استخدام أداة أو حتى اختيار الأداة التي تريد استخدامها أمرًا صعبًا. المعرفة حول أفضل الأدوات لاستخدامها هي معرفة مجتمعية إلى حد ما، مما يعني أنه إن لم تكن بالفعل في مجتمع الويب، فستكون معرفة الأدوات التي تريدها بالضبط أمرًا صعبًا، وهذا هو أحد الأسباب التي دفعتنا إلى كتابة هذه السلسلة من المقالات، ونأمل أن نقدم تلك الخطوة الأولى التي يصعب إيجادها بطريقة أخرى. ستحتاج على الأرجح إلى مجموعة الأشياء التالية: نجح المدرسون أو الموجهون أو الزملاء الطلاب ذوو الخبرة أو الزملاء الذين لديهم بعض الخبرة في حل هذه المشكلات من قبل، ويمكنهم تقديم المشورة. مكان محدد مفيد للبحث، إذ تكون عمليات البحث العامة على الويب عن أدوات مطور الواجهة الأمامية عديمة الفائدة إلا إن عرفتَ اسم الأداة التي تبحث عنها. إذا استخدمتَ مدير الحزم NPM لإدارة اعتمادياتك على سبيل المثال، فيُفضَّل الانتقال إلى صفحة npm الرئيسية والبحث عن نوع الأداة التي تبحث عنها. حاول مثلًا البحث عن "التاريخ date" إن أردتَ أداة تنسيق التاريخ، أو "المُنسِّق formatter" إذا كنت تبحث عن مُنسق شيفرة عام. انتبه إلى درجات الشعبية والجودة والصيانة، وآخر تحديث للحزمة. انقر على صفحات الأداة لمعرفة عدد تنزيلات الحزمة الشهرية، واحتوائها على توثيق جيد يمكنك استخدامه للتأكد من أنها تطبّق ما تريده، وبالتالي تُعَد مكتبة date-fns أداة تنسيق تاريخ جيدة لاستخدامها. إذا أردت البحث عن إضافة Plugin لدمج وظائف الأدوات في محرّر الشيفرة، فألقِ نظرة على صفحة الإضافات / الامتدادات لمحرر الشيفرة، وراجع حزم Atom وامتدادات VSCode على سبيل المثال. ألقِ نظرة على الامتدادات المميزة في الصفحة الأولى، وحاول مرة أخرى البحث عن نوع الامتداد الذي تريده (أو اسم الأداة مثل البحث عن "eslint" في صفحة امتدادات VSCode). إذا حصلتَ على نتائج، فألقِ نظرة على معلومات عدد النجوم أو التنزيلات التي يحتويها الامتداد، إذ يُعَد ذلك مؤشرًا على جودته. المنتديات المتعلقة بالتنمية لطرح أسئلة حول الأدوات التي يجب استخدامها مثل قسم الأسئلة والأجوبة البرمجية في أكاديمية حسوب. إذا اخترت أداة لاستخدامها، فيجب أن يكون طريقة فهم الأداة هو الصفحة الرئيسية لمشروع الأداة والذي يكون غالبًا موقع ويب كامل أو يكون مستندًا تمهيديًا واحدًا في مستودع الشيفرة. يمكن أن ترغب في العثور على بعض البرامج التعليمية المخصصة لبدء استخدام أنواع معينة من الأدوات، لذا تعد المقالات البرمجية ومقالات DevOps في أكاديمية حسوب أماكن الانطلاق الرائعة للبحث. يُحتمَل أن تمر عبر العديد من الأدوات المختلفة أثناء البحث عن الأدوات المناسبة لك، وأن تجربها لمعرفة ما إذا كانت منطقية ومدعومة جيدًا وتطبّق ما تريده منها. يُعَد كل ذلك مناسبًا للتعلم، وسيصبح الطريق أسلس كلما اكتسبت مزيدًا من الخبرة. الخلاصة قدّمنا من خلال هذا المقال مقدمة بسيطة عن أدوات الويب من طرف العميل، وسنقدّم في المقال القادم دورة مكثفة عن سطر الأوامر، إذ تُستدعَى كثير من الأدوات منه، وسنلقي نظرة على ما يمكن أن يفعله سطر الأوامر ثم نحاول تثبيت الأداة الأولى ونستخدمها. هذا المقال جزء من سلسلة مقالات بعنوان تعلم تطوير الويب والتي تشرح كامل عملية تطوير الويب من واجهات أمامية وخلفية بالكامل. ترجمة -وبتصرُّف- للمقالين Understanding client-side web development tools وClient-side tooling overview. اقرأ أيضًا مدخل إلى أدوات التطوير في متصفح الويب DevTools كيف تستخدم أدوات المطوِّر في المتصفحات الحديثة الفرق بين مصمم الويب ومطور الويب وكيفية معرفة الأنسب بينهما الأدوات المستخدمة في بناء مواقع ويب
    1 نقطة
  4. بدأنا في مقال الجزء الأول ببناء مشروع عملي بلغة رست وهو عبارة عن خادم ويب متعدد مهام المعالجة، إذ بنينا الخادم الأساسي وكان أحادي خيط المعالجة، وعملنا في مقال الجزء الثاني على تحويله إلى خادم متعدد خيوط المعالجة، وسننهي في هذا المقال بناء الخادم ليصبح جاهزًا، فإذا لم تكن قرأت المقالات السابقة، فارجع لها قبل قراءة هذا المقال. الإغلاق الرشيق وتحرير الذاكرة تستجيب الشيفرة 20 للطلبات بصورةٍ غير متزامنة عبر استخدام مجمع خيط كما نريد، إذ نحصل على بعض التحذيرات من حقول workers و id و thread التي لن نستخدمها مباشرةً وتذكرنا أننا لم نحرر أي شيء من الذاكرة. عندما نستخدم الحل البدائي الذي هو استخدام مفتاحي "ctrl-c" لإيقاف الخيط الرئيسي، تتوقف الخيوط مباشرةً حتى لو كانوا يخدّمون طلبًا. سننفّذ سمة Drop لاستدعاء join على كل خيط في المجمع لكي ننهي الطلبات التي تعمل قبل الإغلاق، ثم سننفّذ طريقةً لإخبار الخيوط ألا تقبل طلبات جديدة قبل الإغلاق. لرؤية عمل هذا الكود سنعدّل الخادم ليقبل طلبين فقط قبل أن يغلق مجمع الخيط thread pool. تنفيذ سمة Drop على مجمع خيط لنبدأ بتنفيذ Drop على مجمع الخيط الخاص بنا. عندما يُسقط المجمع يجب أن تجتمع كل الخيوط للتأكد من أن عملهم قد انتهى. تظهر الشيفرة 22 المحاولة الأولى لتطبيق Drop، إذ لن تعمل الشيفرة حاليًا. اسم الملف: src/lib.rs impl Drop for ThreadPool { fn drop(&mut self) { for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); worker.thread.join().unwrap(); } } } [الشيفرة 22: ضم كل خيط عندما يخرج المجمع خارج النطاق] أولًا، نمرّ على كل workers في مجمع الخيط، واستُخدمت ‎&mut هنا لأن self هو مرجع متغيّر، ونريد أيضًا تغيير worker. نطبع لكل عامل رسالةً تقول أن هذا العامل سيُغلق، ثم نستدعي join على خيط العمال. إذا فشل استدعاء join نستخدم unwrap لجعل رست تهلع وتذهب إلى إغلاق غير رشيق. سنحصل على هذا الخطأ عند تصريف هذه الشيفرة: $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0507]: cannot move out of `worker.thread` which is behind a mutable reference --> src/lib.rs:52:13 | 52 | worker.thread.join().unwrap(); | ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this method call | | | move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait | note: this function takes ownership of the receiver `self`, which moves `worker.thread` --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:17 For more information about this error, try `rustc --explain E0507`. error: could not compile `hello` due to previous error يوضّح الخطأ أننا لا يمكن أن نستدعي join لأنه لدينا استعارة متغيرة على كل worker وتأخذ join ملكية وسطائها، ولمعالجة هذه المشكلة نحن بحاجة لنقل الخيط خارج نسخة Worker التي تملك thread حتى تستطيع join استهلاك الخيط، وقد فعلنا ذلك في الشيفرة 15 من المقال تنفيذ نمط تصميمي Design Pattern كائني التوجه Object-Oriented في لغة رست. إذا احتفظ Worker بـ Option<thread::JoinHandle<()>>‎، يمكننا استدعاء تابع take على Option لنقل القيمة خارج المتغاير Some وإبقاء المتغاير None في مكانه، بمعنى آخر سيحتوي Worker عامل على متغاير Some في Thread الخاص به وعندما نريد تحرير ذاكرة Worker نستبدل Some بالقيمة None حتى لا يوجد لدى Worker أي خيط لينفذه. لذا نحن نعرف أننا نريد تحديث تعريف Worker على النحو التالي. اسم الملف: src/lib.rs struct Worker { id: usize, thread: Option<thread::JoinHandle<()>>, } الآن لنتابع المصرّف لنجد أية أماكن أُخرى تحتاج تغيير، وبالتحقق من الشيفرة نجد خطأين: $ cargo check Checking hello v0.1.0 (file:///projects/hello) error[E0599]: no method named `join` found for enum `Option` in the current scope --> src/lib.rs:52:27 | 52 | worker.thread.join().unwrap(); | ^^^^ method not found in `Option<JoinHandle<()>>` | note: the method `join` exists on the type `JoinHandle<()>` --> /rustc/d5a82bbd26e1ad8b7401f6a718a9c57c96905483/library/std/src/thread/mod.rs:1581:5 help: consider using `Option::expect` to unwrap the `JoinHandle<()>` value, panicking if the value is an `Option::None` | 52 | worker.thread.expect("REASON").join().unwrap(); | +++++++++++++++++ error[E0308]: mismatched types --> src/lib.rs:72:22 | 72 | Worker { id, thread } | ^^^^^^ expected enum `Option`, found struct `JoinHandle` | = note: expected enum `Option<JoinHandle<()>>` found struct `JoinHandle<_>` help: try wrapping the expression in `Some` | 72 | Worker { id, thread: Some(thread) } | +++++++++++++ + Some errors have detailed explanations: E0308, E0599. For more information about an error, try `rustc --explain E0308`. error: could not compile `hello` due to 2 previous errors لنعالج الخطأ الثاني الذي يشير إلى الشيفرة في نهاية Worker::new، إذ نريد تغليف قيمة thread في Some عندما ننشئ Worker جديد. أجرِ الخطوات التالية لتصحيح هذا الخطأ: اسم الملف: src/lib.rs impl Worker { fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { // --snip-- Worker { id, thread: Some(thread), } } } الخطأ الأول هو في تنفيذ Drop، وذكرنا سابقًا أننا أردنا استدعاء take على قيمة Option لنقل thread خارج worker. أجرِ التغييرات التالية لتصحيح هذا الخطأ: اسم الملف: src/lib.rs impl Drop for ThreadPool { fn drop(&mut self) { for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); if let Some(thread) = worker.thread.take() { thread.join().unwrap(); } } } } كما تحدثنا سابقًا في المقال البرمجة كائنية التوجه OOP في لغة رست، يأخذ التابع take على Option المتغاير Some خارجًا ويبقي None بدلًا عنه. استخدمنا if let لتفكيك Some والحصول على الخيط، ثم استدعينا join على الخيط. إذا كان خيط العامل هو أساسًا None نعرف أن العامل قد حرًر ذاكرته ولا يحصل شيء في هذه الحالة. الإشارة للخيط ليتوقف عن الاستماع إلى الوظائف تُصرّف الشيفرة بدون تحذيرات بعد كل التغييرات التي أجريناها، ولكن الخبر السيء أنها لا تعمل كما أردنا. النقطة المهمة هي في منطق المغلفات المنفذة بواسطة خيوط نسخ Worker، إذ نستدعي حتى اللحظة join لكن لا تُغلق الخيوط لأننها تعمل في loop للأبد بحثًا عن وظائف. إذا أسقطنا Threadpool بتنفيذنا الحالي للسمة drop، سيُمنع الخيط الأساسي للأبد بانتظار الخيط الأول حتى ينتهي، ولحل هذه المشكلة نحتاج لتغيير تنفيذ drop في ThreadPool، ثم إجراء تغيير في حلقة Worker. أولًا، سنغير تنفيذ drop في ThreadPool ليسقِط صراحةً sender قبل انتظار الخيوط لتنتهي. تظهر الشيفرة 23 التغييرات في ThreadPool لتسقط صراحةً sender. استخدمنا نفس تقنياتOption و take كما فعلنا مع الخيط لكي يستطيع نقل sender خارج ThreadPool. اسم الملف: src/lib.rs: pub struct ThreadPool { workers: Vec<Worker>, sender: Option<mpsc::Sender<Job>>, } // --snip-- impl ThreadPool { pub fn new(size: usize) -> ThreadPool { // --snip-- ThreadPool { workers, sender: Some(sender), } } pub fn execute<F>(&self, f: F) where F: FnOnce() + Send + 'static, { let job = Box::new(f); self.sender.as_ref().unwrap().send(job).unwrap(); } } impl Drop for ThreadPool { fn drop(&mut self) { drop(self.sender.take()); for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); if let Some(thread) = worker.thread.take() { thread.join().unwrap(); } } } } [الشيفرة 23: إسقاط sender صراحةً قبل جمع الخيوط الفعالة] يغلق إسقاط sender القناة، وهذا يشير بدوره إلى عدم إرسال أي رسائل إضافية، وعندما نفعل ذلك تعيد كل الاستدعاءات إلى recv التي تجريها الخيوط الفعالة في الحلقة اللانهائية خطأً. نغير حلقة Worker في الشيفرة 24 لتخرج من الحلقة برشاقة في تلك الحالة، يعني أن الخيوط ستنتهي عندما يستدعي join عليهم في تنفيذ drop في ThreadPool. اسم الملف: src/lib.rs impl Worker { fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { let thread = thread::spawn(move || loop { let message = receiver.lock().unwrap().recv(); match message { Ok(job) => { println!("Worker {id} got a job; executing."); job(); } Err(_) => { println!("Worker {id} disconnected; shutting down."); break; } } }); Worker { id, thread: Some(thread), } } } [الشيفرة 24: الخروج صراحةً من الحلقة عندما تعيد recv خطأ] لرؤية عمل هذه الشيفرة: سنعدل main لتقبل فقط طلبين قبل أن تُغلق الخادم برشاقة كما تظهر الشيفرة 25. اسم الملف: src/main.rs fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let pool = ThreadPool::new(4); for stream in listener.incoming().take(2) { let stream = stream.unwrap(); pool.execute(|| { handle_connection(stream); }); } println!("Shutting down."); } [الشيفرة 25: إغلاق الخادم بعد خدمة طلبين عن طريق الخروج من الحلقة] لا نريد أن يتوقف خادم حقيقي بعد خدمة طلبين فقط، وتبين هذه الشيفرة أن الإغلاق الرشيق وتحرير الذاكرة يعملان بصورةٍ نظامية. تُعرّف دالة take في سمة Iterator وتحدد التكرار إلى أول عنصرين بالحد الأقصى. سيخرج ThreadPool خارج النطاق في نهاية main وستُطبَّق سمة drop. شغّل الخادم باستخدام cargo run وأرسل ثلاثة طلبات. سيعطي الطلب الثالث خطأ وسترى الخرج في الطرفية على النحو التالي: $ cargo run Compiling hello v0.1.0 (file:///projects/hello) Finished dev [unoptimized + debuginfo] target(s) in 1.0s Running `target/debug/hello` Worker 0 got a job; executing. Shutting down. Shutting down worker 0 Worker 3 got a job; executing. Worker 1 disconnected; shutting down. Worker 2 disconnected; shutting down. Worker 3 disconnected; shutting down. Worker 0 disconnected; shutting down. Shutting down worker 1 Shutting down worker 2 Shutting down worker 3 يمكن أن ترى ترتيبًا مختلفًا للخيوط الفعالة والرسائل المطبوعة. تعمل الشيفرة وفقًا لهذه الرسائل كما يلي: أخذ العاملان 0 و 3 الطلبين الأولين وتوقف الخادم عن قبول الاتصالات بعد ثاني اتصال، وبدأ تنفيذ Drop في العمل على ThreadPool قبل أخذ العامل 3 وظيفته. يفصل إسقاط sender كل العمال ويخبرهم أن يُغلقوا، ويطبع كل عامل رسالةً عندما يُغلقوا ويستدعي مجمع الخيط join لانتظار كل خيط عامل لينتهي. لاحظ ميّزة مهمة في هذا التنفيذ، إذ قام ThreadPool بإسقاط sender وجرّبنا ضم العامل 0 قبل أن يستقبل أي عامل خطأ. لم يتلق العامل 0 أي خطأ من recv بعد، لذا تنتظر كتلة الخيط الأساسية أن ينتهي العامل 0. في تلك الأثناء استقبل العامل 3 وظيفة ثم استقبلت كل الخيوط خطأ. ينتظر الخيط الأساسي باقي العمال لينتهوا عندما ينتهي العامل 0. وبحلول هذه النقطة يخرج كل عامل من حلقته ويتوقف. تهانينا، فقد أنهينا المشروع ولدينا الآن خادم ويب بسيط يستخدم مجمع خيط للاستجابة بصورةٍ غير متزامنة، ونستطيع إجراء إغلاق رشيق للخادم الذي يحرر من الذاكرة كل الخيوط في المجمع. هذه هي الشيفرة الكاملة بمثابة مرجع. اسم الملف: src/main.rs use hello::ThreadPool; use std::fs; use std::io::prelude::*; use std::net::TcpListener; use std::net::TcpStream; use std::thread; use std::time::Duration; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let pool = ThreadPool::new(4); for stream in listener.incoming().take(2) { let stream = stream.unwrap(); pool.execute(|| { handle_connection(stream); }); } println!("Shutting down."); } fn handle_connection(mut stream: TcpStream) { let mut buffer = [0; 1024]; stream.read(&mut buffer).unwrap(); let get = b"GET / HTTP/1.1\r\n"; let sleep = b"GET /sleep HTTP/1.1\r\n"; let (status_line, filename) = if buffer.starts_with(get) { ("HTTP/1.1 200 OK", "hello.html") } else if buffer.starts_with(sleep) { thread::sleep(Duration::from_secs(5)); ("HTTP/1.1 200 OK", "hello.html") } else { ("HTTP/1.1 404 NOT FOUND", "404.html") }; let contents = fs::read_to_string(filename).unwrap(); let response = format!( "{}\r\nContent-Length: {}\r\n\r\n{}", status_line, contents.len(), contents ); stream.write_all(response.as_bytes()).unwrap(); stream.flush().unwrap(); } اسم الملف: src/lib.rs use std::{ sync::{mpsc, Arc, Mutex}, thread, }; pub struct ThreadPool { workers: Vec<Worker>, sender: Option<mpsc::Sender<Job>>, } type Job = Box<dyn FnOnce() + Send + 'static>; impl ThreadPool { /// Create a new ThreadPool. /// /// The size is the number of threads in the pool. /// /// # Panics /// /// The `new` function will panic if the size is zero. pub fn new(size: usize) -> ThreadPool { assert!(size > 0); let (sender, receiver) = mpsc::channel(); let receiver = Arc::new(Mutex::new(receiver)); let mut workers = Vec::with_capacity(size); for id in 0..size { workers.push(Worker::new(id, Arc::clone(&receiver))); } ThreadPool { workers, sender: Some(sender), } } pub fn execute<F>(&self, f: F) where F: FnOnce() + Send + 'static, { let job = Box::new(f); self.sender.as_ref().unwrap().send(job).unwrap(); } } impl Drop for ThreadPool { fn drop(&mut self) { drop(self.sender.take()); for worker in &mut self.workers { println!("Shutting down worker {}", worker.id); if let Some(thread) = worker.thread.take() { thread.join().unwrap(); } } } } struct Worker { id: usize, thread: Option<thread::JoinHandle<()>>, } impl Worker { fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker { let thread = thread::spawn(move || loop { let message = receiver.lock().unwrap().recv(); match message { Ok(job) => { println!("Worker {id} got a job; executing."); job(); } Err(_) => { println!("Worker {id} disconnected; shutting down."); break; } } }); Worker { id, thread: Some(thread), } } } يمكننا إجراء المزيد إذا أردنا تحسين المشروع، وإليك بعض الأفكار: أضِف المزيد من التوثيق إلى ThreadPool وتوابعه العامة. أضِف بعض الاختبارات لوظيفة المكتبة. غيّر الاستدعاءات من unwrap إلى معالجة خطأ أكثر متانة. استخدم ThreadPool لتنفيذ أعمال غير خدمة طلبات الويب. ابحث عن وحدة مجمع خيط مصرفة على creats.io ونفذ خادم ويب باستخدام الوحدة المصرفة، ثم قارن واجهة برمجة التطبيقات API والمتانة بينها وبين مجمع الخيط الذي نفذناه. خاتمة عظيم جدًا! فقد وصلنا إلى نهاية سلسلة البرمجة بلغة رست . نريد أن نشكرك لانضمامك إلينا في هذه الجولة في رست. أنت الآن جاهز لتنفيذ مشاريع رست ومساعدة الآخرين في مشاريعهم. تذكر أنه هناك مجتمع مرحب من مستخدمي رست الذين يحبون المساعدة في أي صعوبة يمكن أن تواجهها في استعمالك رست. ترجمة -وبتصرف- لقسم من الفصل Final Project: Building a Multithreaded Web Server من كتاب The Rust Programming Language. اقرأ أيضًا المقال السابق: بناء خادم ويب متعدد مهام المعالجة بلغة رست - الجزء الثاني تزامن الحالة المشتركة Shared-State Concurrency في لغة رست وتوسيع التزامن مع Send و Sync مقدمة إلى الخيوط Threads في جافا
    1 نقطة
  5. بدأنا هذه السلسلة بمقال عن كيفية التعامل مع رسائل الأخطاء في بايثون وسنتابع الحديث في هذا المقال عن كيفية التعامل مع الملفات والمسارات في بايثون. وبايثون هي لغة برمجة عالية المستوى، وتفاعلية وكائنية. وتتمتع بمقروئية عالية، إذ تستخدم كلمات إنجليزية بسيطة، على خلاف اللغات الأخرى التي تستخدم الرموز، كما أنّ قواعدها الإملائية والصياغية بسيطة، ما يجعل تعلمها سهلًا موازنةً بلغات برمجة أخرى. ولعلّ الخطوة الأولى قبل الإبحار في تعلّم بايثون هي إعداد البيئة، والتي تعرّف بأنها عملية تنظيم الحاسوب اللازمة لاستخدامه في كتابة الشيفرات البرمجية، الأمر الذي يتضمن تثبيت أي أدوات ضرورية وإعدادها، والتعامل مع أي مشاكل قد تواجهك أثناء عملية الإعداد، ولإنجاز هذه الخطوة لابد من فهمك الجيد لنظام الملفات وكيفية التعامل مع المسارات في بايثون. سنحاول في هذا المقال توصيف بعض المبادئ الأساسية لمساعدتك في إدارة حاسوبك باستخدام نظام الملفات. قد يبدو فهم هذه المبادئ دون جدوى، فنحن في نهاية الأمر نسعى لكتابة الشيفرات لا، إلا أن اكتساب هذه المهارات الأساسية سيوفر عليك الوقت على المدى الطويل. نظام الملفات إن نظام الملفات هو الوسيلة التي يعتمدها نظام التشغيل لتنظيم البيانات وتخزينها واستعادتها، إذ يضم الملف خاصيتين رئيسيتين: اسم الملف (وهو عبارة عن كلمة واحدة عادةً) ومساره. لنفرض مثلًا وجود ملف على حاسوب محمول ذو نظام التشغيل ويندوز 10 يدعى project.docx ضمن المسار C:\Users\Al\Documents، يحدد المسار موقع الملف في الحاسوب، أما الجزء الذي يلي اسم الملف بعد النقطة فهو لاحقة الملف التي تبين نوعه. فيشير مثلًا اسم الملف project.docx إلى أن هذا الملف مستند لبرنامج معالج النصوص Word أما Users و Al و Documents فهي اسماء مجلدات، والتي يمكن أن تحتوي على ملفات ومجلدات أخرى. في مثالنا السابق يوجد الملف project.docx ضمن مجلد المستندات Documents الذي يوجد في المجلد Al الموجود بدوره ضمن مجلد المستخدمين Users، ويبين الشكل التالي ترتيب هذه المجلدات. ملف ضمن تسلسل هرمي للمجلدات إذ يمثل الجزء \:C من مسار الملف المجلد الأساسي الذي يحتوي على جميع المجلدات الأخرى. يعطى المجلد الأساسي في نظام التشغيل ويندوز Windows الاسم \:C، ويسمى أيضًا القرص :C، بينما في أنظمة التشغيل ماك أو إس Mac os ولينكس Linux فيشار إليه بالشكل /. سنعبّر عن المجلد الأساسي بطريقة نظام التشغيل ويندوز، أي بالشكل التالي \:C، أما إن كنت ستكتب أوامر أمثلة الصَدفة التفاعلية في نظام التشغيل ماك أو إس أو لينكس فأدخل / بدلاً عنها. هناك نماذج أخرى مثل محركات الأقراص DVD ومحركات الأقراص القابلة للإزالة USB flash drive والتي ستظهر بشكل مختلف في أنظمة التشغيل المختلفة، ففي نظام التشغيل ويندوز تظهر كمجلد أساسي جديد يحمل رمز حرف معين مثلاً \:D أو \:E، بينما في نظام ماك أو إس فتظهر كمجلد جديد ضمن المجلد Volumes/، وفي نظام التشغيل لينكس تظهر كمجلد جديد ضمن المجلد ‪/mnt ("mount") ومن الجدير بالملاحظة أن أسماء المجلدات والملفات ليست حساسة لحالة الأحرف في نظامي ويندوز أو ماك أو إس، إلا أنها كذلك في نظام تشغيل لينكس. المسارات في بايثون يُستخدم الخط المائل العكسي \ للفصل بين أسماء المجلدات والملفات في نظام التشغيل ويندوز، لكن في نظامي ماك أو إس ولينكس فيتولى الخط المائل الأمامي / تلك المهمة، لذا وبدلًا عن كتابة كل شيفرة بالطريقتين لجعل النص البرمجي المكتوب بلغة بايثون قابلاً للتطبيق على مختلف أنظمة التشغيل، يمكننا استخدام الوحدة pathlib والمعامل / بدلًا من ذلك. من الممكن استيراد مكتبة pathlib من خلال تنفيذ الأمر from pathlib import Path، ولأن صنف المسار Path هو أكثر الأصناف استخدامًا في وحدة pathlib، فمن المسموح كتابة Path وحدها بدلًا من كتابة pathlib.Path. وبإمكاننا أن نمرر إلى الدالة ()Path سلسة نصية هي عبارة عن اسم المجلد أو اسم الملف، وذلك بغية إنشاء كائن مسار Path لاسم هذا المجلد أو الملف. وبما أن أن الكائن في أقصى يسار السطر البرمجي ما هو إلا كائن مسار Path، فيمكننا الآن استخدام المعامل / لدمج كائنات أو سلاسل هذا المسار مع بعضها. والآن لنكتب الشيفرة التالية في الصدفة التفاعلية: >>> from pathlib import Path >>> Path('spam') / 'bacon' / 'eggs' WindowsPath('spam/bacon/eggs') >>> Path('spam') / Path('bacon/eggs') WindowsPath('spam/bacon/eggs') >>> Path('spam') / Path('bacon', 'eggs') WindowsPath('spam/bacon/eggs') ونلاحظ بأنه كوننا ننفذ الشيفرة السابقة على حاسوب يعمل بنظام تشغيل ويندوز، فإن الدالة ()Path تعيد كائن مسار ويندوز windowspath، في حين ستتم إعادة الكائن PosixPath في حال استخدام أحد نظامي التشغيل ماك أو إس أو لينكس. (تعد POSIX مجموعة معايير لأنظمة التشغيل الشبيهة بنظام يونيكس ولن نتطرق لها في دراستنا). ومن الممكن تمرير كائن المسار إلى أي دالة تتطلب اسم ملف في المكتبة المعيارية لبايثون. فعلى سبيل المثال يعد استدعاء الدالة التالية: open(Path('C:\\') / 'Users' / 'Al' / 'Desktop' / 'spam.py') مكافئًا لاستدعاء الدالة التالية: open(r'C:\Users\Al\Desktop\spam.py') المجلد الرئيسي ما من مستخدم إلا ولديه مجلد رئيسي يخزن فيه ملفاته على الحاسوب، ومن الممكن الحصول على كائن مسار لهذا المجلد الرئيسي باستدعاء التابع ()path.home بالشكل: >>> Path.home() WindowsPath('C:/Users/Al') وتوجد المجلدات الرئيسية في مكان محدد بناءً على نوع نظام التشغيل: توجد المجلدات الرئيسية في نظام التشغيل ويندوز ضمن C:\Users. توجد المجلدات الرئيسية في نظام التشغيل ماك أو إس ضمن Users/. توجد المجلدات الرئيسية في نظام التشغيل لينكس ضمن home/. تمتلك النصوص البرمجية غالبًا أذونات القراءة والكتابة على الملفات في المجلد الرئيسي وبالتالي تعد هذه المجلدات مكانًا مثاليًا لتخزين الملفات التي ستتعامل معها برامج بايثون. مجلد العمل الحالي لكل برنامج يعمل على الحاسوب مجلد عمل حالي (cwd) توجد فيه جميع أسماء الملفات والمسارات التي لا تبدأ بالمجلد الأساسي. وعلى الرغم من أن كلمة "مجلد folder" هي الاسم الحديث للدليل Directory، يعد cwd (أو ما يعرف بدليل العمل الحالي) هو المصطلح المعياري وليس "مجلد العمل الحالي". يمكننا الحصول على دليل العمل في هيئة كائن مسار باستخدام الدالة ()Path.cwd وتغييره باستخدام الدالة ()os.chdir، ولإنجاز ذلك سنكتب الشيفرة التالية في الصدفة التفاعلية: >>> from pathlib import Path >>> import os 1 >>> Path.cwd() WindowsPath('C:/Users/Al/AppData/Local/Programs/Python/Python38') 2 >>> os.chdir('C:\\Windows\\System32') >>> Path.cwd() WindowsPath('C:/Windows/System32') اعتبرنا في الشيفرة السابقة أن مسار دليل العمل هو: C:\Users\Al\AppData\Local\Programs\Python\Python381 وبالتالي سيكون مسار الملف project.docx كالآتي: C:\Users\Al\AppData\Local\Programs\Python\Python381\project.docx وعندما نغير دليل العمل ليصبح C:\Windows\System32 سيصبح مسار الملف project.docx بالشكل C:\Windows\System32\project.docx، وسيظهر بايثون رسالة خطأ إن غيرنا المجلد إلى مجلد غير موجود: >>> os.chdir('C:/ThisFolderDoesNotExist') Traceback (most recent call last): File "<stdin>", line 1, in <module> FileNotFoundError: [WinError 2] The system cannot find the file specified: 'C:/ThisFolderDoesNotExist' ويعد استخدام الدالة ()os.getcwd من الوحدة os هو الطريقة الأقدم للحصول على مسار دليل العمل في هيئة سلسلة نصية. المسارات المطلقة والنسبية يوجد طريقتان لتحديد مسار ملف: المسار المطلق وهو الذي يبدأ دائمًا بالمجلد الأساسي. المسار النسبي والذي يشير عادةً إلى دليل العمل الخاص بالبرنامج. وهناك أيضًا المجلدات ذات النقطة (.) أو النقطتين (..). وهي ليست مجلدات حقيقية لكنها أسماء خاصة يمكن استخدامها في المسار. فالنقطة الوحيدة (.) تعد اختصارًا للدلالة على المجلد الحالي أو "هذا المجلد"، أما وجود نقطتين (..) فيشير إلى "المجلد الأب". ويبين الشكل التالي مثالًا لبعض المجلدات والملفات، فعندما يكون دليل العمل بالشكل C:\bacon تكون المسارات النسبية للمجلدات والملفات الأخرى كما هو مبين في الشكل أدناه. أما وجود الرمز في بداية المسار النسبي فهو أمر اختياري، فعلى سبيل المثال يشير كل من spam.txt. و spam.txt إلى الملف ذاته. المسارات النسبية للملفات والمجلدات في دليل العمل C:\bacon البرامج والعمليات يعرف البرنامج بأنه أي تطبيق برمجي يمكن تشغيله، كمتصفح الويب وتطبيق جدول البيانات ومعالج النصوص، في حين أن العملية عبارة عن نسخة قيد التشغيل running instance من البرنامج، فعلى سبيل المثال يبين الشكل أدناه خمس عمليات قيد التشغيل لنفس برنامج الآلة الحاسبة. تشغيل برنامج الآلة حاسبة عدة مرات على شكل عدة عمليات منفصلة إذ تبقى العمليات منفصلة عن بعضها حتى التابعة منها لنفس البرنامج، فمثلًا إن شغلنا عدة نسخ من برنامج بايثون في نفس الوقت ضمن عمليات مستقلة، فيمكن أن يكون لكل منها قيم متغيرات خاصة بها ومختلفة، فلكل عملية دليل العمل ومتغيرات البيئة الخاصة بها وذلك حتى بالنسبة للعمليات التابعة لنفس البرنامج، وعمومًا تُشغّل نوافذ سطر الأوامر عملية واحدة في كل مرة (ومن الممكن أيضًا فتح عدة نوافذ أوامر في نفس الوقت). ولكل نظام تشغيل طريقته لعرض قائمة العمليات قيد التنفيذ، ففي نظام ويندوز من الممكن تشغيل تطبيق مدير المهام عبر الضغط على مفاتيح CTRL+SHIFT+ESC، أما في نظام ماك أو إس فيمكن الوصول إليها من قائمة التطبيقات Application ومنها نختار الخدمات Utilities ومن ثم مراقب الأداء Activity Monitor، أما في نظام أبونتو لينكس يمكننا الضغط على مفاتيح CTRL+ALT+DEL معًا لتشغيل تطبيق يدعى أيضًا بمدير المهام، ويمكن لمدير المهام أيضًا إنهاء عملية ما قيد التشغيل إن لم تكن تستجيب. الخلاصة يتضمن ضبط البيئة كافة الخطوات الضرورية لجعل الحاسوب قادرًا على تشغيل برامجنا بسهولة، وتتطلب هذه العملية منا معرفة بعض مفاهيم الأولية حول كيفية عمل الحاسوب، كفهم نظام الملفات والمسارات والعمليات. إن نظام الملفات هو الآلية التي ينظم بها الحاسوب الملفات، فلكل ملف مسار مطلق كامل أو مسار نسبي بالنسبة لدليل العمل الحالي، ويمكنك التنقل في نظام الملفات من خلال سطر الأوامر. قد يستغرق الأمر وقتًا لتعتاد التعامل مع نظام الملفات باستخدام موجه الأوامر، لذا لا تتردد في البحث مطولًا على الإنترنت عن المساعدة، فهو الأمر الطبيعي الذي يقوم به مطورو البرامج يوميًا. ترجمة -وبتصرف- للفصل الثاني "إعداد البيئة وواجهة سطر الأوامر" من كتاب Beyond the Basic Stuff with Python لصاحبه Al Sweigart. اقرأ أيضًا المقال السابق: أصول طلب المساعدات البرمجية في بايثون عبر الإنترنت التعامل مع الملفات النصية في بايثون كيفية التعامل مع الملفات النصية في بايثون 3 التعامل مع الصفوف، المجموعات والقواميس في بايثون
    1 نقطة
  6. تعرفنا في المقال السابق على كيفية التعامل مع رسائل الأخطاء في بايثون وعلى الطرق المساعدة في فهم فحواها وإيجاد مسببات ظهورها، وذلك من خلال الاستعانة بمتتبع الأخطاء لتحديد مصدر الخطأ أو باستخدام منقح صياغة لتلافي وقوع أخطاء ما أمكن، أو اللجوء إلى الإنترنت بحثًا عن تفسير لمضمون رسالة الخطأ. ولكن ماذا لو فشلت هذه المحاولات، أو إن لم تجد في بحر الإنترنت سؤالًا مشابهًا لسؤالك، في هذه الحالة لابد من طرح سؤالك في أحد المنتديات أو ربما عبر إحدى المجموعات البريدية. في حال اضطررت لطرح سؤال جديد، فيجب عليك الالتزام بالعديد من القواعد والأصول لزيادة احتمالية الرد على سؤالك. سيرشدك هذا المقال نحو كيفية طلب المساعدة البرمجية باحترافية. كيفية طلب المساعدة البرمجية عند فشل كل من عمليات البحث على الإنترنت ومنقحات الصياغة في تحديد مشكلة برنامجك وحلها، ما من سبيل أمامك سوى طلب المساعدة البرمجية عبر الإنترنت، إلا أن لطلب النصيحة آداب وأصول ليكون أكثر فعالية، فعليك الاستفادة بكفاءة من وقت مطوري البرمجيات المحترفين كونهم مستعدون للإجابة عن تساؤلاتك بالمجان. ويجب أن يكون هذا الحل هو الأخير دائمًا بالنسبة لك، فقد تمر ساعات أو أيام قبل أن يرد أحد الأشخاص على سؤالك المنشور هذا إن رد أحدهم عليه أصلًا، لذا يبقى البحث في الإنترنت هو الأسرع عبر البحث عن آخرين قد طرحوا نفس سؤالك وقراءة الإجابات التي تلقوها، ومن هنا جاءت فكرة بناء التوثيقات ومحركات البحث، بغية أتمتة عمليات الإجابة عن الأسئلة التي كان يتعين على البشر الإجابة عنها. وفي حال سدت كل السبل في طريقك واستنفذتَ خياراتك بحيث لم يتبقَ أمامك سوى خيار طرح السؤال على جمهور المبرمجين، فتجنب الأخطاء الشائعة التالية: إضاعة الوقت بالسؤال عما إذا كان من المقبول طرح سؤالك بدلًا من طرحه مباشرةً. أن يكون سؤالك ضمنيًا وغير مباشر. طرح السؤال في الموقع الإلكتروني أو المنتدى غير المناسب. أن يكون عنوان السؤال غير محدد من قبيل "لدي مشكلة" أو "أرجو المساعدة". أن تذكر كون برنامجك لا يعمل دون توضيح الطريقة التي تريدها أن يعمل بها. عدم تضمين رسالة الخطأ كاملةً. عدم مشاركة الشيفرة. مشاركة شيفرة رديئة التنسيق. عدم ذكر الخطوات التي قد جربتَها أصلًا. عدم ذكر معلومات نوع نظام التشغيل وإصداره. طلب كتابة برنامج كامل. إن قائمة "أشياء لا يجب فعلها" السابقة ليست بهدف اللباقة فحسب، وإنما لأن فعلها لن يمكّن من يرغب بمساعدتك من تحقيق ذلك، فالخطوة الأولى لأي شخص قد يساعدك تتمثّل في تنفيذ الشيفرة محاولًا إعادة إظهار المشكلة بنفس الطريقة التي واجهتك، ولإتمام ذلك لا بد من توفر الكثير من المعلومات حول شيفرتك وحاسوبك وتطلعاتك حول نتائج البرنامج. فمن الشائع جدًا تقديم معلومات قليلة جدًا حول السؤال المطروح بدلًا من تقديم الكثير منها، وسنستعرض في الأقسام التالية الممارسات الواجب اتباعها لتجنب هذه الأخطاء الشائعة وفيها سنفترض بأنك تنشر أسئلتك في أحد المنتديات البرمجية، إلا أن القواعد نفسها تنطبق في حال طرحها عبر البريد الإلكتروني لشخص واحد أو لقائمة بريدية. قلل من النقاشات غير المجدية بتقديم كافة المعلومات اللازمة مقدما لو افترضنا أنك تطرح على أحدهم سؤالك وجهًا لوجه، فسيكون من المناسب والمريح سؤاله حول إمكانية طرح سؤالك لمعرفة ما إذا كان متوفرًا، ولكن في المنتديات الأمر مختلف، فمن سيساعدك قد يؤجل رده عليك إلى حين توفر الوقت المناسب له، ونظرًا لاحتمالية وجود ساعات ما بين طرح السؤال والحصول على الردود، فمن الأفضل طرح السؤال مباشرة وتوفير كافة المعلومات التي قد يحتاجها من سيساعدك بدلًا من إضاعة الوقت في السؤال عن إمكانية طرح السؤال، وبذلك وفي حال عدم تلقيك لأي ردود، يمكنك ببساطة نسخ معلومات سؤالك كاملًا لطرحها في منتدى أخر. اطرح سؤالك على هيئة سؤال فعلي قد تفترض مجازًا أن مُساعديك على اطلاع حول ما تتحدث عنه لدى شرح مشكلتك، إلا أن البرمجة مجال واسع جدًا وقد لا يكون لديهم الخبرة في الجزئية التي تواجه مشكلة فيها، لذا من المهم طرح سؤالك على هيئة سؤال فعلي، فعلى الرغم من كون الجمل التي تبدأ بعبارات من قبيل "أريد …. " أو "الشيفرة لا تعمل" قد توضح ماهية سؤالك، إلا أنه من الضروري تضمين أسئلة صريحة ومباشرة، أي جمل تنتهي بإشارات استفهام، وإلا وفي حال عدم استخدامها قد لا يتضح تمامًا ما تطلبه. اطرح سؤالك في المكان المناسب غالبًا سيكون من غير المجدي طرح سؤال حول بايثون في منتدى مخصص لجافاسكربت، أو سؤال حول الخوارزميات في قائمة بريدية مخصصة لأمن الشبكات، فغالبًا ما تتضمن المنتديات والقوائم البريدية على مستندات تتضمن الأسئلة الشائعة FAQ أو صفحات وصف لطبيعتها والتي تبين المواضيع المناسبة للنقاش فيها. فعلى سبيل المثال تتمحور القائمة البريدية python-dev حول الميزات التصميمية للغة بايثون ولا تمثل قائمة بريدية عامة للمساعدة حول بايثون بصورة عامة. وستوجهك صفحة المساعدة إلى المكان المناسب وفق طبيعة سؤالك حول بايثون. لخص سؤالك في العنوان لعل من أحد فوائد نشر سؤالك في منتدى على الإنترنت أن المبرمجين المستقبليين ممن سيواجهون نفس المشكلة سيجدون سؤالك وإجابته لدى البحث على الإنترنت، لذا تأكد من اختيارك لعنوان يلخص سؤالك بالفعل الأمر الذي يساعد على تنظيمه في محركات البحث، فالعناوين العامة من قبيل "أرجو المساعدة" أو "لماذا لا يعمل هذا الأمر؟" مبهمة، وكذلك الأمر في حال إرسال بريد إلكتروني، ففي حال اختيارك لعنوان ذو معنى، فهذا سيساعد المتلقي على معرفة فكرة سؤالك بمجرد تصفحه لصندوقه الوارد. وضح الهدف المرجو من شيفرتك سؤال من قبيل "لماذا لا يعمل برنامجي؟" يتجاهل تفاصيل دقيقة حول ما المتوقع من هذا البرنامج فعله أصلًا، فلن يكون هذا بالأمر الجلي دائمًا لمن سيساعدك كونه لا يعرف على وجه التحديد غايتك المرجوة من البرنامج، وحتى إن كان سؤالك من نوع "لماذا يظهر هذا الخطأ لي؟" فمن المفيد أيضًا تحديد الهدف النهائي للبرنامج، ففي بعض الأحيان قد يرشدك المساعد إلى منهجية مختلفة تمامًا في تحقيق غايتك ما يجعلك تتخطى المشكلة تمامًا بدلًا من إضاعة الوقت في محاولة حلها. ضمّن رسالة الخطأ كاملة تأكد دائمًا من نسخ رسالة الخطأ بأكملها مع ملخص متتبّع الأخطاء، فإن وصف الخطأ وحده كقولك "أتلقى خطأ من نوع Out of range" لا يوفر لمن يساعدك تفاصيلًا كافية لاكتشاف ماهية الخطأ، كما يجب عليك تحديد ما إذا كان خطأً عابرًا أم دائمًا، وفي حال كنت قد اكتشفت الظروف التي يحدث عندها الخطأ، فضمّنها أيضًا في سؤالك. شارك شيفرتك كاملة إلى جانب رسالة الخطأ الكاملة وملخص متتبّع الأخطاء، شارك الشيفرة المصدرية لبرنامجك كاملةً، بحيث يتمكن من سيساعدك من تشغيلها على حاسوبه مستخدمًا منقّح أخطاء لاكتشاف ما يحدث، فيجب عليك توفير نسخة من شيفرتك فيها ما يهم من سيساعدك بالكامل بأقل تعقيد وبحيث تكون قابلة للتعديل وإعادة التنفيذ، وهذا ما أطلق عليه موقع Stack Overflow اختصارًا MCR. إذ يرمز الحرف M إلى Minimal بمعنى أن تكون الشيفرة أقصر ما يمكن مع بقائها تسبب المشكلة التي تواجهك، أما الحرف C فيرمز إلى Complete بمعنى أن تكون الشيفرة كاملة ومتضمنة كل ما يلزم لظهور المشكلة، والحرف R فيرمز إلى Reproducible بمعنى أن الشيفرة ستسبب نفس المشكلة التي تصفها عند كل تنفيذ، أما إن كان برنامجك مضمنًا في ملف واحد، فسيكون من السهل إرفاقه بسؤالك بعد التأكد من تنسيقه بطريقة صحيحة. اجعل شيفرتك مقروءة ومفهومة باستخدام التنسيق الملائم إن الهدف الرئيسي من إرفاق الشيفرة الخاصة ببرنامجك مع سؤالك هو السماح لمن سيساعدك بتشغيل هذه الشيفرة للحصول على نفس الخطأ الظاهر لديك، فلا يحتاج هذا الشخص مجرد الشيفرة فحسب، بل يحتاجها منسقة بالشكل الصحيح، فيجب عليك التأكد من كونه قادرًا على نسخها لتكون جاهزة لتشغيلها مباشرةً، فمن الجدير بالملاحظة مثلًا أن العديد من مضيفي البريد الإلكتروني يزيلون المسافات البادئة تلقائيًا، ما يجعل الشيفرة تبدو بالشكل: def knuts(self, value): if not isinstance(value, int) or value < 0: raise WizCoinException('knuts attr must be a positive int') self._knuts = value فالأمر ليس بمجرد الوقت الذي سيستغرقه من سيساعدك في إعادة إدخال المسافات البادئة لكل سطر في شيفرتك، بل وحيرته بشأن مقدارها لكل سطر. وللتأكد من الحفاظ على صحة تنسيق الشيفرة الخاصة ببرنامجك، انسخها إلى أحد مواقع مشاركة الشيفرات مثل https://pastebin.com/ أو https://gist.github.com/ والتي تخزن شيفرتك على هيئة رابط مختصَر وعام، فمثلًا إن أرفقت الشيفرة مع سؤالك على هيئة رابط مثل https://pastebin.com/XeU3yusC سيكون أيسر وأسهل من إرفاقها كملف مرفق. وإذا كنت في صدد نشر شيفرة برنامجك في أحد المواقع الإلكترونية مثل stackoverflow أو قسم الأسئلة في أكاديمية حسوب أو reddit، فتأكد من استخدامك لأدوات التنسيق التي توفرها الصناديق النصية فيها، فمثلًا باستخدامك لمسافة بادئة مكونة من أربعة مسافات سيضمن بالنتيجة استخدام نمط خط ذو تباعد مفرد للشيفرة بالغالب وهو الأسهل للقراءة، كما يمكنك تضمين الشيفرة ما بين علامات اقتباس مائلة (`) لتنسيقها بنمط خط ذو تباعد مفرد. وعادةً ما تتضمن هذه المواقع رابطًا لشرح قواعد التنسيق، والتي بعدم اتباعها ستظهر شيفرتك بشكل غير واضح، كأن تظهر مكتوبة في سطر واحد بالكامل، كما يلي: def knuts(self, value):if not isinstance(value, int) or value < 0:raise WizCoinException('knuts attr must be a positive int') self._knuts = value ومن المهم أيضًا عدم مشاركتك للشيفرة على هيئة صورة أو لقطة شاشة، الأمر الذي يجعل من المستحيل نسخها، ناهيك عن كونه في هذه الحالة -على الغالب- غير مقروء. اذكر في سؤالك جميع المحاولات التي أجريتها عند نشرك لسؤال ما، لا تنسَ إخبار من سيساعدك بما قد حاولت تجريبه كحلول وما كانت نتائج كل محاولة، لما لهذه المعلومات من دور في توفير الوقت والجهد على من سيساعدك في تجربة حلول غير ناجحة، ناهيك عن الانطباع الذي تعطيه حيال بذلك لجهد في سبيل حل مشكلتك. كما أن تقديمك لهذه المعلومات يوضح أنك تطلب المساعدة فقط، ولست اتكاليًا تنتظر من يكتب لك شيفرة لبرنامجك عوضًا عنك. فالخبر السيئ أن الكثير من طلاب علوم الحاسوب اعتادوا أن يطلبوا من الأشخاص على الإنترنت حل واجباتهم، أو من المستقلين أن يعدّو لهم تطبيقات سريعة مجانًا، متناسين أن منتديات المساعدة البرمجية لم تعد أصلًا لهذا الغرض. وصف الإعدادات التي تستخدمها إن لإعدادات حاسوبك الأثر البالغ في كيفية تنفيذ شيفرة برنامجك وعلى نوعية الأخطاء التي قد تنتج، ولضمان تمكن من سيساعدك من الحصول على نفس المشكلة التي تواجهك على حاسوبه، يجب عليك تقديم المعلومات التالية حول حاسوبك: نوع نظام التشغيل وإصداره، كأن تذكر أنه الإصدار الاحترافي من ويندوز 10 أو إصدار كاتالينا (الخامس عشر) من ماك أو إس. إصدار بايثون المستخدم في تنفيذ برنامجك، كأن تذكر بأن الإصدار 3.7 من بايثون أو الإصدار 3.6.6 منها. أي وحدات خارجية تستخدمها في برنامجك مع ذكر إصدار كل منها، كأن تذكر أنك تستخدم الإصدار 2.1.1 من وحدة جانغو. ولمعرفة إصدارات الوحدات الخارجية المستوردة في برنامجك، يمكنك تشغيل الأمر pip list، كما يمكنك التأكد من رقم إصدار كل منها باستخدام سمة الإصدار __version__، كما في المثال التالي المكتوب ضمن صَدفة بايثون التفاعلية: >>> import django >>> django.__version__ '2.1.1' ورغم كون هذه المعلومات ليست بذلك القدر من الأهمية، إلا أن ذكرها سيقلل من الوقت الضائع في النقاشات (الصد والرد)، لذا من المحبذ عرضها من البداية. أمثلة على أسئلة متكاملة نبين فيما يلي مثالًا على سؤال مطروح بطريقة صحيحة وفقًا للإرشادات والنصائح الواردة في هذا المقال: محرك الويب سيلينيوم: كيف أجد كافّة سمات العنصر؟ لدى استخدامي لوحدة سيلينيوم في بايثون، فبإمكاني الحصول على قيمة أي سمة من سمات كائن عنصر الويب باستخدام التابع ()get_attribute بالشكل: get_attribute(): foo = elem.get_attribute('href') وفي حال عدم وجود اسم السمة href، ستكون القيمة المعادة لا شيء None. سؤالي هو: كيف أحصل على قائمة بكافة سمات كل عنصر؟ فيبدو أنه لا يوجد توابع لجلب السمات من قبيل get_attributes() أو ()get_attribute_names. علمًا أني أستخدم الإصدار 2.44.0 من وحدة سيلينيوم في بايثون. لقد ورد هذا السؤال في قسم الأسئلة في أكاديمية حسوب، وفيه نلاحظ بأن العنوان قد لخص مضمون السؤال كاملًا في جملة واحدة، إذ ذُكرت المشكلة وهي التي تتحدث عن صيغة الخطأ الذي يظهر أثناء التنفيذ، وبذلك إذا قرأ شخص ما هذا العنوان مستقبلًا في نتائج البحث، فسيتضح له مباشرةً فيما إذا كان ذو صلة بسؤاله أم لا. كما أن الشيفرة ضمن السؤال منسقة بطريقة جيدة، وأجزاء النص مفصولة على هيئة فقرات، كما أن وجه السؤال واضح تمامًا، وقد تمت الإشارة له بعبارة "كيف أحل المشكلة؟"، كما يتحدث عن حدوث المشكلة أحيانًا وليس دائمًا، وهذا يدل على أن السائل قد حاول بالفعل إيجاد جواب وجرب حل الموضوع وتجريبه عدة مرات قبل أن يتجه لطرح السؤال. الخلاصة لعل وصولك إلى إجابات عن أسئلتك الخاصة بنفسك هي واحدة من أهم المهارات التي عليك اكتسابها كمبرمج، وهنا يمثّل الإنترنت ثروة من المصادر المتضمنة الإجابات التي تحتاج. إلا أن الإجراء الأول الذي يجب اتخاذه هو محاولة تحليل رسالة الخطأ المبهمة المعروضة من قبل بايثون، وفي حال عدم تمكنك من إيجاد حل لمشكلتك عبر البحث في الإنترنت، فحاول عندها نشر سؤالك في أحد المنتديات البرمجية أو إرسال بريد إلكتروني لأحد المختصين، إذ قدمنا في هذا المقال نصائح وإرشادات من شأنها ضمان كون هذه العملية فعالة ومثمرة من خلال طرح سؤال جيد. وتتمثل مواصفات السؤال الجيد في كونه محددًا ومفصلًا، يوفر الشيفرة المصدرية المسببة للخطأ كاملةً بالإضافة إلى رسالة الخطأ نفسها، شارحًا الإجراءات المجربة أصلًا مع تحديد نوع نظام التشغيل وإصدار بايثون المستخدم. وبحصولك على إجابة لسؤالك، لن تقتصر الفائدة عليك، بل على أي مبرمج مستقبلي قد يواجه نفس مشكلتك. وتذكر أن البرمجة مجال واسع جدًا، ولا يمكن لأحد أن يحيط بجميع تفاصيله، لذا لا تشعر بالإحباط إن اضطررت للبحث باستمرار عن إجابات لأسئلتك، فحتى مطورو البرمجيات المتمرسون يبحثون في الإنترنت عن التوثيقات والحلول يوميًا، وبدلًا من تضييع وقتك بالإحساس بالإحباط ركز على اكتساب مهارة إيجاد الحلول، وهي خطوة مهمة في طريقك لتصبح خبير بايثون. ترجمة -وبتصرف- للفصل الأول "التعامل مع الأخطاء وطلب المساعدة" من كتاب Beyond the Basic Stuff with Python لصاحبه Al Sweigart. اقرأ أيضًا المقال السابق: التعامل مع رسائل الأخطاء في بايثون كيفية استخدام سطر أوامر بايثون التفاعلي كيفية التعامل مع الأخطاء البرمجية
    1 نقطة
  7. تعد بايثون Python إحدى أشهر لغات البرمجة وأكثرها استخدامًا، وهي خيار ممتاز ليبدأ به المبرمجون المبتدئون، إذ يمكن استخدامها في معظم المجالات، بدءًا من ألعاب الفيديو، وحتى تحليل البيانات والتعلم الآلي. بايثون هي لغة برمجة عالية المستوى، وتفاعلية وكائنية. وتتمتع بمقروئية عالية، إذ تستخدم كلمات إنجليزية بسيطة، على خلاف اللغات الأخرى التي تستخدم الرموز، كما أنّ قواعدها الإملائية والصياغية بسيطة، ما يجعل تعلمها سهلًا موازنةً بلغات برمجة أخرى. وفي بدايات تعلّمك لغة بايثون ، وكما هو الحال في رحلة تعلّم أي لغة برمجة، قد تواجهك بعض العقبات ورسائل الأخطاء غير المفهومة، وفي هذه المرحلة من الشائع الشعور بالفشل لدى اضطرارك لاستشارة مواقع الإنترنت عدة مرات في اليوم. لكن حتى أمهر مطوري البرمجيات يبحثون في الإنترنت ويراجعون التوثيقات لإيجاد إجابات حول أسئلتهم البرمجية. كن على يقين بأنه طالما أنك لا تمتلك الموارد الاجتماعية أو المادية اللازمة للحصول على مدرس خصوصي للإجابة على أسئلتك البرمجية، فما من سبل أمامك سوى حاسوبك والإبحار في محركات البحث وصبرك، والخبر الجيد أنه من شبه المؤكد كون جميع تساؤلاتك قد طُرحت من قبل. فحتى تكون مبرمجًا لا بد من امتلاكك مهارة إيجاد إجابات على أسئلتك بنفسك، الأمر الذي يفوق بأهميته معرفتك لأي خوارزمية برمجية أو بنية معطيات ما. سيعمل هذا المقال على إرشادك نحو تطوير هذه المهارة البالغة الأهمية. كيفية فهم رسائل الأخطاء في بايثون عندما يواجه العديد من المبرمجين رسائل الأخطاء المليئة بالثرثرة التقنية، فإن أول ما يفكرون بفعله هو تجاهلها تمامًا، إلا أن رسالة الخطأ هذه تتضمن الإجابة حول الخطأ الحاصل في البرنامج، فإيجاد هذه الإجابة عبارة عن عملية ذات خطوتين: الأولى هي فحص متتبع الأخطاء، والثانية هي البحث في الإنترنت حول رسالة الخطأ هذه. فحص متتبع الأخطاء تتوقف برامج بايثون عن العمل لدى مصادفتها استثناءً دون وجود عبارة استثناء except للتعامل معه، وفي حال حدوث ذلك، تُعرض رسالة بهذا الاستثناء مع تتبّع له وهو ما يدعى أيضًا مكدّس الاقتفاء Stack trace، والذي يُظهر مكان حدوث الاستثناء في برنامجك ومسارات استدعاءات الدوال المسببة له. وبغية التدرب على كيفية قراءة تتبعات الأخطاء، سنكتب البرنامج البسيط التالي ونحفظه باسم abcTraceback.py، إذ تلعب أرقام الأسطر دور المرجع والدليل للسطر وليست جزءًا من الشيفرة. 1. def a(): 2. print('Start of a()') 1 3. b() # Call b(). 4. 5. def b(): 6. print('Start of b()') 2 7. c() # Call c(). 8. 9. def c(): 10. print('Start of c()') 3 11. 42 / 0 # This will cause a zero divide error. 12. 13. a() # Call a(). في البرنامج السابق، تستدعي الدالة ()a الدالة ()b، التي تستدعي بدورها الدالة ()c المتضمنة للتعبير الرياضي 42/0 المسبب لخطأ القسمة على صفر، فعند تشغيل هذا البرنامج، سيبدو الخرج بالشكل: Start of a() Start of b() Start of c() Traceback (most recent call last): File "abcTraceback.py", line 13, in <module> a() # Call a(). File "abcTraceback.py", line 3, in a b() # Call b(). File "abcTraceback.py", line 7, in b c() # Call c(). File "abcTraceback.py", line 11, in c 42 / 0 # This will cause a zero divide error. ZeroDivisionError: division by zero لنتفحص الآن تقرير متتبع الأخطاء سطرًا بسطر، والذي يبدأ من السطر: Traceback (most recent call last): وتهدف هذه الرسالة إلى إبلاغك بأن ما يتلوها هو تقرير متتبّع الأخطاء، وتشير العبارة most recent call last والتي تعني أن الاستدعاء الأخير سيظهر في نهاية التقرير إلى كون استدعاءات التوابع ستظهر في التقرير بنفس ترتيب ورودها في الشيفرة، بدءًا من استدعاء أول دالة وانتهاءً بآخرها. أما السطر التالي فيظهر تقرير تتبّع استدعاء أول دالة: File "abcTraceback.py", line 13, in <module> a() # Call a(). وندعو هذين السطرين بملخص كائن الإطار، كما أنهما يُظهران معلوماتهما ضمن كائن إطار. فعند استدعاء دالة ما فإن كل من بيانات المتغير المحلي والمكان المخصص في الشيفرة لإسناد القيمة المعادة من الدالة بعد استدعائها يُخزنان ضمن كائن إطار، إذ تتضمن كائنات الأطر كل من المتغيرات المحلية وغيرها من البيانات المتعلقة باستدعاء الدوال، إذ يتم إنشاء هذه الكائنات لحظة استدعاء الدوال وينتهي بإعادة الدالة لقيمتها. ويُظهر متتبّع الأخطاء ملخصًا على هيئة إطار لكل إطار قد انتهى دوره بإعادة قيمة دالته، ونلاحظ من التقرير أعلاه أن استدعاء هذه الدالة قد تم في السطر ذو الرقم 13 من الملف abcTraceback.py، ويشير الوسم <module> إلى كون هذا السطر مصرح عنه ضمن المجال العام، ليظهر بعدها السطر 13 نفسه مسبوقًا بمسافتين بادئتين. وتظهر الأسطر الأربعة التالية ملخصات الأطر التالية: File "abcTraceback.py", line 3, in a b() # Call b(). File "abcTraceback.py", line 7, in b c() # Call c(). ومنه نستنج أنه قد تم استدعاء الدالة ()b في السطر الثالث ضمن الدالة ()a، ما أدى بدوره إلى استدعاء الدالة ()c في السطر 7 ضمن الدالة ()b. ومن الجدير بالملاحظة أن تقرير التتبع لا يُظهر استدعاء الدالة ()print الذي تم في كل من الأسطر 2 و 6 و 10 من الشيفرة رغم تشغيلها حتى قبل استدعاء الدوال آنفة الذكر، والسبب في ذلك هو أن التقرير يشمل فقط الأسطر الحاوية على استدعاءات التوابع المسببة للاستثناء. وآخر إطار من ملخص تقرير تتبع الأخطاء يظهر رقم السطر المتضمن للاستثناء الذي لم يتم التعامل معه متبوعًا باسمه ورسالة الخطأ الخاصة به: File "abcTraceback.py", line 11, in c 42 / 0 # This will cause a zero divide error. ZeroDivisionError: division by zero ومن الجدير بالملاحظة أن رقم السطر المعطى في متتبع الأخطاء هو مكان عثور بايثون على آخر خطأ، وبالتالي من الممكن كون مصدر الخطأ الرئيسي في سطر ما قبله. وتُعرف رسائل الخطأ بكونها مختصرة ومبهمة، فالكلمات الثلاث "قسمة على صفر" لن تعني شيئًا ما لم تكن تعلم أنه من المستحيل قسمة أي عدد على الصفر رياضيًا وبأنه يمثل خطأً برمجيًا شائعًا، وفي برنامجنا السابق ليس من الصعب تحديد موطن الخطأ، فبمجرد النظر إلى رقم سطر الشيفرة في إطار ملخص تقرير متتبع الأخطاء يتضح أن خطأ القسمة على صفر يحدث عند التعبير 42/0 من الشيفرة. والآن دعونا ننتقل إلى حالة أصعب قليلًا. لذا، اكتب الشيفرة التالية ضمن محرر النصوص واحفظ الملف باسم zeroDivideTraceback.py: def spam(number1, number2): return number1 / (number2 - 42) spam(101, 42) ولدى تشغيل هذا البرنامج، سيبدو الخرج كالتالي: Traceback (most recent call last): File "zeroDivideTraceback.py", line 4, in <module> spam(101, 42) File "zeroDivideTraceback.py", line 2, in spam return number1 / (number2 - 42) ZeroDivisionError: division by zero إن رسالة الخطأ هي نفسها كما في المثال السابق، إلا أن خطأ القسمة على صفر في السطر البرمجي return number1 / (number2 - 42) غير واضح تمامًا، ولكن من الممكن استنتاج وجود عملية قسمة من وجود المعامل /، وبأن التعبير (number2-42) يساوي الصفر، وهذا ما يمكننا من استنتاج أن الدالة spam() ستعطي خطأ في حال كان الوسيط الثاني number2 المُمرر لها مساويًا للعدد 42. وقد يشير متتبّع الأخطاء أحيانًا إلى كون الخطأ في السطر التالي لمسبب الخطأ الحقيقي. فعلى سبيل المثال، في البرنامج التالي ينقص السطر الأول منه قوس إغلاق دالة الطباعة: print('Hello.' print('How are you?') إلا أن رسالة الخطأ لهذا البرنامج تشير لكون المشكلة في السطر الثاني منه: File "example.py", line 2 print('How are you?') ^ SyntaxError: invalid syntax والسبب في ذلك هو أن مفسر بايثون لن يلاحظ هذا الخطأ إلا عند قراءته للسطر الثاني، فقد يشير متتبّع الأخطاء إلى مكان حدوث الخطأ والذي لن يكون بالضرورة هو نفس موضع مسبب حصول الخطأ الفعلي. وفي حال فشل إطار الملخص في تقديم ما يكفي من معلومات لاكتشاف الخطأ، أو في حال كون المسبب الحقيقي للخطأ في سطرٍ سابق غير موضح في متتبّع الأخطاء، عندها عليك المرور على برنامجك مستخدمًا منقّح الأخطاء، كما يمكنك التحقق من رسائل السجل بحثًا عن السبب. الأمر الذي قد يستغرق وقتًا ليس بالقليل، لذا فإن البحث في الإنترنت حول المشكلة قد يعطيك دلائل مهمة حول كيفية حلها بسرعة أكبر. البحث حول رسائل الخطأ تكون رسائل الأخطاء في الغالب قصيرة جدًا ولا تمثل جملًا كاملة، والسبب في ذلك هو كونها رسائل تذكيرية وليست تفسيرية، إذ يصادفها المبرمجون بانتظام. وإذا كنت تواجه رسالة خطأ للمرة الأولى، فإن نسخها ولصقها في أحد محركات البحث على الإنترنت سيوصلك في الغالب إلى شرح تفصيلي حول الخطأ وأسباب حدوثه المحتملة. ويبين الشكل التالي نتائج البحث عن الجملة python "ZeroDivisionError: division by zero" أي "خطأ القسمة الصفرية: قسمة على صفر" بايثون، إذ من المفيد تضمين رسالة الخطأ ما بين إشارتي تنصيص في إيجاد عبارة موافقة بدقة، كما أن إضافة كلمة Python يؤدي إلى تضييق نطاق البحث أكثر. نسخ رسالة خطأ ولصقها في إحدى أدوات البحث على الإنترنت يمكن أن يؤمن تفسيراتٍ وحلولًا سريعة. ولا يمكن عد البحث حول رسائل الخطأ شكلًا من أشكال الغش أو الاتكالية، فمن شبه المستحيل أن يحفظ الشخص كافة رسائل الخطأ المحتملة لأي لغة برمجة، إذ يبحث مطورو البرمجيات المحترفون عن إجابات لأسئلتهم البرمجية في الإنترنت يوميًا. وفي حال كون أحد أجزاء رسالة الخطأ التي تواجهك هو خاص بشيفرتك أنت، فمن الأفضل استبعاده أثناء البحث، ولتوضيح هذه النقطة لنأخذ رسائل الخطأ التالية: >>> print(employeRecord) Traceback (most recent call last): File "<stdin>", line 1, in <module> 1 NameError: name 'employeRecord' is not defined >>> 42 - 'hello' Traceback (most recent call last): File "<stdin>", line 1, in <module> 2 TypeError: unsupported operand type(s) for -: 'int' and 'str' يوجد في هذا المثال خطأ كتابي في اسم المتغير employeRecord ما سبب حدوث الخطأ 1، وبما أن المعرف employeRecord خاص بشيفرتك، وذلك في رسالة الخطأ NameError: name 'employeRecord' is not defined والتي تعني حدوث خطأ في الاسم بسبب كون اسم المتغير employeRecord غير معرف. أما في السطر الأخير فمن الواضح أن الأجزاء int و str من رسالة الخطأ 2 تعود للقيم 42 و hello على التوالي، ففي هذه الحالة من الأفضل اقتصار البحث على العبارة python "TypeError: unsupported operand type(s)" for والتي تعني خطأ في نمط البيانات ناتج عن كون أحد المعاملات ذو نمط غير مدعوم، وذلك بدلًا من تضمين البحث بأجزاء من الرسالة تخص شيفرتك على وجه التحديد، وإذا فشل هذا البحث المختصر في الوصول إلى نتائج مفيدة، فجرب كتابة رسالة الخطأ كاملةً. تجنب حدوث الأخطاء باستخدام منقحات الصياغة لعل الطريقة الأفضل في إصلاح الأخطاء هي عدم الوقوع بها من الأصل، وهنا يأتي دور منقّحات الأخطاء Linters، وهي عبارة عن تطبيقات تعمل على تحليل الشيفرة المصدرية لتنبهك حول أي خطأ محتمل فيها، أما اسمها "Linters" فقد أتى تيمنًا بأداة جمع الألياف الصغيرة والأوبار في مجفف الملابس. ورغم كون منقّح الأخطاء لن يكتشف أخطاء الشيفرة بالكامل، إلا أن التحليل الساكن الذي يجريه (أي فحص الشيفرة المصدرية دون تشغيلها) قادر على تحديد العديد من الأخطاء الشائعة الناتجة عن الأخطاء الإملائية وسنستعرض في مقالات لاحقة كيفية استخدام تلميحات الكتابة التي يقدمها التحليل الساكن. وتتضمن العديد من محررات النصوص وبيئات التطوير البرمجية المتكاملة IDEs على منقّحات صياغة تعمل في الخلفية، والقادرة على التنبيه إلى الأخطاء المكتشفة بالزمن الحقيقي كما هو موضح في الشكل التالي. منقّح صياغة يشير إلى متغير غير مصرح عنه وذلك في محرر النصوص MU (الشكل الأعلى) وفي المحرر PyCharm (الشكل الأوسط) وفي المحرر Sublime (الشكل الأسفل). وبذلك تعمل إشعارات الأخطاء شبه الفورية التي يوفرها منقّح الأخطاء على تحسين إنتاجية العمل البرمجي بشكل ملموس، فبدون وجوده ستضطر إلى تشغيل برنامجك لتكتشف وجود خطأ، منتقلًا إلى ملخص متتبّع الأخطاء بحثًا عن السطر في الشيفرة المصدرية المتسبب في الخطأ لإصلاح الخطأ الإملائي المسبب له، ولكن ماذا لو ارتكبت عدة أخطاء إملائية؟ عندها لن تجدها إلا بإعادة تنفيذ البرنامج عدة مرات فكل دورة تشغيل ستجد خطأ واحد تتوقف عنده، في حين أن منقّحات الصياغة قادرة على الإشارة لوجود عدة أخطاء معًا ويتم ذلك مباشرةً في محرر النصوص أثناء كتابة الشيفرة، ما يمكنك من تحديد السطر الذي حدثت فيه المشكلة مباشرةً. وقد لا يأتي محرر النصوص أو البيئة البرمجية المتكاملة التي تستخدمها مع منقّح صياغة أصلًا، ولكن إن كانت تدعم الإضافات، فمن شبه المؤكد وجود منقّح صياغة كإضافة، وغالبًا ما تستخدم هذه الإضافات وحدة تنقيح صياغة تدعى Pyflakes أو وحدات أخرى تؤدي هذا الغرض. وبإمكانك تثبيت الوحدة Pyflakes من الرابط https://pypi.org/project/pyflakes/ أو باستخدام أمر تثبيت الحزم pip بكتابة الأمر pip install --user pyflakes، الأمر الذي يستحق العناء لإنجازه. ملاحظة: يمكنك في نظام ويندوز تشغيل كل من الأمرين pip و python، ولكن في حال استخدامك لأنظمة ماك أو إس أو لينكس فتكون أسماء هذين الأمرين بهذا الشكل فقط من أجل الإصدار الثاني من بايثون، أما للإصدار الثالث فيصبحان بالشكل pip3 و python3، انتبه لهذا الموضوع كلما صادفت أحد الأمرين pip أو python في سياق المقال. تأتي بيئة التطوير المتكاملة الخاصة ببايثون IDLE بدون منقّح صياغة وبدون القابلية لتثبيته فيها. الخلاصة لعل وصولك إلى إجابات عن أسئلتك الخاصة بنفسك هي واحدة من أهم المهارات التي عليك اكتسابها كمبرمج، وهنا يمثل الإنترنت ثروة من المصادر المتضمنة الإجابات التي تحتاج. إلا أن الإجراء الأول الذي يجب اتخاذه هو محاولة تحليل رسالة الخطأ المبهمة المعروضة من قبل بايثون، ولا تقلق إن لم تفهم محتواها، فبإمكانك نسخ نص الرسالة إلى أحد محركات البحث وصولًا إلى تفسير حولها باللغة الإنجليزية العادية مع بيان سببها المحتمل، كما أن متتبع الأخطاء سيشير إلى مكان وقوع الخطأ في شيفرة برنامجك. وهنا يلعب منقح الصياغة دورًا مهمًا في الإشارة إلى وقوع الأخطاء المطبعية والمشاكل المحتملة لحظة وقوعها، فهذه المنقحات مفيدة جدًا ولا غنى عنها في التطوير الفعال للبرمجيات، وفي حال كون محرر النصوص أو بيئة التطوير التي تستخدمها لا تملك منقحًا وغير قابلة لإضافته، فمن المفضل أن تنتقل إلى أحد المحررات التي تدعم وجود منقحات الصياغة. وتذكر أن البرمجة مجال واسع جدًا، ولا يمكن لأحد أن يحيط بجميع تفاصيله، لذا لا تشعر بالإحباط إن اضطررت للبحث باستمرار عن إجابات لأسئلتك، فحتى مطورو البرمجيات المتمرسون يبحثون في الإنترنت عن التوثيقات والحلول يوميًا، وبدلًا من تضييع وقتك بالإحساس بالإحباط ركز على اكتساب مهارة إيجاد الحلول، وهي خطوة مهمة في طريقك لتصبح خبير بايثون. ترجمة -وبتصرف- للفصل الأول "التعامل مع الأخطاء وطلب المساعدة" من كتاب Beyond the Basic Stuff with Python لصاحبه Al Sweigart. اقرأ أيضًا كيفية التعامل مع الأخطاء البرمجية أساسيات البرمجة بلغة بايثون إعداد بيئة العمل للمشاريع مع بايثون النسخة العربية الكاملة لكتاب البرمجة بلغة بايثون
    1 نقطة
  8. لغة بايثون هي لغة برمجة سهلة التعلم موازنةً باللغات الأخرى مثل لغة جافا ولغة C ولغة ++C، بالإضافة لكونها متعددة الأغراض فهي تستخدم في بناء تطبيقات سطح المكتب وألعاب الفيديو والرسومات ثلاثية الأبعاد والمواقع الإلكترونية وغيرها، زد على أنها لغة قوية برمجيًا وممتازة للتطبيقات المتقدمة، هذا كله جعلها خيارًا مثاليًا للجميع بصرف النظر عن عملهم وعمرهم وعدد سنوات خبرتهم، بالأخص للراغبين بتعلم البرمجة. هذا المقال جزءًا من سلسلة مقالات حول تصميم لعبة بلغة بايثون ومكتبة Pygame وإليك كامل مقالات السلسلة: بناء لعبة نرد بسيطة بلغة بايثون. بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب PyGame. إضافة لاعب إلى اللعبة المطورة باستخدام بايثون و Pygame. تحريك شخصية اللعبة باستخدام PyGame. إضافة شخصية العدو للعبة. إضافة المنصات إلى لعبة بايثون باستخدام الوحدة Pygame. محاكاة أثر الجاذبية في لعبة بايثون. إضافة خاصية القفز والركض إلى لعبة بايثون. إضافة الجوائز إلى اللعبة المطورة بلغة بايثون. تسجيل نتائج اللعبة المطورة بلغة بايثون وعرضها على الشاشة. إضافة آليات القذف إلى اللعبة المطورة بلغة بايثون. تثبيت بايثون ستحتاج إلى تثبيت بايثون الإصدار 3 لتتابع معنا خطوات العمل، لذا اتبع الخطوات المناسبة لنظام تشغيلك. إن كنت تستخدم نظام تشغيل لينكس، فستجد بايثون متوفرًا ضمنه على الأغلب، استعلم عن إصداره بالأمر التالي: python --version وانظر إلى الخرج فلو تبين لك أن الإصدار الموجود هو 2، أو أن بايثون غير مثبت على الإطلاق، حاول كتابة الأمر بالشكل التالي: python3 --version وإن حصلت على رسالة مفادها عدم التعرف على الأمر، فثبت بايثون 3 باستخدام مركز التطبيقات أو مدير الحزم الخاص بتوزيعة لينكس التي تعتمدها مثل apt في أوبونتو أو dnf في فيدورا. إن كانت توزيعتك هي فيدورا، ثبت بايثون 3 بالأمر التالي: sudo dnf install python3 اتبع الخطوات نفسها في نظام تشغيل macOS لتتأكد من وجود بايثون 3 في النظام، وإن لم يكن مثبتًا، حمله من موقع بايثون الرسمي ثم ثبته، وهنا لديك هذه الطريقة فقط إذ إن macOS لا يملك مدير حزم. أما لو كنت تستخدم نظام تشغيل ويندوز فحمل بايثون 3 من الموقع الرسمي في البداية، ويمكنك الاستعانة بالمقال كيفية تثبيت بايثون 3 وإعداد بيئته البرمجية على ويندوز 10 لهذا الغرض. عمومًا أيًا كان نظام التشغيل الذي تعتمده يمكنك الاستعانة بقسم تثبيت بايثون 3 وإعداد بيئتها البرمجية من المرجع الشامل لتعلم بايثون المتوفر باللغة العربية على أكاديمية حسوب. دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن تشغيل بيئة التطوير المتكاملة IDE فعليًا كل ما تحتاج إليه لكتابة البرامج بلغة بايثون هو محرر شيفرات، ولكن استخدامك بيئة تطوير متكاملة IDE سيسهل عليك كتابة الشيفرة كثيرًا، فهذه البيئات تتضمن وظيفة محرر الشيفرات البسيط مع بعض الأدوات الإضافية الملائمة لكتابة شيفرة بايثون، ويتوفر العديد من الخيارات مفتوحة المصدر لبيئات التطوير المتكاملة، سنعرض منها IDLE 3 و PyCharm. بيئة التطوير IDLE 3 الأساسية هي بيئة التطوير الأساسية المضمنة مع بايثون، وتتميز هذه البيئة بتلوين أجزاء الشيفرة ما يسهل قراءتها واكتشاف الأخطاء على المبرمج، وأيضًا بإعطاء تلميحات لإكمال التعليمات البرمجية، بالإضافة إلى وجود زر تشغيل لتسهيل تشغيلها واختبارها. لبدء استخدام هذه البيئة في لينكس ونظام macOS يكفيك كتابة الأمر idle3 في نافذة الطرفية، أما لاستخدامها في ويندوز فابحث عن بايثون 3 في قائمة ابدأ وستجد هذه البيئة بين خياراتها، وفي حال لم تجد بايثون في قائمة ابدأ، افتح سطر الأوامر بكتابة cmd في خانة البحث، ومن ثم اكتب ضمنه السطر التالي: C:\Windows\py.exe وإن لم ينفع، أعد تثبيت بايثون وتأكد من تفعيل خيار إضافة بايثون إلى متغير البيئة PATH في أثناء عملية التثبيت. وإن لم ينفع ذلك أيضًا، استخدم لينكس ضمن ويندوز نفسه أو بتثبيت لينكس مع ويندوز، فهو في النهاية مجاني، وهذا الانتقال في البيئة لن يكلفك أكثر من حفظ ملفات بايثون خاصتك على قرص USB محمول ونقلها. بيئة التطوير Pycharm النسخة المجتمعية تعدّ Pycharm من أفضل بيئات التطوير مفتوحة المصدر المتوافقة مع بايثون، تتميز بتلوين الشيفرات لتسهيل قراءتها ولاكتشاف أخطاء الكتابة، وإكمال الأقواس وعلامات الاقتباس لضمان صيغ قواعدية سليمة، بالإضافة إلى ميزة ترقيم الأسطر المفيدة في أثناء تنقيح الأخطاء، وعلامات المسافة البادئة، وزر التشغيل لتسهيل اختبار الكود. لتستخدم هذه البيئة ثبّت النسخة المجتمعية من Pycharm، إن كان نظام تشغيلك هو لينكس فيمكنك تثبيتها باستخدام flatpak من منصة FlatHub أو تحميلها من الموقع الرسمي وتثبيتها يدويًا، أما لو كنت تعتمد ويندوز أو macOS فحمل نسخة البرنامج المناسبة لك من موقعه الرسمي، ومن ثم ثبتها. افتح البرنامج بعد التثبيت وأنشئ مشروعًا جديدًا. أخبر بايثون بما تريد تنفيذه الكلمات المفتاحية هي كلمات أساسية تُعرّف الدوال والأصناف وغيرها فهي إذًا الوسيلة التي تخبر بايثون بكل ما تريد تنفيذه. لتجرب إحداها، اكتب السطر التالي ضمن مشروعك الجديد الذي أنشأته على بيئة التطوير: print("Hello world.") والآن شغله بإحدى الطريقتين: إن كنت تستخدم IDLE استعرض قائمة التشغيل وحدد الخيار "تشغيل الوحدة Run Module". أما في PyCharm انقر فوق الزر "تشغيل ملف Run file" ضمن أزرار شريط الأدوات. تطبع print -الكلمة المفتاحية التي جربناها- النص المكتوب بين علامتي اقتباس الموجود ضمن القوسين كما هو أيًا كان. وننوه لك أن بايثون افتراضيًا لا تستخدم إلّا الكلمات المفتاحية الأساسية مثل print و help وتلك الخاصة بالعمليات الحسابية الأساسية وما شابه، ولكن التعليمة import تتيح للمبرمج استيراد المزيد من الوظائف واستخدامها. استخدام وحدة الرسم turtle في بايثون اكتب الأسطر التالية في ملفك (بعد حذف الموجود فيه)، ومن ثم شغله: import turtle turtle.begin_fill() turtle.forward(100) turtle.left(90) turtle.forward(100) turtle.left(90) turtle.forward(100) turtle.left(90) turtle.forward(100) turtle.end_fill() لاحظ الأشكال التي يمكنك رسمها باستخدام مكتبة الرسم turtle والتي تدعى سلحفاة. لتمسح كل الموجود في مساحة الرسم، استخدم: turtle.clear() حاول تخمين معنى الدالة من اسمها الأجنبي: turtle.color("blue") لابد أنك أصبت، سيصبح لون الخط أزرق بدل الأسود، فسهولة فهم التعليمات وتفسيرها هي إحدى ميزات بايثون. سنحاول الحصول على النتيجة نفسها بكتابة كود مختلف أكثر تعقيدًا، وذلك باستخدام الحلقة while التي ستوجه بايثون ليكرر عملية رسم الخط والانعطاف أربع مرات متتالية عوضًا عن إعادة كتابة السطر نفسه أربع مرات كما فعلنا في الفقرة السابقة، أما المتغير الذي سيحدد عدد مرات التكرار فيسمى العداد counter، ستتعلم المزيد عن المتغيرات لاحقًا، ولكن الآن اكتب الأسطر التالية ونفذها لترى كيفية تفاعل المتغير مع الحلقة: import turtle as t import time t.color("blue") t.begin_fill() counter=0 while counter < 4: t.forward(100) t.left(90) counter = counter+1 t.end_fill() time.sleep(2) تعلم بايثون عبر بناء لعبة بسيطة هدفنا أساسًا تعلم البرمجة عبر لغة بايثون، وتمهيدًا لاستخدامها في برمجة متقدمة تعتمد على الرسوميات، سنبدأ في هذا المقال بتعلم منطق اللعبة وكيفية تنظيم البيئة لبناء لعبة نرد بسيطة، يلعب فيها المستخدم مقابل الحاسوب ويلقي كل منهما النرد الافتراضي ليفوز صاحب القيمة الأعلى. التخطيط للعبة يبدأ تطوير البرمجيات عادةً بكتابة توثيق -ولو كان بسيطًا- للمتطلبات والأهداف يبين ما يفترض أن يكون عليه البرنامج، وفي لعبة النرد التي نعمل عليها سيتضمن التوثيق آلية العمل التالية. ابدأ اللعبة واضغط على زر Return أو Enter في لوحة المفاتيح لتبدأ دورة النرد. ستظهر النتيجة على الشاشة. ستُطالب بعدها بإعادة اللعب أو بالخروج. اللعبة بسيطة هذا صحيح، لكن توثيقها سيبين لك كمًّا لا بأس به من التفاصيل لتعمل عليها، مثل حاجتك لهذه المكونات. اللاعب: وهو العنصر البشري الذي سيستخدم اللعبة. AI: وترمز للذكاء الصنعي أي جهاز الحاسوب الذي يحاكي دور اللاعب الخصم، حتى يكون لديك فائز وخاسر. رقم عشوائي: الشائع في لعبة النرد استخدام نرد سداسي الأضلاع وبالتالي الرقم سيكون بين 1 و 6. عامل إجرائي: عملية رياضية بسيطة لموازنة رقمي اللاعبين ومعرفة الأكبر بينهما. رسالة فوز أو خسارة. مطالبة باتخاذ إجراء: إما اللعب مجددًا أو الخروج. بناء الإصدار الأول من لعبة النرد يتضمن الإصدار الأول من البرنامج الميزات الأساسية فقط، قلة هم من يبدأون تطوير برامجهم بميزات كاملة من أول إصدار. سنعرض مفهومين أساسيين قبل البدء. أولًا المتغير variable هو قيمة قابلة للتغيير، يستخدم لتخزين بعض المعلومات التي يحتاجها البرنامج وهو شائع الاستخدام في بايثون، فمثلًا المحرف x هو متغير في المعادلة التالية لأنه يشير إلى قيمةٍ ما أو ينوب عنها: x + 5 = 20 وثانيًا العدد الصحيح integer فيشمل الأعداد الصحيحة الموجبة والسالبة، مثلًا: 1، ‎-1 ،14 ،10947. يتضمن إصدارنا الأول من اللعبة -والمسمى ألفا dice-alpha- متغيرين هما player و ai. لتبدأ بإنشائه، افتح مشروعًا جديدًا، وسمّه dice-alpha ثم اكتب ضمنه الكود التالي: import random player = random.randint(1,6) ai = random.randint(1,6) if player > ai : print("You win") # لاحظ المسافة البادئة else: print("You lose") شغل اللعبة، ولاحظ أن وظيفتها الأساسية تعمل جيدًا، لكنها لا تبدو لعبةً متكاملة حتى الآن، فاللاعب لا يعرف نتيجة رميته ولا رمية الخصم، بالإضافة إلى أنها تنتهي مباشرةً حتى لو رغب اللاعب بالاستمرار، في الواقع يعدّ هذا شائعًا في الإصدارات الأولى من البرامج التي تسمى الإصدارات ألفا، لكنك في نهاية المطاف حللت الإجراء المهم في اللعبة وهو رمي النرد وأصبحت متيقنًا من عمله، فيمكنك استكمال بقية الميزات فيما بعد. تحسين اللعبة سنبني الآن الإصدار الثاني وهو الإصدار بيتا، بإضافة بعض الميزات ليصبح برنامجنا أقرب للعبة فعلًا. 1. إظهار تفاصيل النتيجة في إصدارنا الأول أظهرنا للاعب عبارةً واحدة ليعرف إن فاز أو خسر، والآن سنطوّر الآلية ليعرف اللاعب مقدار العدد العشوائي الذي حصل عليه أي مقدار رميته للنرد وكذلك رمية الخصم. جرب إجراء التعديل التالي في برنامجك، ومن ثم شغله: player = random.randint(1,6) print("You rolled " + player) ai = random.randint(1,6) print("The computer rolled " + ai) بمجرد تشغيله ستحصل على خطأ، والسبب أن بايثون قد فهم برنامجك على أنه عملية حسابية تجمع حروف وأعداد، الحروف هي حروف العبارة التي ستُظهر النتيجة على الشاشة والعدد هو قيمة المتغير player أو المتغير ai، وهذا بالطبع غير منطقي وغير قابل للتطبيق. لتصحيح الخطأ سنجعل بايثون يتعامل مع قيمة المتغير بصفتها نصًا أو بالأحرى سلسلة نصية string بدلًا من معاملتها على أساس أنها عدد صحيح integer. نفذ إذًا التعديل التالي وأعد تشغيل اللعبة ولاحظ النتائج: player = random.randint(1,6) print("You rolled " + str(player) ) ai = random.randint(1,6) print("The computer rolled " + str(ai) ) 2. إضافة عامل التشويق أضفنا بعض التسلية للعبة بإظهار النتائج، والآن سنضيف بعض الإثارة بإبطاء اللعبة في الأجزاء المشوقة، أما وسيلتنا لذلك فهي الدالة time إحدى دوال بايثون. نفذ التالي وتفقد النتائج: import random import time player = random.randint(1,6) print("You rolled " + str(player) ) ai = random.randint(1,6) print("The computer rolls...." ) time.sleep(2) print("The computer has rolled a " + str(player) ) if player > ai : print("You win") # لاحظ المسافة البادئة else: print("You lose") 3. اكتشاف ثغرة التعادل لو ثابرت على اللعب لفترةٍ جيدة، ستكتشف أن لعبتك لا تمتلك التعليمات اللازمة للتعامل مع حالة التعادل أي الحالة التي يحصل فيها اللاعب والحاسوب على القيمة نفسها، وهذه تعدّ ثغرة أو خطأ منطقي في الكود المكتوب، وحتى نعالجها سنجعل بايثون يتحقق من كون القيمتين متساويتين ويعرض عندها نتيجة التعادل. سنستخدم إشارة يساوي مزدوجة == للتحقق من تساوي القيمتين، إذ إن إشارة يساوي مفردة تعني في بايثون إسناد قيمة ما لأحد المتغيرات، أما بخصوص إدراج خيار ثالث للنتيجة، فسنعتمد على الكلمة المفتاحية elif (اختصار لـ else if) وهي مفيدة في الحالات التي تحتاج فيها للمطابقة مع ثلاثة احتمالات أو أكثر ضمن التعليمات الشرطية، بدلاً من مجرد احتمالين أحدهما صحيح والآخر خاطئ. الآن عدّل برنامجك ليغدو كما يلي: if player > ai : print("You win") # لاحظ المسافة البادئة elif player == ai: print("Tie game.") else: print("You lose") وبعدها جرب اللعبة عدة مرات لتصادف حالة التعادل وتتأكد من عملها. يمكنك تعلم المزيد عن الدوال الشرطية في بايثون بالاطلاع على المقال كيفية كتابة التعليمات الشرطية في بايثون 3 ضمن دليل تعلم بايثون على أكاديمية حسوب. بناء الإصدار النهائي للعبة تفوق الإصدار بيتا وظيفيًا على الإصدار ألفا، وكان أكثر قربًا منه للألعاب الحقيقية، والآن سنبني إصدارنا النهائي الأكثر تكاملًا وستتعلم خلاله بناء دالتك الأولى في بايثون. الدالة function هي مجموعة من التعليمات البرمجية التي يتم استدعائها ضمن البرنامج بصورة كتلة واحدة متميزة، تفيد الدوال في تنظيم التطبيقات بالأخص تلك التي تتضمن عددًا كبيرًا من التعليمات البرمجية التي لا يُفترض أن تعمل في وقتٍ واحد وشروطٍ واحدة، والدوال هنا هي من تحدد ما الذي سيحدث وفي أي وقت وشرط سيحدث. عدّل الآن برنامجك ليصبح: import random import time def dice(): player = random.randint(1,6) print("You rolled " + str(player) ) ai = random.randint(1,6) print("The computer rolls...." ) time.sleep(2) print("The computer has rolled a " + str(ai) ) if player > ai : print("You win") elif player == ai: print("Tie game.") else: print("You lose") print("Quit? Y/N") cont = input() if cont == "Y" or cont == "y": exit() elif cont == "N" or cont == "n": pass else: print("I did not understand that. Playing again.") في هذا الإصدار سيُسأل اللاعب إن كان يريد الخروج من اللعبة، وفي حال أجاب بنعم عبر كتابة Y أو y، فإن بايثون سينهي استدعاء الدالة وتتم مغادرة اللعبة. إذًا فقد بنيت دالتك الأولى المسماة نرد dice لكنها لن تعمل ما لم تستدعيها ضمن البرنامج، وهذا ما ستفعله الحلقة While True. أضف التعليمات التالية في نهاية برنامجك، وانتبه للمسافات البادئة فقد أعدنا كتابة آخر سطرين في الكود السابق عن قصد ليكون السياق واضحًا أمامك: … # الحلقة الأساسية while True: print("Press return to roll your die.") roll = input() dice() هذه الحلقة هي أول ما سيعمل في برنامجك، وتتكرر دومًا ما لم يكسرها أمرٌ من بايثون، إذ إن شرط عملها محقق دائمًا وتلقائيًا فهو True، لاحظ تسلسل عملها فهي تطالب المستخدم أولًا باتخاذ إجراء حتى يبدأ اللعب، ومن ثم تستدعي الدالة dice، ومن بعدها بناءً على إجابة المستخدم ستستمر الحلقة بالعمل أو تتوقف. ومن الجدير بالذكر أن الحلقات هي واحدة من أشيع الطرق المستخدمة لبدء التطبيقات فهي تضمن بقاء التطبيق متاحًا أمام المستخدم لفترة كافية تمكنه من استخدام وظائفه المختلفة. يمكنك تعلم المزيد عن الحلقات التكرارية بالاطلاع على المقال كيفية إنشاء حلقات تكرار while في بايثون 3، والمقال كيفية استخدام تعابير break و continue و pass عند التعامل مع حلقات التكرار في بايثون 3 ضمن دليل تعلم بايثون على أكاديمية حسوب. ختامًا تعرفنا في هذا المقال على أساسيات البرمجة بلغة بايثون، وسنتعلم في مقالنا التالي كيفية بناء لعبة فيديو باستخدام الوحدة PyGame المتخصصة في هذا المجال. ترجمة -وبتصرف- للمقال Learn how to program in Python by building a simple dice game لصاحبه Seth Kenlon. اقرأ أيضًا المقال التالي: بناء لعبة رسومية باستخدام بايثون ووحدة الألعاب Pygame تعرف على أشهر لغات برمجة الألعاب برمجة لعبة حجرة ورقة مقص باستخدام لغة بايثون النسخة العربية الكاملة من كتاب البرمجة بلغة بايثون
    1 نقطة
  9. في هذا الجزء من المقالات التعليمية، نتطرَّق إلى لغة JavaScript كما هي بدون تعديلات خاصة بالبيئة. لكن ما زلنا نستخدم المتصفح كبيئة تجريبية، لذلك يجب أن تتعرف على عددٍ قليلٍ من دوال واجهة المستخدم الخاصة به. ستتعرف في هذا الفصل على هذه الدوال التفاعلية الخاصة بالمتصفح. الدالة alert الصياغة: alert(message); تعرض هذه الدالة رسالة نصية وتوقف تنفيذ السكربت مؤقتًا حتى يضغط المستخدم على «موافق» (OK). إليك الشيفرة البسيطة التالية مثلًا: alert("مرحبًا"); تسمى الرسالة النصية التي تظهر على شكل نافذة صغيرة تدعى «النافذة المنبثقة الشرطية» (modal window، وهي عنصر تحكم رسومي)؛ تعني كلمة «شرطية» أنه لا يمكن للزائر التفاعل مع بقية الصفحة، أو الضغط على أزرار أخرى وما إلى ذلك، إذ تشترط عليه التفاعل معها فقط، أي حتى يضغط على «موافق» (Ok) في هذه الحالة. الدالة prompt تقبل الدالة prompt وسيطين (arguments) لتكون صياغتها بالشكل التالي: result = prompt(title, [default]); تعرض هذه الدالة نافذة منبثقة شرطية مع رسالة نصية مخصصة، وحقل إدخال للمستخدم، وزرَّين (موافق [OK] وإلغاء [CANCEL]). الوسيط title: هو عبارة عن النص الذي سيعرض للمستخدم. الوسيط default: هو وسيط اختياري يمثِّل القيمة الأولية لحقل الإدخال الخاص بالمستخدم. قد يكتب المستخدم شيئًا ما في حقل الإدخال، ثمَّ يضغط على موافق (Ok). أو يمكنه إلغاء الإدخال عند الضغط على إلغاء (CANCEL) أو الضغط على مفتاح الهروب (Esc). استدعاء الدالة prompt يرجع سلسلة نصية تمثِّل القيمة التي أدخلها المستخدم في حقل الإدخال أو يرجع القيمة null إذا تم الخروج من النافذة وإلغائها. جرب نفِّذ المثال التالي في الطرفية وعدل عليه: let age = prompt('كم عمرك؟', 100); alert(`عمرك ${age} سنة!`); في IE (أي المتصفح Internet Explorer)، دائمُا ما يتم إضافة الوسيط default. أي هذا الوسيط اختياري في جميع المتصفحات باستثناء المتصفح IE الذي يعدُّه اجباريًّا، وإذا لم نحدِّد قيمته، يفترض المتصفح Internet Explorer أنَّ قيمته "undefined". نفِّذ هذه الشيفرة في متصفح Internet Explorer لرؤية الناتج: let test = prompt("Test"); لجعل الدالة prompt تعمل جيدًا في المتصفح IE، نوصي دائمًا بتمرير قيمة الوسيط الثاني default: let test = prompt("Test", ''); // <-- IE للمتصفح الدالة confirm الصياغة: result = confirm(question); تُظهر الدالة confirm نافذة منبثقة شرطية تحتوي على سؤال question، وزريّن (موافق [OK] وإلغاء [CANCEL]). تكون النتيجة true إذا ضغط المستخدم على الزر "Ok" وتكون false عدا ذلك. جرِّب المثال التالي في طرفيتك: let isBoss = confirm("Are you the boss?"); alert( isBoss ); الخلاصة ذكرنا في هذا المقال ثلاثة دوال للتفاعل مع مستخدمي الموقع وهي: الدالة alert: تعرض رسالة لإعلام المستخدم بشئ ما، وُتعطل كافة عمليات الصفحة حتى يتفاعل مع هذه الرسالة. الدالة prompt: تعرض رسالة تطلب من المستخدم إدخال شيء ما في حقل إدخال خاص لتعيد القيمة المدخلة في سلسلة نصية، أو ترجع القيمة null إذا تم العملية. الدالة confirm: تعرض رسالة (بمثابة سؤال) وتنتظر من المستخدم الرد عليها بالقبول أو الرفض، أي تكون النتيجة true إذا تم الضغط على زر "Ok" أو تكون false عدا ذلك. كل هذه الدوال مشروطة: فهي تتوقف عن تنفيذ السكربت ولا تسمح للمستخدم بالتفاعل مع بقية الصفحة حتى يتم التفاعل مع النافذة التي تعرضها. هناك اثنين من القيود التي تشترك بها جميع الدوال المذكورة أعلاه: يحدد المتصفح الموقع الذي ستظهر فيه النافذة، وعادة ما يكون في الوسط أو الأعلى. يعتمد شكل النافذة أيضًا على المتصفح، ولا يمكننا تعديله. هذا هو ثمن البساطة. هناك طرق أخرى لإظهار نوافذ أكثر جمالًا وفاعلية، ولكن إذا كانت التنسيقات الجمالية غير مهمة، فهذه الدوال تفي بالغرض. .task__importance { color: #999; margin-left: 30px; } .task__answer { border: 3px solid #f7f6ea; margin: 20px 0 14px; position: relative; display: block; padding: 25px 30px; } code { background-color: rgb(250, 250, 250); border-radius: 3px; } تمارين صفحة بسيطة الأهمية: 4 قم بإنشاء صفحة ويب تطلب اسمًا ما ثم تعرضه. الحل شيفرة JavaScript: let name = prompt("ما اسمك؟", ""); alert(name); الشيفرة كاملة: <!DOCTYPE html> <html> <body> <script> 'use strict'; let name = prompt("ما اسمك؟", ""); alert(name); </script> </body> </html> ترجمة -وبتصرف- للفصل Interaction: alert, prompt, confirm من كتاب The JavaScript Language اقرأ أيضًا المقال التالي: المعاملات الشرطية المقال السابق: معاملات الموازنة كامل مقالات دليل تعلم جافاسكربت
    1 نقطة
×
×
  • أضف...