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

ابراهيم الخضور

الأعضاء
  • المساهمات

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

  • تاريخ آخر زيارة

كل منشورات العضو ابراهيم الخضور

  1. ينبغي أن يبقى الفرع الرئيسي دائمًا في المنطقة الخضراء، ويعني ذلك تنفيذ كل خطوات بناء خط الإنتاج بنجاح، إذ يجب أن يُبنى المشروع بنجاح، وأن تُنفَّذ الاختبارات دون أخطاء، ولا يجب أن يعترض المدقق على أي شيء. ما أهمية هذا الأمر؟ من المرجح أنك ستنشر شيفرتك إلى العالم الخارجي من الفرع الرئيسي تحديدًا، وأي إخفاق في هذا الفرع سيعني أنّ الميزات الجديدة لن تُنشر حتى تُحل المشكلة؛ فقد تكتشف أحيانًا ثغرات في نسخة الإنتاج لم يلتقطها خط الإنتاج لمنظومة التكامل المستمر CI/CD، وفي حالات كهذه، سترغب في التراجع إلى النسخة السابقة بطريقة آمنة. كيف ستُبقي فرعك الرئيسي في المنطقة الخضراء إذًا؟ تحاشى دفع أية تغييرات إلى الفرع الرئيسي مباشرةً، بل ادفع شيفرتك إلى فرع آخر يمثّل أحدث نسخة ممكنة للفرع الرئيسي، وعندما ترى أن هذا الفرع جاهزٌ للدمج مع الرئيسي، أنشئ طلب سحب Pull Request -أو اختصارًا PR- على غيت هب GitHub. العمل مع طلبات السحب تمثل طلبات السحب جزءًا جوهريًا من عملية التعاون في تطوير أي مشروع برمجي يُنفَّذه مساهمَين على الأقل، فعندما تُجري أية تعديلات على مشروعك، ستختبرها على جهازك أولًا، ثم تعتمد هذه التغييرات وتدفعها إلى مستودع على الإنترنت -وهو غيت هب GitHub في حالتنا-، ثم تقدم طلب سحب لكي يراجع أحدٌ ما هذه التغييرات قبل أن تُدمج مع الفرع الرئيسي. هناك عدة أسباب تدفعنا لاستخدام طلبات السحب، كما أنّ مراجعة الشيفرة من قبل شخص آخر على الأقل فكرةٌ جيدةٌ دائمًا. قد تتواجد بعض الثغرات حتى في شيفرة المطورين الخبراء، وهذا مشابهٌ لمشكلة الرؤية النفقية tunnel، إذ لا يستطيع المصاب بها سوى رؤية ما أمامه مباشرة وكأنه ينظر من خلال نفق. يمتلك المراجع منظورًا مختلفًا، فقد يقدم وجهة نظر مختلفة. سيكون هناك مطورٌ واحد على الأقل على دراية بالتغيرات التي أجريتها بعد قراءتها. ستسمح لك طلبات السحب أن تُنفِّذ تلقائيًا كل المهام في خط الإنتاج لمنظومة CI قبل أن تصل الشيفرة إلى الفرع الرئيسي، وستزودك GitHub Actions بآلية لتنفيذ طلبات السحب. يمكنك تهيئة مستودع GitHub بطريقة تمنع دمج الشيفرة المرتبطة بطلب سحب إلى أن يُوافق عليها. لتقديم طلب سحب جديد، افتح فرعك في GitHub بالضغط على الزر الأخضر "Compare & pull request" في الأعلى، وسيظهر لك نموذج لتعبئته بوصفٍ لطلب السحب الذي تقدمه. تقدم لك واجهة طلبات السحب في GitHub إمكانية وصف الطلب ومناقشته، حيث تَظهر لك في الأسفل جميع علامات التحقق من منظومة CI (وهي في حالتنا كل فعل من أفعال GitHub Actions التي نستخدمها) التي هُيِّئت للعمل عند كل طلب سحب وحالة هذه العلامات. وما نهدف إليه فعلًا هو لوحة خضراء. يمكنك النقر على تفاصيل "Details" كل علامة تحقق للاطلاع عليها وتشغيل السجلات. تُنفَّذ جميع مخططات العمل التي واجهناها حتى الآن عند دفع الشيفرة إلى الفرع الرئيسي، ولجعلها تعمل عند كل طلب سحب، لا بدّ من تحديث الجزء المسؤول عن مسببات triggers إقلاع المخطط. سنستخدم المسبب "pull_request" للفرع الرئيسي ونربط هذا المسبب بالحدثين "opened"و "synchronize"؛ ويعني هذا مبدئيًا أن المخطط سيُنفَّذ عندما يُقدَّم طلب سحب إلى الفرع الرئيسي، أو عندما يُحدّث. لنغيّر إذًا الأحداث التي تسبب تشغيل مخطط العمل على النحو التالي: on: push: branches: - master pull_request: branches: [master] types: [opened, synchronize] سنمنع قريبًا دفع الشيفرة مباشرةً إلى الفرع الرئيسي، لكننا سننفذ حاليًا مخطط العمل لكل عمليات دفع الشيفرة المباشر إلى الفرع الرئيسي. التمرينان 11.13 - 11.14 يعمل مخطط العمل على النحو المطلوب للحفاظ على نوعية جيدة لشيفرتنا، لكن طالما أنه يُقلع عند دفع الشيفرة إلى الفرع الرئيسي، فسيلتقط الأخطاء متأخرًا. 11.13: طلب سحب حَدِّث مسببات إقلاع مخطط العمل كما اقترحنا سابقًا ليعمل عند تقديم طلب سحب جديد إلى الفرع الرئيسي. أنشئ فرعًا جديدًا وادفع بشيفرتك إليه، ثم افتح طلب سحب إلى الفرع الرئيسي. إذا لم تكن قد تعاملت مع الفروع سابقًا اطلع على المقالات التالية: مقدمة عن التفريع Branching في Git إدارة التفريعات (branches) في Git واستخدامها لتخطيط سير العمل إعادة تأسيس تفريعات طلب السحب وتحديثه في git تنبيه: تأكد عندما تفتح طلب سحب جديد أنك اخترت مستودعك الخاص واجهةً أساسية، إذ سيكون الاختيار افتراضيًا للمستودع الأصلي ولا يجب أن تفعل هذا: سترى في النافذة "Conversation" ضمن واجهة فتح طلب سحب آخر عملية (أو عمليات) دفع للشيفرة، كما سترى الحالة الصفراء لعلامات التحقق الذي يجري تنفيذه: ينبغي أن تكون العلامات باللون الأخضر بعد أن تنتهي عمليات التحقق. تأكد من نجاح كل اختبارات التحقق، ولا تدمج فرعك الآن، فهناك نقاط ينبغي تحسينها في خط الإنتاج. 11.14: تشغيل خطوة النشر للفرع الرئيسي فقط كل شيء يبدو على ما يرام، لكن هناك مشكلةٌ حقيقية في مخطط العمل الحالي، إذ ستُنفَّذ جميع الخطوات بما فيها خطوة النشر عندما نفتح طلب سحب، وبالتأكيد لا نريد حدوث هذا الأمر. ولحسن الحظ، هناك حلٌ بسيط لهذه المشكلة، إذ يمكننا استخدام العبارة الشرطية if في خطوة النشر لكي تضمن عدم تنفيذ هذه الخطوة إن لم تُدمج الشيفرة أو تُدفع إلى الفرع الرئيسي. يتضمن سياق context شتى أنواع المعلومات حول الشيفرة التي ينفذها مخطط العمل. ستجد المعلومات المتعلقة بالموضوع في GitHub context، إذ يمثل الحقل event_name اسم الحدث الذي يسبب تنفيذ المخطط. عندما يُدمج طلب سحب، سيظهر اسم الحدث على أنه "push"، وهو نفسه الحدث الذي يقع عندما تُدفع الشيفرة إلى المستودع، لذلك سنحصل على السلوك المطلوب بإضافة العبارة الشرطية التالية إلى خطوة النشر: if: ${{ github.event_name == 'push' }} ادفع بشيفرة إضافية إلى فرعك، وتأكد من عدم تنفيذ خطوة النشر. ادمج بعد ذلك فرعك مع الفرع الرئيسي وتأكد من حدوث خطوة النشر. إدارة إصدار نسخ البرمجيات الغاية الرئيسية من تحديد الإصدار هي التعريف الفريد للبرمجية التي تعمل والشيفرة المتعلقة بها. يشكّل ترتيب الإصدارات أيضًا جزءًا مهمًا من المعلومات، فلو احتوى الإصدار الحالي لبرنامج ما، على سبيل المثال وظيفةً حيويةً معطلة، سيلزمنا تحديد النسخة السابقة المستقرة من البرنامج لكي نتمكن من التراجع إليها. إدارة الإصدار بطريقة Semantic وبطريقة Hash تُدعى الطريقة التي يُدار بها إصدار برنامج في بعض الأحيان باستراتيجية إدارة الإصدار Versioning strategy. سنطلّع ونوازن استراتيجيتين في هذا المجال، تدعى الأولى الإدارة الدلالية لنُسخ البرمجيات Semantic، إذ يُكتب الإصدار بالشكل التالي: {major}.{minor}.{patch}. فلو كان إصدار نسخة من البرنامج 1.2.3، سيكون 1 هو رقم الإصدار الرئيسي الجذري major و 2 رقم الإصدار الثانوي (البسيط) minor و 3 هو رقم الإصدار الترميمي (الترقيع) patch. وعمومًا، فأية تغييرات تهدف لمعالجة الوظيفة المخفقة في إصدار دون المساس بالطريقة التي يعمل بها التطبيق من الخارج ستكون تغييرات ترميمية؛ أما التغييرات التي تؤدي إلى تغييرات بسيطة في الوظيفة (كما تبدو من الخارج) فستكون تغييرات ثانوية، وندعو تلك التغيرات التي ستؤثر كليًا على التطبيق (أو تغيير وظائفه بصورةٍ كبيرة) بالتغييرات الرئيسية، وقد يختلف تعريف هذه المصطلحات من مشروع لآخر. تتبع على سبيل المثال مكتبات npm ترميز semantic، ففي وقت كتابة هذه السطر (الثالث من آذار 2022)، يُعد الإصدار 17.0.2 هو الأحدث للمكتبة React إذ أن رقم الإصدار الرئيسي هو 17 والثانوي 0 والترميمي 1. أما الإصدار بترميز Hash (أو الترميز SHA) فهو مختلفٌ تمامًا، فرقم الإصدار هو سلسلة نصية عشوائية مشتقة من محتويات المستودع والتغيرات التي اعتمدت فيه. يُنفّذ ذلك في git تلقائيًا مثل رمز Hash معتمد وفريد لأي مجموعة من التغييرات. يستخدم الإصدار برمز غالبًا في الحالات المؤتمتة، فعملية نقل رمز Hash مكون من 32 محرف للتأكد من نشر كل شيء على النحو الصحيح عمليةٌ مضنية وتولّد الكثير من الأخطاء. إلى ماذا يشير الإصدار؟ تحديد الشيفرة الموجودة في كل إصدار أمرٌ مهمٌ جدًا، ويختلف أسلوبي الترميز السابقين في طريقة فعل ذلك؛ فالعملية في Hash (على الأقل في غيت هب GitHub) بسيطة ببساطة البحث عن تغييرات معتمدة للشيفرة commit لها رمز Hash معرّف ومحدد، إذ سيمنحنا ذلك إمكانية معرفة الشيفرة التي نُشرت في كل إصدار. سيتعقد الوضع قليلُا في semantic، فهناك ثلاث طرق لمقاربة الموضوع: الأولى تتعلق بالشيفرة نفسها، والثانية تتعلق بالمستودع أو البيانات الوصفية له، والثالثة تتعلق بأشياء خارج المستودع كليًا. طالما أننا لن نتطرق إلى المقاربة الثالثة (لأنها متشعبة مثل حجر الأرنب)، فستلاحظ أن العملية بسيطة أيضًا وكأنها جدول بيانات يربط بين الإصدار والشيفرة المعتمدة التي يدل عليها. تتلخص المقاربة المتعلقة بالشيفرة برقم إصدار النسخة في ملف، بينما تعتمد مقاربة المستودع وبياناته الوصفية على الوسوم tags أو في حالة GitHub على الإصدارات، إذ يشير الوسم أو الإصدار في هذه المقاربة إلى شيفرة مُعتمدة هي نفسها الموجودة في الإصدار. ترتيب إصدارات النسخ من السهل في semantic ترتيب الإصدارات حتى لو كانت مختلفة (رئيسي، ثانوي، ترميمي)، فسيأتي الإصدار 1.3.7 قبل 2.0.0 والذي سيأتي قبل 2.1.5 وهذا الأخير سيكون قبل 2.2.0. لكننا سنحتاج إلى قائمة بالإصدارت أو الوسوم ( يؤمنها مدير حزم GitHub بصورةٍ ملائمة) لمعرفة الإصدار الأخير، فمن الأسهل الاطلاع على هذه القائمة ومناقشتها، أي من الأسهل أن نقول أننا سنتراجع إلى الإصدار 3.2.4 بدلًا من التعامل بأنفسنا مع رموز hash التي تشير إلى رقم الإصدار. وطبعًا لا نعني إطلاقًا أنّ رموز hash غير ملائمة؛ فلو عرفت أي شيفرة معتمدة سببت مشكلة بعينها، فمن السهل البحث من خلال تاريخ عمليات GitHub والحصول على رموز hash للإصدار السابق؛ لكن لو كانت لديك سلسلتين من رموز Hash على النحو التالي مثلًا: d052aa41edfb4a7671c974c5901f4abe1c2db071 12c6f6738a18154cb1cef7cf0607a681f72eaff3 فلن تستطيع التمييز أيهما قبل الأخرى، وستحتاج إلى مساعدة إضافية مثل سجل عمل GitHub لكشف الترتيب الصحيح. الموازنة بين أسلوبي إدارة الإصدار لقد لمسنا بالمناقشة السابقة بعض إيجابيات وسلبيات كل أسلوب، لكن من الأفضل التطرق إلى مجال استعمال كل منهما. يعمل أسلوب semantic جيدًا عندما يكون لرقم الإصدار أهميةً خاصة أو عندما تكون هناك حاجة للبحث عنه. فكر مثلًا بمكتبات جافا سكربت JavaScript التي تستخدمها؛ فلو كنت تستخدم الإصدار 3.4.6 من مكتبة محددة وظهر تحديث لها يحمل الرقم 3.4.8، فيمكنك أن تأمل بأن انتقالك إلى الإصدار الأحدث سيكون آمنًا؛ لكن لو حمل الإصدار الجديد الرقم 4.0.1 فلن تضمن انتقالًا آمنًا إليه. يُناسب hash الحالات التي تُبنى فيها الشيفرة داخل أدوات برمجية artifact (مثل الملفات الثنائية القابلة للتنفيذ أو قوالب منصة Docker) قابلة بحد ذاتها للرفع أو التخزين، فإذا تطلبت اختباراتك على سبيل المثال بناء حزمتك داخل أداة برمجية، ثم رفعها إلى الخادم واختبارها، فمن الملائم عندها استخدام أسلوب Hash في تحديد الإصدار لأنه سيمنع وقوع الحوادث. تخيل على سبيل المثال أنك تعمل على الإصدار 3.2.2 وفشل أحد الاختبارات، أصلحت بعد ذلك الخلل ودفعت بشيفرتك إلى مستودعك، لكن طالما أنك تعمل ضمن مستودعك فلن تستطيع تحديث رقم الإصدار. لن يتغير اسم الأداة البرمجية دون تحديد إصدار hash. وإن كان هناك خطأ في رفع الأداة البرمجية، فقد يُنفَّذ الاختبار على الأداة الأقدم (طالما أنها لا تزال موجودة وبنفس الاسم). بينما لو أُعطيت الأداة رقم إصدار بأسلوب hash، ينبغي أن يتغير رقم الإصدار عند كل محاولة لدفع شيفرة معتمدة، ويعني هذا أنه في حال أخفق رفع الأداة، سيظهر خطأ لأن الأداة التي ستُنفَّذ عليها الاختبارات غير موجودة. يُعد ظهور الخطأ عندما يحدث شيء ما أفضل غالبًا من مشكلة تهملها منظومة CI بصمت. أفضل ما في الأسلوبين يمكن أن نستشف من المقارنة السابقة أن استخدام أسلوب semantic مناسب لإصدار برمجيات، بينما استخدام أسلوب hash أكثر منطقية أثناء نشر البرمجيات ولن يسبب هذا الأمر تعارضًا بالضرورة. فكر في ذلك على النحو التالي: تتلخص إدارة الإصدارات بأنها تقنية تشير إلى كمية معتمدة من الشيفرة وتعطيها اسمًا فليكن 3.5.5 لن يمنع ذلك طبعًا من إعطاء الشيفرة نفسها رمز hash. هناك أمر ما، فقد ذكرنا في بداية هذا القسم أنه علينا معرفة ما يحدث تمامًا في شيفرتنا، فعلينا أن نكون واثقين مثلًا بأننا اختبرنا الشيفرة التي نريد نشرها. سيعقد وجود أسلوبين متوازيين لإدارة الإصدار (أو تسميته) الأمور قليلًا. فعندما يكون هناك مشروع يستخدم نسخًا من أداة برمجية بحيث يُدار إصدار هذه النسخ بأسلوب hash أثناء اختبارها، يمكننا دائمًا تعقب نتيجة خطوات البناء والتدقيق والاختبار، وبالتالي سيعلم المطورون حالة هذه النسخ. ويحدث ذلك آليًا وبصورةٍ واضحة بالنسبة للمطور، فليس على المطور الاهتمام بما تفعله منظومة CI في الخفاء من حيث استخدام ترميز hash لتسمية النسخة واختبارها. عندما يدمج المطور شيفرته ضمن الفرع الرئيسي، تتولى منظومة CI الأمر من جديد، إذ ستبني هذه المرة وتختبر كل الشيفرة ومن ثم تمنحها رقم إصدار بأسلوب semantic، وتربط هذا الرقم بآخر شيفرة معتمدة ومختبرة وتحمل وسم git. سيكون البرنامج الذي سنصدره في الحالة السابقة مُختبرًا لأن منظومة CI ستتأكد أنّ الاختبارات قد نجحت على الشيفرة الموسومة بوسم git المحدد، وليس خطأً أن نقول أن المشروع سيستخدم أسلوب semantic في إدارة الإصدار ويتجاهل ببساطة فكرة أن منظومة CI ستختبر الفروع الخاصة بكل مطور أو طلبات السحب الخاصة بكل منهم بأسماء مبنية على أسلوب hash في إدارة الإصدار. نقول ذلك لأن النسخة التي تعنينا (التي سنصدرها) ستُمنح رقم إصدار semantic. التمرينان 11.15 - 11.16 لنوسّع مخطط العمل الذي نبنيه لكي يزيد تلقائيًا رقم الإصدار عندما تجري الموافقة على طلب سحب وتنفيذ عملية الدمج ضمن الفرع الرئيسي وأن يوسم النسخة المصّدرة برقم الإصدار. سنستخدم anothrNick/github-tag-action وهو فعل GitHub Actions مفتوح المصدر طوره أحدهم. 11.15: إضافة رقم إصدار سنوّسع مخطط العمل بإضافة خطوة واحدة: - name: Bump version and push tag uses: anothrNick/github-tag-action@1.36.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} سنمرر متغير البيئة environment variable التالي secrets.GITHUB_TOKEN إلى الفعل، وطالما أنّ مصدر الفعل طرف ثالث، سنحتاج إلى شهادة استيثاق token في مستودعك. يمكن الاطلاع أكثر عن الاستيثاق في توثيق GitHub. يمكن أن نمرر عدة متحولات بيئة إلى الفعل anothrNick/github-tag-action. تعدّل هذه المتغيرات الطريقة التي يُعرِّف بها الفعل الإصدارات. يمكنك الاطلاع على تفاصيل أكثر ضمن ملف README الخاص بالفعل على GitHub واستخدام ما يناسبك. وكما سترى في التوثيق سيزداد الرقم الثانوي لرقم الإصدار تلقائيًا minor bump. عدّل التهيئة في الشيفرة السابقة لكي يكون هناك زيادةٌ تلقائية في رقم الترميم patch bump لرقم الإصدار، أي سيزداد الرقم الأخير تلقائيًا. تذكر أننا نريد فقط زيادة رقم الإصدار عندما تطرأ تغييرات على الفرع الرئيسي. لذلك أضف العبارة الشرطية "if" لمنع زيادة رقم الإصدار عند فتح طلب سحب كما فعلنا في التمرين 11.14. أكمل مخطط العمل وحاول تجربته، ولا تضفه مثل خطوة إضافية فقط، وإنما أجري إعداده على أنه عمل منفصل يعتمد على العمل المهتم بتدقيق وكشف الأخطاء والفحص والنشر. أجرِ التغييرات التالية على تعريف مخطط العمل: name: Deployment pipeline on: push: branches: - master pull_request: branches: [master] types: [opened, synchronize] jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: // steps here tag_release: needs: [simple_deployment_pipeline] runs-on: ubuntu-20.04 steps: // steps here تُنفَّذ أعمال مخطط العمل على التوازي كما ذكرنا سابقًا، لكن طالما أننا نريد إجراء التدقيق والاختبار والنشر أولاً، سنحتاج لضبط اعتمادية tag_release بحيث تنتظر عملًا آخر ليُنفّذ أولًا نظرًا لأننا لا نريد وضع علامة على الإصدار ما لم يجتاز الاختبارات ويُنشر. إذا لم تكن متأكدًا من إعدادات التهيئة، يمكنك ضبط قيمة DRY_RUN على true، وبالتالي سيعطي الفعل رقم الإصدار التالي دون إنشاء وسم للإصدار. حالما يعمل مخطط العمل على نحوٍ صحيح، سيشير المستودع إلى وجود بعض الوسوم: وبالنقر على هذه الوسوم ستُعرض ضمن قائمة بكل الوسوم (والتي تمثل آلية لتعريف الإصدار ووسمه): 11.16: تجاوز إنشاء وسوم لحزمة شيفرة معتمدة ونشرها من الأفضل في أغلب الأوقات نشر الفرع الرئيسي إلى وضع الإنتاج.، لكن قد تكون هناك بعض الأسباب المقنعة لتجاوز إنشاء وسم شيفرة معتمدة أو طلب سحب جرى الموافقة على دمجه أو نشرهما. عدّل إعداداتك لكي لا تُنشر إلى وضع الإنتاج أية شيفرة جرى دمجها إن احتوت رسالة طلب السحب الكلمة "skip#"، ولا توسم برقم الإصدار. تلميح: أسهل طريقة لإنجاز ذلك هو تبديل العبارة الشرطية "if" للخطوة المناسبة. ويمكنك كما فعلنا في التمرين 11.14 الحصول على المعلومات المطلوبة من سياق GitHub لمخطط العمل: يمكنك الإستعانة بالشيفرة التالية مثل نقطة انطلاق: name: Testing stuff on: push: branches: - main jobs: a_test_job: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v2 - name: gihub context env: GITHUB_CONTEXT: ${{ toJson(github) }} run: echo "$GITHUB_CONTEXT" - name: commits env: COMMITS: ${{ toJson(github.event.commits) }} run: echo "$COMMITS" - name: commit messages env: COMMIT_MESSAGES: ${{ toJson(github.event.commits.*.message) }} run: echo "$COMMIT_MESSAGES" لاحظ ما الذي طُبع في سجل مخطط العمل. ملاحظة: يمكنك الوصول إلى الشيفرة المعتمدة أو رسائلها عند الدفع أو الدمج مع الفرع الرئيسي فقط، وبالتالي لن تحمل الخاصية github.event.commits أية قيمة. لا حاجة لهذه القيمة على أية حال طالما أننا نرغب في تجاوز هذه الخطوة. ستحتاج غالبًا إلى الدالتين contains و join ضمن عبارة if الشرطية. لا يُعد نشر مخطط العمل أمرًا سهلًا، وغالبًا ما يكون الخيار المتاح هو المحاولة والخطأ، وينصح أحيانًا بوجود مستودع منفصل للتأكد من صحة تهيئة الإعدادات، ثم تُنقل هذه الإعدادات إلى المستودع الفعلي إن كانت صحيحة. كما يمكن أيضًا تثبيت أداة مثل act، التي تساعدك على تشغيل مخطط العمل على جهازك. وعندما تواجهك حالات مختلفة عن التي ناقشناها، كأن تنشئ أفعال خاصة بك، فإن اقتحام غمار أدوات مثل act وتجربتها سيستحق العناء. ملاحظة لاستخدام الأفعال التي يطورها طرف ثالث عندما تستخدم فعل يؤمنه طرف ثالث مثل github-tag-action، من الأفضل أن تحدد أسلوب hash لإدارة الإصدار بدلًا من رقم الإصدار. والسبب في ذلك أن رقم الإصدار الذي أنجز بوسم git قد يكون عرضة للتغيير، فالإصدار الذي يحمل الرقم 1.33.0 هذا اليوم على سبيل المثال، قد يشير إلى شيفرة مختلفة عن تلك الموجودة في نفس الإصدار لكن في الأسبوع القادم. مع ذلك، فالشيفرة المعتمدة على ترميز hash محددة لا تتغير أيًا كانت الظروف، لذا فإن أردنا التيقن 100% من الشيفرة التي نستخدمها، سيكون الخيار الأكثر أمانًا hash. إنّ الإصدار 1.33.0 من الفعل السابق يتوافق مع شيفرة ترميز hash لها هو الإصدار: eca2b69f9e2c24be7decccd0f15fdb1ea5906598، لذلك من الأفضل أن نغير إعدادات التهيئة على النحو التالي: - name: Bump version and push tag uses: anothrNick/github-tag-action@eca2b69f9e2c24be7decccd0f15fdb1ea5906598 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} وعلينا أن نثق عند استخدام أفعال تزودنا بها GitHub بأنها لن تعبث بوسوم الإصدار version tags وأن نختبر شيفرتها بدّقة. وقد ينتهي بك المطاف عند استخدام أفعال من طرف ثالث أمام أفعال تحتوي ثغرات أو حتى مثيرة للشبهة، وحتى لو لم تكن نية المطور الذي كتب الشيفرة سيئة، فقد ينس معلومات الاستيثاق الخاصة به في ركن إنترنت عام، ومن يدري ما قد يحدث بعدها. سنتأكد عند استخدام أسلوب hash أن هذه شيفرة التي نستخدمها لتشغيل مخطط العمل لن تتغير، لأن تغيير الشيفرة المعتمدة المسؤولة عن تنفيذ المخطط سيؤدي إلى تغيير hash. أبق الفرع الرئيسي آمنا سيسمح لك غيت هب أن تهيئ فروعًا محمية، فمن المهم حماية الفرع الأكثر أهمية الذي يجب ألا يخفق أبدًا وهو الفرع الرئيسي. يمكنك أن تختار بين عدة مستويات حماية عبر إعدادات المستودع. لن نغطي كل هذه الخيارات، لكن يمكنك طبعًا الاطلاع عليها من خلال توثيق GitHub. ومن وجهة نظر منظومة CI، ستتمثل الحماية الأكثر أهمية في نجاح خطوات التحقق من الحالة قبل أن يدمج طلب السحب ضمن الفرع الرئيسي. فلو أعددت أفعال GitHub لتنفذ مهام التدقيق والاختبار، فلن يُدمج طلب السحب قبل تصحيح جميع أخطاء التدقيق وقبل أن تنجح جميع الاختبارات. ونظرًا لكونك مدير مستودعك، ستجد خيارًا لتخطي التقييدات هذه. لن يظهر هذا الخيار لغير المدراء. لتهيئ إعدادات الحماية للفرع الرئيسي، توجه إلى إعدادات "Settings" المستودع من القائمة العليا ضمن المستودع. اختر من قائمة الجهة اليسرى فروع "Branches" ثم انقر زر أضف قاعدة "Add rule" بجوار العنصر قواعد حماية الفروع "Branches protection rules". اكتب نموذج لاسم الفرع ("master" سيكون مناسبًا)، ثم اختر طريقة الحماية التي تريد إعدادها. اختر على الأقل "يجب التحقق من نجاح خطوات التحقق من الحالة قبل الدمج Require status checks to pass before merging" لتضمن تسخير الإمكانات الكاملة لاستضافة GitHub Actions. وتحت هذا الخيار عليك اختيار "يجب أن تكون الفروع محدّثة قبل الدمج Require branches to be up to date before merging"، وفعّل جميع الخيارات التي تتحقق من الحالة قبل دمج أية طلبات سحب. التمرين 11.17 إضافة حماية إلى الفرع الرئيسي أضف حماية لفرعك الرئيسي. إذ عليك حمايته بضمان التالي: الموافقة على جميع طلبات السحب قبل دمجها. نجاح جميع خطوات التحقق من الحالة قبل الدمج. لا تفعِّل الخيار "Include administrators" حاليًا، لأنك لو فعلت ذلك فعليك الانتظار حتى يراجع شخص ما طلب السحب الذي قدمته قبل نشر الشيفرة. ترجمة -وبتصرف- للفصل Keeping Green من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: نشر التطبيقات وتوزيعها وفق نهج التسليم المستمر نشر تطبيقات الويب الموجهة لبيئة الإنتاج نشر تطبيقات iOS على متجر Apple Store
  2. سنلقي نظرةً في مقالنا على اﻷجزاء التي يتكون منها سطح المكتب في نظام التشغيل لينكس أوبنتو Ubuntu في إصدارته 20.04؛ وهي النافذة الذي تظهر مباشرةً عند انتهاء تحميل نظام التشغيل. لن أتطرق بالطبع إلى أية مقارنات مع نسخ أقدم، أو إلى التغييرات التي تجري باستمرار على تنظيم سطح المكتب، بل سأعُدُّك مستخدمًا عاديًا دون أية خبرة مسبقة؛ على أساس أنك أردت أن تجرب نظام تشغيل مفتوح المصدر لمجرد الفضول، أو لأنك سمعت عن بعض ميزاته من أحد معارفك، فوجدت نفسك قد تورّطت وثبتت هذا النظام بمساعدة أو دون مساعدة. دعنا نبدأ إذًا هذه الرحلة السريعة التي تقودك بكل بساطة إلى فهم المكونات اﻷساسية لسطح المكتب وكيفية الوصول إلى بعض المعلومات المتعلقة بحاسوبك. اﻷجزاء الرئيسية لسطح مكتب جنوم يتكون سطح المكتب من عدة أقسام أساسية هي: شريط التطبيقات Applications Panel: يقع افتراضيًا في النسخة العربية على يمين الشاشة وفي النسخة اﻹنكليزية على يسارها. يعرض هذا الشريط اختصارات إلى التطبيقات التي ترغب في الوصول إليها بسرعة، ويمكنك دائمًا إضافة او إزالة الاختصارات كما تراه ملائمًا لاحتياجاتك. يدل ظهور نقطة حمراء بجوار التطبيق على أنه نشط؛ في حين تدل النقطتين على وجود نافذتين تعودان لهذا التطبيق وهكذا. زر إظهار التطبيقات Show Applications: يقع هذا الزر على طرف شريط التطبيقات وينتقل بك عند النقر إليه إلى نافذة التطبيقات المثبتة على حاسوبك. ستجد دائمًا مجموعةً من التطبيقات اﻷساسية التي تُثبّت افتراضيًا مع نظام التشغيل، كما ستُعرض فيه أية تطبيقات ستعمل على تثبيتها بنفسك لاحقًا. شريط المهام Taskbar: يقع الشريط أعلى يمين الشاشة في النسخة العربية ويضم اختصارات لأدوات تحكم ومؤشرات على حالة النظام. قد يختلف عدد هذه الاختصارات وفقًا للإعدادات التي نضبطها ( سنرى ذلك لاحقًا في مقالات أخرى)، لكن الاختصارات الموضحة في الصورة التالية موجودة افتراضيًا: شريط اﻷنشطة Activity Bar: يقع هذا الشريط أعلى يمين الشاشة في النسخة العربية ويضم اختصارًا إلى البرنامج الذي يجري تحميله. وبعد إنتهاء التحميل، يختفي الاختصار من شريط اﻷنشطة وتظهر أيقونة البرنامج ضمن شريط التطبيقات. وعندها يكون دور شريط اﻷنشطة لإظهار اختصار إلى التطبيق الذي نعمل عليه حاليًا، إذ يعرض بالنقر عليه مجموعةً من التعليمات المتعلقة ببعض تفاصيل التطبيق أو بإنهائه. يعرض لك سطح المكتب عند النقر على زر "أنشطة" نوافذ جميع البرامج التي حمّلتها. نافذة سطح المكتب Desktop Window: تشغل هذه النافذة المساحة اﻷكبر من الشاشة وتضم افتراضيًا المجلد اﻷساسي "المنزل" ويعنون باسم مستخدم النظام؛ كما يضم سلة المهملات. ويمكنك إضافة مجلدات جديدة أو نسخ ولصق ملفات من وإلى نافذة سطح المكتب. التوقيت والتاريخ Time and Date: يظهران بين شريطي اﻷدوات واﻷنشطة ويعطي بالنقر عليهما تقويمًا بسيطًا يعرض اليوم والشهر والعام، مع إمكانية عرض الأحداث والتنبيهات المرتبطة بأيام معينة. يمكنك أيضًا تفعيل خيار "بلا إزعاج" لإسكات التنبيهات. تفاصيل سطح مكتب جنوم بعد أن عرضنا اختصار تنظيم سطح المكتب وأقسامه الرئيسية، سنغوص فيها الآن بشيء من التفصيل. استكشاف شريط التطبيقات يضم شريط التطبيقات أيقونات مجموعة من التطبيقات، والتي يظهر بعضها افتراضيًا عند تثبيت النظام مثل "متصفح الويب فايرفوكس" وتطبيق "الملفات" وتطبيق البريد اﻹلكتروني "ثندربيرد ميل Thunderbird Mail"؛ وبعضها قد تضعه بنفسك كما سنرى لاحقًا. سيُحمّل التطبيق بمجرد النقر عليه بالزر اليساري للفارة ويختفي عن سطح المكتب بالنقر على زر التصغير في النافذة مجددًا. تظهر عند النقر بالزر اليميني على أي تطبيق ضمن شريط التطبيقات نافذة مهام تُقدم مجموعةً من الخيارات، ويتعلق نوعها وعددها بالتطبيق ذاته. تحوي هذه القائمة عمومًا على تعليمات مثل: نافذة جديدة: وتفتح نافذة أخرى للتطبيق. لهذا اﻷمر أهميته الخاصة في التطبيقات التي يجري فيها سحب وإفلات العناصر من نافذة لأخرى مثل تطبيق "الملفات". أزل من المفضلة: ويستخدم لإزالة أيقونة التطبيق من شريط التطبيقات. أظهر التفاصيل: تنتقل بك هذه التعليمة إلى نافذة توصيف التطبيق، وهي نافذة من نوافذ تطبيق "برمجيات"، الذي يسمح بإضافة أو إزالة التطبيقات من نظامك. تقدم لك هذه النافذة معلومات عن آلية عمل التطبيق ومؤلفه ورخصة استخدامه وآخر إصداراته وتحديثاته وقائمة باﻹضافات المتوفرة التي تدعم وظائف هذا التطبيق. أنهِ: ﻹغلاق التطبيق إن كان مُحمّلًا، حيث لا يظهر هذا الخيار إن لم يكن كذلك. استكشاف نافذة التطبيقات بالنقر على زر التطبيقات الموجود أسفل شريط التطبيقات، ينتقل بك النظام إلى نافذة تعرض أيقونات التطبيقات المثبتة على حاسوبك. تضم هذه النافذة مجموعةً خدميةً متنوعةً من التطبيقات التي تأتي افتراضيًا مع نظام التشغيل أوبونتو، منها برامج التحديث وضبط اﻹعدادات ودعم اللغات واﻷلعاب. لتشغيل أي تطبيق، انقر عليه بزر الفأرة اليساري مرةً واحدة، وسيظهر اختصاره في شريط اﻷنشطة أثناء التحميل، ثم تظهر أيقونته في شريط التطبيقات عندما يكتمل التحميل. ملاحظة 1: إن اختفى اختصار التطبيق من شريط اﻷنشطة ولم تظهر أيقونته في شريط التطبيقات خلال فترة قصيرة، فهنالك مشكلة في تشغيل التطبيق وقد أنهى النظام تشغيله دون إنذار مسبق. ملاحظة 2: لإضافة أي تطبيق إلى قائمة التطبيقات، انقر بالزر اليميني للفأرة على التطبيق واختر "أضف إلى المفضلة". يتواجد في أسفل نافذة التطبيقات خياران هما: "الكل" و "شائعة". بالنقر على الخيار اﻷول، سيعرض لك سطح المكتب جميع البرامج المثبتة على حاسوبك، بينما سيعرض فقط التطبيقات اﻷكثر استخدامًا إن نقرت على "شائعة". تقدم لك هذه النافذة أيضًا ميزة البحث عن أية تطبيقات أو ملفات أو إعدادات من خلال صندوق البحث في أعلاها. ويمكنك كتابة حرف أو أكثر من الاسم حتى يعرض لك كل ما هو موجود بأسلوب منظم وسهل الفهم. تعرض الصورة التالية محاولة البحث عن محرر نصوص، لذلك كتبنا أول حرفين "مح". لاحظ النتائج المتوفرة: لمغادرة نافذة التطبيقات، اضغط على المفتاح "Esc"؛ أو انقر مجدًا على زر التطبيقات. من أهم التطبيقات التي تعرضها القائمة نشير إلى ما يلي: اﻹعدادات: يتيح لك التطبيق واجهةً للتحكم بإعدادات العتاد الصلب والتطبيقات والخدمات المختلفة، وسنفرد لهذا التطبيق مقالات خاصة لأهميته الكبيرة. مُحدّث البرمجيات: يتيح لك التطبيق إمكانية ضبط إعدادات آليات تحديث النظام والبرمجيات المثبتة عليه، وإمكانية تحديد ما تريد تحديثه وما لاتريده واختيار الخوادم التي ستنزّل منها هذه التحدثيات. لهذا البرنامج أهمية كبيرة جدًا في صيانة تطبيقاتك والتحقق من جودة اعتمادياتها Dependencies. برمجيات: وهو تطبيق شديد اﻷهمية يسمح لك بالوصول إلى مخازن أوبنتو سواءً "جنوم-ستور" أو سناب-ستور" لتثبيت البرمجيات اللازمة في عملك. وقد تجده أحيانًا باسم "أوبنتو سوفتوير Ubuntu Software" وفقًا ﻵخر تحديث مثبت على حاسوبك. يعرض لك التطبيق البرمجيات المتوفرة مصنفةً وفقًا لنوعها وطبيعة عملها وتقييم المستخدمين لها. وسنفرد لاحقًا مقالًا خاصًا عن استخدام هذا التطبيق لتثبيت وإزالة البرمجيات. LibreOffice: وهو مجموعة برامج مكتبية Office مفتوحة المصدر تشابه مجموعة برامج مايكروسوفت أوفيس، تساعدك في كتابة وتنسيق الملفات النصية والعروض التقديمية وتصميم جداول البيانات بإمكانات متقدمة ومتميزة. ستجد من هذه السلسة تطبيقات LibreOffice Writer و LibreOffice Calc و LibreOffice Impress و LibreOffice Draw. تعرف على شريط المهام يضم شريط المهام مجموعةً من الاختصارات لبعض اﻹعدادات، وبعض مؤشرات أداء الجهاز والتطبيقات. تظهر ضمن الشريط مجموعات من القوائم تبدأ كلّ منها بسهم صغير نحو اﻷسفل يفتح بالنقر عليه ما تضمه القائمة من خيارات. يظهر افتراضيًا الشريط الرئيسي الموجود في أقصى اليسار ويضم إعدادات الصوت وشبكات الاتصال وأوامر إنهاء التشغيل وتسجيل الخروج. يعرض القسم اﻷول من قائمة الشريط الرئيسي مستوى الصوت، ويليها قسم شبكات الاتصال بأنواعها. تُظهر القائمة وجود شبكة واي-فاي WiFi جاهزة للعمل وشبكة افتراضية VPN مطفأة وشبكة لاسلكية بتقنية بلوتوث جاهزة للعمل أيضَا، وسيظهر بالطبع أي اتصال ضمن هذه القائمة. وبالنقر على زر القائمة المنسدلة بجوار كل اتصال، ستظهر مجموعة الخيارات للتحكم بالاتصال، مثل اختيار شبكة أو إيقافها أو الانتقال إلى إعدادات الاتصال. يلي هذا القسم التالي خيارات الانتقال إلى لوحة إعدادات النظام وأوامر قفل سطح المكتب "أوصد" وأوامر اﻹطفاء الكامل والخروج. يظهر أيضًا شريط اللغة الذي يضم قائمًةً بمجموعة اللغات المثبتة كمصدر دخل Input Source، أي اللغات التي يمكن الكتابة بها عند استخدام لوحة المفاتيح. ويعرض الشريط أيضًا خيار "أظهر تخطيط لوحة المفاتيح" الذي يعطي تسمية المفاتيح وفقًا لنظام التشغيل أوبنتو. لا تتفاجئ بظهور أشرطة مهام أخرى، فقد تعرض بعض البرمجيات والتطبيقات أشرطة مهام خاصة بها لتساعدك في التعامل مع إعداداتها. تعرف على نافذة سطح المكتب وهي الواجهة الرئيسية لنظام أوبنتو وتمثل في الواقع مجلدًا لا يختلف عن بقية المجلدات عمومًا من الناحية الوظيفية إلا أنه لا يقبل عمليات السحب واﻹفلات. إذ لا يمكن جر وإفلات أي مجلد أو ملف من نافذة ما إلى سطح المكتب، إلا أن عمليات النسخ واللصق متاحة. تظهر قائمة سطح المكتب بالنقر على أي نقطة من نافذة سطح المكتب بالزر اليميني وتعرض الخيارات التالية: "مجلد جديد New Folder": ﻹنشاء مجلد جديد على سطح المكتب. "لصق Paste": لصق المجلدات أو الملفات الموجودة في الحافظة. "اعرض سطح المكتب باستخدام تطبيق الملفات Show Desktop in Files": يفتح تطبيق "الملفات" سطح المكتب ويعرضه كأي مجلد آخر. "افتح باستخدام الطرفية Open in Terminal": يفتح سطح المكتب باستخدام برنامج الطرفية. "غير الخلفية Change Background": يفتح إعدادات تغيير صورة الخلفية. "إعدادت العرض Display Settings": يفتح إعدادات ضبط شاشة العرض المستخدمة. "اﻹعداداتSettings": يفتح تطبيق اﻹعدادات. إطفاء الحاسوب انقر على شريط المهام الرئيسي في أقصى يسار شريط اﻷدوات، ثم اختر اﻷمر " إطفاء \ خروج" لتظهر لك النافذة التالية: اختر اﻷمر "أطفئ" ﻹيقاف التشغيل أو "أعد التشغيل"، كما يمكنك إلغاء العملية بالنقر على زر "ألغِ" إن وصلت إلى هذا المكان بطريق الخطأ. سيُطفأ النظام تلقائيًا بعد 60 ثانية إن لم تتخذ قرارك كما توضح لقطة الشاشة السابقة. خلاصة تعرفنا في هذا المقال على البنية التنظيمية لسطح مكتب جنوم، وهي الواجهة الرسومية الرئيسية لنظام لينكس أوبونتو؛ كما تحدثنا بشيء من التفصيل عن أقسام سطح المكتب وأهم المؤشرات والاختصارات التي يحويها كل قسم، ثم عرضنا آلية إطفاء الحاسوب بالطريقة الصحيحة. لقد أصبحنا اﻵن مستعدين للانتقال إلى المرحلة الثانية من مراحل استثمار نظام أوبنتو، وهي التعامل مع المجلدات والملفات. إقرأ أيضًا ما هو نظام التشغيل لينكس؟ تغيير اللغة في نظام لينكس أوبنتو إلى العربية في ماذا يختلف Ubuntu عن Debian؟
  3. لقد أضفنا حتى الآن عدة ميزات إلى تطبيقنا لكن دون أي اتصال بالخادم، إذ يستخدم تطبيق قائمة المستودعات المقيَّمة الذي نفذناه في المقال السابق أساسيات React Native -على سبيل المثال- بيانات وهمية، ولا يرسل نموذج تسجيل الدخول بيانات التحقق من المستخدم إلى أية وصلة تخديم endpoint مفوَّضة باستقبال هذه البيانات، لذا سنتعلم في هذا المقال كيف سنتصل بالخادم مستخدمين طلبات HTTP، وكيف سنستخدم المكتبة Apollo Client ضمن تطبيقات React Native، وكذلك طريقة تخزين البيانات في جهاز المستخدم. سنحتاج قبل الشروع بتعلم تلك النقاط إلى خادم لنتواصل معه، لذلك فقد أنجزنا خادمًا كاملًا ووضعناه في المستودع rate-repository-api. سيلبي الخادم "rate-repository-api" كل ما تحتاجه الواجهة البرمجية لتطبيقنا خلال هذا القسم، إذ يستخدم "rate-repository-api" قاعدة بيانات SQLite والتي لا تحتاج إلى إعدادات، كما يؤمن واجهة برمجية خاصة بالمكتبة Apollo GraphQL، إضافةً إلى بعض وصلات التخديم التي تؤمن واجهة برمجية متوافقة مع REST. قبل أن تغوص أعمق في مادة هذا المقال، عليك أن تُعدَّ الخادم "rate-repository-api" باتباع الإرشادات الموجودة في ملف README الخاص بالمستودع. ننصحك إن كنت ستستخدم المقلّد emulator لتطوير التطبيق، أن تشغله على نفس الحاسوب الذي يشغّل الخادم، فسيسهل ذلك طلبات الاتصال عبر الشبكة على نحوٍ واضح. طلبات HTTP تزودنا React Native بالواجهة البرمجية Fetch API لتنفيذ طلبات HTTP الخاصة بتطبيقنا، كما تدعم أيضًا الواجهة البرمجية القديمة XMLHttpRequest API والتي ستمكننا من استخدام مكتبات خارجية مصدرها طرف ثالث مثل Axios. وهذه الواجهات هي نفسها التي استخدمناها في بيئة المتصفح، كما أنها متاحة لكامل التطبيق ولا حاجة لإدراجها. قد يتفق المطورون الذين تعاملوا مع الواجهتين البرمجيتين السابقتين، أن Fetch API أسهل استخدامًا وأكثر عصرية، لكن للواجهة XMLHttpRequest API استعمالاتها أيضًا، ولأجل تبسيط الموضوع سنتعامل فقط مع Fetch API في أمثلتنا. يمكن استخدام Fetch API لإرسال طلبات HTTP باستخدام الدالة fetch وسيكون الوسيط الأول لهذه الدالة عنوان المورد URL وطلب HTTP الافتراضي لها هو GET: fetch('https://my-api.com/get-end-point'); أما الوسيط الثاني للدالة فهو كائن خيارات يمكنك استعماله لإنشاء طلب HTTP آخر، أو ترويسة طلب، أو متن body طلب: fetch('https://my-api.com/post-end-point', { method: 'POST', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, body: JSON.stringify({ firstParam: 'firstValue', secondParam: 'secondValue', }), }); انتبه إلى أنّ العناوين "URL's" مصطنعة ولن تستجيب لطلباتك غالبًا. تعمل Fetch API موازنةً بالمكتبة Axios في مستوى أدنى قليلًا، فلا توجد مثلًا أية عمليات تحويل أو تفسير لمتن الطلب أو الاستجابة، فعليك مثلًا أن تحدد نوع المحتوى content-type بنفسك وأن تستخدم التابع JSON.stringify لتحويل متن الطلب إلى نص. تعيد الدالة fetch وعدًا (promise) يُحَل resolves إلى كائن الاستجابة Response، وانتبه إلى أنّ رموز الحالة للأخطاء التي تحصل مثل 400 أو 500 لن تُرفض كما هو الوضع في Axios مثلًا. يمكن أن نفسّر متن الاستجابة المنسقة بأسلوب JSON باستخدام التابع Response.json: const fetchMovies = async () => { const response = await fetch('https://reactnative.dev/movies.json'); const json = await response.json(); return json; }; وللاطلاع على أساسيات Fetch API بشيء من التفصيل، اقرأ مقال الواجهة البرمجية fetch في JavaScript ومقال استعمالات متقدمة للواجهة البرمجية Fetch في جافاسكربت وأضف إليهما مقال تتبع تقدم عملية تنزيل البيانات عبر Fetch ومقاطعتها في جافاسكربت. لنبدأ بالاستخدام التطبيقي للمكتبة Fetch API، إذ يؤمن الخادم rate-repository-api وصلة تخديم تعيد قائمةً مرقمةً من المستودعات المقيَّمة. ستتمكن من الولوج إلى وصلة التخديم الموجودة على العنوان "http://localhost:5000/api/repositories" بمجرد أن يعمل الخادم. تُرقّم البيانات بأسلوب الترقيم المعتمد على المؤشرات cursor based pagination format، وستجد البيانات الفعلية خلف المفتاح "node" في المصفوفة "edges". لا يمكن، لسوء الحظ، الوصول إلى الخادم rate-repository-api مباشرةً من خلال تطبيقنا بطلب العنوان "http://localhost:5000/api/repositories"، إذ نحتاج لإرسال طلب إلى وصلة التخديم هذه عبر التطبيق الوصول إلى الخادم باستخدام عنوان IP الخاص به في الشبكة المحلية التي ينتمي إليها. ولإيجاد هذا العنوان، افتح أدوات تطوير Expo بتنفيذ الأمر npm start. سترى في أدوات التطوير عنوانًا له بالبادئة "//:exp" فوق شيفرة QR: انسخ عنوان IP الموجود بين البادئة "//:exp" والنهاية ":"، وسيكون في مثالنا 192.168.100.16. أنشئ بعد ذلك عنوان URL بالتنسيق التالي "http://:5000/api/repositories" ثم توجه إليه من خلال المتصفح، وستحصل على نفس الاستجابة التي حصلت عليها باستخدام عنوان الخادم المحلي "localhost". بعد أن حددنا عنوان وصل التخديم، سنستخدم البيانات الفعلية التي يزودنا بها الخادم في تطبيق قائمة المستودعات المقيَّمة. أشرنا سابقًا أننا نستخدم بيانات وهمية مخزّنة في المتغير repositories. اِحذف هذا المتغير واستعض عن البيانات الوهمية في الملف "RepositoryList.jsx" الموجود في المجلد "components" بهذه الشيفرة: import { useState, useEffect } from 'react'; // ... const RepositoryList = () => { const [repositories, setRepositories] = useState(); const fetchRepositories = async () => { // ‫صحح عنوان IP إن كان مختلفًا لديك const response = await fetch('http://192.168.100.16:5000/api/repositories'); const json = await response.json(); console.log(json); setRepositories(json); }; useEffect(() => { fetchRepositories(); }, []); // Get the nodes from the edges array const repositoryNodes = repositories ? repositories.edges.map(edge => edge.node) : []; return ( <FlatList data={repositoryNodes} // Other props /> ); }; export default RepositoryList; استخدمنا الخطاف useState للحفاظ على حالة قائمة المستودعات، كما استخدمنا الخطاف useEffect لاستدعاء الدالة fetchRepositoriesعندما يُثبّت المكوّن RepositoryList ضمن شجرة المكوّنات. استخلصنا المستودعات الفعلية ووضعناها في المتغير repositoryNode واستبدلنا به المتغير السابق repositories الموجود في الخاصية data العائدة للمكوّن FlatList، وبذلك يمكننا أن نرى البيانات الفعلية التي يعطيها الخادم ضمن التطبيق. من الجيد عادةً تسجيل استجابة الخادم لتتمكن من تحرّيها كما فعلنا في الدالة fetchRepositories. ينبغي أن تكون قادرًا على الاطلاع على السجلات في أدوات تطوير Expo عن طريق الوصول إلى سجلات جهازك كما تعلمنا في المقال السابق (فقرة عرض سجلات العمل). إن استخدمت تطبيق جوّال Expo وأخفق طلب HTTP، تأكد أن هاتفك وحاسوبك الذي يشغّل الخادم ينتميان إلى نفس الشبكة اللاسلكية. وإن لم تستطع ذلك، استخدم المقلّد على نفس الحاسوب الذي يعمل عليه الخادم أو هيئ نفق توصيل tunnel إلى الخادم المحلي. يمكنك استخدام المكتبة Ngrok مثلًا لإنجاز ذلك. يمكن إعادة كتابة شيفرة إحضار البيانات الموجودة في المكوّن RepositoryList، إذ يعرف المكوّن مثلًا تفاصيل الطلبات عبر الشبكة كعنوان وصلة التخديم، وبالإضافة إلى ذلك، تحمل شيفرة إحضار البيانات إمكانية لإعادة استخدامها. لنعد إذًا كتابة شيفرة المكوّن بنقل شيفرة إحضار البيانات إلى خطاف خاص بها. سننشئ أولًا مجلدًا باسم "hooks" ضمن المجلد "src" ومن ثم سنضع فيه الملف "useRepositories.js" الذي يحتوي الشيفرة التالية: import { useState, useEffect } from 'react'; const useRepositories = () => { const [repositories, setRepositories] = useState(); const [loading, setLoading] = useState(false); const fetchRepositories = async () => { setLoading(true); // ‫صحح عنوان IP إن كان مختلفًا لديك const response = await fetch('http://192.168.100.16:5000/api/repositories'); const json = await response.json(); setLoading(false); setRepositories(json); }; useEffect(() => { fetchRepositories(); }, []); return { repositories, loading, refetch: fetchRepositories }; }; export default useRepositories; لنستخدم الآن الخطاف الجديد useRepositories في المكوّن RepositoryList: // ... import useRepositories from '../hooks/useRepositories'; const RepositoryList = () => { const { repositories } = useRepositories(); const repositoryNodes = repositories ? repositories.edges.map(edge => edge.node) : []; return ( <FlatList data={repositoryNodes} // Other props /> ); }; export default RepositoryList; وهكذا لن يكون لدى المكوّن RepositoryList أية فكرة عن طريقة الحصول على مستودعات القائمة، وربما سنطلب هذه المستودعات مستقبلًا باستخدام الواجهة البرمجية للمكتبة GraphQL بدلًا من واجهة REST، ونرى ما الذي سيحدث. العمل مع المكتبتين GraphQL و Apollo client تعرفنا في القسم 8 على GraphQL وكيفية إرسال استعلامات إلى خادم Apollo في تطبيقات React بالاستفادة من المكتبة Apollo Client. ولحسن الحظ، يمكنك استخدام Apollo client في تطبيقات React Native بنفس الطريقة التي استخدمناها في بناء تطبيقات React الخاصة بالويب. وكما أشرنا سابقًا، سيزودنا الخادم "rate-repository-api" بواجهة برمجية للمكتبة GraphQL نُفِّذت باستخدام Apollo client، وبالتالي ستتمكن من الولوج إلى أرضية عمل GraphQL بالتوجه إلى العنوان http://localhost:5000/graphq. تمثل أرضية عمل GraphQL أداة تطوير لإرسال استعلامات GraphQL، وتفقد تخطيط الواجهة البرمجية للمكتبة GraphQL، وعرض توثيق هذه المكتبة. ويفضل أن تجرب دائمًا أية استعلامات سيرسلها تطبيقك من خلال أرضية عمل GraphQL قبل تضمينها في الشيفرة. ومن الأسهل أيضًا تنقيح الأخطاء المحتملة في الاستعلامات ضمن أرضية عمل GraphQL موازنةً مع تنقيحها باستخدام التطبيق. وإن لم تكن متأكدًا من الاستعلامات المتاحة أو كيفية استخدامها، انقر على النافذة "docs" لفتح التوثيق: سنستعمل في تطبيقات React Native المكتبة Apollo Boost، وهو أسلوب لا يتطلب أية قواعد للتهيئة zero-config للبدء باستخدام Apollo client. وللتكامل مع React، سنستخدم المكتبة apollo/react-hooks@ والتي تؤمن خطافات مثل useQuery و useMutation تساعدنا في العمل مع المكتبة Apollo client. لنبدأ بتثبيت الاعتماديات اللازمة: npm install @apollo/client graphql سنحتاج قبل البدء باستخدام عميل Apollo إلى إعدادٍ جزئي لمجمّع Metro لمعالجة الملفات ذات الامتداد "cjs." التي يستخدمها عميل Apollo. لنثبّت أولًا الحزمة "expo/metro-config@" التي تحتوي على إعدادات Metro الافتراضية: npm install @expo/metro-config يمكننا بعد ذلك إضافة الإعداد التالي إلى الملف "metro.config.js" في المجلد الجذري للمشروع: const { getDefaultConfig } = require('@expo/metro-config'); const defaultConfig = getDefaultConfig(__dirname); defaultConfig.resolver.sourceExts.push('cjs'); module.exports = defaultConfig; أعِد تشغيل أدوات تطوير Expo لتطبيق الإعدادات المُجراة. لننشئ الآن دالةً خدميّة utility function لتكوين عميل Apollo وتهيئته على النحو المطلوب. أنشئ بدايةً المجلد "utils" ضمن المجلد "src"، وأنشئ ضمنه الملف "apolloClient.js"، ثم هيئ عميل Apollo ضمن هذا الملف ليتصل مع خادم Apollo: import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; const httpLink = createHttpLink({ // ‫صحح عنوان IP إن كان مختلفًا لديك uri: 'http://192.168.100.16:4000/graphql', }); const createApolloClient = () => { return new ApolloClient({ link: httpLink, cache: new InMemoryCache(), }); }; export default createApolloClient; يستخدم عميل Apollo للاتصال بخادم Apollo العنوان URL ذاته الذي استخدمناه مع Fetch API ونفس رقم المنفذ 4000، ما عدا أنّ المسار هو "graphql/". وأخيرًا علينا تزويد التطبيق بعميل Apollo وذلك باستخدام سياق العمل ApolloProvider. سنضيفه إذًا إلى المكوّن App في الملف "App.js": import { NativeRouter } from 'react-router-native'; import { ApolloProvider } from '@apollo/client'; import Main from './src/components/Main'; import createApolloClient from './src/utils/apolloClient'; const apolloClient = createApolloClient(); const App = () => { return ( <NativeRouter> <ApolloProvider client={apolloClient}> <Main /> </ApolloProvider> </NativeRouter> ); }; export default App; تنظيم الشيفرة المتعلقة بالمكتبة GraphQL سيعود الأمر إليك دائمًا في تنظيم الشيفرة المتعلقة بالمكتبة GraphQL ضمن تطبيقك. لكن ولأجل الحصول على هيكلية مرجعية، لنلق نظرةً على طريقة بسيطة لكنها فعالة في تنظيم هذه الشيفرة. عرّفنا في هذه الهيكلية كلًا من الاستعلامات والطفرات mutations والاجتزاءات fragments وغيرها من الكيانات التي قد نستخدمها في ملفات خاصة بها وتتواجد في نفس المجلد. إليك صورة توضح هيكلية يمكنك اعتمادها: يمكنك استيراد معرّف القالب المجرّد gql المُستخدم في تعريف استعلامات من مكتبة "apollo/client@". وإن اتبعنا الهيكلية التي اقترحناها منذ قليل، فمن الأفضل إنشاء الملف "queries.js" في المجلد "graphql" ليحتوي الشيفرة اللازمة لتنفيذ استعلامات GraphQL في تطبيقنا. يمكن أن نخزّن كل استعلام ضمن متغّير خاص ثم نصدّره كالتالي: import { gql } from '@apollo/client'; export const GET_REPOSITORIES = gql` query { repositories { ${/* ... */} } } `; // other queries... يمكن إدراج تلك المتغيرات واستخدامها بالاستفادة من الخطاف useQuery على النحو التالي: import { useQuery } from '@apollo/client'; import { GET_REPOSITORIES } from '../graphql/queries'; const Component = () => { const { data, error, loading } = useQuery(GET_REPOSITORIES); // ... }; وينطبق على الطفرات ما ينطبق على الاستعلامات. طبعًا لا بدّ من تعريف الطفرات في ملف منفصل مثل "mutations.js"، ويُفضّل استخدام الاجتزاءات (fragments) في الاستعلامات لتفادي تكرار كتابة الحقول نفسها عدة مرات. تطوير هيكلية التطبيق عندما يأخذ التطبيق في النمو، سيزداد حجم بعض الملفات لتصبح ربما كبيرة جدًا لإدارتها بصورةٍ صحيحة. لنفترض أنه لدينا مكوّن A سيصيّر مكونين B و C. ستُعرّف جميع هذه المكونات ضمن الملف "A.jsx" والذي سيوضع في المجلد"components". نريد الآن أن ننقل المكونين A و B إلى ملفين مستقلين "B.jsx" و "C.jsx" دون أن نجري تغييرًا كبيرُا في تنظيم الشيفرة. سيكون أمامنا في هذه الحالة خيارين: الأول، إنشاء الملفين "B.jsx" و"C.jsx" في المجلد "components". وستكون هيكلية التطبيق على النحو التالي: components/ A.jsx B.jsx C.jsx ... الثاني، إنشاء مجلد A في المجلد "components" ثم إنشاء الملفين "B.jsx"و"C.jsx" ضمنه. ولتفادي إخفاق المكونات التي تُدرِج الملف "A.jsx" في شيفرتها، انقل الملف "A.jsx" إلى المجلد "A" وغيّر اسمه إلى "index.jsx". سينتج عن هذا الأسلوب الهيكلية التالية: components/ A/ B.jsx C.jsx index.jsx ... يُعد الخيار الأول مناسبًا تمامًا إن لم يكن المكونين C وB قابلين للاستخدام خارج حدود المكوّن A، فلا فائدة من وضعهما في ملفات منفصلة في المجلد "components"؛ أما الخيار الثاني فهو مناسبٌ لأسلوب الوحدات المستقلة، إذ أنه لا يسبب أية مشاكل في إدراج المكونات، لأن إدراج مسار مثل "A/." سيطابق إدراج كلا الملفين "A.jsx" و"A/index.jsx". التمرين 10.11 إحضار المستودعات باستخدام Apollo client نريد استبدال ما نفذناه ضمن الخطاف useRepositories مستخدمين المكتبة Fetch API باستعلام GraphQL. شغّل أرضية عمل Apollo على العنوان "http://localhost:4000"، ثم افتح توثيق المكتبة بالنقر على النافذة "docs". يستخدم الاستعلام عدة وسطاء اختيارية، فلا حاجة لتحديدها الآن. كوّن استعلامًا ضمن أرضية عمل Apollo لإحضار المستودعات بالاستفادة من قيم الحقول التي تعرضها حاليًا في واجهة التطبيق. ستُرقّم النتائج التي تضم قرابة 30 نتيجة افتراضيًا. يمكنك تجاهل موضوع الترقيم حاليًا. عندما يعمل الاستعلام ضمن أرضية عمل Apollo، اِستخدمه ليحل مكان شيفرة المكتبة FetchAPI في الخطاف useRepositories. يمكن أن تنفِّذ ذلك باستخدام الخطاف useQuery. أدرج بعدها معّرف القالب المجرّد gql من المكتبة بالطريقة التي شرحناها سابقًا. حاول أن تستخدم الهيكلية التي اقترحناها سابقًا لتنظيم الشيفرة المتعلقة بالمكتبة GraphQL. ولتجنب مشاكل الذاكرة الخبيئة مستقبلًا، استخدم سياسة الإحضار (fetch policy) "cache-and-network"، التي يمكن استخدامها مع الخطاف useQuery على النحو التالي: useQuery(MY_QUERY, { fetchPolicy: 'cache-and-network', // خيارات أخرى }); يجب أن لا تؤثر التغييرات في شيفرة الخطاف useRepositories على أداء المكوّن RepositoryList بأي شكل من الأشكال. متغيرات البيئة سيعمل كل تطبيق على الأرجح في أكثر من بيئة، ومن الواضح أن بيئتي التطوير والإنتاج أقرب مثالين عن الفكرة، لكن خارج هاتين البيئتين، هناك البيئة التي نشغّل عليها التطبيق حاليًا. تحتاج البيئات المختلفة عادةً اعتماديات مختلفة، فقد يستخدم الخادم المحلي الذي نتعامل معه قاعدة بيانات محليّة، بينما سيتعامل الخادم الذي سيُنشَر في بيئة الإنتاج مع قاعدة بيانات بيئة الإنتاج. ولكي نجعل شيفرتنا مستقلة عن بيئة التشغيل، لا بد من ربط هذه الاعتماديات بمعاملات أو متغيرات. لاحظ مثلًا أننا نستخدم في تطبيقنا قيمة جاهزة تعتمد بشدة على بيئة التشغيل وهي عنوان الخادم. تعلمنا سابقًا أنه بالإمكان تزويد البرامج قيد التشغيل بمتغيرات بيئة، إذ يمكن تعريف هذه المتغيرات من خلال سطر الأوامر أو من خلال ملف تهيئة بيئة التشغيل الذي ينتهي بلاحقة مثل "env." ومكتبات يؤمنها طرف ثالث مثل Dotenv. لكن ولسوء الحظ لا تدعم React Native الاستخدام المباشر لمتغيرات البيئة، لكن يمكننا الوصول إلى إعدادت تهيئة Expo الموجودة في الملف "app.json" في زمن التشغيل من خلال شيفرة JavaScript. وبالتالي يمكن استخدام هذه الإعدادات لتعريف المتغيرات المتعلقة بالبيئة والوصول إليها. نستطيع الوصول إلى إعدادات التهيئة بإدراج الثابت Constants من الوحدة "expo-constants" كما فعلنا ذلك عدة مرات مسبقًا. وبإدراج هذا الثابت، ستزودنا الخاصية Constants.manifest بكل الإعدادات. لنجرب ذلك بكتابة شيفرة ضمن المكوّن App وظيفتها طباعة محتويات هذه الخاصية في سجل العمل: import { NativeRouter } from 'react-router-native'; import { ApolloProvider } from '@apollo/client'; import Constants from 'expo-constants'; import Main from './src/components/Main'; import createApolloClient from './src/utils/apolloClient'; const apolloClient = createApolloClient(); const App = () => { console.log(Constants.manifest); return ( <NativeRouter> <ApolloProvider client={apolloClient}> <Main /> </ApolloProvider> </NativeRouter> ); }; export default App; ستجد الآن كل إعدادات التهيئة في سجل العمل. تقتضي الخطوة الثانية استخدام الإعدادات لتعريف متغيّرات تعتمد على بيئة التشغيل. لنبدأ المهمة بتغير اسم الملف "app.json" إلى "app.config.json". بهذا التغيير سنصبح قادرين على استخدام شيفرة جافا سكريبت داخل ملف التهيئة. غير محتوى الملف بحيث يتحوّل الكائن: { "expo": { "name": "rate-repository-app", // … بقية الضبط } } إلى كائن قابل للتصدير، يحتوي على الخاصية expo: export default { name: 'rate-repository-app', // … بقية الضبط }; يتلقى الكائن expo الخاصية extra ضمن إعدادات التهيئة، وذلك لتمرير أية إعدادات خاصة بالتطبيق. ولنرى كيف يعمل هذا الأمر، سنضيف المتغير env إلى إعدادات تهيئة تطبيقنا: export default { name: 'rate-repository-app', // … بقية الضبط extra: { env: 'development' }, }; أعد تشغيل أدوات تطوير Expo لتطبيق التغييرات. من المفترض أن تتغير قيمة الخاصية Constans.manifest بحيث تضم الخاصية extra التي تحتوي على إعدادات التهيئة الخاصة بتطبيقنا. يمكننا الآن الوصول إلى المتغير env من خلال الخاصية Constants.manifest.extra.env ولأن وضع القيم الجاهزة في الشيفرة أمر طائش، سنستخدم متغير بيئة بديلًا لذلك: export default { name: 'rate-repository-app', // rest of the configuration... extra: { env: process.env.ENV, }, }; تعلمنا سابقًا كيفية إسناد قيمة لمتغير البيئة من خلال سطر الأوامر، وذلك بتحديد اسم المتغيّر وقيمته قبل الأمر الفعلي. فعلى سبيل المثال، شغل أدوات تطوير Expo، ثم أسند القيمة "test" إلى متغير البيئة ENV: ENV=test npm start لو ألقيت نظرةً على سجل العمل، فستجد أن الخاصية Constants.manifest.extra.env قد تغيرت. يمكننا كذلك تحميل متغيرات البيئة من الملف "env." كما تعلمنا في الأقسام السابقة. لكن علينا أولًا تثبيت المكتبة Dotenv: npm install dotenv لنضف الآن الملف "env." إلى المجلد الجذري للمشروع على أن يحتوي ما يلي: ENV=development سندرج أخيرًا المكتبة ضمن الملف "app.config.js": import 'dotenv/config'; export default { name: 'rate-repository-app', // … بقية الضبط extra: { env: process.env.ENV, }, }; أعد تشغيل أدوات تطوير Expo لتطبيق التغييرات التي أجريتها على الملف "env". ملاحظة: لا تضع بيانات حساسة ضمن إعدادات التطبيق، لأن المستخدم بعد تنزيل التطبيق قد يكون قادرًا من الناحية النظرية على تحليل شيفرتك وسيحصل بالتالي على هذه البيانات الحساسة. التمرين 10.12 متغيرات البيئة استخدم متغير بيئة ضمن ملف "env." لتحديد عنوان خادم Apollo بدلًا من كتابته ضمن الشيفرة، وذلك عند تهيئة عميل Apollo. يمكنك تسمية هذا المتغير "APOLLO_URI" مثلًا. لا تحاول الوصول إلى متغير البيئة على النحو التالي: process.env.APOLLO_URI خارج الملف "app.config.js"، بل استخدم الكائن Constants.manifest.extra كما فعلنا في المثال السابق. كذلك لا تدرج المكتبة Dotenv خارج الملف "app.config.js" وإلا قد تواجهك المشاكل. تخزين البيانات في جهاز المستخدم قد تحتاج في بعض الأحيان إلى تخزين بعض البيانات في جهاز المستخدم. ومن أبرز السيناريوهات التي تضطرك إلى ذلك هو تخزين شهادة التحقق من المستخدم token لكي تكون قادرًا على الحصول عليها عندما يغلق المستخدم التطبيق ثم يعيد فتحه. لقد استخدمنا عند تطوير تطبيقات الويب الذاكرة المحلية للمتصفح من خلال الكائن localStorage. تؤمن Recat Native بالمقابل ذاكرة تخزين مقيمة هي الذاكرة غير المتزامنة (AsyncStorage). يمكن استخدام أمر التثبيت في Expo لتثبيت نسخة من الحزمة reactnativecommunity/async-storage@ متوافقة مع نسخة Expo SDK المستخدمة: expo install @react-native-async-storage/async-storage تتشابه الواجهة البرمجية للحزمة AsyncStorage مع الواجهة البرمجية للذاكرة المحلية localStorage بعدة نواحٍ، فكلاهما ذاكرة تعتمد مبدأ "مفتاح-قيمة". ويكمن الاختلاف الكبير بينهما، كما يوحي الاسم، أنّ عمليات AsyncStorage غير متزامنة. من المفيد أن نُجري تجريدًا بسيطًا لشيفرة العمليات، طالما أن AsyncStorage ستعمل مع مفاتيح نصية ضمن فضاء الأسماء العام global namespace. يمكن إنجاز هذا التجريد باستخدام الأصناف class. إذ يمكن، على سبيل المثال، إنشاء صنف لبطاقة تسوق، نخزّن فيها المنتجات التي يريد أن يشتريها مستخدم: import AsyncStorage from '@react-native-async-storage/async-storage'; class ShoppingCartStorage { constructor(namespace = 'shoppingCart') { this.namespace = namespace; } async getProducts() { const rawProducts = await AsyncStorage.getItem( `${this.namespace}:products`, ); return rawProducts ? JSON.parse(rawProducts) : []; } async addProduct(productId) { const currentProducts = await this.getProducts(); const newProducts = [...currentProducts, productId]; await AsyncStorage.setItem( `${this.namespace}:products`, JSON.stringify(newProducts), ); } async clearProducts() { await AsyncStorage.removeItem(`${this.namespace}:products`); } } const doShopping = async () => { const shoppingCartA = new ShoppingCartStorage('shoppingCartA'); const shoppingCartB = new ShoppingCartStorage('shoppingCartB'); await shoppingCartA.addProduct('chips'); await shoppingCartA.addProduct('soda'); await shoppingCartB.addProduct('milk'); const productsA = await shoppingCartA.getProducts(); const productsB = await shoppingCartB.getProducts(); console.log(productsA, productsB); await shoppingCartA.clearProducts(); await shoppingCartB.clearProducts(); }; doShopping(); ومن الجيد أيضًا أن نحدد فضاء أسماء للمفاتيح في AsyncStorage، ذلك أنها قيم نصيّة. وفي هذا السياق، سنجد أن فضاء الأسماء هو بادئة نزوّد بها مفاتيح التخزين، إذ سيمنع استخدام فضاء الأسماء مفاتيح التخزين من التصادم مع مفاتيح أخرى للمكتبة AsyncStorage. عرّفنا فضاء الأسماء في المثال السابق على شكل وسيط للدالة البانية، كما استخدمنا التنسيق "namespace:key مفتاح: فضاء أسماء" من أجل مفاتيح التخزين. يمكن إضافة عنصر إلى ذاكرة التخزين مستخدمين التابع AsyncStorage.setItem. سيكون مفتاح العنصر هو الوسيط الأول للتابع بينما ستكون قيمة المفتاح هي المعامل الثاني. وطالما أن قيمة المفتاح هي قيمة نصية، فلا بد من تحويل القيم غير النصية إلى نصية باستخدام التابع JSON.stringify. يُستخدَم التابع AsyncStorage.getItem للحصول على عنصر محدد من ذاكرة التخزين، ووسيط هذا التابع هو مفتاح العنصر. أما التابع AsyncStorage.removeItem فيُستخدم لحذف عنصر من ذاكرة التخزين بتحديد مفتاحه. التمرينان 10.13 - 10.14 10.13: استخدام الطفرات في نموذج تسجيل الدخول لا يستطيع نموذج تسجيل الدخول حاليًا فعل أي شيء حيال معلومات توثيق المستخدم التي يرسلها، لذلك سنحاول تحسين الوضع قليلًا في هذا التمرين. اطلع أولًا على توثيق الاستيثاق authentication documentation الخاص بالخادم "rate-repository-api"، ثم اختبر الاستعلامات التي تُزوَّد بها ضمن أرضية عمل Apollo. إن لم تحتوي قاعدة البيانات على أي مستخدمين يمكن وضع بعض البيانات فيها، وستجد إرشاداتٍ لذلك في الفقرة "getting started"من الملف "README" الموجود في المستودع "rate-repository-ap". عندما تتفهم الطريقة التي تعمل بها استعلامات الاستيثاق، أنشئ الملف "useSignIn.js" في المجلد "hooks" وضع فيه شيفرة الخطافuseSignIn الذي يرسل الطفرة باستخدام الخطاف useMutation. تقبل الطفرة authenticate وسيطًا وحيدًا هو credentials من النوع "AuthenticateInput". يحتوي نوع عنصر الإدخال (input type) حقلين لاسم المستخدم وكلمة المرور. ستكون القيمة التي يعيدها الخطاف على الشكل [signIn, result]، إذ يمثل الوسيط result نتيجة الطفرات كما يعيدها الخطاف useMutation، ويمثل الوسيط signIn دالة تنفيذ الطفرة باستخدام وسيط هو كائن من الشكل {username, password}. تلميح: لا تمرر دالة الطفرة إلى القيمة المعادة مباشرةً، بل أعد دالة تستدعي دالة الطفرة على النحو التالي: const useSignIn = () => { const [mutate, result] = useMutation(/* mutation arguments */); const signIn = async ({ username, password }) => { // استدعي دالة الطفرة بالوسطاء المناسبين }; return [signIn, result]; }; بعد إنجاز الخطاف، استخدمه في دالة الاستدعاء onSubmit العائدة للمكوّن SignIn على النحو التالي مثلًا: const SignIn = () => { const [signIn] = useSignIn(); const onSubmit = async (values) => { const { username, password } = values; try { const { data } = await signIn({ username, password }); console.log(data); } catch (e) { console.log(e); } }; // ... }; يمكنك عدُّ التمرين مكتملًا عندما تُسجَّل نتيجة طفرات authenticate في سجل عمل التطبيق بعد إرسال بيانات النموذج. وينبغي أن تتضمن نتيجة الطفرة شهادة التحقق من المستخدم. 10.14: تخزين شهادة التحقق- الخطوة 1 بعد أن حصلنا على شهادة التحقق لا بدّ من تخزينها. أنشئ الملف "authStorage.js" في المجلد "utils" بحيث يحتوي الشيفرة التالية: import AsyncStorage from '@react-native-async-storage/async-storage'; class AuthStorage { constructor(namespace = 'auth') { this.namespace = namespace; } getAccessToken() { // احصل على شهادة التحقق } setAccessToken(accessToken) { // أضف الشهادة إلى ذاكرة التخزين } removeAccessToken() { // احذف شهادة التحقق من ذاكرة التخزين } } export default AuthStorage; أنجز شيفرة التوابع التالية: AuthStorage.getAccessToken و AuthStorage.setAccessToken و AuthStorage.removeAccessToken. استخدم المتغير namespace لمنح المفاتيح فضاء أسماء كما فعلنا في المثال السابق. تحسين طلبات المكتبة Apollo Client بعد أن أنجزنا آلية لتخزين شهادة التحقق من المستخدم، حان الوقت لاستخدامها. هيئ ذاكرة التخزين في المكوّن App: import { NativeRouter } from 'react-router-native'; import { ApolloProvider } from '@apollo/client'; import Main from './src/components/Main'; import createApolloClient from './src/utils/apolloClient'; import AuthStorage from './src/utils/authStorage'; const authStorage = new AuthStorage(); const apolloClient = createApolloClient(authStorage); const App = () => { return ( <NativeRouter> <ApolloProvider client={apolloClient}> <Main /> </ApolloProvider> </NativeRouter> ); }; export default App; مررنا نسخةً من الصنف الذي يتعامل مع ذاكرة التخزين AuthStorage إلى الدالة createApolloClient مثل وسيط، لأننا سنرسل لاحقًا شهادة التحقق إلى خادم Apollo مع كل طلب. يتوقع خادم Apollo أن تكون شهادة التحقق ضمن ترويسة الاستيثاق وبنفس تنسيق حامل الشهادة <ACCESS_TOKEN>. يمكن تحسين طلب Apollo Client باستخدام الدالة setContext. لنرسل شهادة التحقق إلى خادم Apollo من خلال عميل Apollo بتعديل الدالة createApolloClientفي الملف "apolloClient.js": import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; import Constants from 'expo-constants'; import { setContext } from '@apollo/client/link/context'; // ‫قد تحتاج إلى تغيير هذا بناءً على كيفية تكوين URI لخادم Apollo const { apolloUri } = Constants.manifest.extra; const httpLink = createHttpLink({ uri: apolloUri, }); const createApolloClient = (authStorage) => { const authLink = setContext(async (_, { headers }) => { try { const accessToken = await authStorage.getAccessToken(); return { headers: { ...headers, authorization: accessToken ? `Bearer ${accessToken}` : '', }, }; } catch (e) { console.log(e); return { headers, }; } }); return new ApolloClient({ link: authLink.concat(httpLink), cache: new InMemoryCache(), }); }; export default createApolloClient; استخدام React Context لتوزيع البيانات يبقى علينا في النهاية إجراء تكامل بين ذاكرة التخزين والخطاف useSignIn. ولكي ننجز ذلك لا بدّ من السماح للخطاف بولوج شهادة التحقق التي هيئنا نسخة منها في المكوّن App. سنستخدم الواجهة Context التي تزودنا بها React لأداء هذه المهمة. أنشئ المجلد "contexts" ضمن المجلد "src"، ثم أنشئ ضمنه الملف "AuthStorageContext.js" وضع فيه الشيفرة التالية: import React from 'react'; const AuthStorageContext = React.createContext(); export default AuthStorageContext; ستتمكن الآن من استخدام المكوّن AuthStorageContext.Provider لتوزيع نسخة من ذاكرة التخزين على المكوّنات الأبناء ضمن سياق التنفيذ context. لنضفه إلى المكوّن App: import { NativeRouter } from 'react-router-native'; import { ApolloProvider } from '@apollo/client'; import Main from './src/components/Main'; import createApolloClient from './src/utils/apolloClient'; import AuthStorage from './src/utils/authStorage'; import AuthStorageContext from './src/contexts/AuthStorageContext'; const authStorage = new AuthStorage(); const apolloClient = createApolloClient(authStorage); const App = () => { return ( <NativeRouter> <ApolloProvider client={apolloClient}> <AuthStorageContext.Provider value={authStorage}> <Main /> </AuthStorageContext.Provider> </ApolloProvider> </NativeRouter> ); }; export default App; يمكن الوصول إلى نسخة ذاكرة التخزين في دالة الخطاف useSignIn باستخدام الخطاف useContext العائد للمكتبة React على النحو التالي: // ... import { useContext } from 'react'; import AuthStorageContext from '../contexts/AuthStorageContext'; const useSignIn = () => { const authStorage = useContext(AuthStorageContext); // ... }; انتبه إلى أنه من غير الممكن الولوج إلى القيمة التي يعيدها سياق العمل باستخدام الخطاف useContext مالم يُستخدم هذا الخطاف في مكوّن ابن للمكون Context.Provider. يُعد الوصول إلى نسخة ذاكرة التخزين باستخدام (useContext(AuthStorageContext مطولًا تمامًا ويكشف عن تفاصيل التنفيذ. دعنا نحسن هذا من خلال تنفيذ خطاف useAuthStorage في ملف "useAuthStorage.js" في مجلد "hooks": import { useContext } from 'react'; import AuthStorageContext from '../contexts/AuthStorageContext'; const useAuthStorage = () => { return useContext(AuthStorageContext); }; export default useAuthStorage; يعد تنفيذ الخطاف بسيطًا جدًا ولكنه يحسن إمكانية قراءة الخطافات والمكونات التي تستخدمها وصيانتها. يمكننا استخدام الخطاف لإعادة تشكيل خطاف useSignIn كما يلي: // ... import useAuthStorage from '../hooks/useAuthStorage'; const useSignIn = () => { const authStorage = useAuthStorage(); // ... }; ستجعل إمكانية توزيع البيانات على المكونات الأبناء من React Context مفتاحًا لحل عدد هائل من الحالات. لتطلع أكثر على هذه الحالات، اقرأ المقالة How to use React Context effectively للمؤلف "Kent C. Dodd"، لتعرف كيف توافق بين استخدام الخطاف useReducer وReact context لتنفيذ آلية لإدارة الحالة. وربما ستجد هذا مفيدًا لحل التمارين القادمة. التمرينان 10.15 و 10.16 10.15: تخزين شهادة التحقق- الخطوة 2 حسّن شيفرة الخطاف useSignIn لكي يخزّن شهادة التحقق التي تنتج عن الطفرة authenticate، بحيث لا تتغير القيمة التي يعيدها الخطاف. ينبغي أن يكون التغيير الوحيد في المكوّن SignIn هو تحويل المستخدم إلى واجهة عرض قائمة المستودعات بعد أن يسجل دخوله بنجاح. يمكنك إنجاز ذلك باستخدام الخطاف useNavigate. عليك أن تعيد ضبط مخزن عميل Apollo بعد تنفيذ الطفرة authenticate وتخزين شهادة التحقق في ذاكرة التخزين. سيسبب ذلك مسح الذاكرة المؤقتة وإعادة تنفيذ كل الطلبات النشطة. يمكن إنجاز ذلك باستخدام التابع resetStore العائد للمكتبة Apollo Client. يمكن الوصول إلى عميل Apollo عبر الخطاف useSignIn باستخدام الخطاف useApolloClient. وانتبه إلى أنّ ترتيب خطوات التنفيذ مهم جدًا وينبغي أن يكون على النحو التالي: const { data } = await mutate(/* خيارات */); await authStorage.setAccessToken(/* شهادة التحقق مأخوذة من البيانات */); apolloClient.resetStore(); 10.16: تسجيل الخروج ستكون الخطوة الأخيرة هي تنفيذ ميزة تسجيل الخروج. يمكن استخدام الاستعلام me للتحقق من بيانات الشخص الذي سجّل دخوله. فإن كانت نتيجة الاستعلام "null" فلن يكون الشخص مخوّلًا بالوصول. شغّل أرضية عمل Apollo، ثم نفّذ الاستعلام التالي: { me { id username } } ستكون النتيجة غالبًا "null"، والسبب في ذلك أنّ أرضية عمل Apollo غير مفوّضة بالوصول. ويعني ذلك أنها لم ترسل شهادة تحقق مع الطلب. راجع توثيق الاستيثاق لتفهم آلية استخلاص شهادة تحقق من الطفرة authenticate. استخدم هذه الشهادة في ترويسة الاستيثاق كما هو موّضح في التوثيق. نفّذ بعد ذلك الاستعلام me من جديد وسترى معلومات المستخدم الذي سجّل دخوله. افتح الملف "AppBar.jsx" الذي يحتوي على المكوّنAppBar والذي يحتوي بدوره على النافذتين "Sign in" و"Repositories". عدّل النوافذ بحيث تظهر النافذة "Sign out" إن سجل المستخدم دخوله، والنافذة "Sign in" إن سجّل خروجه. يمكنك إنجاز ذلك باستخدام الاستعلام me مع الخطاف useQuery. من المفترض أن تُحذف شهادة التحقق من ذاكرة التخزين عند الضغط على النافذة "Sign out"، وأن يُعاد ضبط مخزن عميل Apollo باستخدام التابع resetStore، إذ سيُعاد تنفيذ كل الاستعلامات النشطة تلقائيًا عند استدعاء التابع resetStore، ويعني ذلك إعادة تنفيذ الاستعلام me. تذكّر أن ترتيب خطوات التنفيذ مهم جدًا، ويجب إزالة شهادة التحقق من ذاكرة التخزين قبل إعادة ضبط مخزن عميل Apollo. ترجمة -وبتصرف- للفصل Communicating with server من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: أساسيات React Native مدخل إلى React Native مدخل إلى التحريك في React Native الاتصال مع الخادم في تطبيق React معتمد على Redux
  4. الآن وبعد أن كتبنا تطبيقًا جيدًا، قد حان الوقت لنشره وتوزيعه على المستخدمين الفعليين. لقد فعلنا ذلك في القسم 3 بدفع مستودع git إلى خوادم الاستضافة السحابية Heroku بكل بساطة. تُعد عملية إصدار برمجيات على منصة هيروكو Heroku أمرًا بسيطًا موازنةً بغيرها من الاستضافات، لكن لا تزال هناك طبعًا بعض المخاطر، فلا شيء سيمنعنا من الدفع بشيفرة لا تعمل إلى وضع الإنتاج عن طريق الخطأ. سنتعرف في الفقرات القادمة على مبادئ النشر الآمن للتطبيقات، ومبادئ نشر البرمجيات بالمقاييس الصغيرة والواسعة. يمكن لأي شيء أن يحدث خطأ نريد تحديد بعض القواعد التي تضبط عملية نشرنا للتطبيقات، لكن علينا بداية إلقاء نظرةٍ على بعض المحدوديات الواقعية: "إن أمكن لشيءٍ ما أن يخفق، فسيخفق": هي عبارة يتضمنها قانون مورفي، ومن المهم تذكرها دائمًا عند التخطيط لمنظومة النشر التي سنتبعها، ومن الأشياء التي ينبغي أخذها بالحسبان أيضًا: ماذا لو توقف الحاسوب عن العمل أثناء نشر التطبيق؟ ماذا سيحدث إن انقطع الاتصال بالإنترنت أثناء نشر التطبيق؟ ماذا سيحدث إن أخفقت أية تعليمات من سكربت أو منظومة النشر؟ ماذا سيحدث إن لم يعمل تطبيقي، لسببٍ أو لآخر، على الخادم بعد نشره؟ هل يمكنني التراجع rollback إلى النسخة السابقة؟ ماذا سيحدث إذ أرسل مستخدم ما طلب HTTP إلى التطبيق قبل أن يكتمل نشره (لا يوجد وقتٌ لإرسال استجابة له)؟ هذه عينة صغيرة من المشاكل التي قد تواجهك أثناء النشر أو بالأحرى عينة من الأمور التي ينبغي التخطيط لها. لا ينبغي لمنظومة النشر التي نعتمدها أن تترك البرنامج في حالة إخفاق أيًا كان سببه، كما ينبغي علينا أن نعرف (أو أن نجد بسهولة) حالة منظومة النشر. وطالما نتحدث عن النشر وعن التكامل المستمر CI عمومًا، هناك قاعدةٌ مهمةٌ أخرى عليك تذكرها: "الأخطاء الصامتة قاتلة". لا يعني هذا طبعًا عرض الأخطاء على مستخدم البرنامج، بل يعني أنه يجب علينا الانتباه إلى أي شيء قد يخفق. فلو كنا على دراية بمشكلة محتملة الوقوع، يمكننا إصلاحها. فإن لم تعطي منظومة النشر أية أخطاء لكنها فشلت، سنصل إلى المرحلة التي نعتقد فيها أننا أصلحنا كل الأخطاء الحرجة ومع ذلك تخفق المنظومة، وبالتالي سنترك الثغرة في بيئة الإنتاج غير مدركين لخطورة الوضع. ما الذي تمنحه منظومة النشر الجيدة؟ من الصعب وضع قواعد محددة أو متطلبات خاصة بمنظومة النشر، لكننا سنحاول ذلك: عندما تخفق المنظومة في أية خطوة، يجب أن تخفق دون أية آثار جانبية. لا ينبغي أبدًا أن تترك المنظومة البرنامج في حالة فشل. ينبغي أن تخبرنا المنظومة عن أية حالات إخفاق، فمن الأفضل تنبيهنا إلى حالات الإخفاق عوضًا عن النجاح. ينبغي على المنظومة أن تسمح لنا بالتراجع إلى النسخة المنشورة سابقًا. يفضل أن نتراجع بسهولة إلى نسخة أقل عرضة للإخفاق بالموازنة مع النسخة المنشورة كاملةً. يبقى الخيار الأفضل لنا هو التراجع الآلي في حال أخفق النشر. ينبغي أن تكون المنظومة قادرةً على التعامل مع طلبات HTTP قبل انتهاء أو أثناء عملية النشر. ينبغي أن تتأكد المنظومة أنّ البرنامج الذي ننشره سيلبّي المتطلبات التي وضعناها لعملية النشر (لا تنشر مثلًا برنامج أخفق في أحد الاختبارات). لنحدد أيضًا بعض الأشياء التي نريدها في منظومة النشر الافتراضية التي نقترحها: نريدها أن تكون سريعة. لا نريد وقتًا يتوقف فيه البرنامج عن العمل downtime أثناء النشر (هذا أمر مختلف عن معالجة طلبات المستخدمين قبل انتهاء أو أثناء النشر). التمارين 11.10 - 11.12 قبل أن نبدأ بالتمارين عليك إعداد تطبيقك لبيئة عمل هيروكو Heroku. وهنا لن ندفع الشيفرة بأنفسنا، إذ سينفِّذ مخطط عمل GitHub Actions المهمة من أجلنا. تأكد من تثبيت Heroku CLI ثم سجِّل دخولك مستخدمًا واجهة سطر الأوامر CLI عن طريق heroku login. أنشئ تطبيقًا على هيروكو HeroKu باستخدام الأمر: heroku create --region eu {your-app-name}‎ وانتق منطقةً قريبةً من موقعك الجغرافي. ولِّد شهادة تحقق Token لملفك على Heroku باستخدام الأمر: heroku authorizations:create ثم خزّن معلومات الاستيثاق على ملف ضمن حاسوبك لكن لا تدفعه إلى GitHub. ستحتاج إلى شهادة التحقق من أجل مخطط عمل نشر التطبيق. اطلع أكثر على شهادة تحقق هيروكو عبر الإنترنت. 11.10: نشر تطبيقك على منصة هيروكو Heroku وسّع مخطط العمل بخطوة لنشر تطبيقك على منصة هيروكو Heroku. نفترض فيما سيأتي أنك ستستخدم AkhileshNS/heroku-deploy وهو فعل GitHub Actions الخاص بالنشر على هيروكو والذي طوره مجتمع GitHub Actions. تحتاج إلى شهادة التفويض التي حصلت عليها سابقًا من أجل نشر تطبيقك. ومن الأفضل تمرير قيمتها إلى GitHub Actions باستخدام أسرار المستودع repository secrets: يمكنك الآن الوصول إلى قيمة الشهادة على النحو التالي: ${{secrets.HEROKU_API_KEY}} إذا جرى كل شيء على ما يرام، سيبدو مخطط العمل على الشكل التالي: جرِّب تطبيقك عبر متصفح، لكن الأخطاء ستظهر غالبًا. سنجد أنّ منصة هيروكو تفترض وجود الملف "Procfile" في المستودع والذي يوجّهه لطريقة تشغيل البرنامج. أضف إذًا ملف "Procfile" مناسب إلى المستودع وتأكد أنّ التطبيق سيعمل جيدًا. تذكرة: راقب باستمرار ما يحدث عبر سِجِل الخادم عندما تجرب عملية النشر. استخدم لذلك الأمر heroku logs دائمًا. 11.11: التحقق من عمل التطبيق قبل التوسّع أكثر في التطبيق، تحقق أن التطبيق يعمل جيدًا بعد النشر. لا نحتاج في الواقع لخطوة جديدة في مخطط العمل، إذ يحتوي الفعل deploy-to-heroku على خيار يفي بالغرض. أضف وصلة تخديم end point بسيطة مهمتها التحقق من عمل التطبيق في الواجهة الخلفية. ويمكنك أيضًا نسخ الشيفرة التالية: app.get('/health', (req, res) => { res.send('ok') }) من الجيد أيضًا وجود وصلة تخديم اختبارية في التطبيق، لكي يمتلك إمكانية إجراء بعض التعديلات في الشيفرة ويتأكد من أن التغيرات قد ظهرت أيضًا في النسخة المنشورة: app.get('/version', (req, res) => { res.send('1') // غير هذه القيمة للتأكد من أنها نُشرت في النسخة الجديدة }) راجع التوثيق لتعرف كيف ستضم آلية التحقق من عمل التطبيق إلى خطوة النشر، واستخدم عنوان وصلة التخديم التي أنشأتها للتحقق من عمل التطبيق، وقد تحتاج غالبًا إلى الخيار "checkstring" حتى يُنفَّذ الأمر. تأكد من أنّ GitHub Actions سينتبه إذا ما سبب النشر إخفاق التطبيق. استخدم لاختبار ذلك أمر إقلاع خاطئ مثلًا في الملف "Procfile". قبل الانتقال إلى التمرين التالي، أصلح مشاكل خطوة النشر وتأكد أن التطبيق سيعمل بالشكل المطلوب مجددًا. 11.12: التراجع من الأفضل إذا أخفق التطبيق بعد النشر أن تتراجع إلى الإصدار السابق. ولحسن الحظ، يجعل هيروكو Heroku هذا الأمر بسيطًا جدًا. ينتج عن كل عملية نشر على Heroku إصدار، ويمكنك معرفة الإصدارات الموجودة لتطبيق بتنفيذ الأمر heroku releases: $ heroku releases === calm-wildwood-40210 Releases - Current: v8 v8 Deploy de15fc2b mluukkai@iki.fi 2022/03/02 19:14:22 +0200 (~ 8m ago) v7 Deploy 8748a04e mluukkai@iki.fi 2022/03/02 19:06:28 +0200 (~ 16m ago) v6 Deploy a617a93d mluukkai@iki.fi 2022/03/02 19:00:02 +0200 (~ 23m ago) v5 Deploy 70f9b219 mluukkai@iki.fi 2022/03/02 18:48:47 +0200 (~ 34m ago) v4 Deploy 0b2db00d mluukkai@iki.fi 2022/03/02 17:53:24 +0200 (~ 1h ago) v3 Deploy f1cd250b mluukkai@iki.fi 2022/03/02 17:44:32 +0200 (~ 1h ago) v2 Enable Logplex mluukkai@iki.fi 2022/03/02 17:00:26 +0200 (~ 2h ago) v1 Initial release mluukkai@iki.fi 2022/03/02 17:00:25 +0200 (~ 2h ago) يمكن التراجع إلى إصدار محدد بكتابة أمر واحد ضمن سطر الأوامر، والأفضل من ذلك سيتولى الفعل deploy-to-heroku مهمة التراجع نيابةً عنا. اقرأ توثيق GitHub Actions مجددًا وعدّل مخطط العمل لتمنع إخفاق التطبيق عند النشر. يمكنك محاكاة الأمر أيضًا بكتابة أمر خاطئ في الملف "Procfile" والتجربة: تحقق أنّ التطبيق سيستمر في العمل حتى لو أخفق النشر. تنبيه: على الرغم من إمكانية التراجع التلقائي، قد يخفق البناء في العالم الحقيقي. لذلك يُعد إيجاد سبب المشكلة وإصلاحها بسرعة أمرًا جوهريًا. ويبقى سجل هيروكو Heroku عادةً هو المكان الأنسب للبحث والتقصي عن المسببات: ترجمة -وبتصرف- للفصل Deployment من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: استخدام GitHub Actions لتحقيق التكامل المستمر والنشر المستمر نشر تطبيقات الويب الموجهة لبيئة الإنتاج نشر تطبيقات iOS على متجر Apple Store
  5. كيف سيبدو موقع الويب الذي تبنيه؟ يناقش هذا المقال أعمال التخطيط والتصميم التي تجري قبل كتابة الشيفرة بما في ذلك المعلومات التي سيقدّمها الموقع وخطوط الكتابة والألوان والوظيفة التي ينجزها الموقع. التخطيط قبل كل شيء لا بد من تجميع بعض الأفكار قبل أن تبدأ بأيّ شيء، أي ما الذي سيقدِّمه موقعك؟ فبإمكانك برمجة موقع الويب ليفعل أيّ شيء تقريبًا، لكن وطالما أنها تجربتك الأولى، فلا بد أن تُبقي الأمور بسيطةً قدر المستطاع، لذلك سنبدأ ببناء صفحة ويب بسيطة بعنوان وصورة وبعض المقاطع النصية، وقبل أن نبدأ لا بد من الإجابة على الأسئلة التالية: ما الموضوع الذي يدور حوله هذا الموقع؟ هل يدور حول الحيوانات الأليفة أو حول مدينة محددة أو شخصية ما. ما المعلومات التي ستقدِّمها حول هذا الموضوع؟ اكتب عنوانًا وبعض الفقرات ثم فكّر بصورة مناسبة لتعرضها على الصفحة. كيف يبدو موقعك؟ ماهو لون الخلفية؟ ما هي أنواع خطوط الكتابة المناسبة؟ ملاحظة: تحتاج المشاريع الأكثر تعقيدًا إلى تفاصيل أكثر تتعلق بالألوان وخطوط الكتابة والفراغات ما بين العناصر في الصفحة وأسلوب الكتابة الملائم وهكذا، إذ تُدعى هذه التفاصيل عادةً بدليل التصميم design guide أو نظام التصميم أو دليل المنتج، كما يمكنك الاطلاع على أمثلة عن ذلك في معرض فايرفوكس للتصاميم. رسم الخطوط الأولى لتصميمك أمسك ورقةً وقلمًا وحاول رسم شكل الموقع الذي تريده، إذ لن تجد الكثير لرسمه في الصفحة البسيطة التي سنبنيها، لكن من الأفضل أن تعتاد الأمر منذ اللحظة، إذ سيساعدك ذلك كثيرًا، ولا حاجة بالطبع إلى رسم متقن. ملاحظة: يبدأ المصممون برسم تصوراتهم عن الموقع رسمًا تقريبيًا على ورقة مهما كان معقدًا، ثم يبنون نسخةً رقميةً باستخدام محرر رسومي أو تقنيات ويب أخرى، وغالبًا ما يضم فريق ويب مصممي رسوميات ومصممي تجربة المستخدِم، إذ يضع مصممي الرسوميات (الغرافيك) التصور المرئي للموقع، بينما تقتصر مهمة مصممي تجربة المستخدِم على تصوّر تجربة المستخدِم لهذا الموقع وطبيعة تفاعله معه وتوجيه التصميم لتحقيق التجربة الأفضل. اختيار المواد المساعدة من الأفضل أن تبدأ بتجميع المحتوى الذي ستعرضه على موقعك في هذه المرحلة. النصوص لا بد أن يكون عنوان الصفحة والمقاطع النصية التي ستعرضها محضرة مسبقًا، لذا تأكد من ذلك. السمة اللونية للصفحة انتق لونًا مناسبًا باستخدام أيّ أداة لانتقاء الألوان، فعندما تنقر على اللون المطلوب، فسترى ستة محارف تشبه الرمز التالي 6600AB# عادةً، إذ يُعَدّ هذا الرمز رمزًا ست عشريًا يمثل اللون، وبعدها انسخ هذا الرمز واحفظه في مكان يسهل عليك العودة له لاحقًا. الصور استخدم محرك البحث الذي تراه مناسبًا لإيجاد الصور المناسبة لموقعك. انقر على الصورة حين تجدها لعرضها بأبعاد أكبر. انقر بالزر اليميني على الصورة (أو انقر عليها مع ضغط زر Ctrl في ماك) ثم اختر "حفظ الصورة باسم Save Image As" وانتق مكانًا مناسبًا على جهازك لحفظها فيه، كما يمكنك نسخ عنوان الصورة من شريط عنوان المتصفح وحفظه لاستخدامات لاحقة. انتبه إلى أنّ معظم الصور الموجودة على ويب محمية بحقوق نشر معيّنة، ولكن يمكنك استخدام مرشّح رخص الاستخدام من جوجل Google's license filter مثلًا إذا كنت تستخدم "صور جوجل Google Images" في البحث وذلك للتقليل من مشاكل خرق هذه الحقوق، ثم انقر على زر "أدوات Tools" ثم اختر "التراخيص الإبداعية العامة Creative Commons licenses" من قائمة "حقوق الاستخدام Usage Rights". خطوط الكتابة لاختيار خط كتابة معيّن: انتقل إلى خطوط الكتابة من جوجل Google Fonts" واعثر على الخط المناسب. انسخ أسطر الشيفرة التي يزوّدك بها جوجل إلى المحرر النصي لديك واحفظها لاستخدامات لاحقة. ترجمة -وبتصرف- للمقال ?What will your website look like. اقرأ أيضًا المقال السابق: تثبيت البرمجيات الأساسية للانطلاق في تطوير الويب أفضل 12 أداة انتقاء للألوان لمصممي الويب الألوان في تصميم الرسوميات ونظرية الألوان الحركات في تصميم الويب: لماذا نستخدمها ومتى؟ فلسفة تصميم الويب المتجاوب
  6. سنلقي نظرةً قبل أن نبدأ التعامل مع GitHub Actions على ماهيته والطريقة التي يعمل بها. يعمل GitHub Actions على مبدأ مخططات العمل workflows؛ ومخطط العمل هو سلسلة من الأعمال التي تُنفَّذ عندما يقع حدثٌ معين، وتتضمن هذه الأعمال بحد ذاتها التعليمات التي يجب أن يُنفّذها GitHub Actions. سيبدو تنفيذ مخطط عمل نموذجي على النحو التالي: وقوع حدثٌ ما، مثل دفع push شيفرة إلى الفرع الرئيسي. البدء بتنفيذ مخطط العمل. الإنهاء والتنظيف. الاحتياجات الأساسية نحتاج عمومًا إلى المتطلبات التالية لتشغيل منظومة التكامل المتواصل Continuous Integration -أو اختصارًا CI- ضمن مستودع: مستودع. بعض التعريفات بالمهام التي ستنفذها منظومة CI، وقد يكون ذلك على هيئة ملف ضمن المستودع، أو يمكن أن يُعرَّف ضمن منظومة CI. يجب أن تعرف المنظومة أنّ المستودع (والملف في داخله) موجودٌ فعلًا. تحتاج المنظومة إلى الأذونات اللازمة لتنفيذ الأفعال التي يفترض أن تُنفذها، فلو أردنا من المنظومة أن تكون قادرةً على النشر في بيئة الإنتاج مثلًا، فستحتاج إلى بيانات الاستيثاق الخاصة بهذه البيئة. سنحتاج ما ذكرناه على الأقل في النموذج التقليدي للمنظومة. سنرى لاحقًا كيفية اختصار بعض الخطوات أو تنفيذها بطريقة مريحة لا تسبب لك أية مشاكل تقلق منها. لاستضافة GitHub Actions إيجابياتٌ عظيمة بالموازنة مع الاستضافة الذاتية؛ إذ سيُستضاف المستودع مع مزوِّد لمنظومة CI، أي سيؤمن لك GitHub Actions المستودع ومنظومة CI معًا، ويعني ذلك أننا عندما نُمكِّن الأفعال ضمن المستودع، سيكون GitHub Actions على علم مسبقًا بأنه لدينا مخططات عمل مُعرًّفة، وبما تعنيه هذه التعريفات. التمرين 11.2 سننفذ في معظم تمرينات هذا القسم خط إنتاج لمنظومة CI/CD من أجل المشروع الصغير الموجود على غيت هب GitHub. تنبيه: قد لا تعمل الشيفرة مع الإصدار 15 من Node، وإذا حدث ذلك ولم يُقلع المشروع، انتقل للعمل على الإصدار 14 وإلا عليك حل مشاكلك بنفسك. المشروع النموذجي عليك أولًا إنشاء نسخةٍ من مستودع المشروع ضمن حسابك الخاص ولاستخدامك الشخصي. لاشتقاق المستودع، انقر على الزر "Fork" في أعلى ويمين واجهة المستودع بجانب الزر "Star": سيبدأ بعد ذلك بإنشاء مستودع جديد يُدعى "github_username}/full-stack-open-pokedex}"، وستُنقل بعد انتهاء العملية إلى مستودعك الجديد تلقائيًا: انسخ المشروع الآن إلى جهازك، وكما جرت العادة إبدأ بتفقد الملف "package.json" فهو المكان الأنسب للاطلاع على تفاصيل مشروع جديد. حاول أن تنفّذ ما يلي: تثبيت الاعتماديات باستخدام الأمر npm install. تشغيل الشيفرة في وضع التطوير. إجراء الاختبارات. تدقيق lint الشيفرة. قد تلاحظ وجود بعض أخطاء التدقيق والاختبارات المخفقة في المشروع، دعها كما هي حاليًا، إذ سنتكفل بحلها في التمارين القادمة. وكما ذكرنا في القسم 3، لا ينبغي تشغيل شيفرة React في وضع التطوير بعد نشرها في وضع الإنتاج، لذلك حاول أن تُنفِّذ ما يلي: أنشئ نسخة إنتاج من المشروع. شغل نسخة الإنتاج على جهازك محليًا. ستجد سكربتًا خاصًا لتنفيذ المهمتين السابقتين في المشروع. خذ وقتًا لدراسة هيكيلية المشروع. وكما ستلاحظ، فإن الواجهتين الأمامية والخلفية موجودتان في نفس المستودع، وقد اعتدنا في الأقسام الأولى على وجودهما في مستودعين منفصلين. لكن هذا الأمر سيبسط الأمور عند إعداد بيئة CI. ستجد بالمقابل أنّ الواجهة الأمامية في معظم مشاريع منهاجنا لم تُنفّذ باستخدام "create-react-app"، لكنها تمتلك إعدادات تهيئة بسيطة باستخدام webpack تتكفل بإنشاء بيئة التطوير وبإنشاء حزمة الإنتاج. التعامل مع مخططات العمل تُعد مخططات العمل الأساس الذي تبنى عليه منظومات CI في غيت هب GitHub، فهي مساراتٌ لعملية يمكنك إعدادها لتنفيذ مهام تلقائيًا، مثل بناء التطبيقات واختبارها وتدقيقها وإصدارها ونشرها. تبدو عادةً هيكلية مخططات العمل على النحو التالي: مخطط العمل مهمة خطوة خطوة مهمة خطوة ينبغي أن يحدد كل مخطط مهمةً واحدةً على الأقل تحتوي على خطوات لتنفيذ إجراءات مستقلة. ستُشغّل هذه المهمات على التوازي بينما تُنفًّذ الخطوات في كل مهمة على التتالي. تتنوع الخطوات من تنفيذ سطر أوامر محدد إلى الأفعال المعرَّفة مسبقًا، لهذا تحمل الاستضافة اسم أفعال غيت هب "GitHub Actions". يمكنك إنشاء الأفعال الخاصة بك أو أن تستخدم أفعالُا نشرها آخرون، وهي في الواقع كثيرة، وسنعود إليها لاحقًا. ينبغي أن تُحدِّد مخططات العمل الخاصة بك ضمن المجلد "github/workflows." في مستودعك كي يميزها غيت هب، ولكل مخطط عمل ملفٌ مستقلٌ خاصٌ به والذي يجب تهيئته باستخدام لغة تقسيم البيانات YAML. يُشتق الاسم YAML من العبارة "YAML Ain't Markup Language" والتي تعني "ليست لغة توصيف"؛ فكما تُلمّح إليه التسمية، فالهدف منها أن تكون مفهومةً للبشر. تُستخدم هذه اللغة في كتابة ملفات التهيئة، وستجد أنها سهلة الفهم فعلًا. عليك الانتباه إلى أهمية الانزياحات Indentation في بداية الأسطر البرمجية في YAML، وللاطلاع أكثر حول قواعد اللغة يمكنك الرجوع إلى شبكة الإنترنت. يتضمن مخطط العمل في مستند YAML هذه العناصر الثلاث: name الاسم: ويشير إلى اسم المخطط. triggers المُسبب: الأحداث التي تؤدي إلى تنفيذ المخطط. jobs المهام: المهام المختلفة التي سيُنفّذها المخطط، وقد يحتوي المخطط البسيط مهمةً واحدةً فقط. سيبدو تعريف مخطط بسيط على النحو التالي: name: Hello World! on: push: branches: - master jobs: hello_world_job: runs-on: ubuntu-20.04 steps: - name: Say hello run: | echo "Hello World!" وكما هو واضح، سيكون المُسبب هو عملية دفع الشيفرة إلى الفرع الرئيسي. يحتوي المخطط أيضًا على مهمة واحدة اسمها hello_world_job سيجري تنفيذها ضمن بيئة افتراضية تعمل على نظام التشغيل أوبنتو Ubuntu 20.04، وتتضمن هذه المهمة خطوة واحدة اسمها Say hello ستُنفِّذ الأمر "!echo "Hello World ضمن الصدفة shell. ربما تتساءل، متى يبدأ غيت هب بتنفيذ مخطط معين؟ هناك العديد من الخيارات المتاحة، لكن وبصراحة، يمكنك أن تهيئ المخطط ليعمل حالما: يقع حدث ما، مثل الحالة التي يدفع فيها أحدهم اعتمادًا commit إلى مستودع، أو عندما تحدث مشكلة أو يقدم أحدهم طلب سحب pull request. تُنفَّذ مهمةٌ مجدولةٌ مسبقًا ومحددة باستخدام تعابير cron. يقع حدث خارجي، كأن يُنفَّذ أمر ضمن تطبيق خارجي، مثل تطبيق الرسائل Slack. وللاطلاع على مزيدٍ من الأحداث المسببة لبدء تنفيذ مخطط عمل، عُد إلى توثيق GitHub Actions. التمرينان 11.3- 11.4 لنربط كل ما خلصنا إليه، دعونا نشغِّل GitHub Actions ضمن المشروع النموذجي. 11.3: تطبيق Hello world أنشئ مخططًا يُظهر العبارة "!Hello World" للمستخدم. عليك أن تنشئ المجلد "github/workflows."، والملف "hello.yml" الذي سيحتوي الإعدادات ضمن مستودعك. ولتطلع على ما أنجزه مخطط عمل GitHub Actions الخاص بك، يمكن التوجه إلى النافذة Action ضمن واجهة غيت هب GitHub، حيث من المفترض أن ترى مخطط العمل في مستودعك والخطوات التي أنجزها. ستبدو نتيجة تنفيذ مخططك على النحو التالي إن كانت تهيئة المخطط صحيحة: يُفترض أن ترى الرسالة "!Hello World" نتيجةً لتنفيذ المخطط، وإذا حدث ذلك، ستكون جميع الخطوات قد نُفِّذت بنجاح، وسيكون أول مخططات عمل GitHub Actions الخاصة بك قيد العمل. سيعطيك أيضًا GitHub Actions معلومات عن البيئة (نظام التشغيل، وإعداداته) التي يعمل ضمنها مخطط العمل. وتظهر أهمية ذلك أثناء حدوث أمر طارئ، إذ سيسهل هذا الأمر تنقيح الأخطاء إن استطعت تكرار كل الخطوات على جهازك. 11.4: التاريخ ومحتويات المجلد وسًع مخطط العمل لإضافة خطوات لطباعة التاريخ ومحتويات المجلد الحالي بالصياغة الطويلة long format. يمكن تنفيذ هاتين الخطوتين باستخدام الأمرين date و ls بكل بساطة. سيبدو مخطط عملك الآن على النحو التالي: وطالما أن الأمر ls -l سيُظهر افتراضيًا البيئة الافتراضية التي يعمل عليها مخطط العمل، ستلاحظ أنها لا تحتوي على أية شيفرات. إعداد وتجهيز خطوات التدقيق والاختبار والبناء بعد إنجاز التمارين الأولى، سيكون لدينا مخطط عمل بسيط لكنه لن يفيدنا في عملية الإعداد. لنجعل مخطط العمل قادرًا على فعل مهمة حقيقية. سننجز فعلًا action قادرًا على تدقيق الشيفرة. فإذا أخفق التدقيق، سيُظهر Github Actions الحالة الحمراء. سيبدو المخطط الذي سنخزنه ضمن الملف "pipeline.yml" مبدئيًا على النحو التالي: name: Deployment pipeline on: push: branches: - master jobs: قبل أن نتمكن من تنفيذ الأمر الذي سيبدأ خطوة التدقيق، لا بدّ من تنفيذ فعلين لإعداد البيئة الملائمة للمهمة. إعداد بيئة العمل إعداد بيئة العمل أمرٌ ضروري لتهيئة خط الإنتاج Pipeline، لذلك سنستخدم بيئة العمل الافتراضية Ubuntu 20.04 لأنها ستكون البيئة التي ستعمل عليها نسخة الإنتاج. ولا بدّ من تطابق البيئة نفسها في منظومة CI وفي وضع الإنتاج قدر المستطاع، لتحاشي الحالات التي تعمل فيها الشيفرة نفسها بصورةٍ مختلفة في كليهما، وبالتالي لن تتحقق الغاية من استخدام CI. سنوضح تاليًا الخطوات في مهمة "البناء" لكي تستطيع منظومة CI تنفيذها. وكما لاحظنا في التمارين السابقة، لن تحتوي بيئة العمل افتراضيًا أية شيفرات، لذلك لا بدّ من التحقق من الشيفرة من المستودع. هذه الخطوة سهلة وهي على النحو التالي: name: Deployment pipeline on: push: branches: - master jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 تُستخدم التعليمة uses لإخبار المخطط أن يُنفِّذ فعلًا محددًا. ويُعرَّف الفعل بأنه قطعة من الشيفرة قابلة لإعادة الاستخدام مثل الدوال، ويمكن تعريف الأفعال داخل المستودع ضمن ملف مستقل، أو استخدام الأفعال الموجودة في المستودعات العامة. سنستخدم هنا الفعل العام actions/checkout وبنسخة محددة هي "v3@" لتلافي فشل التعديلات إن جرى تحديث الفعل. ويُنفِّذ الفعل checkout ما يوحي به اسمه، إذ يتحقق من شيفرة المشروع المصدرية من git. وطالما أنّ التطبيق قد كتب باستخدام جافا سكربت، فلا بدّ من تهيئة "Node.js" لكي نتمكن من استخدام الأوامر الموجودة في الملف "package.json". ولإعداد "Node.js" يمكن استخدام الفعل actions/setup-node. سنختار الإصدار "16" لأنه الإصدار الذي تستخدمه بيئة الإنتاج. # name and trigger not shown anymore... jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' تُستخدم التعليمة with لإسناد معامل parameter إلى الفعل، إذ يحدد المعامل هنا نسخة Node.js التي ننوي استخدامها. أخيرًا، لا بُد من تثبيت الاعتماديات اللازمة. وكما تفعل عادةً على جهازك، نفِّذ الأمر npm install. ستبدو خطوات المهمة على النحو التالي: jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' - name: npm install run: npm install وهكذا ستكون البيئة الآن جاهزةً لأداء مهمة حقيقية ومهمة. التدقيق Lint يمكنك الآن تنفيذ السكربتات التي يحتويها الملف "package.json" كما لو أنك تنفذها على حاسوبك الشخصي، فكل ما عليك فعله لتدقيق الشيفرة، هو إضافة إعدادٍ لتشغيل الأمر npm run eslint: jobs: simple_deployment_pipeline: runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v2 with: node-version: '16' - name: npm install run: npm install - name: lint run: npm run eslint التمرينات 11.5 - 11.9 11.5: تدقيق مخطط عمل نفّذ أو انسخ والصق مخطط العمل "Lint" واعتمد شيفرته في مستودعك، ثم أنشئ ملف yml جديد لهذا المخطط، يمكنك تسميته "pipeline.yml". ادفع بشيفرتك إلى الفرع الرئيسي ثم توجه إلى النافذة "ِActions" وانقر على المخطط الذي أنشأته على اليسار. ستجد أن هذا المخطط سيفشل في الإقلاع: 11.6: إصلاح الشيفرة ستجد بعض المشاكل في الشيفرة تتطلب الإصلاح. افتح سِجِل مخطط العمل وتحقق من وجود أخطاء. إليك تليمحين مهمين: من الأفضل أن تصلح أحد الأخطاء بتحديد ملف مناسب لعملية التدقيق (راجع القسم الثالث لمزيد من المعلومات عن كيفية تنفيذ ذلك)؛ كما يمكن إيقاف أحد الاعتراضات التي تخص تنفيذ الأمر console.log بإيقاف القاعدة التي تسببه في السطر الذي توجد به. أجرِ التعديلات اللازمة على الشيفرة المصدرية لكي ينجح مخطط العمل في الإقلاع، وحالما تعتمد الشيفرة الجديدة سيعمل المخطط وستجد خرجًا مُحدَّثًا باللون الأخضر من جديد. 11.7: البناء والاختبار لنوسِّع مخطط العمل الذي يُنفِّذ حاليًا مهمة التدقيق. أضف أوامر البناء والاختبار إلى مخطط العمل، وستبدو النتيجة قريبةً من التالي: ستلاحظ أيضًا وجود بعض المشاكل. 11.8: العودة إلى الوضع الصحيح تحقق من الاختبارات التي أخفقت وأصلح المشكلة في الشيفرة (لا تُغيّر الاختبارات). سيعمل المخطط ويظهر الخرج باللون الأخضر مجددًا عند إصلاح المشاكل. 11.9: اختبار مشترك بسيط للواجهتين تستخدم مجموعة الاختبارات الحالية jest لتتأكد من عمل مكونات React بالطريقة المطلوبة، وهذا تمامًا ما فعلناه في فصل "اختبار تطبيقات React" من القسم 5. يُعد اختبار كل مكوًن بصورةٍ منفصلة أمرًا مفيدًا لكنه لا يضمن عمل كل النظام بالطريقة المطلوبة. وللتأكد أكثر، سنكتب اختبارًا بسيطًا مشتركًا بين الواجهتين الأمامية والخلفية end to end testing، مستخدمين المكتبة Cypress وعلى نحوٍ مشابه للعمل الذي أنجزناه في الفصل الذي يحمل العنوان "الاختبار المشترك للواجهتين" في القسم 5. سنهيئ cypress (ستجد الطريقة في الفصل الذي أشرنا إليه)، ثم سننفذ الاختبار التالي: describe('Pokedex', function() { it('front page can be opened', function() { cy.visit('http://localhost:5000') cy.contains('ivysaur') cy.contains('Pokémon and Pokémon character names are trademarks of Nintendo.') }) }) عرِّف سكربت npm التالي: test:e2e لتشغيل الاختبار المشترك للواجهتين "e2e" باستخدام سطر الأوامر. تنبيه: لا تستخدم الكلمة "spec" في تسمية ملف اختبار cypress، لأنها ستجعل jest ينفذ شيفرة الملف أيضًا، وقد يسبب ذلك عدة مشاكل. تنبيه آخر: على الرغم من قدرة الصفحة على تصيير أسماء "مخلوقات البوكيمون Pokemon" لتبدأ بأحرف كبيرة، إلا أنها مكتوبةٌ بأحرف صغيرة في المصدر، فاسم البوكيمون "Ivysaur" هو أصلًا "ivysaur" تحقق من نجاح الاختبار على جهازك، وتذكر أن الاختبارات ستفترض أن تطبيقك يعمل عندما تُنفِّذ الاختبار. وإن كنت قد نسيت بعض التفاصيل، راجع القسم 5. حالما يعمل الاختبار المشترك للواجهتين على جهازك، ضعه في مخطط عمل GitHub Action، وأسهل الطرق لتنفيذ ذلك هو استخدام الفعل الجاهز cypress-io/github-action، وستكون الخطوة المناسبة لحالتنا على النحو التالي: - name: e2e tests uses: cypress-io/github-action@v2 with: command: npm run test:e2e start: npm run start-prod wait-on: http://localhost:5000 لقد استخدمنا ثلاثة خيارات: command: ويحدد كيف سنشغل اختبار cypress. start: يزودنا بسكربت npm الذي يُشغِّل الخادم. wait-on: يمنع الاختبار من العمل قبل أن يقلع الخادم على العنوان http://localhost:5000. عندما تتأكد من عمل خط الإنتاج، اكتب اختبارًا آخر للتأكد أنّ المستخدم قادرٌ على الانتقال من الصفحة الرئيسية إلى صفحة "بوكيمون" محدد مثل "ivysaur". لا حاجة لتعقيد الاختبار، بل تأكد فقط أن الصفحة التي تنتقل إليها بنقر الرابط، ستحتوي بعض المعلومات الصحيحة مثل النص "chlorophyll" في حالة البوكيمون "ivysaur". ملاحظة: تُكتب أسماء البوكيمون بالأحرف الصغيرة، ويمكن الكتابة بالأحرف الكبيرة في CSS، لذلك لا تكتب أثناء البحث الاسم "Chlorophyll"، بل اكتب "chlorophyll". ملاحظة: لا تحاول الانتقال إلى صفحة البوكيمون "bulbasaur"، فربما لسببٍ ما لن تعمل صفحة هذا البوكيمون. ستبدو النتيجة النهائية على الشكل التالي: إن الأمر الجيد المتعلق بالاختبار المشترك للواجهتين هو الثقة بأنّ البرنامج سيعمل على نحوٍ جيد من وجهة نظر المستخدم النهائي. لكن سيكون الثمن الذي تدفعه بالمقابل هو الاستجابة البطيئة، إذ سيستغرق تنفيذ مخطط العمل بالكامل وقتًا أطول بكثير. ترجمة -وبتصرف- للفصل Getting started with GitHub Actions من سلسلة Deep Dive Into Modern Web Development. اقرأ أيضًا المقال السابق: مدخل إلى التكامل المستمر والنشر المستمر CI/CD التكامل المستمر: تثبيت Concourse CI على أوبنتو إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls إعادة تأسيس تفريعات طلب السحب وتحديثه في git
  7. سنعرض في هذا المقال الأدوات التي تلزم في عملية تطوير موقع ويب بسيط وكيفية تثبيتها تثبيتًا صحيحًا. الأدوات التي يستخدمها المحترفون حاسوب: قد يبدو الأمر بديهيًا للبعض، لكن البعض الآخر لا يستخدِمه فعليًا، فهو يقرأ هذا المقال عن طريق الهاتف الجوال أو عبر حاسوب مكتبة عامة، أي لا بد من امتلاك حاسوب مكتبي أو محمول يعمل على ويندوز أو ماك أو لينوكس إذا قررت أن تكون مطور ويب حقيقي. محرر نصي: يساعدك في كتابة الشيفرة، وقد يكون نصيًا تمامًا مثل فجيوال ستديو كود Visual Studio Code أو نوت باد بلس بلس ++Notepad، أو هجينًا مثل دريم ويفر Dreamweaver وويب ستورم WebStorm، ولن تناسبك محررات النصوص المكتبية لأنها تعتمد على عناصر خفية تتداخل مع محركات التصيير التي تستخدِمها المتصفحات لتنفيذ الشيفرة. متصفح ويب: لتخابر شيفرتك من خلاله، وستجد الكثير من المتصفحات لكن أكثرها استخدامًا فايرفوكس وكروم وأوبِرا وسفاري وإنترنت إكسبلورر ومايكروسوفت إيدج، ولا بد أيضًا من اختبار أداء صفحاتك على متصفحات الهواتف الجوّالة وعلى المتصفحات القديمة التي لاتزال جمهورك يستخدِمها مثل إنترنت إكسبلورر 8 و 10، كما سيساعدك لينكس linux - وهو متصفح يعتمد على طرفية تُقاد بالأوامر النصية- في اختبار تجربة المستخدِمين ذوي المشاكل البصرية لموقعك. محرر صور: لإعداد الصور والرسوم البيانية لموقعك. نظام لإدارة الإصدارات version control system: لإدارة الملفات على الخوادم أو التعاون مع فريق من المطورين على مشروع ومشاركة الشيفرة والدعم وتحاشي التضارب في عملية تحرير الشيفرة، تُعد حاليًا غت Git أكثر هذه الأنظمة شعبية مع خدمتي الاستضافة جيت هاب GitHub وجيت لاب GitLab. برنامج لنقل الملفات عبر بروتوكول FTP: ويُستخدَم للتعامل مع حسابات خوادم الاستضافة القديمة لإدارة الملفات عليها، لهذا تستبدل جيت هذا البروتوكول بوتيرة متزايدة، كما توجد هناك مجموعة أخرى من البرامج التي تعتمد FTP و FTPS مثل سايبر دك Cyberduck أو فيتش Fetch أو فايلزيلا FileZilla. برنامج أتمتة المهام automation system: مثل Webpack و Grunt و Gulp لتنفيذ المهام المتكررة مثل اختزال أو تصغير الشيفرة وإجراء الاختبارات. مكتبات وأطر عمل وغيرها لتسريع كتابة شيفرات المهام الشائعة، فعادةً ما تكون المكتبات على هيئة ملفات جافاسكربت أو CSS جاهزة لتأمين وظائف جاهزة لاستخدامها في الشيفرات، في حين يمثِّل إطار العمل منظومةً متكاملةً نوعًا، إذ يقدِّم الوظائفية السابقة مع بعض الصيغ المخصصة لكتابة تطبيقات ويب بناءً عليها. أدوات إضافية أخرى. الأدوات التي يحتاجها المطور المبتدئ قد تبدو هذه القائمة مخيفةً، لكنك في الواقع قادر على البدء دون استخدام أيٍّ منها، إذ تحتاج في الحد الأدنى إلى محرر نصي ومتصفح حديث. تثبيت المحرر النصي قد يكون المحرر مثبتًا أصلًا على حاسوبك مع نظام التشغيل مثل "نوتباد" Notepad في ويندوز و"تيكست إديت" TextEdit مع ماك أو إس macOS، كما تختلف المحررات النصية التي تأتي مع لينكس حسب النسخة، فيأتي مثلًا "غيت إديت" gedit مع أوبونتو، وقد تستفيد أكثر من محررات أفضل من المحررات السابقة لتطوير ويب، إذ ننصحك البدء بالمحرر "فيجوال استوديو كود" Visual Studio Code، وهو محرر مجاني يزودك بعروض مباشرة لنتائج شيفرتك وبعض التلميحات المتعلقة بكتابتها. تثبيت متصفح ويب حديث حاول تثبيت متصفحين مما سنعرض في هذه القائمة وفقًا لنظام التشغيل لديك، وجهزهما للاختبار: لينكس: فايرفوكس Firefox أو كروم Chrome، أو أوبرا Opera أو بريف Brave. ويندوز: فايرفوكس أو كروم أو أوبرا أو إنترنت إكسبلورر أو مايكروسوفت إيدج أو بريف، علمًا أنه يأتي إيدج افتراضيًا مع ويندوز 10، كما يمكنك تثبيت هذا المتصفح أو إكسبلورر 11 لنسخ ويندوز 7 وما بعد. ماك أو إس: فايرفوكس أو كروم أو أوبرا أو سفاري أو بريف، علمًا أنه يأتي سفاري افتراضيًا مع ماك أو إس أو نظام آي أو إس. ملاحظة: لا يتوافق إنترنت إكسبلورر مع بعض الميزات الحديثة لويب، وقد لا يتمكن من تنفيذ مشروعك، فلا داعي لأن تقلق بهذا الشأن أو أن تجعل مشروعك متوافقًا معه وخاصةً وأنت في مرحلة التعلم، لأن قلة قليلة من الأشخاص فقط هم من يستخدموه، وقد يتطلب التوافق مع هذا المتصفح في بعض المشاريع دعمًا خاصًا. تثبيت خادم ويب محلي لتجريب بعض المشاريع ستحتاج إلى خادم ويب لتحصل على النتيجة الصحيحة، اطلع على مقال "إعداد خادم اختبار محلي" لتفاصيل أكثر. ترجمة -وبتصرف- للمقال Installing basic software. اقرأ أيضًا المقال السابق: عالم الويب ومعاييره مدخل إلى خادم الويب دليل إعداد خادم ويب محلي خطوة بخطوة
  8. يقدِّم لك هذا المقال خلفيةً مفيدةً حول عالم الويب وظهوره والتقنيات المعيارية له وكيف تعمل معًا، كما يطلعك على تمّيز مهنة مطوري الويب وعن الممارسات العملية الأفضل التي عليك تعلّمها. موجز عن تاريخ ويب سنختصر الأمر قدر المستطاع لوجود الكثير من المعلومات المفصّلة عن تاريخ ويب خارج إطار هذا المقال والتي سنشير إليها لاحقًا، ويمكنك أيضًا البحث باستخدام أحد محركات البحث المفضلة لديك إذا كنت مهتمًا بتفاصيل أكثر. طوّر الجيش الأميريكي في ستينيات القرن الماضي شبكة اتصال دُعيت آربانت ARPANET، إذ يمكن عدّ هذه الشبكة هي البداية المبكرة لويب، وقد استخدمت تقنية تحويل أو تبديل حزم البيانات وشهدت أول تنفيذ لمجموعة بروتوكولات TCP/IP، كما تُشكِّل التقنيتين السابقتين البنية التحتية التي قامت عليها شبكة الإنترنت. كتب تيم برنرز-لي Tim Berners-Lee -ويشار إليه عادةً بالاسم TimBL- عام 1980 برنامجًا نصيًا دُعي "ENQUIRE" والذي مهَّد لمفهوم الربط بين العقد المختلفة، أيبدو مألوفًا؟ وبتسريع الوقت حتى عام 1989، إذ كتب تيم عملَين أحدهما بعنوان "مقترح لإدارة المعلومات Information Management: A Proposal" والآخر بعنوان النص التشعبي HyperText خلال عمله مستشارًا في المنظمة الأوروبية للطاقة النووية CERN، وقد قدّم هذان العملان خلفيةً معرفيةً عن الكيفية التي يفُتَرض أن تعمل بها ويب، كما وتلقى العملان كمًا لا بأس به من الاهتمام، وكان هذا كافيًا ليسمح له مديروه بمتابعة العمل نحو إنشاء منظومة نصوص تشعبية عالمية؛ أما بحلول عام 1990، فقد كان تيم قد أنشأ كل الأشياء الضرورية اللازمة لتشغيل النسخة الأولى لويب.بروتوكول HTTP ولغة HTML، بالإضافة إلى متصفح ويب الأول والذي دُعيَ حينها WorldWideWeb وخادم HTTP وبعض صفحات ويب لاستعراضها. توسّع عالم الويب بشدة في السنوات التي تلت مع ظهور عدد من المتصفحات الجديدة وإعداد آلاف خوادم ويب وكتابة ملايين الصفحات، ولا بد من الإشارة في هذه العجالة إلى تأسيس تيم لمجمّع World Wide Web Consortium واختصارًا W3C، وهي منظمة تجمع ممثلين عن شركات تقنية عالمية مختلفة للعمل معًا لوضع مواصفات ومعايير للويب، وبعد ذلك ظهرت تقنيات مثل CSS ومن ثم جافاسكربت وأخذت تبدو الويب بعدها شبيهةً بما هي عليه اليوم. معايير ويب تُعَدّ معايير ويب Web standards التقنيات التي نستخدِمها لبناء مواقع الويب، إذ تظهر هذه المعايير على هيئة مستندات تقنية طويلة تُدعى التوصيفات specifications والتي تفصّل تمامًا الطريقة التي ينبغي لتقنية ما العمل وفقها، كما لا تقدِّم هذه المستندات فائدةً كبيرةً في تعلّم استخدام التقنية التي تصفها ولذلك وُجِدت مواقع مثل موسوعة حسوب وتوثيق MDN التي تعرض التوثيقات بطريقة مختصرة ومبسطة، وإنما هي موجَّهة إلى مهندسِي البرمجيات لتطبيق هذه التقنيات، إذ يصف المستند HTML Living Standard على سبيل المثال كيفية تطبيق شيفرة HTML تمامًا، أي جميع عناصر اللغة، والواجهات البرمجية المرتبطة بها، وغير ذلك من التقنيات المحيطة بها. تُنشَأ معايير ويب من قِبَل هيئات قياسية مثل المنظمات والمعاهد التي تدعو تِقنيين من شركات مختلفة للاتفاق على أفضل الطرائق التي ينبغي أن تعمل وفقها التقنيات لتلبي احتياجاتهم، إذ تُعَدّ W3C من أهم هذه الهيئات، ونجد أيضًا WHATWG التي تصون وتطوِّر المعايير المستخدم للغة HTML، و ECMA التي تنشر معايير ECMAScript التي تُبنى عليها جافاسكربت، و Khronos التي تنشر تقنيات الرسوميات ثلاثية الأبعاد مثل WebGL وغيرها من الهيئات. المعايير مفتوحة المصدر لا بد أن تبقى الويب وتقنياتها مجانيةً للمساهمين في بنائها ومستخدِميها وغير خاضعة لبراءات الاختراع أو رخص الاستخدام، وهذا الموضوع هو الميزة الأساسية لمعايير ويب والتي وافق عليها تيم-لي ومجمّع W3C منذ البداية، لذلك يمكن لأيّ كان كتابة الشيفرات مجانًا لبناء موقع ويب، كما يمكن لأيّ كان المساهمة في عملية تطوير وإنشاء معايير ويب. لا يمكن لأي شركة التحكم بتقنيات الويب لأنها بُنيَت لتكون مفتوحة المصدر بالتعاون بين شركات مختلفة، وهذا أمر جيد حقًا، فلن ترغب مطلقًا أن تضع أيّ شركة قيودًا ماليةً على تقنيات ويب فجأة، أو أن تصدر نسخةً مدفوعةً من HTML عليك شرائها لتستمر في استخدامها، أو أن تقرر الشركة -في أسوأ سيناريو- أنّ الموضوع لم يَعُد يهمها ثم توقف العمل به، وبالتالي يسمح هذا الأمر ببقاء الويب وتقنياتها متاحةً مجانًا للجميع. لا تفكك الويب قد تسمع بمصطلح آخر يتعلق بمعايير ويب هو "لا تفكك الويب"، ويعني ذلك أنّ أيّ تقنية جديدة في عالم الويب لا بد وأن تكون متوافقةً مع ما بُني سابقًا -أي يجب استمرار مواقع الويب القديمة بالعمل-، ومع ما سيُبنى لاحقًا -أي أن التقنيات التي ستظهر لاحقًا لا بد أن تبقى متوافقة مع التقنيات الحالية-، ومع تقدمك في مسيرتك في التعلم ستعرف كيف يتحقق ذلك من خلال التصميم والتنفيذ الذكي لهذه المفاهيم. من الجيد أن تكون مطور ويب تُعَدّ صناعة الويب سوقًا ملفتًا ومهمًا إذا كنت تبحث عن عمل، وتشير الأرقام الحالية إلى وجود أكثر من 19 مليون مطور ويب في العالم، وسيتضاعف هذا العدد في العقد القادم، وفي الوقت ذاته، هناك نقص في الخبرات ضمن هذه الصناعة، لذلك فالوقت الآن مناسب جدًا من أجل تعلم تطوير مواقع ويب. لا تتعلق صناعة الويب فقط بأمور الترفيه والألعاب، وإنما يزداد تعقيد بناء مواقع الويب عما كان عليه، إذ عليك قضاء المزيد من الوقت في دراسة التقنيات المختلفة التي ستستخدِمها، وجميع الأساليب والممارسات العملية التي يجب تعلمها، والنماذج التقليدية التي سيطلب منك إنجازها، فقد تحتاج أشهرًا عدة لتبدأ باستيعابها، وبعد ذلك عليك الاستمرار في تعلم المزيد لكي تبقى معلوماتك مواكبةً لآخر التطورات بما في ذلك الأدوات والميزات الجديدة التي تظهر على منصات عمل ويب، كما عليك التمرن أكثر لصقل مهاراتك في هذه المهنة. هل يبدو الأمر صعبًا؟ نسعى في هذا السياق إلى منحك كل الإمكانات لتنطلق ومن ثم ستسهل بقية الأمور عليك، فحالما تعتنق مفهومَي التغيُّر والشك في عالم ويب، فستستمتع بما تفعله، وعلى أساس أنك فرد في مجتمع ويب، فستجد شبكةً كاملةً من المعارف والمواد القيّمة التي ستساعدك وسترى الإمكانات الإبداعية التي يوفّرها هذا العمل، كما ستغدو مبدعًا في العالم الرقمي، فاستمتع إذًا بهذه التجربة وبالمكاسب المحتملة التي ستحققها في تجربتك في تطوير الويب. نظرة على بعض تقنيات ويب العصرية لا بد أن تتعلم عددًا من التقنيات إذا قررت أن تصبح مطورًا للواجهات الأمامية، لذلك سنصف في هذه الفقرة هذه التقنيات باختصار. المتصفحات ربما تستخدِم الآن متصفحًا لقراءة هذا المقال، فالمتصفحات هي برمجيات يستخدِمها الناس ليستعرضوا محتويات الويب ويتفاعلوا معها مثل فايرفوكس وكروم وأوبرا وسفاري وإيدج. بروتوكول HTTP يُعَدّ بروتوكول نقل النص التشعبي Hypertext Transfer Protocol واختصارًا HTTP بروتوكولًا لنقل الرسائل التي تسمح للمتصفح بالتواصل مع خوادم ويب (المكان الذي تُثبت عليه مواقع الويب)، إذ تجري المحادثة النمطية بين المتصفح والخادم بصورة تشبه التالي: "Hello web server. Can you give me the files I need to render bbc.co.uk"? "Sure thing web browser — here you go" [Downloads files and renders web page] لا يمكن للبشر بالطبع قراءة الصيغة الفعلية لرسائل التواصل والتي تُدعى طلبات واستجابات، لكن قد يعطيك مثالنا السابق تصوّرًا عن العملية. HTML و CSS وجافاسكربت وهي التقنيات الرئيسية الثلاث التي سنستخدِمها لبناء مواقع ويب: HTML لغة ترميز النصوص التشعبية Hypertext markup language: وهي لغة ترميزية تتكون من عناصر مختلفة يمكن أن تُغلِّف محتوى ويب ضمنها وتوضِّح معناها وهيكليتها، إذ تبدو شيفرة HTML البسيطة قريبة من التالي: <h1>This is a top-level heading</h1> <p>This is a paragraph of text.</p> <img src="cat.jpg" alt="A picture of my cat"> يمكنك تشبيه اللغة إذا وازنتها مع بناء سكني بأساسات وجدران المنزل التي تعطيه شكله وتجعله متماسكًا. CSS التنسيقات المورثة Cascading Style Sheets: وهي لغة مبنية على قواعد مخصصة لتطبيق تنسيقات معينة على عناصر HTML مثل ضبط ألوان النصوص والخلفيات وإضافة الأطر وتحريك الأشياء أو تخطيط الصفحة بطريقة معينة، وإليك مثالًا بسيطًا يحوِّل نصوص الفقرات <p> في HTML إلى اللون الأحمر: p { color: red; } ووفقًا لتشبيه المنزل السكني، فستكون CSS بمثابة الطلاء وورق الجدران والسجاد واللوحات التي تضعها داخل المنزل. جافاسكربت JavaScript: هي لغة البرمجة التي تستخدِمها لإضافة التفاعل في مواقع الويب، ابتداءً بالتغيير الديناميكي للتنسيق إلى إحضار البيانات من الخادم مرورًا بتنفيذ الرسوميات ثلاثية الأبعاد، إذ ستخزِّن شيفرة جافاسكربت التالية على سبيل المثال مرجعًا إلى عنصر الفقرة <p> ومن ثم تغيّر النص الموجود ضمنه: let pElem = document.querySelector('p'); pElem.textContent = 'We changed the text!'; وبالعودة لتشبيه المنزل السكني، فستكون جافاسكربت بمثابة الطباخ أو التلفاز أو مجفف الشعر، أي الأشياء التي تزيد من إمكانات منزلك. الأدوات حالما تتعلم التقنيات الأساسية التي تُستخدم في بناء صفحات الويب، فستبدأ بالتعرف على أدوات عديدة تُسهِّل عملية بناء الصفحات وتجعلها أكثر فاعليةً، وإليك بعض الأمثلة: أدوات مطوري ويب الموجودة في المتصفحات العصرية والتي تُستخدم في تنقيح شيفرتك. أدوات الاختبار التي تُستخدم في تنفيذ اختبارات تظهر سلوك شيفرتك إذا حققت المطلوب أم لا. المكتبات وأطر العمل frameworks المبنية على أساس جافاسكربت والتي تسمح بتطوير أنواعًا مختلفةً من مواقع الويب بطرق أسرع وأكثر فاعليةً. المنقِّحات Linters التي تحدِّد مجموعةً من القواعد وتدقق شيفرتك بحثًا عن أيّ خرق لهذه القواعد. المُصغِّرات Minifiers التي تزيل المساحات الفارغة من الشيفرة لتبدو أقل حجمًا، وبالتالي ستزداد سرعة تنزيلها من خوادم الويب. اللغات التي تنفذ ضمن الخوادم وأطر العمل المتعلقة بها تُعَدّ HTML و CSS وجافاسكربت لغات تعمل في الواجهة الأمامية (من جهة العميل)، أي أنها تُنفَّذ باستخدام المتصفحات لتظهر صفحة الويب كما يراها المستخدِم. هناك أيضًا مجموعة أخرى من لغات البرمجة تُدعى لغات الواجهة الخلفية (من جهة الخادم) أي أنها تُنفّذ على الخادم قبل أن تًرسل نتيجة التنفيذ إلى المتصفح لعرضها، إذ يقتصر الاستخدام النمطي لهذه اللغات على الحصول على بعض البيانات من قواعد البيانات ومن ثم توليد شيفرة HTML لاحتواء هذه البيانات وإرسالها إلى المتصفح ليعرضها للمستخدِم، ونذكر من هذه اللغات ASP.NET و Python و PHP و NodeJS. أفضل الممارسات عند تطوير مواقع الويب تحدثنا بإيجاز عن التقنيات التي ستستخدِمها في بناء مواقع الويب، وسنتحدث الآن عن أفضل الممارسات العملية التي عليك تبنيها لتتأكد من استخدام تلك التقنيات بأفضل طريقة ممكنة. سيأتي المصدر الأساسي لعدم الثقة عندما نتحدث عن تصميم مواقع ويب من عدم معرفتك بمجموعة التقنيات التي يعتمد عليها المستخدِمين في تصفح موقعك: قد يستخدِم أحدهم جهاز آيفون بشاشة صغيرة وضيقة. قد يستخدِم آخر حاسوبًا محمولًا بنظام ويندوز له شاشة عرض واسعة. أما الثالث فقد يكون ضريرًا ويستخدم قارئًا آليًا لمحتوى الشاشة. وقد يستخدم الرابع حاسوبًا مكتبيًا قديمًا لا يستطيع تشغيل أية متصفحات حديثة. عليك تصميم موقعك وفق الآلية الدفاعية بما أنك لا تعرف ببساطة كيف سيتصفحه المستخدِم، ف، لذا اجعل موقعك مرنًا قدر الإمكان لكي يتمكن جميع المستخدِمين من الوصول إلى محتواه بصرف النظر عن اختلاف تجربتهم له، أي عليك باختصار إفادة الجميع من الويب قدر المستطاع، كما ستصادف في مرحلة ما من رحلتك التعليمية المفاهيم التالية: التوافق مع متصفحات مختلفة Cross-browser compatibility: وهو أسلوب يحاول التأكد من عمل صفحة الويب بالصورة المطلوبة ضمن أكبر عدد ممكن من المتصفحات، ويتضمن ذلك استخدام تقنيات تدعمها معظم المتصفحات، وتقديم تجربة تصفح أفضل في المتصفحات القادرة على التعامل مع هذه التقنيات (تحسين مستمر)، وكتابة شيفرة يمكن اختزالها بسهولة إلى صيغة أبسط تستطيع المتصفحات القديمة عرضها لإعطاء تجربة تصفح مفيدة (تراجع رشيق graceful degradation)، كما يتضمن الأمر الكثير من الاختبارات لمتابعة أي مشاكل على متصفح محدد، ومن ثم العمل أكثر على إصلاح تلك المشاكل. تصميم متجاوب للصفحات Responsive web design: وهو أسلوب لخلق مرونة من الناحية الوظيفية والتخطيطية للصفحات بحيث تتلاءم تلقائيًا مع المتصفحات المختلفة، ومثالنا على ذلك صفحة ويب تُعرَض بتخطيط معيّن على شاشة واسعة لمتصفح حاسوب ومن ثم تأخذ تخطيطًا متجاوبًا مع حجم الشاشة مثل تخطيط العمود الواحد على متصفح هاتف محمول، إذ يمكنك تجريب أيّ موقع على الأحجام الصغيرة بتصغير حجم نافذة المتصفح وملاحظة سلوكه المتجاوب مع الأحجام الصغيرة الأداء Performance: ويستهدف تحميل صفحة ويب بالسرعة الممكنة مع المحافظة على وضوحها وسهولة استخدامها لكي لا يشعر المستخدِم بالإحباط ويغادرها. سهولة الوصول Accessibility: ويعني إمكانية استخدام الموقع من قِبَل أكبر عدد ممكن من الأشخاص المختلفين من جميع النواحي وترتبط بمفاهيم مثل التنوع، والشمولية، والتصميم الشمولي، كما يتضمن ذلك أشخاصًا ذوي إعاقة بصرية أو سمعية أو إدراكية أو حركية، ويتعدى الأمر مفهوم الإعاقة إلى السن والثقافة والتجهيزات المستخدَمة والمحدودية التقنية مثل الاتصال البطيء بالإنترنت. التدويل Internationalization: ويعني ذلك إمكانية استخدام موقع الويب من قِبَل أشخاص ينتمون إلى ثقافات مختلفة أو يتكلمون لغات مختلفة عن لغتك، وهنالك اعتبارات تقنية للموضوع مثل تبديل تخطيط الصفحات ليتلاءم مع اللغات التي تُكتَب من اليمين إلى اليسار أو مع اللغات التي تكتب عموديًا، واعتبارات إنسانية مثل استخدام لغة بسيطة وواضحة بعيدة عن اللهجات، ليزداد احتمال فهم الأشخاص الذين يتكلمون لغتك على أساس لغة ثانية أو ثالثة لما تعرضه. الخصوصية والأمان Privacy & Security: يرتبط المفهومان ببعضهما لكنهما مختلفان، إذ تعني الخصوصية السماح للأشخاص بتنفيذ ما يريدونه دون أن تتجسس على نشاطاتهم أو تجمع أية بيانات أكثر مما تحتاجه فعلًا، بينما يعني الأمان بناء موقعك بطريقة لا تُمكّن المستخدِمين المشبوهين من سرقة المعلومات التي يضمها الموقع عنك أو عن عملائك. الانطلاق في عالم ويب سنعرض في هذا المقال بعض المهارات العملية اللازمة لتنطلق في عالم تطوير ويب مثل اختيار البرمجيات التي تعمل عليها والأدوات اللازمة لبناء صفحات ويب بسيطة ونشرها وكتابة شيفرتها، كما سنفرد لاحقًا لكل العناوين التي نمر عليها مقالات خاصةً لشرح مستفيض أكثر. عليك الكثير لتتعلمه وتفعله حتى تصل إلى مرحلة تطوير موقع ويب احترافي، فإذا كنت حديث العهد في هذا المجال، فسنشجِّعك على البدء بموقع بسيط، ولن تكون جاهزًا مباشرةً لتبني موقع فيسبوك جديد، لكنك ستكون قادرًا على بناء مواقع بسيطة ونشرها، وبالاطلاع على المقالات التي سنشير إليها باختصار والعمل بمضمونها، ستنتقل من الصفر إلى نشر أول موقع بسيط لك على الإنترنت، فلنبدأ جولتنا. تثبيت البرمجيات الأساسية هناك الكثير من الأدوات والبرمجيات التي تُستخدَم في بناء وتطوير مواقع ويب، وقد تربكك بالفعل كثرة محررات الشيفرة وإطارات العمل وأدوات الاختيار، إذ سنرشدك في مقال تثبيت البرمجيات الأساسية خطوةً بخطوة إلى تثبيت البرمجيات التي تحتاجها لتبدأ عملية بناء مواقع ويب بسيطة. التفكير بالمظهر العام لموقع الويب الذي تبنيه عليك التخطيط لمظهر ومحتوى موقعك قبل الشروع في كتابة الشيفرة، فما هي المعلومات التي سيعرضها؟ وما هي خطوط الكتابة والألوان التي ستستخدِمها؟ التعامل مع الملفات يتكون موقع ويب من ملفات عدة: نصية وشيفرات وأوراق تنسيق ووسائط متعددة وغيرها. لا بد إذًا من تنظيم هذه الملفات وفق هيكلية منطقية عندما تبدأ بناء موقعك وأن تتأكد من ترابط هذه الملفات مع بعضها. أساسيات HTML تُستخدَم شيفرة HTML في هيكلة محتوى ويب وتعطيه المعنى والغاية، أي هل المحتوى الذي تقدِّمه على سبيل المثال سيكون مقطعًا نصيًا أم قائمة نقطية؟ هل ستزوِّد صفحتك بالصور؟ هل ستعرض جداول تضم بيانات؟ أساسيات CSS تُعَدّ التنسيقات المورثة Cascading Style Sheets واختصارًا CSS شيفرةً خاصةً بتنسيق صفحات ويب، فهل سيكون نص ما مثلًا أسود أم أحمر؟ في أيّ مكان من الصفحة ستعرض محتوًى معينًا؟ ما الصورة التي ستضعها في خلفية الصفحة؟ أو ما الألوان التي ستختارها لموقعك؟ أساسيات جافا سكربت جافا سكريبت هي لغة البرمجة التي تستخدمها لإضافة ميزات تفاعلية إلى موقعك مثل الألعاب أو الأشياء التي تحدث عند النقر على زر أو عندما تُدخل نصًا في نموذج أو عندما تُحدث تأثيرات حركية في تنسيق العناصر أو عند تصميم الرسوميات المتحركة وغيرها الكثير. نشر موقعك على شبكة الإنترنت عندما تُنهي كتابة شيفرة موقعك وتنظيم جميع الملفات التي يضمها، سيحين الوقت لنشره على شبكة الإنترنت ليطَّلع عليه الناس. كيف يعمل الويب قد لا تكون لديك فكرة عن الأشياء المعقدة التي تجري خلف الستار عندما تتصفح مواقعك المفضلة، لكننا سنختصر ما يحدث في جزئية لاحقة من هذه السلسلة عندما تستعرض صفحة ويب في متصفح حاسوبك. ختامًا، قد يهمك مقال آلية عمل شبكة الإنترنت؟، وقد ترغب بالاطلاع أكثر على تاريخ الشبكة العنكبوتية العالمية، وننصحك أيضًا بالرجوع إلى مقالة المدخل الشامل لتعلم تطوير الويب ترجمة -وبتصرف- للمقال The web and webstandards. اقرأ أيضًا الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث الحماية من مواقع الإنترنت في العالم الرقمي التأثير النفسي للألوان في تصميم الويب
  9. سنبني خلال هذا المقال خط إنتاج Pipeline لنشر المشروع النموذجي الذي بدأناه في التمرين 11.2. إذ سننشئ نسخة خاصةً بنا من مستودع المشروع لكي نتعامل معها، ثم سنبني في آخر تمرينين خط إنتاج آخر لنشر بعض التطبيقات الخاصة بنا والتي بنيناها سابقًا. يضم القسم 21 تمرينًا من المفترض إكمالها جميعًا حتى تنهي هذا المنهاج، وعليك أن تسلم حلول هذه التمرينات إلى منظومة تسليم التمارين بنفس الأسلوب المُتبع في القسم السابق، إذ تُسلَّم التمرينات إلى نسخة مختلفة من المنهاج. ستعتمد المعلومات في هذا القسم على مفاهيم اطلعنا عليها سابقًا، لذلك ننصحك بإكمال الأقسام 0-5 قبل البدء بهذا القسم. لن تكتب الكثير من أسطر الشيفرة في هذا القسم، فهو يغطي في معظم الأوقات مواضيع عن التهيئة. وعلى الرغم من أن تنقيح الشيفرة صعب، لكن تنقيح أوامر التهيئة أصعب بكثير، فعليك إذًا التحلي بالصبر والمثابرة في هذا القسم. تجهيز التطبيقات لمرحلة الإنتاج ستضطر بعد الانتهاء من كتابة الشيفرة عاجلًا أم آجلًا إلى نقل تطبيقك إلى مرحلة الإنتاج، أي إلى مستخدميه الحقيقيين، ثم ستضطر بعدها إلى صيانة هذا التطبيق باستمرار وإصدار نسخٍ جديدة منه والعمل مع مطورين آخرين لتوسيعه. لقد استخدمنا حاليًا غيت هب GitHub لتخزين الشيفرة المصدرية، لكن ما الحل عندما نعمل ضمن فريق من المطورين؟ ستظهر عدة مشاكل عند تعاون عدة مطورين، فقد يعمل التطبيق جيدًا على حاسوبي، لكن قد يخفق على حواسيب مطورين آخرين يعملون على أنظمة تشغيل مختلفة، أو يستخدمون نسخًا مختلفة من المكتبات التي أدرجناها في التطبيق. يُشار إلى هذه المشكلة بالعبارة "التطبيق يعمل على جهازي works on my machine". هناك مشكلة أخرى، فلو أجرى مطورين تعديلات على شيفرة التطبيق ولم يتفقا من سينشر التعديلات التي أنجزها، من سيمنع أحدهما من محي تعديلات الآخر وكتابة تعديلاته مكانها؟ سنغطي في هذا القسم أساليب العمل المشترك لبناء ونشر التطبيقات بطريقة منضبطة ومحددة جيدًا، يظهر فيها بكل وضوح ما الذي سيحدث وتحت أية ظروف. بعض المصطلحات المفيدة نستخدم في هذا القسم مصطلحات قد لا تعرفها أو لم تفهمها جيدًا، سنناقش هذه المصطلحات تاليًا، وحتى لو كنت على دراية بهذه المصطلحات، اطلع على هذه الفقرة لنكون على وفاق في فهم المصطلح عند وروده. الفروع Branches يسمح نظام غيت Git بوجود نسخ، أو مسارات streams، أو إصدارات مختلفة من الشيفرة تتعايش معًا دون الحاجة لإلغاء بعضها بعضًا؛ فعندما تُنشئ مستودعًا سيكون هذا المستودع بمثابة الفرع الرئيسي (ندعوه في غيت بالاسم "main" أو "master"، لكن الأمر مختلف في المشاريع القديمة). لا بأس بهذا الأسلوب إذا كان هناك مطور واحد يستخدم هذا الفرع، ويعمل على تطوير ميزة واحدة للتطبيق كل مرة. سيكون استخدام الفروع مفيدًا عندما تتعقد بيئة التطوير، إذ سيعمل كل مطور على فرع أو أكثر، وسيمثل كل فرع نسخةً مختلفةً قليلًا عن نسخة الفرع الرئيسي. وعندما تكتمل الميزة التي يجري تطويرها في أحد الفروع ستُدمج مع الفرع الرئيسيٍ، وبالتالي ستصبح هذه التغييرات أو الميزات الجديدة جزءًا من التطبيق الرئيسي. وهكذا سيتمكن كل مطور من العمل على مجموعة من التعديلات بحيث لا يعيق بقية المطورين من العمل على أفكارهم الخاصة قبل إكمال هذه التعديلات. لكن ما الذي سيحدث لبقية الفروع الخاصة بالمطورين الآخرين عندما يدمج أحد المطورين تعديلاته ضمن الفرع الرئيسي؟ إذ سيبتعد بقية المطورين عن النسخة القديمة التي يعملون عليها. وكيف سيعرف المطورون أن تعديلاتهم التي يجرونها على النسخة السابقة ستكون متوافقةً مع الحالة الجديدة التي يفرضها دمج التعديلات ضمن الفرع الرئيسي؟ سنحاول الإجابة عن هذا السؤال الجوهري في هذا القسم. يمكنك الاطلاع على مزيدٍ من المعلومات حول الفروع من خلال قراءة المقالة "أساسيات التفريع (Branching) والدمج (Merging) في Git". طلبات السحب Pull requests يجري عادةً دمج فرع ضمن الفرع الرئيسي وفق آلية تُعرف بطلب السحب، أو كما يُعرف أحيانًا بالاختصار "PR"، إذ يطلب المطور الذي أجرى بعض التعديلات أن تُدمج التعديلات التي أجراها ضمن الفرع الرئيسي، وحالما يُقبل هذا الطلب أو يُفتتح للمراجعة، يمكن لمطور آخر أن يتحقق من أن كل شيء سيجري على مايرام بعد الدمج. لو اقترحت مثلًا تعديلًا على مادة منهجنا، فقد قدمت فعلًا طلب سحب. بناء التطبيق Build لهذا المصطلح معانٍ مختلفة في لغات البرمجة المختلفة. فلا حاجة في بعض اللغات المترجمة، مثل روبي Ruby، أو بايثون Python إلى خطوة بناء فعلية إطلاقًا. عندما نتكلم عن البناء عمومًا، فإننا نعني بذلك إعداد التطبيق ليعمل على المنصة التي صُمِّم لأجلها، وقد يعني ذلك، على سبيل المثال، أننا لو أردنا كتابة التطبيق بلغة TypeScript ثم تنفيذه على Node، فستكون خطوة البناء هي عملية نقل شيفرة TypeScript إلى جافا سكربت JavaScript. ستغدو هذه الخطوة إجبارية وأكثر تعقيدًا في اللغات المُصرَّفة، مثل C و Rust، إذ تتطلب شيفرتها التصريف إلى شيفرة قابلة للتنفيذ. وكنا قد اطلعنا في القسم 7 على برنامج webpack، وهو أداةٌ رائدة حاليًا في بناء نسخ إنتاج من تطبيقات React أو تطبيقات واجهة أمامية مكتوبة بلغة جافاسكربت JavaScript أو TypeScript. نشر التطبيقات Deploy يشير مصطلح "النشر" إلى وضع التطبيق في المكان الذي يمكن للمستخدم النهائي الوصول إليه واستخدامه؛ فقد يعني هذا المصطلح بالنسبة للمكتبات مثلًا وضعها ضمن حزم ثم دفعها إلى أرشيف للحزم (مثل npmjs.com) بحيث يمكن للمستخدمين إيجادها وتضمينها في مشاريعهم. تختلف صعوبة نشر خدمة (مثل تطبيق ويب) حسب تعقيدها، فقد اشتمل مخططنا لنشر التطبيق في القسم 3 مثلًا على تنفيذ بعض السكربتات يدويًا ثم دفع شيفرة المستودع إلى خدمة استضافة Heroku. سنطور في هذا القسم "خط إنتاج" لنشر كل جزء من شيفرتك آليًا إلى Heroku إن لم تسبب هذه الشيفرة أية مشاكل. وقد يكون النشر أحيانًا على درجة عالية من التعقيد خاصةً إذا تطلب التطبيق احتياجات خاصة، كأن يكون متاحًا دائمًا للعمل أثناء تطويره "لا إيقاف من أجل النشر zero downtime deployment"، أو كان علينا أن نأخذ في الحسبان بعض الأمور مثل نقل قواعد البيانات. لن نغطي النقاط المتعلقة بالنشر الذي يحمل تعقيدات مثل التي ذكرناها، لكن من المهم أن تدرك وجودها. ما هو التكامل المتواصل؟ يختلف المفهوم الدقيق لمصطلح التكامل المتواصل Continuous Integration -أو اختصارًا "CI"- عن كيفية استخدامه في مجال التطوير. ستجد نقاشًا قديمًا لكنه يحمل أثرًا كبيرًا عن استخدام هذا المصطلح في مدونة "مارتن فلور". وإذا أردنا التحديد الدقيق للمصطلح CI سنقول أنه يعني غالبًا "دمج التغييرات التي نفذها المطور مع الفرع الرئيسي" ثم أضافت ويكيبيديا Wikipedia العبارة "عدة مرات في اليوم" إلى المصطلح. وهذا الأمر صحيح عادةً، لكن عندما نشير إلى CI في مجال البرمجيات، فنحن نتحدث غالبًا عما سيحدث بعد عملية الدمج الفعلية للتغيرات، إذ قد نحتاج إلى إنجاز بعضٍ من هذه الخطوات: التدقيق lint: للحفاظ على الشيفرة واضحة وقابلة للصيانة. البناء build: وضع كل الشيفرة المُنجزة في برنامج واحد. الاختبار test: لضمان عدم إخفاق أية ميزات موجودة مسبقًا. التحزيم packaging: وضع كل ما نحتاجه في حزمة سهل الحمل والنقل. التحميل/ النشر deploy: لجعل البرنامج متاحًا للاستخدام. سنناقش كل خطوة من تلك الخطوات (عندما نجد فائدةً من ذلك) بشيء من التفصيل لاحقًا. وعلينا أن نتذكر دائمًا أنّ هذه العملية ستكون محددةً بدقة. يعيق التحديد الدقيق strict definition عادةً سرعة التطوير أو الإبداع في إيجاد الحلول، لكن من المفترض أن لا يكون هذا صحيحًا بالنسبة للتكامل المتواصل، إذ يجب وضع هذه القيود بطريقة مرنة تسمح بالتطوير والعمل المشترك. سيسمح استخدام أنظمة CI جيدة، مثل GitHub Actions الذي سنغطيه في هذا القسم بتنفيذ كل ما ذكرناه آليًا وبصورة سحرية. التحزيم والنشر مثل جزء من نظام التكامل المتواصل CI ينبغي التذكير من حين إلى آخر، أنّ عملية التحزيم وعملية النشر خاصة لا تُعدان أحيانًا جزءًا من نظام CI، لكننا سنعدّهما جزءًا من النظام، لأنه من المنطقي في العالم الحقيقي أن نضع كل الخطوات التي أشرنا إليها معًا. ويعود جزءٌ من ذلك للحفاظ على التسلسل في سياق العمل وخط إنتاج البرنامج (الطريق إلى إيصال المنتج إلى المستخدم النهائي)، بينما يعود الأمر في شقه الآخر إلى حقيقة أنّ هذه النقطة هي ما يسبب إخفاق العملية ككل. ستظهر المشاكل غالبًا في مرحلة التحزيم من نظام CI كونها مرحلةٌ لا تختبر محليًا، فمن المنطقي إذًا اختبار عملية تحزيم المشروع خلال سير العمل في CI حتى لو لم نضع هذه الحزمة موضع العمل، كما يمكن في بعض مسارات العمل أن نختبر حزمةً قد بُنيت فعلًا مسبقًا. سيؤكد ذلك أننا اختبرنا الشيفرة بنفس الشكل الذي سننشرها فيه خلال مرحلة الإنتاج. إذًا ما هو وضع عملية النشر؟ سنتحدث عن الاستمرارية وإمكانية التكرار مطولًا في الفصول القادمة، لكن تجدر الإشارة هنا إلى أننا نحتاج إلى عملية تبدو متماثلةً دائمًا، سواءٌ أجرينا الاختبارات في فرع تطوير أو في الفرع الرئيسي. نحتاج في الواقع إلى العملية نفسها "حرفيًا" بحيث يظهر الاختلاف فقط في نهايتها، وذلك عند تحديد ما إذا كنا في الفرع الرئيسي أم لا، وإن كنا نريد النشر أم لا. وفي هذا السياق من المنطقي تضمين خطوة النشر في سير عمل CI طالما أنها ستخضع للصيانة في نفس الوقت الذي نطورها فيه. يشير المصطلحان: "التسليم المتواصل Continuous Delivery" و"النشر المتواصل Continuous Deployment" -أو اختصارًا CD- إلى منظومة CI عندما تتضمن مرحلة النشر. لن نزعجك بالتعريف الدقيق، إذ يمكنك الاطلاع عليه من خلال Wikipedia، أو منشورات مدونة "مارتن فلور"، أو من خلال أكاديمية حسوب، لكننا نستخدم الاختصار CD ليشير إلى أسلوب ممارسة عملي يقتضي إبقاء الفرع الرئيسي متاحًا للنشر والتطوير في أي وقت. لكن ماذا عن المنطقة الغامضة بين مصطلحي CI وCD؟ فلو كان علينا مثلًا أن نجري بعض الاختبارات قبل أن ندمج أية شيفرات جديدة ضمن الفرع الرئيسي، هل نعد ذلك شكلًا من أشكال CI لأننا سنجري دمجًا متواصلًا مع الفرع الرئيسي؟ أم شكلًا من أشكال CD لأننا نتحقق بذلك أن الفرع الرئيسي قابلًا للنشر باستمرار؟ تقع بعض المفاهيم إذًا على الخط الفاصل بين المصطلحين، فمن المنطقي كما أشرنا سابقًا، أن نعد CD جزءًا من CI. لهذا السبب، سيُستخدم غالبًا المصطلح CI/CD للدلالة على العملية برمتها. وانتبه إلى أننا سنستخدم المصطلحين CI و CI/CD بالتناوب طوال الوقت في هذا القسم. أين تكمن أهمية استخدام نظام CI؟ لقد ذكرنا سابقًا مشكلة "يعمل على جهازي" ومشكلة نشر تغييرات متعددة المصادر، لكن ماذا عن بقية المشاكل؟ ماذا لو حملّت "سارة" الشيفرة مباشرةً إلى الفرع الرئيسي؟ ماذا لو استخدم "أحمد" فرعًا ولم يكلف نفسه عناء إجراء بعض الاختبارات قبل دمج ما عدّله ضمن الفرع الرئيسي؟ ماذا لو حاول "عبد الله" بناء نسخة إنتاج من التطبيق لكن بمعاملات خاطئة؟ سيمكِّننا استخدام التكامل المتواصل وفق طريقة منهجية في العمل في: منع رفع الشيفرات مباشرةً إلى الفرع الرئيسي. تنفيذ عملية CI لكل طلبات السحب إلى الفرع الرئيسي وتمكينها من دمج التغييرات. بناء حزم إنتاج للبرامج التي نطورها في بيئة معروفة تمتلك نظام CI. وهنالك أيضًا بعض الإيجابيات لتوسيع هذه الإعدادات: إذا استخدمنا CD في كل مرةٍ ننفذ فيها عملية دمج مع الفرع الرئيسي، سنكون واثقين من عمل الفرع الرئيسي وفق نظام الإنتاج. إذا سمحنا بإتمام عملية الدمج فقط في الحالة التي يكون فيها الفرع الرئيسي محدّثًا، سنضمن أن لا يلغي المطورون التغييرات التي نفذها غيرهم. تنبيه: سنفترض في هذا القسم أن الشيفرة الموجودة في الفرع الرئيسي ("mian" أو "master") ستعمل وفق نظام الإنتاج. ونظرًا لوجود عدد هائل من مخططات العمل (workflows) على git، قد يكون هناك على سبيل المثال حالات يظهر فيها فرع خاص للإصدار release branch يحتوي على الشيفرة التي تعمل وفق نظام الإنتاج. مبادئ هامة من المهم أن نتذكر أنّ CI/CD ليس هدفًا بحد ذاته، لكن الهدف هو تطوير أسرع وأفضل للتطبيقات بأقل عددٍ من الثغرات، وتحقيق أفضل تعاون بين المطورين. ولهذا لا بدّ من تهيئة نظام CI بما يلبّي المهمة التي ننفذها والمشروع بحد ذاته، كما ينبغي أن نبقي الهدف الرئيسي من استخدامه في حساباتنا دائمًا. يمكننا التفكير بنظام CI بمثابة جوابٍ على الأسئلة التالية: كيف سنتأكد أنّ جميع الاختبارات ستُطبّق على كامل الشيفرة التي ستُنشر؟ كيف سنضمن جاهزية الفرع الرئيسي للنشر في كل الأوقات؟ كيف سنتأكد أنّ النسخ التي تُبنى ستكون متوافقة، وستعمل دائمًا على المنصات التي صُمِّمت للنشر عليها؟ كيف سنضمن أن التغييرات الجديدة لن تلغي التغييرات الأقدم؟ كيف سننجز عملية النشر بضغطة زر أو بطريقة آلية، عندما يدمج مطور التغييرات التي أجراها مع الفرع الرئيسي؟ وهناك أيضًا دلائل علمية على الفائدة الهائلة التي يقدمها نظام CI/CD، فبناءً على دراسة واسعة في كتاب ": Building and Scaling High Performing Technology Organizations"، يقترن استخدام CI/CD بشدة مع النجاحات على صعيد المؤسسات (تحسين الأرباح وجودة المنتج وزيادة الحصة السوقية وتقليل زمن التسويق)، وكذلك من ناحية المطورين، فقد جعلتهم أكثر سعادةً وأقل إرهاقًا. سلوك موثق تشيع في أوساط المبرمجين طرفةٌ مفادها أنّ الثغرات هي "ميزات غير موثقة". لكن يجب علينا تفادي أية حالات لا نعلم تمامًا نتيجتها. فلو اعتمدنا مثلًا على عنوان طلب السحب لنحدد ما إذا كان إصدار البرنامج رئيسيًا major، أو ثانويًا minor، أو ترميميًا patch (سنتحدث عن معنى كل إصدار لاحقًا)، سيكون علينا الانتباه إلى الحالة التي يُغفل فيها المطور من وضع عنوانٍ لطلب السحب الذي قدمه. وماذا لو وضع هذا العنوان بعد بدء عملية البناء أو الاختبار؟ أو أنه غيَّر العنوان خلال مرحلةٍ ما، فما الذي سيكون عليه هذا الإصدار؟ من الممكن أن تغطي جميع الحالات التي قد تتوقعها، ومع ذلك، قد تظهر بعض الثغرات عندما يُنفّذ المطور شيئًا "إبداعيًا" لم تتوقعه إطلاقًا، فمن الجيد إذًا أن تنتهي العملية التي ستخفق بأمان في هذه الحالة. فلو عدنا إلى المثال السابق عندما يغير المطور عنوان الطلب أثناء تنفيذ عملية البناء. إذا لم نتمكن من توقع سيناريو مثل هذا مسبقًا، فمن الأفضل ربما أن تتوقف عملية البناء، وأن نبلِّغ المستخدم بأنّ شيئًا غير متوقع قد حدث، فنشر إصدار خاطئ سينتج حتمًا مشاكلًا أكبر، وسيكون إيقاف العملية وإخطار المستخدم هو الحل الأكثر أمانًا. يحدث الشيء ذاته في كل مرة قد نملك أفضل اختبارات لبرمجياتنا يمكن تخيلها، وقد تكون قادرةً على اصطياد أية مشكلة محتملة، لكنها ستبقى عديمة الجدوى إن لم ننفذها على الشيفرة قبل نشرها. علينا أن نضمن أنّ الاختبارات قابلةً للتنفيذ، كما نريد أن نضمن أنها ستعمل مع الشيفرة التي سننشرها فعليًا. فلن يفيدنا الاختبار الذي ينجح مثلًا ضمن فرع "سارة" ويفشل عند دمجه مع الفرع الرئيسي. وطالما أننا سننشر محتويات الفرع الرئيسي، لذا علينا أن نتأكد من نجاح الاختبارات على نسخة من الفرع الرئيسي بعد أن ندمج معه فرع "سارة". ستوصلنا المناقشة السابقة إلى مبدأ جوهري وهو التأكد أنّ السلوك نفسه سيحدث كل مرة، أو أنّ المهام المطلوبة ستُنفَّذ جميعها وبالترتيب الصحيح. يجب أن تبقى الشيفرة قابلة للنشر دائما إنّ وجود شيفرة قابلة للتوزيع والنشر دائمًا أمر مريح جدًا وخاصةً عندما يحتوي الفرع الرئيسي على شيفرة تعمل في وضع الإنتاج؛ فإذا ظهرت ثغرةٌ مثلًا وتطلب الأمر معالجتها، يمكنك سحب نسخة من الفرع الرئيسي (وهي الشيفرة التي تُنفًّذ في وضع الإنتاج) وحل المشكلة، ثم تقديم طلب سحب لإعادة الشيفرة إلى الفرع الرئيسي (دمج من جديد). ويجري هذا الأمر عادةً مباشرةً دون أية مشاكل. إذا اختلفت الشيفرة الموجودة في الفرع الرئيسي عن شيفرة الإنتاج ولم يكن الفرع الرئيسي قابلًا للنشر، سيكون عليك البحث عن الشيفرة التي تعمل في وضع الإنتاج وسحب نسخة عنها، ثم إيجاد الثغرة ومعالجتها، كما عليك إيجاد طريقة لإعادة الشيفرة إلى الفرع الرئيسي والعمل على نشر الجزء المحدد الذي أصلحته. لن يكون هذا الأمر مريحًا وستكون طريقة تنفيذه مختلفةً كليًا عن مخطط نشر التطبيقات الاعتيادي. معرفة أجزاء الشيفرة المنشورة- مجموع SHA/الإصدار من المهم غالبًا تحديد الشيفرة التي تعمل فعليًا في وضع الإنتاج. ولقد ناقشنا سابقًا أن شيفرة الفرع الرئيسي هي من تعمل في هذا الوضع في الحالة النموذجية، لكن هذا الأمر ليس ممكنًا دائمًا؛ فقد تتعرض عملية البناء للإخفاق عندما نحاول تشغيل شيفرة الفرع الرئيسي في وضع الإنتاج، وقد نجري عدة تغييرات على الشيفرة ونريدها أن تُنشر جميعها مباشرةً. ما نحتاج إليه في حالات مثل هذه (وهي فكرة جيدة عمومًا)، هو معرفة الشيفرة التي تعمل في وضع الإنتاج بالضبط؛ إذ يمكن معرفة ذلك أحيانًا عن طريق رقم الإصدار version، وأحيانًا بمجموع SHA sum (وهو جدول HASH يعرِّف بصورةٍ فريدة اعتماد git) متصل بالشيفرة. سنناقش موضوع تحديد رقم الإصدار لاحقًا في هذا القسم. الآلية الأكثر فائدةً هي ربط معلومات الإصدار مع تاريخ جميع الإصدارات، فلو اكتشفنا مثلًا وجود ثغرة في اعتماد محدد، يمكننا أن نعرف متى أُصدر هذا الاعتماد وكم عدد المستخدمين الذين تأثروا بالثغرة. وتظهر فائدة هذه المقاربة عندما تسبب الثغرة أخطاءً في بيانات قواعد البيانات، وهكذا من الممكن تقفي أثر البيانات الخاطئة بناءً على تاريخ إنشائها. أنماط إعدادات منظومة CI علينا تخصيص خادم منفصل لتشغيل مهام منظومة التكامل المتواصل CI لكي نلبي بعضًا من المتطلبات التي ذكرناها سابقًا، إذ سيقلل وجود خادم منفصل المخاطر الناتجة عن اختلاط عمليات أخرى بعملية منظومة CI/CD جاعلةً نتيجتها غير متوقعة. هنالك خياران: استضافة خادم خاص بنا أو الخدمة السحابية cloud service. استضافة Jenkins وإعدادات بيئة الاستضافة الذاتية self-host تُعد استضافة Jenkins الخيار الأكثر شعبيةً من بين خيارات الاستضافة الذاتية، فهي مرنةٌ جدًا وتمتلك عدة إضافات plugin لكل شيء تقريبًا (ماعدا الشئ الوحيد الذي تريده). تمثل هذه الاستضافة خيارًا جيدًا للعديد من التطبيقات. يعني استخدام الاستضافة الذاتية أن تكون بيئة الاستضافة تحت سيطرتك بالكامل، وكذلك جميع الموارد، ولن تكون أسرارك عرضةً للكشف من قبل الآخرين، كما ستتمكن من فعل ما تشاء بالعتاد الصلب. لكن ولسوء الحظ هناك جانبٌ مظلم لاستضافة Jenkins فهي صعبة الإعداد، إذ تتطلب المرونة الكبيرة في الإعداد وجود العديد من قوالب template الشيفرة التي تتطلب الإعداد ليعمل كل شيء، ويتطلب استخدام Jenkins بالتحديد إعداد منظومة CI/CD باستخدام لغة Jenkins الخاصة بالنطاق domain-specific. ولا ننس مخاطر إخفاق العتاد الصلب والذي قد يسبب مشكلةً في حالات الازدحام. تعتمد فاتورة الاستضافة الذاتية على العتاد الصلب الذي تختاره غالبًا، فأنت تدفع مقابل الخادم وما ستفعله على الخادم لن يغير من فاتورتك. استخدام GitHub Actions وحلول أخرى معتمدة على الاستضافة السحابية لن تضطر للتفكير كثيرًا عند إعداد بيئة الاستضافة في الاستضافة السحابية، فكل ما عليك فعله هو أن تطلب من الاستضافة ما تريده، ويتضمن ذلك عادةً وضع ملف في مستودعك (ثم إخبار منظومة CI بقراءته)، أو التحقق من وجود ملف كهذا في المستودع. سيكون ملف تهيئة CI في الاستضافة السحابية أبسط قليلًا، وخاصةً إن لم تتعدّى الحدود "الطبيعية" للاستخدام، لكن قد تغدو خيارات هذه الإستضافة محدودةً قليلًا إن أردت فعل أشياء خاصة بين الفينة والأخرى، أو قد تجد صعوبةً في ذلك، خاصةً في إنجاز مهام محددة لم تُبنى المنصة السحابية لكي تنجزها. سنركز في هذا القسم على الاستخدامات التي تعد "طبيعية"، فقد تتطلب إعدادات بعض المهام الخاصة عتادًا صلبًا خاصًا على سبيل المثال. وبعيدًا عن إعدادات التهيئة التي ذكرناها سابقًا، قد تواجهنا مشاكلًا تتعلق بمحدودية الموارد على الاستضافة السحابية، فلو بدت النسخة بطيئة على الاستضافة الذاتية، يمكنك ببساطة حجز خادم أقوى وتضع ما تحتاجه من الموارد ضمنه، لكن هذا الأمر قد يكون مستحيلًا في الاستضافة السحابية. ستعمل العقد التي تبنيها في GitHub Actions مثلًا على معالجين افتراضيين (vCPU) و8 جيجابايت من ذواكر الوصول العشوائي. ستعتمد فاتورتك في الاستضافة السحابية على الوقت المستغرق في بناء تطبيقك، وهذا أمر يجدر أخذه بالحسبان. لماذا نفضل خيارا على آخر؟ إن كان مشروعك صغيرًا إلى متوسط الحجم ولن يحتاج أية متطلبات خاصة (مثل الحاجة إلى بطاقة رسومية لتنفيذ الاختبارات)، ستكون الاستضافة السحابية الحل المناسب غالبًا، إذ ستكون الإعدادات بسيطةً ولن تدخل دوامة إعدادات النظام الخاص بك، كما ستكون الكلفة أقل للمشاريع الصغيرة خاصة؛ أما بالنسبة للمشاريع الأضخم والتي تحتاج إلى موارد أكبر أو بالنسبة للشركات الكبيرة التي تضم عدة فرق للتطوير وعدة مشاريع، قد يكون اختيار منظومة استضافة ذاتية هو الخيار الأنسب. لماذا استخدمنا GitHub Actions في هذه السلسلة؟ يُعدّ GitHub Actions الخيار الأنسب كوننا نستخدم غيت هب GitHub، إذ سيؤمن لنا منظومة CI قوية تعمل مباشرةً دون الحاجة إلى إعداد خادم أو خدمة سحابية يؤمنها طرف ثالث. إضافةً إلى سهولة استخدامه، يُعد GitHub Actions خيارًا جيدًا من عدة جوانب، فقد يكون أفضل خدمة سحابية موجودة حتى اللحظة، إذ يحظى بشعبية كبيرة منذ إصدار النسخة الأساسية منه في نوفمبر (تشرين الثاني) عام 2019. التمرين 11.1 قبل أن ننغمس في إعداد خطوط إنتاج لأنظمة CI/CD، لا بدّ من مراجعة ما قرأناه. لنتهيأ للانطلاق فكر بحالة افتراضية نكون فيها أمام تطبيق يجري تطويره من قِبل فريق من 6 مطورين وسيصدر قريبًا. لنفترض أنّ اللغة المستخدمة في تطوير التطبيق ليست JavaScript/TypeScript فلنقل Python، أو Java، أو Ruby، أو أية لغات قد تفكر بها. اكتب موضوعُا بسيطًا من 200-300 كلمة تجيب فيه أو تناقش النقاط التي سنطرحها تاليًا. يمكنك التحقق من عدد الكلمات التي تكتبها عبر موقع wordcounter. خزّن إجابتك في ملف اسمه "exercise1.md" في جذر المستودع الذي ستنشئه في التمرين 11.2 ناقش النقاط التالية: بعض الخطوات الشائعة في إعداد CI بما فيها التدقيق والاختبار والبناء، وكذلك الأدوات اللازمة لتنفيذ هذه الخطوات في بيئة عمل اللغة التي تختارها. يمكنك البحث عن الأجوبة عبر غوغل Google. ما هي بدائل إعداد منظومات CI عن GitHub Actions أو Jenkins؟ يمكنك الاستعانة بمحرك البحث غوغل. أين سيكون تطبيق هذه الإعدادات أفضل، على استضافة ذاتية أو استضافة سحابية؟ لماذا؟ ما هي المعلومات التي ستحتاجها لاتخاذ قرارك؟ تذكر أنه لا توجد إجابات صحيحة أو خاطئة لجواب هذا السؤال. ترجمة -وبتصرف- للفصل Introduction to CICD من سلسلة Deep Dive Into Modern Web Development اقرأ أيضًا ما هو Git إعادة تأسيس تفريعات طلب السحب وتحديثه في git إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls التكامل المستمر: تثبيت Concourse CI على أوبنتو
  10. يشرح هذا المقال مفاهيم تصميمية أساسية تتمثل بسهولة أو إمكانية الوصول accessibility إلى محتوى مواقع ويب وكيفية تصميم مواقع ويب يستطيع معظم زائريها الحصول على محتواها بسهولة ومتعة. تسهيل وصول جميع المستخدمين إلى مواقع ويب لن يتمكن بعض الزائرين من تجربة موقعك بالطريقة التي تأملها نظرًا لمعوقات فيزيائية أو تقنية قد تعترضهم. لذلك سنناقش في هذا المقال المبادئ العامة لسهولة الوصول accessibility (تترجم أحيانًا إلى شمولية أي شمولية التصميم لكل المستخدمين) وسنشرح بعض القواعد المتعلقة بها. المبادئ العامة لسهولة الوصول قد نربط إمكانية الوصول في البداية بالمعوقات السلبية مثل قولنا بأنّ الوصول إلى هذا البناء ممكن عندما تُعتمد مجموعة قواعد ناظمة مثل عرض الباب أو حجم المرافق الصحية أو موقع المصعد، وهذه مقاربة ضيقة لمفهوم إمكانية أو سهولة الوصول، وفكِّر بالأمر على أساس طريقة مميزة لدعم الآخرين ولخدمة العملاء، فما الذي قد يستفيده الناس في البرازيل من موقعك الذي يعتمد اللغة الإنكليزية؟ هل يمكن لمستخدِمي الهواتف الذكية تصفح مواقع ويب مزدحمة ومخصصة لشاشات الحواسب المكتبية الواسعة والتي تستخدِم حزمة استهلاك بيانات غير محدودة؟ بالطبع سيغادر الزوار موقعك في حالات مثل هذه، إذ ينبغي التفكير عمومًا بالمنتج الذي تقدِّمه انطلاقًا من وجهات النظر المختلفة لجميع العملاء المستهدَفين ومن ثم التكيف معها، فهذه هي سهولة الوصول. سهولة الوصول في عالم ويب تعني سهولة الوصول في سياق عالم ويب قدرة الجميع على الوصول إلى المحتوى الذي تقدِّمه دون النظر إلى الإعاقة التي يعانيها الزائر أو مكانه أو أية محدودية تقنية قد يواجهها أو أية ظروف أخرى. لنتأمل مقطع فيديو: حالة ضعف السمع: كيف يمكن لشخص لديه تدهور في حاسة السمع الاستفادة من مقطع الفيديو؟ لا بدّ إذًا من تزويد الفيديو بالكلمات أو تقدّم نص الفيديو بأكمله، وتأكد أيضًا من قدرة المستخدِم على ضبط مستوى الصوت بما يلبي احتياجاته الخاصة. حالة ضعف البصر: قدّم أيضًا نص الفيديو بأكمله لكي يطَّلع المستخدِم على المضمون دون أن يشغِّله، كما يمكنك تقديم وصفًا صوتيًا لما يحدث في الفيديو. إمكانية التوقف المؤقت: قد لا يفهم المستخدِم ما تقوله إحدى الشخصيات في الفيديو، لذلك من الأفضل تقديم إمكانية إيقاف المقطع مؤقتًا ليتسنى له قراءة كلماته أو إدراك ما يجري. إمكانية استعمال لوحة المفاتيح: لكي يتمكن المستخدِم من الوصول إلى الفيديو أو الخروج منه وتشغيله وإيقافه دون أن يعلق داخله. تتضمن أساسيات سهولة الوصول في ويب أشياءً مثل: ضع دائمًا نصًا بديلًا للصورة للمستخدِمين الذين يعانون من مشاكل بصرية أو لمن لديه اتصال ضعيف بالإنترنت عندما يحتاج الموقع إلى صورة لنقل معنى معين. تأكد من إمكانية تشغيل جميع المستخدِمين لبعض الواجهات الرسومية مثل عرض القوائم بنقرة زر واحدة أي لمسة أو ضغطة على زر "Return" مثلًا. حدِّد بصراحة لغة المحتوى الذي تعرضه لكي تتمكن البرمجيات التي تقرأ محتوى الشاشة من قراءة النصوص بصورة صحيحة. تأكد من قدرة المستخدِم على التنقل بين الأدوات التي تعرضها الصفحة من خلال لوحة المفاتيح فقط دون أن يعلق ضمنها، أي القدرة على الدخول والخروج على الأقل. وهذه النقاط هي البداية فقط. أدارت منظمة W3C منذ عام 1999 مجموعة عمل تُدعى "مبادرة سهولة الوصول على الويب Web Accessibility Initiative" لتطوير معايير إمكانية الوصول من خلال الإرشادات والمواد الداعمة والموارد على المستوى العالمي، ويمكنك الاطلاع على المزيد من خلال موقع المبادرة WAI، كما قد تجد بعض الأفكار في مقالات أكاديمية حسوب. تصميمات موجهة لجميع المستخدمين عندما تشرع في تصميم موقع ويب ينبغي علينا التفكير أولًا بتصميم شمولي Universal Design للموقع يلائم جميع مستخدِميه بغض النظر عن أية إعاقات قد يعانونها أو أية قيود تقنية أو ثقافية أو مكانية. يناقش هذا المقال بعض الأفكار السريعة والناجحة في تصميم أكثر شمولية لمواقع ويب، ولكن لا بدّ أن تكون أولًا على دراية بمفهوم التصميم الشمولي Universal design. التلاؤم اللوني من الأمور المهمة التي تجعل النصوص في مواقع ويب مقروءة هو استخدام خلفية ذات لون ملائم تسهل متابعة النص، إذ سيساعد ذلك مَن يعاني من إعاقة بصرية أو من يستخدِم هاتفه الذكي للقراءة في الخارج وعلى الطرقات. تُحدِّد منظمة W3C التلاؤم اللوني من خلال خوارزمية تحسب نسبة السطوع luminosity ratio بين الخلفية والواجهة، وقد تكون هذه الحسابات معقدةً، لكن بعض الأدوات الجاهزة قد تساعدنا في إنجاز الأمر. اختُبر التلاؤم اللوني لصفحة المقال الأصلي في الصورة السابقة وأعطى نتيجة 8.30:1 وهذا الرقم أعلى بكثير من الحد الأدنى المقبول الذي يقدَّر بالنسبة 4.5:1 وبالتالي لا بد أن يساعد التلاؤم اللوني للصفحة الكثيرين من ذوي الإعاقة البصرية في قراءتها. حجم خط الكتابة يمكنك تحديد حجم خط الكتابة في موقع ويب بوحدات قياس نسبية relative أو مطلقة absolute. وحدات القياس المطلقة لا تُحسَب هذه الوحدات حسابًا تناسبيًا، وإنما تعتمد على حجم محدد بصورة أساسية في الحساب، إذ تُقدَّر وحدة القياس المطلقة غالبًا بالبيكسل px، فإذا وضعت الشيفرة التالية مثلًا في ملف تنسيق CSS: body { font-size:16px; } فأنت تطلب من المتصفح أن يكون حجم الخط 16 بيكسل دائمًا، وقد تلتف بعض المتصفحات الحديثة على هذه القاعدة متظاهرةً أن حجم الخط سيكون 16 بكسل عندما يكون معامل تكبير الصفحة 100%، أي الحجم الطبيعي، ومع هذا وعلى امتداد سنوات عدة فقد عرض إنترنت إكسبلورر عمدًا الخطوط التي ضُبط حجمها على 16 بكسل مثلًا بالحجم 16 بكسل تمامًا بغض النظر عن معامل التكبير وصولًا إلى النسخة 8 التي لا بد من الانتباه لها لأنها لاتزال مستخدَمة. وحدات القياس النسبية تُحسَب هذه الأحجام نسبةً إلى العنصر الأب، وهي أكثر وضوحًا فيما يخص سهولة الوصول لأنها تحترم الإعدادات الخاصة بنظام المستخدِم، كما يُعبَّر عن الوحدات النسبية بالرموز em و% وrem: الحجم المبني على النسبة المئوية %: تخبر هذه الوحدة المتصفح أنّ حجم الخط في العنصر هو نسبة مئوية من حجم الخط في العنصر الأب الذي حُدِّد فيه حجم الخط، فإذا لم يكن للعنصر أب، فستجري الحسابات بالنسبة إلى حجم الخط الافتراضي للمتصفح (16 بكسل عادةً). الحجم المبني على الوحدة Em: تُحسَب اعتمادًا على أسلوب النسبة المئوية ذاته لكن على أساس أجزاء من 1 وليس 100، كما يُقال أن "em" هو عرض الحرف الأبجدي "M" على أساس حرف كبير (إذ يمكن وضعه ضمن مربع بصورة تقريبية). الحجم المبني على الوحدة rem: تُحسَب على أساس نسبة من حجم الخط للعنصر الجذري، ويعبَّر عنها على أساس أجزاء من 1 كما هو حال Em. لنفترض أننا نريد حجمًا أساسيًا للخط مقداره 16 بكسل وحجمًا مقداره 32 بكسل لعنصر العنوان الرئيسي h1، فإذا وجدنا ضمن العنصر h1 الوسم span الذي يطبق تنسيق الصنف subheading، فيجب تصيير ما داخل span أيضًا بالنسبة إلى حجم الخط الافتراضي (16 بكسل عادة)، وإليك شيفرة HTML لتوضيح الفكرة: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Font size experiment</title> </head> <body> <h1>This is our main heading <span class="subheading">This is our subheading</span> </h1> </body> </html> أما شيفرة CSS المبنية على النسبة المئوية: ‫/* 100% من حجم الخط الأساسي للمتصفح والذي يكون عادة 16 بكسل */ body { font-size:100%; } /* أي حوالي 32 بكسل body ضعفي حجم المحدد */ h1 { font-size:200%; } /* أي العودة إلى القياس 16 بكسل h1 نصف */ span.subheading { font-size:50%; } سنواجه المشكلة نفسها عند استخدام وحدة القياس Em: ‫ /* 1em = 100% من قياس الخط الأساسي الذي يكون عادة 16 بكسل*/ body { font-size:1em; } /*أي حوالي 32 بكسل body ضعفي حجم المحدد */ h1 { font-size:2em; } /* أي العودة إلى القياس 16 بكسل h1 نصف */ span.subheading { font-size:0.5em; } لاحظ كيف ستغدو الحسابات مزعجةً إذا أردت ملاحقة العنصر الأب ثم أب الأب وهكذا، كما تُنفّذ معظم التصاميم على برمجيات تستخدِم البكسل، لذلك من الأفضل أن تجري الحسابات من قِبَل الشخص الذي كتب شيفرة CSS تقاس الوحدة rem بالنسبة إلى حجم العنصر الجذري وليس لأيّ عنصر أب، لذلك يمكن كتابة تنسيق CSS كما يلي: ‫/* 1em = 100% من قياس الخط الأساسي الذي يكون عادة 16 بكسل*/ body { font-size:1em; } /*أي حوالي 32 بكسل body ضعفي حجم المحدد */ h1 { font-size:2rem; } /*الحجم الأصلي*/ span.subheading { font-size:1rem; } يبدو الأمر أسهل، أليس كذلك؟ يعمل هذا التنسيق على إنترنت أكسبلورر 9 وغيره من المتصفحات الحالية، لذلك يعود اختيار وحدة القياس لك بالمطلق. لماذا قد أستخدم وحدات القياس النسبية لأنك لا تعرف متى سيرفض المتصفح تكبير أو تصغير حجم النص الذي يعتمد البيكسل على أساس وحدة قياس، كما أنّ موقعك قد يتلقى زيارات ممن يستخدِمون متصفحات قديمةً، لذلك سنقدِّم لك النصائح التالية: استخدم وحدة القياس rem وستكون النتائج مرضيةً في جميع المتصفحات. دع مهمة عرض الخطوط في المتصفحات القديمة لمحركاتها الداخلية، إذ تتجاهل هذه المحركات أيّ خاصية أو قيمة لتنسيقات CSS لا تتوافق معها، وهكذا ستبقى قادرًا على عرض صفحتك على تلك المتصفحات، وعلى أية حال، ستختفي المتصفحات القديمة مع الوقت حتى لو لم يتفق ذلك مع رؤية المصمم. حجم السطر هنالك جدل طويل قائم حول طول الأسطر في ويب، وإليك القصة كاملةً. لقد أدرك العاملون في مجال الطباعة مع ظهور المجلات المطبوعة أن أعين القراء ستعاني عند الانتقال من سطر لآخر إذا كان السطر طويلًا جدًا، وكان الحل هو ظهور الأعمدة، ولم يتغير الأمر كثيرًا عندما انتقلنا إلى عالم الويب، ولا تزال أعين القراء تلاحق الأسطر، لذلك كان الحل بتحديد حجم السطر ليضم ما بين 60 إلى 70 محرفًا فقط لتسهيل الأمر على القارئ، إذ يمكنك لإنجاز الأمر تحديد حجم العنصر الذي يحتوي على النص، وإليك شيفرة HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Font size experiment</title> </head> <body> <div class="container"> <h1>This is our main heading <span class="subheading">This is our subheading</span> </h1> <p>[lengthy text that spans many lines]</p> </div> </body> </html> لدينا عنصر div له صنف التنسيق container، إذ يمكننا تنسيق div بضبط عرضه باستخدام الخاصية width أو من خلال ضبط عرضه الأعظمي لكي لا يزداد كثيرًا باستخدام الخاصية max-width، فإذا أردت موقعًا مرنًا أو متجاوبًا ولم تكن تعرف العرض الافتراضي الذي يأخذه المتصفح، فيمكنك استخدام الخاصية max-width لكي تضبط عدد المحارف في السطر بحدود 70 محرفًا لا أكثر: div.container { max-width:70em; } النصوص البديلة عن الصور والمقاطع الصوتية ومقاطع الفيديو تضم مواقع الويب أشياء أخرى غير النصوص، ولا بد من الانتباه إليها: الصور قد تكون الصور لمجرد العرض وتدعى بالصور الاستعراضية أو قد تحتوي على معلومات، لكن لا ضمانة بأن يراها المستخدِم لأسباب منها: استخدام ذوي الإعاقة البصرية قارئات الشاشة التي تتعامل مع النصوص فقط. استخدام شبكات إنترانت محلية تفرض قيودًا على عرض الصور من مصادر خارجية أو شبكات توريد محتوى CDN. تعطيل المستخدِم عرض الصور لتوفير حزمة البيانات المتاحة وخاصةً عند استخدام الهواتف الجوالة. أما الصور الاستعراضية Decorative، فتُستخدَم لتزيين الصفحات ولا توصل أية معلومات حقيقة، كما يمكن استبدالها في معظم الحالات بصورة خلفية، وتأكد من وضع نص فارغ على أساس قيمة للسمة alt في عنصر الصورة كي لا يتجاهل المتصفح عرض النص البديل. <img src="deco.gif" alt=""> وأما الصور التي تحتوي على معلومات Informative، فتُستخدَم لإيصال معلومات محددة، مثل عرض رسم بياني أو وجه أحد ما أو أية معلومات أخرى، إذ عليك أن تقدِّم على الأقل نصًا بديلًا في هذه الحالة (السمة alt)، فإذا أمكن وصف الصورة جيدًا، فيكفي استخدام النص البديل، وإلا عليك تقديم محتوى الصورة تقديمًا آخرًا في الصفحة نفسها مثل أن تعرض بالإضافة إلى الرسم البياني جدولًا يضم المعلومات نفسها، أو الجأ إلى السمة longdesc التي تحمل عنوان URL يشير إلى مصدر يشرح صراحةً محتوى الصورة. الصوت والصورة لابد أن تقدِّم بديًلا عن الوسائط السمعية والبصرية أيضًا. ترجمة الفيديو أو عرض كلماته: لا بد من إضافة كلمات الفيديو لمساعدة الزوار ذوي الإعاقة السمعية أو الذين لا يمتلكون مكبرات صوتية أو من يعمل في بيئات صاخبة. تقديم نص الفيديو أو الملف الصوتي كاملًا: سيكون عرض الكلمات أثناء تشغيل الفيديو ممتازًا لمن لديه الوقت لمتابعته، لكن قد لا يتمكن العديد من الزوار من ذلك، بالإضافة إلى اعتماد محركات البحث على النصوص لفهرسة المحتوى، لذلك من الأجدى تقديم نصوص كاملة توضِّح ما يقال في الفيديو أو في المقطع الصوتي. ضغط الصور عندما يرغب الزائر في عرض الصور على المتصفح لكنه يعاني من محدودية في حزمة تراسل البيانات وخاصةً في البلدان النامية وعلى أجهزة الهاتف المحمول، لذلك اضغط الصور على موقعك إذا كنت تريده ناجحًا، وستجد العديد من الأدوات التي تساعدك في ذلك: برمجيات تُثبَّت على جهازك: ستجد ImageOptim على ماك، وستجد PNGcrush على دوس ولينوكس ويونكس، بينما يعمل OptiPNG على كل المنصَّات. أدوات على الإنترنت: مثل smushit!‎ من ياهو Yahoo و Online Image Optimizer من Dynamic Drive، إذ يحوِّل هذا الأخير الصور تلقائيًا من تنسيق إلى آخر إذا كان أكثر فعاليةً فيما يخص تخفيض استهلاك حزمة تراسل البيانات. نظرة إلى ميزات HTML التي تدعم سهول الوصول هنالك مجموعة من الميزات الخاصة في HTML قد تسهل وصول الأشخاص ذوي الإعاقة إلى محتوى صفحة ويب، وسنستعرض بعضها في هذه الفقرة. التنقل عبر المفتاح TAB يمكن للزائرين الذين لا يمتلكون أجهزة تأشير مثل الفأرة، أو لا يستطيعون استخدامها التنقل عبر الروابط من خلال استخدام المفتاح TAB، إذ ينبغي أن تكون الروابط مرتبةً بطريقة منطقية لاستخدام هذه الميزة، لذلك تقدِّم HTML السمة tabindex التي تحدِّد الترتيب، فإذا كانت شيفرة HTML المكتوبة خطيةً ومتتابعةً كما ينبغي، فستظهر الروابط وفق الترتيب المنطقي تلقائيًا. <ul> <li><a href="here.html" tabindex="1">Here</a></li> <li><a href="there.html" tabindex="3">There</a></li> <li><a href="anywhere.html" tabindex="2">Anywhere</a></li> </ul> تعرض الشيفرة السابقة التي قدمناها لمجرد توضيح الفكرة ترتيب استخدام TAB من "Here" إلى "Anywhere" إلى "There". عناوين الروابط إذا لم يشرح الرابط نفسه بنفسه، أو كان من الأفضل شرح وجهة الرابط بتفاصيل أكثر، فيمكنك إضافة معلومات عن الرابط باستخدام السمة title. <p>I'm really bad at writing link text. <a href="inept.html" title="Why I'm rubbish at writing link text: An explanation and an apology.">Click here</a> to find out more.</p> مفاتيح الوصول تزوِّد مفاتيح الوصول Access keys المستخدِم بطريقة سهلة للتنقل بتعيين اختصار إلى الرابط عبر لوحة المفاتيح، إذ يتلقى الرابط التركيز عندما يضغط المستخدِم Ctrl أو Alt مع مفتاح الوصول، وتختلف مجموعة الأزرار التي تُضغَط معًا من نظام لآخر. <a href="somepage.html" accesskey="s">Some page</a> روابط التجاوز تعمل روابط التجاوز Skip Links على أساس رديف للتنقل عبر المفتاح TAB، إذ تسمح بالقفز إلى جزء محدَّد من الصفحة، فقد يرغب أحد الزوار بتجاوز الكثير من الروابط إلى المحتوى الرئيسي بدلًا من التنقل من رابط لآخر حتى الوصول إلى المطلوب. <header> <h1>The Heading</h1> <a href="#content">Skip to content</a> </header> <nav> <!-- navigation stuff --> </nav> <section id="content"> <!--your content --> </section> ترجمة -وبتصرف- للمقال ?What is accessibility، والمقال ?How can we design for all types of users، والمقال ?What HTML features promote accessibility. اقرأ أيضا الفرق بين إمكانية الوصول والشمولية في تصميم تجربة المستخدم سهولة وصول جميع الزوار لمواقع وتطبيقات الويب التحقق من سهولة الوصول لصفحات الويب المبادئ الخمسة الأساسية في قابلية الاستخدام إعداد صور متجاوبة في صفحات الويب
  11. انصب تركيزنا في هذا القسم على بناء منظومة تكامل مستمر CI بسيطة وفعالة ومحكمة، تساعد المطورين على العمل معًا والحفاظ على جودة الشيفرة ومن ثم نشرها بأمان. ما الذي يمكننا فعله أكثر؟ لنتذكر أنه في العالم الحقيقي ستمتد أيادٍ إلى الكعكة غير أياد المطورين والمستخدمين. حتى وإن لم يكن ذلك صحيحًا، وخاصة بالنسبة للمطورين، إلا أنّ هناك الكثير الذي تقدمه منظومة CI غير ما اطلعنا عليه. مجال الرؤية والفهم في جميع الشركات ما عدا الصغيرة منها، لا تُتخذ القرارات حول تطوير المنتجات حصرًا من طرف المطورين. يشير مصطلح أصحاب الشأن "stakeholder" إلى الأشخاص داخل وخارج فريق التطوير، الذين لديهم مصلحة في مراقبة تقدم عملية التطوير.عند هذا المستوى، هناك غالبًا تكاملٌ بين git وأي برنامج لإدارة المشاريع أو تتبع الثغرات قد يستخدمه الفريق. يُعد امتلاك مرجع إلى نظام التتبع في طلبات السحب أو في الشيفرة المعتمدة أكثر الطرق شيوعًا لتنفيذ ذلك. وهكذا، عندما تعمل على النقطة رقم 123 مثلًا، بإمكانك عندها تسمية طلب السحب الخاص بك BUG-123: Fix user copy issue، وسيلاحظ نظام تتبع الثغرات عندها الجزء الأول من اسم طلب السحب، وسينقل النقطة إلى قائمة النقاط المنفَّذة Done عندما يُدمج الطلب. تنبيهات عندما تنتهي عملية CI بسرعة، فمن المناسب أن نراقب العملية فقط وننتظر النتائج، لكن مع ازدياد حجم المشاريع ستزداد أيضًا فترة تنفيذ عمليات بناء واختبار الشيفرة. سيقودنا ذلك إلى الحالة التي تستغرق فيها ظهور نتائج بناء الشيفرة وقتًا طويلًا، مما يدفع المطور للتفكير في العمل على مهمة أخرى، وهذا سيقود بدوره إلى نسيان عملية البناء. ستظهر المشكلة في طرحنا هذا خاصة عندما نتحدث عن دمج طلبات السحب التي قد تؤثر على عمل مطور آخر، إما بالتسبب بمشاكل في عمله أو تأخير هذا العمل. وقد يقودنا ذلك أيضًا إلى الحالة التي تعتقد فيها أنك نشرت شيئًا، لكنك في الواقع لم تنهي عملية النشر، وسيؤدي ذلك إلى سوء التواصل مع أعضاء فريقك أو مع الزبائن (كأن تقول: "جرب من جديد، لا بدّ أنّ المشكلة قد حُلَّت"). هناك عدة أساليب لحل هذه المشكلة، تتدرج من إنشاء تنبيهات بسيطة إلى عمليات أكثر تعقيدًا تدمج ببساطة الشيفرة التي تمرر إليها إن تحققت جملةٌ من الشروط الموضوعة مسبقًا. سنناقش حاليًا التنبيهات مثل حل بسيط، كونها الوحيدة التي تتعلق بسير مخطط عمل الفريق. يرسل غيت هب افتراضيًا بريدًا إلكترونيًا عند إخفاق البناء. يمكن تغيير ذلك لإرسال تنبيهات بغض النظر عن حالة البناء، كما يمكن تهيئته لإنذارك على واجهة ويب غيت هب GitHub. طبعًا هذا الأمر رائع، لكن ماذا لو أردنا أكثر من ذلك؟ ماذا لو لم يعمل هذا الحل لسببٍ ما مع حالتنا؟ يمكن أن يتكامل غيت هب GitHub مع عدة تطبيقات رسائل مثل Slack لإرسال التنبيهات، وستكون هذه التطبيقات قادرةً على تحديد متى ترسل هذه التنبيهات بناءً على منطق يفرضه غيت هب GitHub. التمرين 11.18 أعددنا قناة fullstack_webhookعلى مجموعة Discord على العنوان "https://study.cs.helsinki.fi/discord/join/fullstack" لاختبار تكامل منظومة الرسائل. ستحتاج طبعًا إلى بريد إلكتروني للتسجيل، وانتبه إلى ضرورة استخدام عنوان خطاف الويب webhook الخاص بالتطبيق Discord لتنفيذ هذا التمرين. ستجد هذا الخطاف في الرسالة المنبثقة القناة "fullstack_webhook". ويُستحسن عدم الالتزام بالخطاف على غيت هب GitHub. أفعال لتنبيه المستخدم إلى نجاح أو فشل البناء ستجد العشرات من أفعال GitHub Actions التي طورها مطورون مستقلون على GitHub Action Marketplace بمجرد أن تبحث عن العبارة discord. اختر واحدًا لتستخدمه في هذا التمرين. وقد اخترنا discord-webhook-notify لأنه حصل على تقييم مرتفع وله توثيق جيد. هيئ الفعل بحيث يعطي نوعين من التنبيهات: مؤشر على النجاح إن نُشرت النسخة. مؤشر على الفشل إن أخفق البناء. في حال وقوع خطأ، لا بدّ أن تكون رسالة الخطأ مسهبة لمساعدة المطور على إيجاد الخطأ بسرعة وإيجاد الشيفرة المعتمدة التي سببت هذا الخطأ. ابحث في توثيق GitHub عن كيفية التحقق من حالة المهمة. يمكن أن تبدو التنبيهات على النحو التالي: المقاييس Metrics لقد أشرنا في الفقرة السابقة أنه عندما ينمو المشروع ستزداد مدة إنجاز خطوات البناء والاختبار، وهذا ليس بالأمر المثالي، فكلما طالت حلقة وصول النتائج ستصبح دورة التطوير بطيئة. وعلى الرغم من إمكانية القيام بأشياء لتقليل الوقت اللازم للبناء، من المفيد أيضًا أن ننظر جيدًا إلى الصورة الكلية للوضع. فمن الجيد أن نعرف كم استغرقت عملية البناء قبل أشهر عدة موازنةً مع ما تستغرقه الآن. هل يسلك الاختلاف منحًى خطيًا أم يظهر على هيئة قفزات فجائية؟ كما أنّ معرفة السبب الكامن خلف زيادة زمن البناء سيساعدنا جدًا في حل المشكلة؛ فإذا زاد زمن التنفيذ على نحوٍ خطي من 5 إلى 10 دقائق خلال سنة، فيمكننا أن نتوقع بأنه سيزداد أيضًا بضع دقائق خلال عدة أشهر قادمة ليصل إلى 15 دقيقة، وستكون لدينا فكرةً عن قيمة ما ننفقه من وقت لتسريع عمل منظومة CI. يمكن أن تكون المقاييس ذاتية- التسجيل self-reported وتدعى أيضًا مقاييس "دفع-Push"، إذ تسجل كل عملية بناء الوقت الذي تستغرقه، أو أن نحضر البيانات من واجهة برمجية بعد انتهاء العملية وتدعى أحيانًا مقاييس "سحب-Pull". يتمثل خطر التسجيل الذاتي في الوقت الذي ستستغرقه عملية التسجيل بحد ذاتها، والتي قد يكون لها أثر على الوقت الكلي المستغرق للبناء. يمكن أن تُرسل هذه البيانات إلى قاعدة بيانات تعمل وفق سلاسل زمنية time-series DB، أو إلى سِجِل من نوع آخر. هناك عدة خدمات سحابية لتجميع قياساتك بكل سهولة، ومن الخيارات الجيدة الخدمة Datadog. المهام الدورية هناك بعض المهام الدورية التي يجب تنفيذها ضمن فرق تطوير البرمجيات، إذ يمكن أتمتة بعضها من خلال بعض الأدوات المتوفرة، وعليك أتمتة بعضها الآخر. تتضمن الفئة الأولى من المهام الدورية التحقق من الحزم لتفادي الاختراقات الأمنية، وقد تساعدك في ذلك العديد من الأدوات الجاهزة. سيكون بعض هذه الأدوات مجانيًا لمشاريع محددة (مفتوحة المصدر مثلًا) مثل الأداة Dependabot التي يقدمها GitHub. وإليك النصيحة التالية: من الأفضل دائمًا استخدام أدوات جاهزة لأداء هذه المهام، إن سمحت بذلك ميزانيتك، بدلًا من الاعتماد على حلولك الخاصة، فإن لم تكن مهتمًا بتطوير أدوات تتعلق بأمور الأمن مثلًا، استخدم Dependabot للتحقق من الثغرات الأمنية بدلًا من تطوير الأداة بنفسك. لكن ماذا عن المهام التي لا تتوفر لها أدوات مساعدة؟ يمكنك أتمتة هذه المهام بنفسك عن طريق GitHub Actions أيضًا، إذ يزودك GitHub Actions بمُطلِقات أحداث المجدولة scheduled trigger التي يمكن استخدامها لتنفيذ مهمة محددة في وقت محدد. التمارين 11.19 -11.21 11.19: التحقق الدوري من سلامة البرمجيات لدينا الثقة الآن بأنّ خط الإنتاج الذي عملنا عليه سيمنع نشر الشيفرة المخفقة، لكن مع ذلك هناك مصادر عديدة للأخطاء؛ فعندما يعتمد تطبيقنا مثلًا على قاعدة بيانات قد لا تكون متوفرة دائمًا، سيتوقف التطبيق عن العمل في لحظةٍ ما. لهذا من المفيد جدًا التحقق دوريًا من سلامة عمل التطبيق عن طريق إرسال طلب HTTP-GET إلى الخادم. ندعو هذه العملية عادة بعملية التحقق من الاتصال "ping". من الممكن أن نجدول أفعال GitHub لتُحدّث دوريًا وبصورة منتظمة. استخدم الفعل url-health-check أو أي بديل له وجدول عملية التحقق من الخادم الذي تنشر عليه التطبيق. حاول محاكاة الحالة التي يخفق فيها تطبيقك، تأكد حينها أن عملية التحقق ستكتشف الخطأ. اكتب مخطط العمل الدوري الذي أوجدته على ملف خاص. تنبيه: سيستغرق GitHub Actions وقتًا طويلًا حتى يبدأ بتنفيذ مخطط العمل الذي جدولته للمرة الأولى، فقد تطلب منا الأمر قرابة الساعة، لذلك تُعد فكرة إطلاق مخطط العمل مباشرةً بتنفيذ عملية دفع للشيفرة إلى الاستضافة فكرةً جيدة. انتقل بعد ذلك لتنفيذ المخطط المجدول بعد أن تنجح معك هذه الحيلة. تنبيه: عندما تنجح في تنفيذ ما طلبناه، من الأفضل أن تقلل مرات التحقق من الاتصال مع الخادم إلى مرة كل 24 ساعة أو عطل القاعدة، وإلا ستكلفك عملية التحقق المستمرة ساعاتك المجانية المتاحة خلال الشهر. 11.20: خط إنتاج خاص بك ابنِ خط إنتاج CI/CD لبعض التطبيقات التي أنجزتها سابقًا. من التطبيقات المرشحة للعمل عليها تطبيق دليل الهاتف الذي طورناه في القسمين 2 و3 من المنهاج، أو تطبيق المدونة الذي طورناه في القسم 4 والقسم 5، أو تطبيق الطرائف الذي بنيناه بالاستعانة بالمكتبة Redux في القسم 6. ستضطر غالبًا إلى إعادة هيكلية التطبيق لتجمع قطع الشيفرة المتفرقة، وعليك في الخطوة الأولى وضع الواجهتين الأمامية والخلفية في مستودع واحد. لست مجبرًا على ذلك طبعًا، لكنه سيسهل عليك الأمر كثيرًا. إحدى الهيكليات المقترحة هي وضع الواجهة الخلفية في جذر المستودع وأن تضع الواجهة الخلفية ضمن مجلد فرعي، ويمكنك أيضًا نسخ ولصق بنية التطبيق النموذجي الذي نفذناه في هذا القسم، أو أن تحاول الاستفادة من التطبيق النموذجي الذي اطلعنا عليه في القسم 7. ربما من الأفضل أن تنشئ مستودعًا جديدًا لهذا التمرين، ومن ثم تنسخ وتلصق الشيفرة ضمنه. قد تضطر غالبًا في العمل الواقعي إلى تنفيذ ذلك ضمن المستودع القديم، لكن الإنطلاقة الجديدة الآن ستسهل علينا الأمر. سيستغرق منك هذا التمرين وقتًا وجهدًا، لكن الحالة التي تواجهها هنا، وهي بناء خط إنتاج لنشر شيفرة قديمة، شائعة جدًا في الحياة العملية. لن يُنفّذ هذا التمرين في نفس المستودع الذي نفذت فيه التمارين السابقة، لأنك لا تستطيع أن تعيد سوى مستودع واحد إلى منظومة تسليم التمارين، ضع رابطًا إذًا للمستودع الآخر ضمن المستودع الذي أشرت إليه في نموذج التسليم. 11.21: حماية الفرع الرئيسي وتقديم طلب سحب احمِ الفرع الرئيسي للمستودع الذي أنجزت فيه التمرين السابق، وامنع المدراء أيضًا هذه المرة من دمج الشيفرة مع الفرع الرئيسي دون مراجعتها. قدم طلب سحب، واطلب من أحد مستخدمي GitHub التالية أسماؤهم mluukkai و/ أو kaltsoon أن يراجع شيفرتك، وبعد أن تنتهي المراجعة، ادمج الشيفرة مع الفرع الرئيسي، وانتبه إلى أن يكون المراجع من المتعاونين معك في المستودع. اتصل بنا على Discord لكي نراجع شيفرتك، ومن الأفضل إرسال رسالة خاصة تتضمن رابط دعوة. بعدها يكون العمل قد أُنجز. ترجمة -وبتصرف- للفصل Expanding further من سلسلة Deep Dive Into Modern Web Development اقرأ أيضًا المقال التالي: مدخل إلى الحاويات المقال السابق: نشر إصدارات التطبيق بأمان في منظومة التكامل والتسليم المستمر نشر التطبيقات وتوزيعها وفق نهج التسليم المستمر إعداد التكامل المستمر والنشر المستمر باستخدام الخدمتين CircleCI وCoveralls
  12. من الجيد الاطلاع على التخطيطات layouts الأكثر استخدامًا لصفحات الويب قبل البدء بتصميمها، وهناك سبب يدفعنا في الواقع للخوض في تصميم الصفحات، إذ ستبدأ العمل عادةً انطلاقًا من صفحة فارغة، ومن ثم يأخذك العمل إلى نواحٍ عدة، فإذا لم تمتلك بعض الخبرة، فستشعر بالقلق عندما تبدأ من نقطة الصفر، ولهذا السبب سنرشدك في هذا المقال إلى قواعد عامة وجوهرية تساعدك في تصميم موقعك بناءً على خبرة طويلة تمتد 25 عامًا. حتى وإن كان التركيز حاليًا على تصميم المواقع المخصصة للهواتف الذكية، لكن المكوّنات الأساسية لبناء صفحات الويب بقيت كما يلي: الترويسة Header: وهي الجزء الذي يظهر أعلى الصفحة ويحتوي على معلومات مكررة في كل الصفحات مثل اسم الموقع وشعاره بالإضافة إلى منظومة سهلة الاستخدام لأغراض التنقل بين الصفحات. المحتوى الرئيسي Main Content: وهي المنطقة الأوسع من الصفحة، وتحتوي على المعلومات الخاصة التي ينبغي عرضها في هذه الصفحة تحديدًا. إضافات ولوحات على الجوانب Stuff on the side: وتضم أيّ شيء لا يجب أن يتواجد في القسم الرئيسي، أي ما يلي: معلومات مشتركة بين مجموعة فرعية من الصفحات. معلومات مكملة لما ورد في المحتوى الرئيسي. منظومة تنقل بديلة. التذييل Footer: يُشاهَد في أسفل الصفحة ويتضمن كما الترويسة معلومات عامة تتعلق بالموقع لكنها أقل أهمية. تشترك الكثير من الصفحات بهذه الأقسام، لكن قد تختلف بطريقة توضعها، وإليك بعض الأمثلة، إذ يمثل 1 الترويسة، ويمثل 2 التذييل، في حين يمثل A المحتوى الرئيسي؛ أما B1 و B2 فهما بعض الأقسام على جانبي الصفحة: تخطيط أحادي العمود: وهو تخطيط مفيد جدًا لمتصفحات الهواتف الجوّالة لتجنب الفوضى في الشاشات الصغيرة. تخطيط ثنائي الأعمدة: ويستهدف عادةً الأجهزة اللوحية لأن شاشاتها أكثر عرضًا من الهواتف الجوالة. تخطيط ثلاثي الأعمدة: ويناسب متصفحات الحواسب المكتبية التي تتميز بشاشات كبيرة على الرغم من أنّ عرض المحتوى ضمن شاشات أصغر هو ما يفضله العديد من مستخدمي الحواسب المكتبية. لكن المتعة الحقيقية ستبدأ عندما تمزج بين التخطيطات الثلاث السابقة في الصفحة نفسها، ويبقى ما عرضناه مجرد أمثلة قد تأخذ بها أو لا. قد تلاحظ كيف يمكن أن يتغير موقع المحتوى الرئيسي في الصفحة إلا أنّ الترويسة (1) تبقى في الأعلى، كما يبقى التذييل (2) في الأسفل، وطالما أنّ المحتوى الرئيسي (A) هو الأكثر أهميةً، فامنحه المساحة الأكبر من الصفحة. إذًا سنعرف في مقالنا على أقسام صفحة الويب والمكان الأفضل لوضعها، وننصحك قبل إكمال قراءة المقال أن تعرف تمامًا ما تريد إنجازه عندما تفكر في تصميم موقع ويب، وسنناقش في مقالات أخرى التصميم المتجاوب للمواقع أي المواقع التي تتغير تخطيطات صفحاتها بناءً على حجم الشاشة. تخطيط أحادي العمود يقدم التخطيط وحيد العمود جميع محتويات الصفحة تقديمًا متتابعًا ومباشرًا، وتذكَّر أنّ الكثير من متابعيك يستعرضون موقعك من خلال الحواسب المكتبية، فاحرص أن يكون المحتوى مقروءًا وسهل الاستعمال على تلك الأجهزة أيضًا. تخطيط ثنائي الأعمدة تُصمَّم المدونات عادةً وفق تخطيط العمودين، إذ يُستخدَم العمود العريض لنشر المحتوى الرئيسي والآخر الضيق لعرض بقية الأشياء مثل بعض المكوّنات الخاصة وأدوات التنقل الإضافية والروابط الإعلانية. انظر إلى الصورة (B1) في الشكل السابق تحت الترويسة مباشرةً، إذ تتعلق هذه الصورة بالمحتوى الرئيسي، لكن المحتوى يبدو معقولًا أكثر دونها، لذلك بالإمكان أن تعدها جزءًا من المحتوى الرئيسي أو من المحتوى الجانبي، وليس الأمر بهذه الأهمية، لأن ما يهم فعلًا هو وضع المحتوى الرئيسي فقط أو ما يتعلق به مباشرةً تحت الترويسة. حالة قد تخدعك إليك هذه الصفحة من موقع MICA التي تبدو وكأنها تستخدِم ثلاثة أعمدة لكنها ليست كذلك: تعوم Float اللوحتين B1 و B2 حول المحتوى الرئيسي، وتذكر المصطلح "يعوم" عندما تبدأ بتعلم التنسيقات المورثة CSS. لِمَ قد نظن أنّ الصفحة منسقة في ثلاثة أعمدة؟ لأن الصورة في أعلى يمين الصفحة لها شكل الحرف "L" ولأن القسم B1 يبدو وكأنه عمود يدعم المحتوى الرئيسي المنزاح، ولأن حرفي "M" و"I" للشعار "MICA" يُشكِّلان خطان عموديان يعطيان انطباعًا قويًا بوجود ثلاث أعمدة، وهذا مثال جيد عن تخطيط كلاسيكي لصفحة ويب مع لمسة إبداعية، فالتخطيط البسيط أسهل تنفيذًا، لكن امنح نفسك مع ذلك فرصةً للاستكشاف والتعبير عن إبداعاتك في هذا المجال. حالة أخرى ستخدعك أكثر تعتمد هذه الصفحة من موقع The Opera de Paris على تخطيط العمودين، لكنك ستلاحظ العديد من الحيل هنا وهناك قد تشوش نظرتك إلى تخطيطها، فالترويسة تحديدًا تتداخل مع صورة المحتوى الرئيسي، وطريقة انحناء قائمة الترويسة التي تتماشى مع الانحناء أسفل الصورة تجعلنا نتوقع أنهما شيء واحد علمًا أنهما تقنيًا مختلفان تمامًا، كما تبدو الصورة السابقة المأخوذة لموقع "Opera" أكثر تعقيدًا من الصورة التي تسبقها من موقع "MICA"، لكنها أسهل تنفيذًا مع الانتباه إلى نسبية الكلمة "سهل". وهكذا نرى إمكانية إبداع مواقع ويب رائعة بتخطيطات بسيطة، وألق نظرةً إذًا على مواقع الويب التي تفضِّلها ثم اسأل نفسك أين الترويسة؟ أين المحتوى الرئيسي والجانبي والتذييل؟ سيلهمك ذلك إلى تصاميم خاصة بك ويمنحك تلميحات عما يفيدك في عملك وعما لا يفيد. ترجمة -وبتصرف- للمقال ?What do common web layouts contain. اقرأ أيضًا المقال السابق: البدء بتصميم موقع ويب التحكم في تخطيط الصفحة وضبط محاذاة العناصر في CSS
  13. يغطي هذا المقال الخطوة الأولى والأهم للانطلاق في أيّ مشروع، وهي تحديد ما نريده من مشروعنا وخصوصًا مواقع الويب، إذ يركِّز الكثيرون في هذا المضمار على الجانب التقني من المشروع، لكن ما يهم فعلًا -وعلى الرغم من أهمية التقنية التي يستخدِمها المرء في حرفته- هي الغاية التي ينشد الوصول إليها، فالكثير من المشاريع التي أخفقت لم يكن سبب إخفاقها هو الناحية التقنية أو المعرفية، وإنما ضبابية أهدافها ورؤيتها، لهذا السبب، عندما تخطر في بالك فكرةً وتريد نقلها لتصبح موقع ويب، لا بد لك من الإجابة على بعض الأسئلة قبل أيّ شيء آخر: ما الذي أريد إنجازه بدقة؟ كيف سيساعدني موقع الويب في الوصول إلى أهدافي؟ ما الذي يتوجب علي فعله وبأي ترتيب للوصول إلى أهدافي؟ تُدعى هذه الخطوات فكرة المشروع أو التصور الأولي للمشروع project ideation، وهي ضرورية للوصول إلى هدفك سواءً كنت مبتدئًا أم مطوّرًا محترفًا. لا يبدأ المشروع عادةً بالالتفات إلى نواحيه التقنية، فلا يؤلف الموسيقيون مقطوعاتهم حتى يتكون لديهم تصوّر أولي لما يرغبون في عزفه، ولا الرسامون ولا الكتَّاب ولا مطورو مواقع الويب، إذ تأتي التقنية ثانيًا، كما لا ينفي ذلك اطلاقًا الدور الحيوي للتقنية، فلا بد أن يتقن الموسيقيون العزف على الآلات، لكنهم لا يقدِّمون أعمالًا دون تصوّر لما سيقدِّمونه، لهذا عليك التروِّي والعودة إلى التفاصيل لتقرِّر ما تريده قبل القفز إلى كتابة الشيفرة واستخدام أدوات البناء. سيساعدك الجلوس ومناقشة أفكارك مع أصدقائك، لكن لا تتوقع فائدةً كبيرةً، إذ عليك الجلوس وتنظيم أفكارك لتصل إلى رؤية واضحة للطريق الذي ستمشيه لتحويل أفكارك إلى واقع، فجُلّ ما تحتاجه في هذه المرحلة قلم وورقة وبعض الوقت للإجابة على الأسئلة التي سنطرحها تباعًا في مقالنا. ما الذي أريد إنجازه بالتحديد؟ يبدو أنّ هذا السؤال هو الأهم لأنه يقود كل شيء آخر، لذا ضع قائمةً بكل الأهداف التي تريد تحقيقها مثل بيع البضائع لكسب المال أو التعبير عن آراء سياسية أو التعرف على أصدقاء جدد، أو أيّ شيء تريده. افترض أنك موسيقي وقد ترغب بأن: يستمع الناس إلى موسيقاك. تبيع بعض المنتجات. تتعرف على موسيقيين آخرين. تناقش الآخرين بموسيقاك. تعلم الموسيقى من خلال الفيديوهات. تنشر صورًا لقططك. تتعرف على أصدقاء جدد. عندما تنتهي من وضع قائمة الأهداف، فلا بدّ من ترتيبها حسب الأولوية التي تراها من الأكثر إلى الأقل أهمية والتي قد تكون بالصورة التالية: التعرف على أصدقاء جدد. استماع الناس إلى موسيقاك. مناقشة الآخرين بموسيقاك. التعرف على موسيقيين جدد. بيع بعض المنتجات. تعليم الموسيقى من خلال الفيديوهات. نشر صور لقططك. سيساعدك التمرّن على كتابة أهدافك بهذه الصورة على اتخاذ القرارات (هل عليّ تنفيذ هذه الميزات أو استخدام هذه الخدمات أو اعتماد تصاميم معينة)، وبعد ترتيبنا لقائمة الأهداف، فلننتقل إلى السؤال الثاني. كيف سيقربني موقع الويب من أهدافي؟ وضعتَ قائمةً بأهداف وترى أنك بحاجة إلى موقع ويب لتحقيق هذه القائمة، ولنعد قليلًا إلى عناصر القائمة، سنجد أنها تضم خمسة أهداف تتعلق بالموسيقى، وهدف يتعلق بالعلاقات الشخصية، وأخيرًا هدف ليس له علاقة إطلاقًا بالموسيقى وإنما بصور القطط، فهل من المنطقي بناء موقع ويب يحقق كل هذه الأهداف؟ هل الأمر ضروري؟ فقد تجد أن خدمات الويب الموجودة قد تحقق أهدافك دون عناء بناء موقع ويب جديد، فالتعرف على أصدقاء جدد مثلًا هي حالة واضحة للاستفادة من تلك الخدمات، إذ ستمُضي وقتك في تصميم وبناء وصيانة موقع بدلًا من البحث جديًا على أصدقاء جدد. طالما أنّ أهم ما في الأمر هو الوصول إلى أهدافنا، فمن الأفضل استغلال إمكانياتنا في تجريب الأدوات الموجودة بدلًا من البدء من الصفر، وكذلك الأمر بالنسبة إلى نشر الصور، إذ توجد فعلًا خدمات كثيرة لهذه الغاية، ولا مبرر أبدًا لإهدار الوقت في بناء موقع ويب لنشر صور القطط، كما ترتبط الأهداف الخمسة الأخرى بالموسيقى، وستجد الكثير من خدمات الويب التي تغطي هذه الأهداف، لكن من المنطقي في هذه الحالة التفكير في بناء موقع ويب خاص بك لهذه الغايات، فقد يساعدك موقع الويب في تجميع كل الأشياء التي تحتاجها في مكان واحد (وهذا أمر مفيد في تحقيق الأهداف 3 و5 و6) ويعزز العلاقات بينك وبين العامة (تكمن فائدته في تحقيق الهدفين 2 و4). باختصار، وطالما أن الأهداف تحوم حول الموضوع نفسه، فقد يساعدنا تجميع كل شيء في المكان نفسه على تحقيق أهدافنا، كما يساعد متابعينا في التواصل معنا، وبالتالي ستجد الطريق الأفضل لبلوغ أهدافك دون أن تبدد جهودك سدًى عند الإجابة على السؤال "كيف يساعدني موقع الويب في الوصول إلى أهدافي؟". ما الذي يتوجب علي فعله وبأي ترتيب للوصول إلى أهدافي؟ الآن وقد حددت أهدافك، فقد حان الوقت لتحويل هذه الأهداف إلى خطوات قابلة للإنجاز، وعليك التذكُّر دائمًا بأنّ الأهداف تتطور مع الوقت حتى عند تنفيذ المشروع وليست جامدةً، وخاصةً عندما تصادف عقبات غير متوقعة أو عندما ستغير رأيك بمسألة ما. لنعد إلى مثالنا السابق بدلًا من الإسهاب في التفسيرات ولنوضح الأمر: ليستمع الناس إلى موسيقاك عليك ما يلي: تسجيل بعض الألحان. تحضير بعض الملفات الصوتية التي يمكن استخدامها على الويب (هل يمكن الاستفادة من خدمة موجودة؟). امنح الآخرين إمكانية الوصول إلى موسيقاك في بعض أقسام موقعك. لمناقشة الآخرين بموسيقاك عليك ما يلي: كتابة بعض المقالات لبدء الحوار. حدِّد الطريقة التي ستظهر عليها مقالاتك. انشر هذه المقالات على الويب. للتعرف على موسيقيين جدد عليك ما يلي: زوّد متابعيك بقنوات للتواصل معك (بريد إلكتروني، فيس بوك، هاتف، بريد). حدد الطريقة التي سيصل فيها الآخرون إلى قنوات الاتصال التي توفرها عبر موقعك. لبيع بعض المنتجات عليك ما يلي: حضِّر منتجاتك وخزّنها. جِد طريقةً مناسبةً لشحنها. جِد طريقةً مناسبةً للدفع. جِد آليةً مناسبةً على موقعك تسهِّل على الناس طلب منتجاتك. لتعليم الموسيقى من خلال الفيديوهات عليك ما يلي: سجِّل مقاطع فيديو لدروسك. اجعل فيديوهاتك مناسبةً للاستعراض عبر الويب (مجددًا، هل يمكن الاستفادة من خدمة موجودة؟). امنح الآخرين إمكانية الوصول إلى فيديوهاتك في بعض أقسام موقعك. تجدر الإشارة هنا إلى نقطتين: الأولى: وهي أنّ بعض الأعمال لا تتعلق بالويب مثل تسجيل الموسيقى وكتابة المقالات، ولهذه النشاطات التي تجري دون اتصال بالإنترنت أهمية كبيرة قد تفوق الجانب المرتبط بالويب في مشروعك، فعندما تهتم ببيع منتجات على سبيل المثال، فمن الأجدى والأوفر من ناحية الوقت إيجاد حلول لتأمين المنتجات وطريقة للدفع والشحن قبل الشروع في بناء الموقع الذي سيستخدِمه الآخرون في طلب تلك المنتجات. الثانية: تحضير خطوات قابلة للتنفيذ سيقودك غالبًا إلى أسئلة جديدة عليك البحث عن إجابة لها. إذ ستجد عادةً مزيدًا من الأسئلة أكثر مما قد تتوقع مثل هل عليَّ تعلّم كل هذه الأمور بنفسي؟ هل أطلب من شخص آخر ذلك؟ هل استخدم خدمات تؤمنها أطراف أخرى؟ الخلاصة كما رأينا، قد تقودك فكرة بسيطة مثل "أريد بناء موقع ويب" إلى قائمة طويلة من الخطوات التي ينبغي تنفيذها والتي تنمو أكثر كلما فكرت بتفاصيلها أكثر، وقد يطغى الأمر على تفكيرك بسرعة، فلا حاجة للإجابة على كل الأسئلة، ولن تضطر إلى تنفيذ كل ما وضعته على قائمتك، فالأهم هنا أن يكون لديك تصوّر عما تريد وكيف ستصل إلى مبتغاك، وحالما تتوضَّح الرؤية، عليك أن تقرِّر متى وكيف تبدأ، وجزِّء المهام الضخمة إلى خطوات أصغر قابلة للتنفيذ بحيث تصل بك في النهاية إلى الإنجاز الذي تنتظر. نأمل أن ترشدك هذه المقالة إلى رسم ملامح خطتك لبناء موقع ويب، وربما سيكون مناسبًا الاطلاع على الطريقة التي تعمل بها شبكة الإنترنت على أساس خطوة ثانية. ترجمة -وبتصرف- للمقال ?How do I start to design my website. اقرأ أيضًا الفرق بين مصمم الويب ومطور الويب وكيفية معرفة الأنسب بينهما أدوات ضرورية لتصميم مواقع الويب HTML و CSS للمبتدئين: كيف تصمم أول صفحة ويب لك 50 تصميمًا مميزًا لمواقع إلكترونية نموذجية يحتذى بها
  14. تُعد أداة التهيئة في راسبيري باي حزمةً برمجيةً فعالةً لضبط كثيرٍ من الإعدادات على جهاز راسبيري باي، ابتداءً من الواجهات المتوفرة في الجهاز وصولًا إلى البرامج والتحكُّم بها عبر الشبكات الحاسوبية. قد يصعُب ضبط الإعدادات المختلفة على المستخدمين الجدد، لذلك سيأخذ هذا الملحق بيدك خطوةً خطوة في كل شرح كل إعداد وبيان الغاية منه. تستطيع تحميل الأداة من قائمة راسبيري باي ضمن فئة "التفضيلات Preferences"، أو من خلال واجهة سطر الأوامر بكتابة الأمر التالي في نافذة برنامج "الطرفية Terminal": raspi-config ستجد اختلافًا بين طريقتي عرض النسخة الرسومية لأداة التهيئة ونسخة واجهة سطر الأوامر، إذ ستظهر الخيارات في فئات مختلفة. سيعتمد هذا الملحق على النسخة الرسومية. نافذة النظام تضم نافذة النظام System tab خيارات تتحكم بمجموعة الإعدادات التالية: كلمة المرور Password: انقر على الزر "تغيير كلمة المرور Change Password" لاختيار كلمة مرور جديدة للمستخدم الحالي (المستخدم 'pi' هو المستخدم الافتراضي). اسم المضيف Hostname: وهو الاسم الذي يعرِّف به باي نفسه على الشبكات، إذ ينبغي أن يمتلك كل جهاز باي اسمًا فريدًا إن كان هناك عدة أجهزة على نفس الشبكة. واجهة الإقلاع Boot: سيقلع باي وصولًا إلى "سطح المكتب Desktop" بالوضع الافتراضي للإعداد، ويمكن اختيار "To CLI" للإقلاع وصولًا إلى واجهة سطر الأوامر التي شرحناها في الملحق "C". تسجيل دخول تلقائي Auto Login: عندما يكون الخيار "مثل مستخدم حالي As current user" مفعلًا (وهو مفعلٌ افتراضيًا)، سيحمّل راسبيان سطح المكتب دون طلب اسم المستخدم وكلمة المرور. التحقق من الاتصال بالشبكة عند الإقلاع Network Boot: إذا كان الخيار "انتظار شبكة الاتصال wait for network" مفعلًا، فلن يُحمّل راسبيان سطح المكتب حتى يضمن وجود اتصال بالشبكة. شاشة مؤقتة Splash Screen: عندما يُفعَّل هذا الخيار، تختفي رسائل إقلاع راسبيان خلف شاشة رسومية مؤقتة. فيديو باي 4 Pi 4 Video: يُتاح هذا الإعداد في النموذج Pi 4 ويعطيك القدرة على تبديل مخرج الفيديو، إذ يمكِّنك الخيار "4K HDMI" من بث الفيديوهات بدقة "4K" عبر أحد منفذي micro أو HDMI أو كلاهما؛ بينما يمكِّن الخيار "تماثلي Analog" عرض الفيديوهات المركبة composite video عبر منفذ الفيديو 3.5 مم، ويُعد هذا الخيار جيدًا إذا كان لديك شاشة أو تلفاز قديم ليس له منفذ HDMI. لا يُفعّل افتراضيًا أيًا من الخيارين السابقين وتُعرض الفيديوهات بدقة 1080p عبر منافذ micro أو HDMI. انتبه إلى أنّ تفعيل الخيار "4K" سيزيد من استهلاك الطاقة والحمل على وحدة المعالجة المركزية CPU ووحدة معالجة الرسوميات GPU، لذلك من الأفضل إلغاء تفعيل هذا الخيار إذا لم تكن بحاجته حاجةً ماسةً لتوجيه موارد الجهاز لمهامٍ أخرى. نافذة الواجهات وتضم الإعدادات التي تتحكم بواجهات العتاد الصلب المتوفرة على باي، وهي: الكاميرا Camera: يمكّن أو يعطّل واجهة الكاميرا التسلسلية Camera Serial Interface -أو اختصارًا CSI-، للتعامل مع تجهيزة كاميرا راسبيري باي. SSH: يمكّن أو يعطّل واجهة المفسر المؤمّنة Secure Shell Interface، والتي تسمح بتشغيل واجهة سطر الأوامر على باي من حاسوب آخر على الشبكة باستخدام عميل SSH. VCN: يمكّن أو يعطّل واجهة الشبكة الافتراضية Virtual Network Computing، والتي تسمح لك باستعراض الواجهة الرسومية لسطح مكتب باي من حاسوب آخر على الشبكة باستخدام عميل VCN. SPI: يمكّن أو يعطّل واجهة الطرفيات التسلسلية Serial Peripheral Interface، التي تُستخدم للتحكم ببعض التجهيزات المتصلة بالمنصة GPIO. I2C: يمكّن أو يعطّل الممر الناقل بين الدارات المتكاملة Inter-Integrated Circuit التي تُستخدم للتحكم ببعض التجهيزات المتصلة بمنصة GPIO. المنفذ التسلسلي Serial Port: يمكّن أو يعطّل المنفذ التسلسلي Serial port الخاص براسبيري باي والمُتاح عبر المنصة GPIO. واجهة سطر الأوامر التسلسلية Serial Console: تمكّن أو تعطّل واجهة الأوامر التسلسلية المتاحة للمنفذ التسلسلي، ويمكن تعديل هذا الإعداد عند تمكين الإعداد Serial Port. 1-Wire: يمكّن أو يعطّل الواجهة 1-Wire التي تُستخدم للتحكم ببعض التجهيزات المتصلة بمنصة GPIO. Remote GPIO: تمكّن أو تعطّل خدمة شبكة تسمح بالتحكم بمنصة GPIO لحاسوب باي من حاسوب آخر على الشبكة باستخدام المكتبة GPIO Zero. نافذة الأداء وتضم الإعدادات التي تتحكم بحجم الذاكرة المتاحة وسرعة عمل المعالج. رفع تردد التشغيل Overclock: يتيح لك هذا الإعداد جملةً من الخيارات التي تزيد أداء باي لكنه بالمقابل يزيد من استهلاك الطاقة والحرارة واحتمال قصر عمر التجهيزة؛ وهو غير متاح في كل نماذج باي. ذاكرة وحدة المعالجة الرسومية GPU Memory: وتتيح لك ضبط حجم الذاكرة المخصص للاستخدام من قبل معالج رسوميات باي. قد تزيد الذاكرة التي تزيد عن 128 ميغا بايت (افتراضية) الأداء أثناء تصيير الرسوميات ثلاثية الأبعاد والمهام الإعتيادية لوحدة معالجة الرسوميات للأغراض العامة general-purpose GPU -أو اختصارًا GPGPU-، على حساب الذاكرة المخصصة لنظام التشغيل راسبيان؛ بينما يحسِّن تخفيض الذاكرة المخصصة للرسوميات أداء بعض المهام الحساسة للذاكرة على حساب انخفاض أداء تصيير الرسوميات ثلاثية الأبعاد والكاميرا وبعض ميزات عرض الفيديوهات التي قد تصبح غير متاحة. نافذة إعدادات الموقع الجغرافي وتضم الإعدادات التي تتحكم بالمنطقة الجغرافية التي صّممت باي لتعمل ضمنها بما في ذلك إعدادات لوحة المفاتيح. محلي Locale: يسمح لك باختيار موقعك، وهو إعدادٌ يتعلق بالنظام نفسه ويضبط اللغة والبلد ومجموعات المحارف. انتبه إلى أنّ تغيير اللغة في هذا الإعداد سيؤثر فقط على لغة التطبيقات التي تتوفر ترجمةً لها إلى اللغة المختارة. المنطقة الزمنية TimeZone: ويتيح لك اختيار منطقتك الزمنية وذلك بانتقاء منطقة من العالم يليها اختيار أقرب مدينة إليك. إذا اتصلت باي بالانترنت وعرضت الساعة توقيتًا خاطئًا، يكون السبب عادةً اختيار منطقة زمنية خاطئة. لوحة المفاتيح Keyboard: يتيح لك اختيار نمط لوحة المفاتيح ولغتها ومخطط محارفها؛ فإذا لاحظت أن لوحة المفاتيح تطبع حروفًا أو رموزًا خاطئةً، يمكن تصحيحها من خلال هذا الإعداد. البلد الذي تستخدم فيه WIFI: ويسمح لك باختيار البلد لأغراض تنظيم استخدام أمواج الراديو للاتصال اللاسلكي. احرص على اختيار البلد الذي تستخدم فيه باي، فاختيارك لبلد آخر قد يُفقدك القدرة على الاتصال بنقاط الوصول اللاسلكية المجاورة التي قد تخضع لقوانين البث اللاسلكي. إذًا، من الأفضل اختيار البلد قبل محاولة الاتصال بالشبكات اللاسلكية. ترجمة -وبتصرف- للملحق The Raspberry Pi Configuration Tool من كتاب The Official Raspberry Pi Beginner's Guide اقرأ أيضًا المقال السابق: واجهة سطر أوامر راسبيان في راسبيري باي تجميع راسبيري باي والتحضير لاستعماله إعداد Raspberry Pi للعمل
  15. تستطيع الوصول إلى معظم برامج راسبيري باي عبر سطح المكتب، إلا أنك تحتاج واجهةً لكتابة تعليمات نصية تُعرف بواجهة سطر الأوامر Command-line interface -أواختصارًا CLI- للوصول إلى بعض البرامج. يؤمن هذه الواجهة في راسبيان تطبيقٌ يُدعى "الطرفية Terminal". لن يحتاج معظم المستخدمين إلى تعلُّم العمل عبر واجهة سطر الأوامر CLI، لكن ما سيقدمه هذا الملحق هو مدخلٌ بسيط لمن يرغب بتعلم مزيدٍ عنها. فتح تطبيق الطرفية يصل المستخدم إلى CLI عبر برنامجٍ يُدعى "الطرفية Terminal"، وهو برنامج يُحمِّل ما يُعرف تقنيًا بواجة الطباعة الافتراضية عن بُعد Virtual teletype terminal؛ إذ تعود هذه التسمية إلى الفترة الزمنية التي أعطى فيها مستخدمي الحاسوب الأوامر عبر آلة كاتبة كهروميكانيكية بدلًا من استخدام لوحة المفاتيح والشاشة. يمكنك فتح الطرفية عن طريق النقر على أيقونة راسبيري لفتح القائمة والانتقال إلى فئة "برامج ملحقة Accessories"، ثم النقر على "الطرفية Terminal". يمكن سحب نافذة الطرفية إلى سطح المكتب كما يمكن تكبيرها وتصغيرها وتغيير حجم خط الكتابة إن كان من الصعب قراءته، أو ليناسب حجم النافذة وذلك بالنقر على القائمة "تحرير Edit" ثم اختيار "تكبير Zoom in"، أو "تصغير Zoom out"K أو بالضغط على المفتاح "CTRL" ثم أحد الزرين "+" أو "-". محث الطرفية أول ما تراه في الطرفية هو المحث Prompt الذي يكون منتظرًا تعليماتك. يظهر المحث في راسبيان على الشكل التالي: pi@raspberrypi:~ $ يشير الاسم ما قبل "@" إلى اسم المستخدم وما بعده إلى اسم الحاسوب الذي تستخدمه وهو افتراضيًا "raspberrypi". بعد الرمز ":" ستشاهد الرمز "~" وهو اختصارٌ يشير إلى المجلد الرئيسي Home directory ويمثِّل مجلد العمل الذي تعمل ضمنه حاليًا current working directory -أواختصارًا CWD-؛ أما الرمز "$" فيشير إلى أن المستخدم الحالي غير مفوّض unprivileged، أي يحتاج إلى كلمة مرور ليُنفّذ مهامًا، مثل إضافة أو إزالة البرامج. الانطلاق في العمل اكتب التعليمة التالية ثم اضغط المفتاح "Enter": cd Desktop سيتغير المُحِث إلى: pi@raspberrypi:~/Desktop $ أصبح سطح المكتب الآن هو مجلد العمل الحالي الذي يقع مباشرةً تحت المجلد الرئيسي، والذي يشير إليه الرمز "~"، ونُفِّذ ذلك من خلال تعليمة تغيير مجلد العمل cd. يمكنك العودة إلى المجلد الرئيسي بأربعة طرق، حاول أن تجرب كل منها على حدى، ثم جرّب استخدامها للعودة إلى مجلد فرعي لسطح المكتب. الطريقة الأولى- باستخدام الأمر التالي: cd .. إذ يُعد الرمز ".." اختصارًا للمجلد الذي يقع مباشرةً فوق مجلد العمل الحالي أو المجلد الأب، وطالما أنّ المجلد الرئيسي هو الأب المباشر لمجلد سطح المكتب فستصل إليه. عُد إلى سطح المكتب وحاول تجريب الأمر التالي. الطريقة الثانية- باستخدام الأمر التالي: cd ~ ويعني الأمر حرفيًا "توجَّه إلى المجلد الرئيسي"، إذ يمكنك الانتقال بهذه التعليمة إلى المجلد الرئيسي من أي مجلد تعمل عليه، على خلاف الطريقة الأولى التي تنقلك إلى المجلد الأب الأعلى مباشرةً من مجلد العمل الحالي. عُد إلى سطح المكتب وحاول تجريب الطريقة الثالثة التالية. الطريقة الثالثة- باستخدام الأمر التالي: cd إذا لم تضع عنوان المجلد الذي ستنتقل إليه بعد التعليمة cd سيقودك افتراضيًا إلى المجلد الرئيسي. عُد إلى سطح المكتب وحاول تجريب الأمر الأخير التالي. الطريقة الرابعة- باستخدام الأمر التالي: cd /home/pi إذ يمثِّل المسار ما بعد التعليمة cd المسار المطلق absolute path والذي سيعمل بغض النظر عن المجلد الحالي، وينقلك إلى المجلد الرئيسي من أي مجلد تعمل عليه كما هو حال التعليمتين السابقتين، لكن عليك ذكر اسم المستخدم (pi في حالتنا هذه). التعامل مع الملفات لكي تتمرن على أساليب التعامل مع الملفات، انتقل إلى سطح المكتب واكتب الأمر: touch Test سيظهر على سطح المكتب عند تنفيذ التعليمة السابقة ملفٌ اسمه "Test"، إذ تُستخدم التعليمة touch عادةً لتحديث معلومات الوقت والتاريخ لملف، لكن في الحالة التي لا يكون فيها هذا الملف موجودًا (مثل حالتنا) تُنشئ التعليمة هذا الملف. جرّب التعليمة التالية: cp Test Test2 سيظهر على سطح المكتب ملفٌ آخر باسم "Test2" ويمثّل نسخةً مطابقةً للملف الأصلي. لنحذف هذه النسخة على النحو التالي: rm Test2 لن يظهر الملف على سطح المكتب بعد الآن. حاول أن تجرّب الآن التعليمة التالية: mv Test Test2 تنقل هذه التعليمة الملف "Test"، إذ سيختفي عن سطح المكتب ليحل محله الملف "Test2"، الذي يعد نسخةً مطابقةً أيضًا عن الملف الأصلي، وتُستخدم هذه الطريقة في تغيير اسم ملف مثلًا. إذا لم يكن سطح المكتب هو مجلد العمل الحالي، قد تحتاج إلى معرفة ما يحتويه هذا المجلد من مجلدات وملفات لذلك اكتب التعليمة: ls إذ تًظهر هذه التعليمة قائمةً بمحتويات المجلد الحالي أو محتويات أي مجلد آخر تحدده لهذه التعليمة. أضِف بعض الخيارات إلى تعليمتك لتتمكن من عرض تفاصيل أكثر، مثل الملفات المخفية وحجم الملفات: ls -larth تتحكم الخيارات التالية بتعليمة ls: l: يعرض النتائج في قائمة عمودية طويلة. a: يعرض جميع الملفات والمجلدات. r: يعكس الترتيب الاعتيادي للمعروضات. t: يعرض المحتويات وفقًا لتاريخ أخر تعديل، ومع r سيعرض لك الملفات الأقدم في بداية القائمة. h: يُظهر حجم الملف بطريقة مقروءة للبشر ليسهل فهمه. تشغيل البرامج لا يمكن تشغيل بعض البرامج إلا باستخدام سطر الأوامر، بينما يمتلك البعض الآخر واجهات رسومية وواجهة لسطر الأوامر؛ إذ تُعد "أداة تهيئة البرمجيات Pi software configuration tool" مثالًا عن الحالة الأخيرة، والتي تُشغَّل عادةً من قائمة راسبيري باي. لنجرّب طريقة سطر الأوامر بكتابة التعليمة: raspi-config ستكون نتيجة التعليمة رسالة خطأ مفادها أنه لا يمكن تشغيل البرنامج إلا في حالة كان مستخدم جذر رئيسي root user، لذلك حاول تغيير التعليمة إلى: sudo raspi-config التوجيه sudo هو اختصار لعبارة "switch-user do"، وهي تجبر راسبيان على تنفيذ الأمر كأنه مستخدمٌ رئيسي. لا تستخدم هذا التوجيه ما لم يتطلب البرنامج الذي تشغله امتيازات عالية مثل حالة تثبيت أو إزالة برامج أو ضبط إعدادات النظام، فلا يجب أن تُشغّل لعبة مثلًا باستخدام sudo. اضغط على المفتاح "TAB" مرتين، ثم اختر "إنهاء Finish" واضغط على المفتاح "Enter" لإغلاق أداة التهيئة والعودة إلى واجهة سطر الأوامر. نفذ أخيرًا التعليمة التالية: exit التي ستنهي جلسة العمل وتغلق برنامج الطرفية. استخدام الطرفيات TTYs لا يمثِّل برنامج "الطرفية Terminal" الواجهة الوحيدة لسطر الأوامر، بل بالإمكان الانتقال إلى أية طرفيات قيد العمل، والتي تُعرف بواجهات الأوامر البعيدة teletype -أو اختصارًا TTYs-. للانتقال إلى tty2 اضغط على المفتاحين "CTRL" + "ALT" معًا واضغط معهما الزر "F2". لا بدّ من تسجيل دخولك باستخدام كلمة المرور واسم المستخدم، وستتمكن بعد ذلك من التعامل مع هذه الطرفية كما فعلنا سابقًا. هذه الطرفيات مفيدةٌ خاصةً عندما لا تكون قادرًا على الوصول إلى سطح المكتب لسببٍ أو لآخر. لمغادرة tty2 اضغط على المفتاحين "CTRL" + "ALT" معًا واضغط معهما الزر "F7". عند العودة إلى tty2 مجددًا سترى كل ما أنجزته سابقًا قبل مغادرتها. اكتب التعليمة exit ثم اضغط على المفاتيح "CTRL+ALT+F7" للعودة إلى سطح المكتب، وتأتي أهمية تنفيذ هذه التعليمة قبل مغادرة TTY في تسجيل خروجك تلقائيًا، إذ سيتمكن أي شخصٍ قادرٍ على الوصول إلى TTY من العبث بحسابك دون الحاجة لكتابة كلمة المرور. تهانينا، لقد اجتزت خطوتك الأولى في احتراف واجهة سطر الأوامر الخاصة بالنظام راسبيان. ترجمة -وبتصرف- للملحق The command-line interface من كتاب The Official Raspberry Pi Beginner's Guide اقرأ أيضًا المقال التالي: أداة التهيئة في راسبيري باي المقال السابق: تثبيت أنظمة التشغيل والبرامج على راسبيري باي إنشاء أمر جديد في بيئة سطر الأوامر في راسبيري باي التعامل مع بيئة سطر الأوامر في راسبيري باي
  16. لابد من نشر الموقع على شبكة الإنترنت حالما تنتهي من كتابة الشيفرة وتنظيم الملفات التي تكوّنه ليتمكن الجميع من الوصول إليه، إذ سنشرح في هذا المقال كيف تنشر موقعك التجريبي البسيط على الإنترنت بأقل جهد ممكن. ماهي الخيارات المتاحة يُعَدّ نشر موقع ويب موضوعًا معقّدًا لوجود طرق وأساليب كثيرة لتنفيذه، ولن نحاول في هذا المقال توثيق كل الطرق الممكنة، وإنما سنصف إيجابيات وسلبيات ثلاثة نهج مناسبة للمبتدئين، ثم نفصّل إحداها والتي تُعَدّ الأفضل للكثير من القراء. الحصول على استضافة واسم نطاق يفضِّل الكثيرون الدفع مقابل الحصول على استضافة واسم نطاق وذلك لتحكّم أفضل في محتوى ومظهر موقع الويب: الاستضافة Hosting: هي مساحة تخزين مُستأجَرة على خادم ويب تابع لشركة الاستضافة، إذ توضَع ملفات الموقع على هذا الخادم الذي يتيح محتواه للزائرين. اسم النطاق Domain name: هو العنوان الفريد الذي ستجد عليه موقع ويب محدَّد مثل ‎/hsoub أو ‎/google، ويمكنك استئجار اسم النطاق لعام أو أكثر من شركة مُسجّلة Domain Registrar. تستخدِم معظم مواقع ويب الاحترافية الطريقة السابقة لتنشر محتواها على شبكة الإنترنت، وبالإضافة إلى ذلك، سيتطلب الأمر برنامجًا يستخدِم بروتوكول نقل الملفات FTP لنقل ملفاتك إلى الخادم، ويمكنك الاطلاع على مقال أساسيات تحديد الكلفة المادية الكاملة لبناء موقع ويب، كما تتنوع برامج FTP كثيرًا، لكن وظيفتها بالمجمل هي استخدام المعلومات التي تزودك بها شركة الاستضافة وهي اسم المستخدِم وكلمة المرور واسم المضيف عادةً، وذلك لتأمين الاتصال مع خادم الاستضافة ونقل الملفات إليه، ثم يُظهِر البرنامج بعد الاتصال ملفاتك المحلية وملفات خادم الويب في نافذتين متجاورتين ليسهل نقل الملفات بين المكانين. نصائح لإيجاد استضافة ونطاق لا نرشح في هذا المقال أيّ شركة استضافة أو شركة مسجِّلة، فعليك البحث بنفسك عما يناسبك، إذ تتيح لك كل المسجلات وسيلةً للتحقق من توفر اسم نطاق معين وحجزه. تمنحك بعض مزودات الخدمة الموجودة على حاسوبك الشخصي أو ضمن شبكة مكتبك إمكانية استضافة محدودة لموقعك، إذ لن تكون الميزات المتاحة كثيرةً، لكنها ممتازة لتجربته الموقع. ستجد أيضًا خدمات استضافة مجانية مثل Neocities و Google sites و Blogger و Wordpress، وقد تجني فائدة ما تدفع، لكن موارد مجانية مثل هذه قد تكوِّن خيارًا تجريبيًا ممتازًا أيضًا. تزوّدك بعض الشركات بخدمتي الاستضافة وحجز أسماء نطاقات معًا. استخدام أدوات على شبكة الإنترنت مثل جيت-هاب و جوجل آب تساعدك بعض الأدوات في نشر موقعك مثل: جيت-هاب GitHub: وهو موقع كتابة شيفرة تشاركي يسمح لك برفع ملفات الشيفرة إلى مستودعات تخزين على منظومة التحكم بالإصدار Git، إذ تستطيع بعد ذلك مشاركة شيفرة المشاريع المختلفة والتعاون في العمل عليها، وطالما أنّ المنظومة مفتوحة المصدر، فيمكن لأيّ كان الوصول إلى الشيفرة على جيت-هاب واستخدامها والتعلم منها وتطويرها، كما تقدِّم جيت-هاب أيضًا ميزةً مفيدةً هي صفحات جيت-هاب GitHub Pages التي تسمح لك باستضافة شيفرة موقعك على ويب. محرّك جوجل آب Google App Engine: وهي منصة قوية تسمح لك ببناء وتشغيل التطبيقات بالاستفادة من البنية التحتية لجوجل، سواءً أردت بناء تطبيق ويب من الصفر أو استضافة موقع ويب ساكن، ولمزيد من المعلومات راجع مقال رفع موقع ويب إلى شبكة الإنترنت. هناك عدة خيارات أخرى مجانية، لكنك قد تتخطى بسهولة حدود الميزات المتاحة. استخدام بيئة عمل متكاملة مبنية على ويب هناك العديد من تطبيقات الويب التي تحاكي بيئة تطوير مواقع ويب وتسمح لك بإدخال شيفرة HTML و CSS وجافاسكربت واستعراض نتيجة تنفيذ الشيفرة على أساس موقع ويب حقيقي داخل نافذة المتصفح، وتُعَدّ هذه الأدوات عمومًا سهلة الاستخدام نسبيًا وممتازةً لأغراض التعلّم ومشاركة الشيفرة، إذ بإمكانك إذا أردت مشاركة أسلوب برمجي أو طلب مساعدة في تنقيح شيفرة من زميل في مكتب مجاور، كما أنها مجانية لبعض الميزات الأساسية، لكنها لا تزوّدك عادةً بمساحة لتخزين ملفات الدعم أو ملفات المساعدة والتي تدعى بالأصول assets مثل الصور، وحاول أن تجرب بعضها مثل JSFiddle و Glitch و JS Bin و CodePen g لتجد ما يناسبك. النشر باستخدام جيت-هاب سنناقش الآن كيف تنشر موقعك على صفحات جيت-هاب بسهولة: سجّل في موقع جيت-هاب أولًا وأكِّد امتلاكك عنوان البريد الإلكتروني الذي استخدمته في التسجيل. أنشئ مستودعًا لتخزين الملفات. أدخِل في الصندوق Repository name الظاهر في الصفحة الموضحة في الشكل التالي العبارة username.github.io، إذ يمثل username اسم المستخدم، فقد يُدخِل "مازن" الاسم "mazen.github.io" مثلًا، ثم فعِّل بعد ذلك الخيار Initialize this repository with a README وانقر بعدها زر أنشئ مستودعًا create repository. اسحب وأفلت محتوى الموقع ضمن المستودع واحفظ التغييرات. انتقل باستخدام متصفحك إلى الموقع "username.github.io -وفقًا لما اخترته-، وسيعرض محتوى موقعك. ترجمة -وبتصرف- للمقال Publishing your website. اقرأ أيضًا مدخل إلى خادم ويب. مدخل إلى أسماء النطاقات على شبكة الإنترنت. أساسيات تحديد الكلفة المادية الكاملة لبناء موقع ويب
  17. صُمم البرنامج "نوبس NOOBS" لتسهيل عملية تثبيت أنظمة التشغيل على راسبيري باي ما أمكن، إذ يمكنك شراء بطاقة ذاكرة microSD ثُبت عليها نوبس مسبقًا من أي موزّع لتجهيزات باي، أو اتباع التعليمات التالية لتثبيت البرنامج على بطاقة ذاكرة خاصة بك. تنزيل نوبس NOOBS لتثبيت نوبس على بطاقة ذاكرة فارغة، عليك تنزيل البرنامج من موقع ويب راسبيري باي على حاسوب قادر على قراءة بطاقة الذاكرة microSD و full-size SD مع محوِّل لبطاقة microSD، ويمكنك استخدام قارئ بطاقات ذاكرة بواجهة USB كذلك. استخدم المتصفح في الوصول إلى موقع التنزيلات الخاص براسبيري باي وانقر على برنامج نوبس المُعلّم بأيقونة راسبيري باي في الصفحة التي يحملها المتصفح، ثم انقر "تنزيل ملف مضغوط Download ZIP" ضمن الفئة "تنزيل نوبس دون اتصال أو عبر الشبكة NOOBS Offline and network install". يستغرق تنزيل نوبس وقتًا وخاصة إن كان الاتصال بالإنترنت بطيئًا. عند انتهاء التنزيل أدخل بطاقة الذاكرة في الحاسوب، وستظهر على شكل سواقة مفردة قابلة للإزالة، وقد تُضطرإلى تهيئتها format أولًا إن لم تظهر بهذا الشكل. خياري تنزيل: لاحظ وجود نسختين قابلتين للتنزيل على صفحة تنزيلات نوبس، هما: NOOBS و NOOBS Lite. تنزِّل النسخة الأولى نوبس ونسخة عن آخر إصدار لنظام التشغيل راسبيان في حزمة واحدة؛ بينما تنزِّل النسخة الثانية نوبس فقط. ما يحتاجه معظم المستخدمين هي النسخة الأولى، فلا تنزل النسخة الثانية إلا إذا كنت تخطط لتثبيت نظام تشغيل آخر غير راسبيان. تُثبَّت النسختان بالطريقة ذاتها كما نشرحها في هذا الملحق. تهيئة بطاقة الذاكرة microSD لتهيئة بطاقة ذاكرة مستخدمة سابقًا لتثبيت نوبس، ينبغي لمستخدمي ويندوز أو ماك أو إس تنزيل أداة تهيئة بطاقة الذاكرة "SD Card Association SD Memory Card Formatter"، ثم تثبيتها، أما بالنسبة لمستخدمي لينوكس، فالأداة "disk management tool" هي المستخدمة في حذف أية تقسيمات على البطاقة، ثم إنشاء جزء وحيد single partition وتهيئته وفق نظام الملفات VFAT، ثم إكمال هذا الدليل. أدخل بطاقة الذاكرة في الحاسوب إن لم تكن قد فعلت ذلك، ثم شغِّل الأداة "SD Card Formatter". ابحث عن بطاقة الذاكرة ضمن القائمة "اختر بطاقةً Select card"، إذ قد تجد أكثر من بطاقة لها نفس اسم بطاقتك إن كنت قد استخدمتها سابقًا مع راسبيري باي، لذلك اختر واحدةً منها في هذه الحالة وتحقق من اختيارك للقرص الصحيح (بطاقة الذاكرة) بالاطلاع على معلومات القرص في قسم "معلومات البطاقة card information" الذي يعرض حجم ونوع بطاقة الذاكرة microSD التي أدخلتها. حاول أن تختار الآخرى إن كانت المعلومات المعروضة ليست صحيحة (ليست معلومات بطاقتك)، وتحقق من صحة المعلومات من جديد حتى تتأكد تمامًا بأنها البطاقة الصحيحة. تحقق كذلك من عمل نسخة احتياطية لأية ملفات مخزنة عليها قد تحتاجها لاحقًا، ثم سمِّ البطاقة "NOOBS" من خلال الصندوق "عنوان وحدة التخزين volume label" وانقر زر "تهيئة format" وأكّد -عندما يُطلب منك ذلك- رغبتك في تهيئة القرص. لن يستغرق خيار التهيئة السريعة "quick format" سوى ثوانٍ معدودة ليكتمل. أغلق بعد ذلك أداة التهيئة. تثبيت نوبس وهي عمليةٌ بسيطة مثل عملية سحب وإفلات. ابحث عن ملف نوبس الذي نزلته مسبقًا وستجده عادةً في مجلد " التنزيلات Downloads". يُدعى هذا الملف "ملف أرشيف Archive file"، ويحتوي نسخًا عن كثيرٍ من الملفات التي ضُغطت ضمنه لتقليل حجمها وتسريع تنزيلها. انقر على الأرشيف نقرًا مزدوجًا لفتحه، ثم اضغط على المفتاحين "CTRL+ A" في نظام ويندوز، أو "⌘+A" في نظام ماك أو إس لاختيار جميع ملفات الأرشيف، ثم اسحب هذه الملفات إلى بطاقة الذاكرة microSD ثم أفلتها وانتظر حتى تكتمل عملية النسخ والتي قد تستمر عدة دقائق. أخرج بطاقة الذاكرة عندما ينتهي نسخ الملفات من الحاسوب وضعها في راسبيري باي. عندما تُقلع باي مرةً أخرى سيُحمّل برنامج نوبس وسيطلب منك اختيار نظام التشغيل الذي تود تثبيته. تثبيت البرامج وإزالتها يأتي مع نظام التشغيل راسيبان Raspbian مجموعةً من البرامج المُختارة من قبل مؤسسة راسبيري باي لكنها طبعًا ليست الوحيدة التي تعمل على راسبيان. سترشدك الأفكار التالية إلى طريقة تصفُّح برامج إضافية وتثبيتها أو إزالتها لتوسيع إمكانيات باي. بُنيت الإرشادات في هذا الملحق على ما شرحناه في المقال الثالث "نظام تشغيل راسبيري باي (راسبيان)" من هذه السلسلة دليل راسبيري باي حول استخدام بعض البرمجيات الأساسية، لذلك من الأفضل العودة إلى هذا الفصل -إن لم تفعل بعد- قبل استخدام الطرق التي سنشرحها في هذا الملحق. سعة بطاقة الذاكرة: تستهلك البرامج الإضافية التي تثبتها مساحةً أكبر على بطاقة الذاكرة. تسمح لك مثلًا بطاقات الذاكرة بحجم 16 جيجابايت أو أكثر بتثبيت برامج أكثر، ويمكنك التحقق من أن بطاقة الذاكرة التي تنوي استخدامها مناسبةٌ لراسبيري باي من خلال موقع دعم راسبيري. تصفح البرامج الموجودة يمكن تصفُّح قائمة البرمجيات المُتاحة لراسبيان، والتي تُعرف باسم مستودعات البرمجيات software repositories من خلال النقر على أيقونة راسبيري والانتقال إلى فئة "تفضيلات Preferences"، ثم النقر على "إضافة/ إزالة البرامج Add/Remove Software". ستظهر نافذة الأداة بعد عدة ثوانٍ. يتضمن الجانب الأيسر للنافذة قائمةً بالفئات تشبه تلك التي تراها في قائمة راسبيري باي. ستعرض لك نافذة إضافة / إزالة البرامج جميع البرمجيات التي تندرج تحت فئة معينة عند النقر عليها؛ ويمكنك أيضًا البحث عن برنامج أو توصيف برنامج بكتابته في صندوق البحث في أعلى يسار النافذة، مثل "محرر نصوص text editor"، أو "ألعاب games"، وستجد نتيجة البحث على هيئة قائمة من البرامج التي حققت معيار البحث من كل الفئات. لمزيدٍ من المعلومات حول أي برنامج منها، انقر عليه ضمن القائمة وستُعرض المعلومات في الفراغ أسفل النافذة. في حال ضمّت فئةٌ من الفئات كثيرًا من البرمجيات المتاحة للتثبيت، سيستغرق ذلك وقتًا أطول من نافذة إضافة/إزالة البرامج لعرضها. تثبيت برنامج فعّل مربع التحقق بجوار البرنامج الذي تريد تثبيته بالنقر عليه. ويمكنك طبعًا النقر على مربعات التحقق قبل مجموعة البرامج التي تحتاجها لكي تثبتها الأداة في نفس الوقت. ستتحول الأيقونة إلى جانب البرنامج الذي تختاره إلى أيقونة صندوق مفتوح وعليه الرمز "+" للإشارة إلى أنه جاهزٌ للتثبيت؛ وعندما تكتمل قائمة البرامج التي تحتاجها انقر على أحد الزرين "OK" أو "Apply"، إذ لا فرق بين الزرين السابقين سوى أنّ الأول يغلق النافذة عند الانتهاء من التثبيت بينما يبقيها الثاني مفتوحة. سيُطلب منك إدخال كلمة المرور للتأكد من هويتك، فلن ترغب بالتأكيد أن يعبث أحد بالبرامج التي تثبتها على باي قد تلاحظ أحيانًا أنّ مجموعة حزم قد جرى تثبيتها مع البرنامج الذي ثبته، إذ تُعرف هذه الحزم بالاعتماديات dependencies ويحتاجها برنامجك للعمل بصورةٍ جيدة، مثل حزمة المؤثرات الصوتية التي تحتاجها الألعاب، أو قاعدة بيانات للعمل مع مخدم ويب. يمكنك الوصول إلى برنامجك بعد اكتمال التثبيت ضمن الفئة التي ينتمي إليها في قائمة راسبيري باي. تذَكر أن الفئات في قائمة راسبيري باي قد تختلف عن الفئات في أداة إضافة / إزالة البرامج، وقد لا تجد اختصارًا لبعض البرامج التي ثبتّها في قائمة راسبيري إطلاقًا والتي تعرف ببرامج سطر الأوامر Command-line software، إذ ينبغي تشغيلها من برنامج الطرفية "Terminal". لمزيدٍ من المعلومات حول سطر الأوامر والطرفية راجع الملحق "C" (واجهة سطر الأوامر). إلغاء تثبيت برنامج لإزالة أو إلغاء تثبيت برنامج، افتح أداة إضافة / إزالة البرامج، ثم ابحث عن البرنامج الذي تريد إلغاء تثبيته وألغِ تفعيل مربع التحقق إلى جواره بالنقر عليه؛ كما يمكنك استخدام صندوق البحث لإيجاد البرنامج المطلوب؛ وتستطيع كذلك إلغاء تثبيت عدة برامج معًا بالنقر على مربع التحقق بجوار كل منها وإلغاء تفعيله، وسيتغير عندها شكل الأيقونة إلى صندوق مفتوح بجواره سلة محذوفات للإشارة بأن هذا البرنامج سيُحذف أو يُلغى تثبيته. انقر بعد ذلك على أحد الزرين "OK" أو "Apply" لتبدأ العملية، وسيطلب منك إدخال كلمة المرور إن لم تكن قد أدخلتها لسببٍ ما خلال الدقائق القليلة الماضية، كما قد يُطلب منك تأكيد عملية إلغاء تثبيت البرنامج وأية اعتماديات مرتبطة به أيضًا. سيختفي البرنامج من قائمة باي عند اكتمال عملية إلغاء التثبيت، ولن تُحذف طبعًا أية ملفات كنت قد أنشأتها بهذا البرنامج، مثل الرسوميات أو الصور أو المستندات وغيرها. ترجمة -وبتصرف- للملحقين Installing NOOBS to a microSD card و Installing and uninstalling software من كتاب The Official Raspberry Pi Beginner's Guide اقرأ أيضًا المقال السابق: ربط كاميرا مع لوحة راسبيري باي وتشغيلها تجميع راسبيري باي والتحضير لاستعماله ما هو حاسوب راسبيري باي Raspberry Pi؟
  18. تستطيع التقاط صورٍ عالية الدقة وتسجيل مقاطع فيديو باستخدام تجهيزة الكاميرا، التي تتصل مع باي Pi Camera Module وتساعدك في إنشاء مشاريع محتوًى بصري مميزة. إذا كنت مهتمًا بإنتاج محتوًى بصري مهم، أو "رؤية حاسوبية Computer Vision" كما تُعرف في حقل الروبوت، فستكون كاميرا باي بدايةً جيدة. تظهر التجهيزة على شكل دارة صغيرة مربعة الشكل لها كابل شريطي ribbon cable يمكن وصله إلى راسبيري باي عبر المنفذ التسلسلي للكاميرا Camera Serial Interface -أو اختصارًا CSI-؛ مما يسمح لباي بالتقاط صورٍ ثابتة أو متحركة بدقةٍ عالية للاستخدامات المتنوعة. تُعرف كاميرا باي حتى لحظة تحرير هذه النسخة من الكتاب بأنها التجهيزة "v2" أو تجهيزة النسخة 2.1 المبنية على حساس الصورة "Sony IMX219"، وهو نفسه الحساس الذي قد تجده خلف هاتفك الذكي أو جهازك اللوحي. تصل دقة الحساس إلى 8 ميغا بكسل وهذا يعني أنه قادرٌ على التقاط صورٍ مكونة من 8 ملايين بيكسل pixel موزعةٍ إلى 3280 بيكسل عرضًا و2464 بيكسل طولًا (جداء الرقمين السابقين سيتجاوز قليلًا 8 ملايين). يمكن للكاميرا التقاط مقاطع فيديو إضافةً إلى الصور الثابتة وبدقة Full HD التي تعتمدها معظم أجهزة التلفاز بمعدلٍ يصل إلى 30 إطارًا في الثانية ليساعدك على إظهار حركةٍ سلسةٍ ويعزّز إمكانية تأثيرات الحركة البطيئة. يمكن رفع معدل الالتقاط إلى 60 إطارًا في الثانية بتخفيض الدقة إلى 720p وإلى 90 إطار في الثانية بتخفيض الدقة أكثر إلى 480p؛ وهي دقة منظومة VGA للشاشات التقليدية. تثبيت كاميرا راسبيري باي مثل تجهيزة إضافية، لا بدّ من فصل التغذية الكهربائية عن باي وسحب كابل التغذية قبل وصل تجهيزة الكاميرا. أوقف تشغيل راسبيري باي بالنقر على أيقونة راسبيري باي، ثم اختيار الأمر "إيقاف التشغيل Shutdown". انتظر حتى تتوقف باي عن العمل، ثم انزع كابل التغذية الكهربائية. افتح علبة الكاميرا وستجد دارةً صغيرةً مربعة هي الكاميرا نفسها وكابلًا شريطيًا سيكون متصلًا بالكاميرا في معظم الحالات. اقلب الكاميرا بحيث تواجه عدستها الأرض إذا لم يكن الكابل متصلًا بها، ثم ابحث عن وصلةٍ بلاستيكية مسطحة لها طرفان ناتئان قليلًا. اضغط على النتوئين للداخل واسحبهما للخلف، فيتحرك معك جزءٌ من الوصلة إلى الخارج. ازلق الكابل الشريطي في الوصلة بحيث تكون حافته الفضية إلى الأسفل والقطعة الزرقاء لطرفه نحو الأعلى، ثم ادفعه جيدًا في الوصلة وأعِد الجزء الذي سحبته إلى مكانه. يمكنك وصل أي من طرفي الكابل الشريطي إلى الكاميرا وتأكد عند وصله بأنه مركبٌ جيدًا، حيث يجب ألا يخرج من مكانه إذا حاولت سحبه. شكل 1-8 توصيل الكابل الشريطي إلى الكاميرا سنركِّب الطرف الآخر على باي بنفس الطريقة. جد أولًا منفذ الكاميرا "CSI" وارفع الغطاء قليلًا إلى الأعلى، وقد يكون من الأسهل لو أخرجت باي من حاضنتها إن كنت تستخدم واحدة. ازلق كابل الكاميرا في الوضعية التي يكون فيها منفذ HDM لراسبيري باي متجهًا نحوك، ثم ادفع الغطاء بلطف إلى مكانه. تأكد عند وصل الكابل بأنه مركبٌ جيدًا، حيث يجب ألا يخرج من مكانه إذا حاولت سحبه. شكل 2-8 توصيل الكابل الشريطي للكاميرا مع منفذ CSI لباي يأتي مع عدسة الكاميرا رقعةٌ بلاستيكية زرقاء لحمايتها من الخدش أثناء التصنيع والشحن والتركيب. جد النتوء الصغير على طرف الرقعة وانتزعه بلطف لتصبح الكاميرا جاهزةً للاستخدام. صل التغذية الكهربائية مجددًا إلى باي واتركها حتى تحمّل راسبيان. لا بدّ من إخبار باي أنك وصلت الكاميرا لتتمكن من استخدامها. انقر على أيقونة راسبيري، ثم انتقل إلى فئة "تفضيلات preferences" وانقر على "إعداد راسبيري باي Raspberry Pi Configuration". انقر على نافذة "واجهات interfaces" في نافذة الأداة السابقة عندما يكتمل تحميلها، ثم ابحث عن "كاميرا Camera" وانقر على زر الخيارات الدائري إلى يسار الكلمة "تمكين Enabled" لتفعيله. انقر الزر "OK"، ستطلب منك الأداة إذنًا لإعادة تشغيل باي. دعها تفعل ذلك وستصبح الكاميرا جاهزةً عندما يقلع النظام من جديد. شكل 3-8 لا بدّ من تفعيل الكاميرا باستخدام أداة إعداد راسبيري باي اختبار الكاميرا للتأكد من تثبيت الكاميرا وتفعيل واجهتها على نحوٍ صحيح، يمكن استخدام أداة الصور الثابتة rapistill وأداة الفيديو raspivid المصممتين لالتقاط الصور من خلال تجهيزة الكاميرا باستخدام واجهة سطر الأوامر command-line interface -أو اختصارًا CLI-. لن تجد هاتين الأداتين مثل بقية البرامج ضمن قائمة راسبيري باي الرئيسية بل ينبغي تحميلهما من برنامج الطرفية "Terminal"، الذي تجده في فئة "البرامج الملحقة Accessories". بالنقر على البرنامج ستظهر نافذةٌ لها خلفيةٌ سوداء وأسطرٌ باللونين الأزرق والأخضر تمثًِل الطرفية التي تسمح لك بالتعامل مع واجهة سطر الأوامر. شكل 4-8 نافذة برنامج الطرفية Terminal التي تسمح لك بالوصول إلى سطر الأوامر اكتب الأمر التالي في الطرفية لاختبار الكاميرا: raspistill -o test.jpg وبمجرد الضغط على المفتاح Enter ستظهر صورةٌ كبيرة لما تعرضه الكاميرا على الشاشة، ويُعرف ذلك باسم العرض المباشر والذي يستمر خمس ثوانٍ ما لم تحدد خلاف ذلك. تلتقط الكاميرا بعد 5 ثوان صورةً ثابتة لما تعرضه وتخزّنها في المجلد "home" باسم test.jpg. إذا أردت التقاط صورةٍ أخرى، نفِّذ التعليمة السابقة مجددًا ولا تنس تغيير اسم ملف الخرج بعد الخيار o- وإلا ستخزن الصورة الجديدة فوق القديمة. شكل 5-8 العرض المباشر للكاميرا إذا كانت صورة العرض المباشر مقلوبةً رأسًا على عقب، فعليك تنبيه raspistil بأن الكاميرا مقلوبة. صُممت تجهيزة الكاميرا لكي يكون الكابل الشريطي خارجًا من الحافة السفلية؛ فإذا كان خارجًا من أحد جانبي أو من أعلى باي كما هو الحال في بعض الكاميرات التي ينتجها طرفٌ ثالث، فعليك تدوير الصورة 90 أو 180 أو 270 درجة باستخدام الخيار rot-. استخدم ببساطة الأمر التالي إذا خرجت الكاميرا من الأعلى: raspistill -rot 180 -o test.jpg بينما لو خرجت الكاميرا مع الشريط من الجانب الأيمن، دوّر الصورة 90 درجة؛ ودوّرها 270 درجة، إذا خرجت من الجانب الأيسر؛ وإذا كانت الزاوية الأصلية لالتقاط الصورة غير صحيحة استخدم الخيار rot- لتدويرها إلى وضعها الصحيح. لرؤية الصورة الملتقطة: افتح برنامج "مدير الملفات File Manager" من قائمة راسبيري فئة "برامج ملحقة Accessories"، ثم انتقل إلى المجلد "home/Pi" وستجد الصورة باسم "test.jpg". انقر على الصورة نقرًا مزدوجًا لفتحها ضمن برنامج "عارض الصور image viewer". تستطيع بالطبع إرسال الصورة عبر البريد الإلكتروني؛ أو رفعها إلى موقع ويب؛ أو نقلها إلى وسيط تخزين خارجي. شكل 6-8 عرض الصورة الملتقطة تعرف على مكتبة picamera يعدّ استخدام مكتبة بايثون picamera الطريقة الأكثر مرونة في التحكم بتجهيزة كاميرا باي سواءً بالعرض المباشر أو بالتقاط الصور والفيديوهات، كما تسمح لك بدمج ما التقطته في برامجك الخاصة، وكذلك مع البرامج التي تستخدم المنصة GPIO من خلال مكتبة GPIO Zero. أغلق برنامج الطرفية إذا كان مفتوحًا بالنقر على زر الإغلاق X في أعلى يمين النافذة، ثم افتح ثوني بالطريقة المعتادة. أنشئ مشروعًا جديدًا واحفظه باسم "Camera". أدرج المكتبات التي يحتاجها برنامجك من خلال كتابة الأسطر التالية: from picamera import PiCamera from time import sleep camera = PiCamera() يتيح لك سطر الشيفرة الأخير التحكم بتجهيزة الكاميرا من خلال الدالة camera. لتبدأ العرض، اكتب الشيفرة التالية: camera.start_preview() sleep(10) camera.stop_preview() انقر على أيقونة التشغيل "Run" وسيختفي سطح المكتب ويحل مكانه عرضٌ مباشرٌ على كامل الشاشة لما تراه الكاميرا. حاول تحريك الكاميرا أو التلويح بيدك أمام عدساتها وستلاحظ تغيُّر الصورة المعروضة على الشاشة لتطابق التغيير الجاري. يتوقف العرض وينتهي تنفيذ برنامجك بعد عشر ثوانٍ. شكل 7-8 عرض ما تراه الكاميرا على كامل الشاشة. دوّر الصورة إذا ظهرت بزاوية عرضٍ خاطئة حتى تحصل على الاتجاه الصحيح وذلك باستخدام سطر الشيفرة التالي: camera.rotation = 180 بوضعه تحت السطر: camera = PiCamera() إذا كان العرض مقلوبًا رأسًا على عقب، ستجعله تعليمة الدوران السابقة بوضعه الصحيح. تسمح لك تعليمة الدوران بتدوير الصورة بزاوية 90 و 180 و 270 درجة، ويتعلق اختيار زاوية الدوران الصحيحة بمكان خروج كابل الكاميرا إذا كان من يمين تجهيزة الكاميرا أو أعلاها وهكذا. إذًا، تذكّر كتابة تعليمة دوران الصورة في بداية كل برنامج لتفادي العرض الخاطئ. التقاط صور ثابتة يتوجب تعديل برنامجك لالتقاط صورة وتخزينها بدلًا من عرض ما تراه الكاميرا فقط. ابدأ أولًا بتعديل قيمة التأخير الزمني (10)sleep إلى (5)sleep، ثم اكتب السطر التالي بعدها مباشرةً: camera.capture('/home/pi/Desktop/image.jpg') تُخزّن الدالة صورةً ثابتة، ولا بدّ أن تحدد ضمنها اسم الصورة التي تلتقطها ومكان تخزينها. لاحظ أنك تخزن الصورة في الشيفرة السابقة على سطح المكتب، ابحث عنها في جوار "سلة المحذوفات Wastebasket". ابعد نافذة ثوني إذا كانت تعيق الرؤية، ثم انقر على ملف الصورة التي التقطها برنامجك لتراها. تهانينا، لقد كتبت أولى برامجك للكاميرا! شكل 8-8 فتح الصورة التي التقطتها التقاط مقاطع فيديو تستطيع أيضًا تصوير مقاطع فيديو وتخزينها. احذف كل الشيفرة بين الدالتين ()camera.start_preview و()camera.stop_preview، ثم اكتب الشيفرة التالية تحت الدالة الأولى: camera.start_recording('/home/pi/Desktop/video.h264') sleep(10) camera.stop_recording() تعرض الكاميرا ما تراه كما في الحالة السابقة لكنها تسجل في نفس الوقت مقطع فيديو في ملفٍ على سطح المكتب. ستستمر العملية 10 ثوان، لذلك قد تفكر في فعل شيءٍ ما أمام الكاميرا ليبدو الفيديو أكثر تشويقًا، وسيتوقف بعد ذلك التسجيل. يمكنك حينها العودة إلى سطح المكتب ومتابعة الفيديو، حيث ستجده باسم "video.h264"، وستظهر رسالةٌ لطيفة على الطرفية عند انتهاء عرض الفيديو. تهانينا، ستلتقط من الآن فصاعدًا مقاطع فيديو باستخدام كاميرا باي! زر لتحريك الرسوميات سنحاول تصميم مشروعٍ مميز اعتمادًا على ما تعلمته في هذا المقال وخبرتك التي اكتسبتها في توصيل المكوّنات الفيزيائية إلى أرجل المنصة GPIO. سنُصمم استوديو خاص بك لتحريك الرسوميات والصور؛ حيث تمثّل تحريك الرسوميات عملية التقاط الكثير من الصور المتلاحقة لغرضٍ ما أو لشخص، ومن ثم تحريك الصور بتتابعٍ معين ليظهر الغرض وكأنه يتحرك. وبالطبع سترى أن الغرض ساكن إذا نظرت إلى كل صورةٍ على حدى؛ ولكن إذا عرضتها على نحوٍ متتابع بسرعة، فسيبدو وكأنه يتحرك وبالسرعة التي تريد. ستحتاج في هذا المشروع إلى: زر كبس Push button. لوحة اختبار. أسلاك بوصلات طرفية "M2M". زوج أسلاك بوصلات طرفية "M2F". أسلاك بوصلات "F2F"، إذا لم تستخدم لوحة الاختبار، وبالطبع سيصعب عليك عندها ضغط الزر براحة. إذا أردت أن تتذكر أية معلومات عن هذه المكوّنات، عليك مراجعة مقال "البرمجة الفيزيائية باستخدام سكراتش وبايثون". ستحتاج الآن إلى أغراض لتحريكها والتي قد تكون أي شيء، مثل لعبة أو زهرة أو شخصية. جمِّع الدارة أولًا بتثبيت الزر على لوحة الاختبار، ثم صِل مسار التغذية السالب للوحة مع أحد أرجل الأرضية GND للمنصة GPIO بواسطة سلك M2F. استخدم سلك M2M لوصل أحد أرجل الزر بمسار التغذية السالب للوحة وسلك M2F لوصل رجله الأخرى بالرجل GP2 للمنصة GPIO. الشكل 9-8 وصل الزر إلى أحد أرجل المنصة GPIO أنشئ مشروعًا جديدًا في ثوني واحفظه باسم "Stop Motion"، وابدأ بإدراج المكتبات اللازمة لعمل الكاميرا ومنصة GPIO: from picamera import PiCamera from gpiozero import Button camera = PiCamera() button = Button(2) اكتب الآن الشيفرة التالية: camera.start_preview() button.wait_for_press() camera.capture('/home/pi/Desktop/image.jpg') camera.stop_preview() انقر على أيقونة التشغيل وسيظهر على الشاشة العرض المباشر لما تراه الكاميرا؛ حيث سيبقى العرض على الشاشة مستمرًا حتى تضغط على الزر ليختفي العرض المباشر وينتهي برنامجك بعد أن يخزّن الصورة الملتقطة على سطح المكتب. ابحث عن الصورة التي تحمل الاسم "image.jpg" وحاول فتحها للتأكد أن البرنامج يعمل على مايرام. يتطلب تحريك الرسوميات إنشاء كثيرٍ من الصور لتعطي انطباعًا بالحركة عندما تعرض على نحوٍ متتالي، ولهذا ستحتاج إلى مجلدٍ خاص على سطح المكتب لتخزين جميع هذه الصور. انقر على سطح المكتب بالزر اليميني في أي مكانٍ فارغ، ثم اختر الأمر "إنشاء Create New" ثم "مجلد Folder" وسمِّه "animation" (استخدم أحرف صغيرةً بالكامل)، ثم انقر الزر "OK". شكل 10-8 إنشاء مجلد جديد لتخزين الصور التي تلتقطها الكاميرا. ليس مريحًا إعادة تشغيل برنامجك في كل مرة تلتقط فيها صورة، لذا لا بدّ من تغييره ليستخدم حلقة. وعلى خلاف الحلقات التي استخدمناها سابقًا ستحتاج إلى حلقةٍ تنهي العملية بسلاسة؛ فلو أوقفت البرنامج والكاميرا في حالة العرض المباشر، فلن تكون قادرًا على الوصول إلى سطح المكتب بعده! ستحتاج لإنجاز الأمر إلى تعليمتي try وexcept. احذف كل الشيفرة التي تأتي بعد الدالة camera.start_preview، ثم اكتب: frame = 1 تُنشئ هذه التعليمة المتغير الجديد frame وتسند له القيمة 1. يخزِّن البرنامج في هذا المتغير رقم الإطار الحالي وسنستخدمه للتأكُّد من تخزين ملفٍ جديد كل مرة وإلا ستُخزن الصور فوق بعضها كلما ضُغط الزر. سننشئ الآن الحلقة على النحو التالي: while True: try: تخبر التعليمة try بايثون بأن ينفذ ما بداخلها من التعليمات، والتي ستكون تعليمات التقاط الصورة: button.wait_for_press() camera.capture('/home/pi/Desktop/animation/frame%03d.jpg' % frame) frame += 1 نلفت انتباهك إلى عدة حيلٍ ذكية في الشيفرة السابقة وأولها استخدام التعبير 03d%؛ والذي يسمح بإضافة أصفارٍ إلى عددٍ ليُكتب بثلاث خانات؛ أي سيُكتب العدد "1" على النحو التالي "001"، ويكتب العدد "12" على النحو التالي "012". يساعدك هذا الحل على تخزين الصورة وفق الترتيب الصحيح دون أن تخزّن فوق بعضها. أما التعليمة frame% في آخر السطر ستجعل بايثون يستخدم رقم الإطار اسمًا لملف الصورة الملتقطة. يزيد السطر الذي يليه قيمة المتغير frame بمقدار واحد فستتحول قيمته من 1 إلى 2 عند أول ضغطة على الزر وهكذا. سنستخدم التعليمة except لتحديد نهاية عملية التقاط الصور وتخزينها. اكتب الشيفرة التالية منتبهًا للإزاحة؛ ولذلك أزِل مستوًى واحدًا من المسافة البادئة في السطر الأول حتى يعرف بايثون أنها ليست جزءًا من try: except KeyboardInterrupt: camera.stop_preview() break سيبدو البرنامج الكامل على النحو التالي: from picamera import PiCamera from time import sleep from gpiozero import Button camera = PiCamera() button = Button(2) camera.start_preview() frame = 1 while True: try: button.wait_for_press() camera.capture('/home/pi/Desktop/animation/frame%03d.jpg' % frame) frame += 1 except KeyboardInterrupt: camera.stop_preview() break انقر على أيقونة التشغيل "Run"، ثم اضغط مفتاحي لوحة المفاتيح "Ctrl" و"C". ليس بالضرورة ضغط المفتاحين معًا فيكفي ضغط "Ctrl" باستمرار ثم ضغط "C" وتحرير المفتاحين بعدها. ينفِّذ هذان الزران معًا ما يُسمى مقاطعة interrupt مصدرها لوحة المفاتيح لإيقاف عمل البرنامج. وهذا ما يفعله تمامًا السطر: except KeyboardInterrupt: حيث تتوقف عملية التقاط الصور مباشرةً عندما ننفِّذ طلب مقاطعةً بواسطة لوحة المفاتيح؛ وإلا ستعيق نافذة العرض المباشر للكاميرا الوصول إلى سطح المكتب إذا أنهيت البرنامج بالنقر على أيقونة الإيقاف "Stop". على الرغم من تنفيذ بايثون لأية شيفرات صحيحة، لكن في حالتنا يأتي أمر الإيقاف من الشيفرة التي ستنهي العرض المباشر للكاميرا ومن ثم توقِف البرنامج على النحو الصحيح. وهكذا ستكون مستعدًا الآن لتحريك الرسوميات. ثبِّت الكاميرا في مكانٍ مناسب لالتقاط صورة الغرض الذي تريد تحريكه، وتأكد بأنه ثابت لا يتحرك، فإذا تحركت الكاميرا ستُفسد العملية. ضع الغرض في موقعه الأولي، ثم انقر أيقونة التشغيل وراقب العرض المباشر للكاميرا لتتأكد أن كل شيء في مكانه الصحيح. اضغط الزر لالتقاط أول صورة (أول إطار)، ثم حرِّك الغرض بلطف؛ فكلما كان اختلاف الموقع بين الصورتين ضئيًلا كان الرسم المتحرك الناتج أكثر نعومة. اضغط الزر مرةً أخرى لالتقاط الإطار الثاني وحرِّك الغرض وهكذا كرّر العملية حتى تنتهي. كلما زاد عدد الصور المُلتقطة، كلما زادت مدة الرسم المتحرك الذي تصممه. اضغط مفتاحي لوحة المفاتيح "Ctrl+C" لإيقاف البرنامج ثم افتح المجلد "animation" على سطح المكتب بالنقر المزدوج عليه. تحقق من أي صورة بالنقر عليها نقرًا مزدوجًا واستعراض تفاصيلها. شكل 11-8 الصور الملتقطة في المجلد المخصص لها ليس لدينا حتى اللحظة سوى مجلدٍ ممتلئ بالصور الثابتة ولا بدّ من تحويلها إلى فيديو لكي ننشئ الرسم المتحرك الذي نريده. لذلك، انقر على أيقونة باي وانتقل إلى فئة "البرامج الملحقة Accessories"، ثم انقر على برنامج الطرفية "terminal" التي تمثّل واجهة سطر الأوامر(ستُناقش بمزيدٍ من التفصيل في الملحق "C"). بعد أن يكتمل تحميل برنامج الطرفية استخدم الأمر التالي للانتقال إلى المجلد "animation" على سطح المكتب: cd Desktop/animation وانتبه أن يكون الحرف D في كلمة Desktop كبيرًا؛ لأن راسبيان حساسٌ لحالة الأحرف فلن يعمل أي أمر إذا لم تكتبه تمامًا كما هو في الأصل. عندما تنتقل إلى المجلد المطلوب اكتب الأمر التالي: avconv -r 1 -i frame%03d.jpg -r 10 animation.h264 يحمل الأمر السابق البرنامج avconv، الذي يقرأ الصور الثابتة من المجلد ويحوّلها إلى فيديو يُدعى animation.h264. قد يستغرق الأمر عدة دقائق وفقًا لعدد الصور الثابتة في المجلد؛ وستعرف أنه انتهى من عمله عندما ترى محث الطرفية يومض في سطرٍ جديد. ابحث عن الملف "animation.h264" في مجلد الصور وانقر عليه نقرًا مزدوجًا لتشغيله، كما يمكنك استخدام الطرفية بكتابة الأمر التالي: omxplayer animation.h264 بمجرد تحميل الفيديو سترى ما أنجزته. تهانينا، لقد حولت باي إلى أداة لإنشاء الرسوم المتحركة. إذا رأيت أن الفيديو سريع كثيرًا أو بطيء كثيرًا، غيِّر الخيار r 10- في تعليمة تشغيل البرنامج avconv زيادةً أو نقصانًا؛ حيث يتحكم هذا الخيار بمعدل الإطارات المعروضة في الثانية. كلما زاد المعدل كلما كان الفيديو أكثر دقة وسلاسة لكنه سيعرض مشاهدًا أقل في حجم محدد للمقطع. والعكس صحيح، فنقصان المعدل يجعل الملف أقل نعومة لكنه سيعرض مشاهدًا أكثر في نفس الحجم. إذا أردت أخيرًا حفظ مقطع الفيديو انقله إلى المجلد "فيديوهات Videos" وإلا سيُسجَّل مقطع فيديو جديد فوقه في كل مرةٍ تشغِّل فيها برنامجك. الإعدادات المتقدمة للكاميرا إذا أردت التمتُّع بقدرةٍ أكبر على التحكم بإعدادات تجهيزة كاميرا راسبيري باي، يمكنك الاستفادة من مكتبة picamera في بايثون للوصول إلى الإعدادات المختلفة للكاميرا، وقد فصلنا فيما يلي هذه الإعدادات مع قيمها الافتراضية لتستخدمها لاحقًا في برامجك: إعداد الموازنة التلقائية للون الأبيض camera.awb_mode يضبط هذا الإعداد الموازنة التلقائية للون الأبيض في الكاميرا: camera.awb_mode = 'auto’ ويُضبط على أحد الخيارات التالية: off auto افتراضي. sunlight cloudy shade tungsten fluorescent incandescent flash horizon بدِّل بين الخيارات السابقة إذا رأيت الصورة مائلةً للزرقة أو الاصفرار. إعداد الإضاءة camera.brightness يحدّد مقدار إضاءة الصورة الملتقطة. camera.brightness = 50 حيث تكون الصورة مظلمةً عندما تكون قيمة الإعداد 0 وشديدة الإضاءة (أقرب إلى اللون الأبيض) عندما تكون قيمته 100. إعداد التأثيرات اللونية camera.color_effects يغيّر هذا الإعداد التأثيرات اللونية التي تستخدمها الكاميرا، حيث يُترك هذا الإعداد عادةً دون تغيير. camera.color_effetcs = None لكن إن زوّدت الإعداد بزوجٍ من الأرقام، سيغير ذلك طريقة تسجيل الكاميرا للألوان. حاول أن تضع القيمة (128،128) لإنتاج صورٍ بالأبيض والأسود. إعداد وضوح الصورة camera.contrast يضبط هذا الإعداد وضوح الصورة؛ حيث تجعل القيم العالية الصورة أكثر حيوية؛ بينما تجعل القيم المنخفضة الصورة باهتةً جدًا. يمكنك استخدام قيم بين 100- وهي القيمة الدنيا و 100 وهي أعلى قيمة. camera.contrast = 0 إعداد القص camera.crop يسمح لك بقص أجزاءٍ من الصورة من الأطراف أو الأعلى والتقاط الجزء الذي تريده من الصورة. camera.crop = (0.0, 0.0, 1.0, 1.0) حيث تمثّل الأرقام ما بين القوسين إحداثيات X و Y والعرض والارتفاع. تُلتقط الصورة افتراضيًا بأكملها، لكن إن أردت رؤية تأثير هذا الإعداد، حاول تغيير آخر قيمتين إلى 0.5- و 0.5. إعداد التعويضات camera.exposure_compensation يضبط يدويًا كمية الضوء الواصل إلى حساس الكاميرا الضوئي عند التقاط الصورة. camera.exposure_compensation = 0 وعلى خلاف تغيير السطوع brightness يتحكم هذا الإعداد بالكاميرا نفسها وليس بالصورة، ويأخذ قيمه بين 25- (معتمٌ جدًا) إلى 25 (ساطع جدًا). إعداد درجة الإضاءة camera.exposure_mode يضبط نمط التعرض الضوئي exposure (نمط تحديد كمية الضوء التي تصل إلى الحساس الضوئي للكاميرا) أو المنطق الذي تتبعه الكاميرا في تحديد هذه الكمية. camera.exposure_mode = ‘auto’ يأخذ هذا الإعداد هذه القيم: off auto افتراضي night backlight spotlight sports snow beach verylong fixedfps antishake fireworks إعداد معدل التقاط الإطارات camera.framerate يحدِّد عدد الصور التي تلتقطها الكاميرا في الثانية عند تصوير مقطع فيديو أو ما يسمى معدل التقاط الإطارات. camera.framerate = 30 تسمح لك المعدلات العالية بالتقاط فيديوهات أكثر نعومة، لكنها تستهلك حجمًا أكبر في الذاكرة. وبالتالي يرتبط المعدل الالتقاط العالي بانخفاض الدقة المستخدمة التي يمكن التحكم بها أيضًا من خلال الإعداد "camera.resolution". إعداد القلب الأفقي camera.hflip camera.hflip = False يقلب هذا الخيار الصورة الملتقطة أفقيًا أو بالنسبة للمحور X عندما يأخذ القيمة True. إعداد التأثيرات camera.image_effect يطبق هذا الإعداد مجالًا من التأثيرات على تيار الفيديو والتي ستظهر في العرض المباشر وفي الصور والفيديوهات المخزّنة. camera.image_effect = ‘none’ هذه التأثيرات هي: blur cartoon colorbalance colorpoint colorswap deinterlace1 deinterlace2 denoise emboss film gpen hatch negative none oilpaint pastel posterise saturation sketch solarize washedout watercolor إعداد camera.ISO يغيّر إعدادات ISO للكاميرا والتي تؤثر على حساسيتها للضوء. camera.ISO = 0 تضبط الكاميرا هذا الإعداد تلقائيًا وفقًا لكمية الضوء المتاحة. كما يمكنك ضبطه يدويًا باختيار أحد القيم التالية: 100 أو 200 أو 320 أو 400 أو 500 أو 640 أو 800؛ وكلما زادت القيمة تحسَّن أداء الكاميرا في ظروف الإضاءة المنخفضة؛ لكن ستزداد في المقابل خشونة الصور أو الفيديوهات الملتقطة. إعداد camera.meter_mode يتحكم بكيفية تحديد الكاميرا لكمية الضوء المتاح عندما تضبط مقدار تعرضها للضوء. camera.meter_mode = ‘average’ تقسِّم الكاميرا افتراضيًا كمية الضوء التي تصلها بالتساوي على كامل الصورة. وإليك بقية الخيارات: backlit matrix spot إعداد الدقة camera.resolution يضبط هذا الإعداد دقة الصورة أو الفيديو المُلتقط على هيئة زوجٍ من الأعداد يمثّلان العرض والارتفاع. camera.resolution = (1920,1080) يُساعدك اختيار دقةٍ منخفضة على توفير مساحة التخزين وزيادة معدل الالتقاط؛ بينما تسمح لك الدقة العالية في زيادة جودة الصورة لكنها تستهلك مساحة تخزينٍ أكبر. إعداد التدوير camera.rotation يتحكم بزاوية تدوير الصورة. camera.rotation = 0 يأخذ هذا الإعداد قيمًا من 0 درجة مرورًا بالزاوية 90 و 180 و 270 رجوعًا إلى 0. استخدم هذا الخيار عندما لا تكون قادرًا على ضبط موقع الكاميرا وخرج الكابل من أسفل التجهيزة. إعداد الإشباع camera.saturation يضبط هذا الإعداد درجة إشباع الصورة أو درجة وضوح الألوان ويأخذ قيمًا بين 100- و 100. camera.saturation = 0 إعداد الحدة camera.sharpness يضبط هذا الإعداد حدة تمايز ألوان الصورة ويأخذ قيمًا بين 100- و 100. camera.sharpness = 0 إعداد سرعة الغالق camera.shutter_speed يحدد سرعة فتح وإغلاق غالق الكاميرا shutter عند التقاط صورة أو فيديو. camera.shutter_speed = 0 يمكن ضبط هذا الإعداد يدويًا بواحدة الميكرو ثانية، وكلما زادت مدة بقاء الغالق مفتوحًا كان ذلك أفضل للبيئات المنخفضة الإضاءة والعكس صحيح في البيئات عالية السطوع؛ ويفضل أن يبقى هذا الخيار على وضعه الافتراضي بحيث يُضبط من قِبل الكاميرا تلقائيًا. إعداد القلب العمودي camera.vflip يقلب هذا الخيار الصورة الملتقطة عموديًا أو بالنسبة للمحور Y عندما يأخذ القيمة True. camera.vflip= False إعداد التثبيت camera.video_stabilization يفعِّل هذا الخيار تقنية تثبيت الفيديو عندما يأخذ القيمة True. camera.video_stabilization = False فعّل هذا الخيار عندما تتحرك الكاميرا أثناء التسجيل كأن تكون مرتبطة بروبوت أو محمولة باليد، وذلك لتخفيف الاهتزازات في مقطع الفيديو الذي تصوره. يمكنك الاطلاع على مزيدٍ من المعلومات عن الإعدادات السابقة والإعدادات التي لم نذكرها على الموقع الرسمي للمكتبة picamera ترجمة -وبتصرف- للفصل الثامن "The Raspberry Pi Camera Module" من كتاب The official Raspberry Pi beginner's guide. اقرأ أيضًا المقال السابق: الحوسبة الفيزيائية: برمجة راسبيري باي مع لوحة سنس هات Sense HAT بدء استخدام راسبيري باي تعرف على جهاز راسبيري باي Raspberry Pi تجميع راسبيري باي والتحضير لاستعماله
  19. تُعد سنس هات Sense HAT، التي اسُتخدمت في محطة الفضاء الدولية، لوحةً إلكترونيةً مستقلة ومتعددة الوظائف تُضاف إلى راسبيري باي عبر المنصة GPIO، ومزُوّدة بحسّاسات sensors ومصفوفة عرض ضوئية LED matrix display. تُدعم أجهزة راسبيري باي Raspberry Pi بنوع خاص من اللوحات الإلكترونية المضافة التي تُدعى بالتجهيزات المتصلة من الأعلى Hardware attached on top -أواختصارًا HAT-، والتي يمكنها إضافة أي شيء إلى راسبيري باي باي ابتداءً من المايكروفون مرورًا بالأضواء والمرحّلات Relays وحتى الشاشات. تُعد سنس هات من أكثر تجهيزات هات فائدةً وقد صّممت خصيصًا لمهمة الفضاء أسترو باي Astro Pi، وهي مهمةٌ مشتركةٌ بين مؤسسة راسبيري باي ووكالة فضاء المملكة المتحدة ووكالة الفضاء الأوروبية، والتي كانت قد اطّلعت على تجهيزات هات المُخصصة لراسبيري واختارت سنس هات لتنقلها إلى محطة الفضاء الدولية مع الصاروخ الذي حمل معدات المختبر المداري "Cygnus"؛ ولا تزال سنس هات التي لقبها رواد الفضاء "إد ED" و"إيزي Izzy" تُنفِّذ الشيفرات وتُجري اختبارات علمية يُساهم بها أطفال المدارس من كل أنحاء أوروبا. يمكنك الحصول على التجهيزة سنس هات نفسها لدى معظم موزعي راسبيري باي، كما يمكنك استخدام برمجيات تحاكي عمل سنس هات إن لم تشأ شراء واحدة. تعرف على سنس هات سنس هات هي لوحةٌ إلكترونيةٌ مُضافةٌ متعددة الوظائف تُوصل براسبيري باي، وتضم اللوحة مصفوفةً أبعادها 8X8 من المؤشرات الضوئية الحمراء والخضراء والزرقاء RGB القابلة للبرمجة والتي يمكن التحكم بها لإنتاج أي لون تقريبًا من ملايين الألوان المتاحة، إضافةً إلى متحكّم بمقبض ألعاب Joystick بخمس وجهات وستة حساسات مدمجة، هي: جيروسكوب Gyroscope، الذي يتحسس للتغيُّرات في زاوية الدوران مع الزمن، أو كما يُعرف تقنيًا بالسرعة الزاويّة angular velocity، وذلك بتعقب اتجاه حقل الجاذبية للأرض، وهو الحقل الناتج عن قوة الجاذبية التي تشد الأشياء إلى مركز الأرض. ببساطة، يستشعر الجيروسكوب دوران سنس هات بالنسبة لسطح الأرض ويحدّد سرعة دورانها. مقياس التسارع Accelerometer: خلافًا للجيروسكوب الذي يقيس تغيرات زاوية الحركة بالنسبة لسطح الأرض يقيس مقياس التسارع القوة المسببة لتسارع الحركة في الاتجاهات المختلفة، وستتمكن بقراءة البيانات الناتجة عن الحساسين السابقين من تحديد وجهة سنس هات وكيف تتحرك. مقياس حقل مغناطيسي Magnetometer، الذي يقيس شدة الحقل المغناطيسي، ويساهم أيضًا في تتبُّع حركة سنس هات بقياس شدة الحقل المغناطيسي الأرضي وتقدير جهة الشمال المغناطيسي، كما يُستخدم في الكشف عن الأجسام المعدنية والحقول الكهربائية. دُمجت الحساسات الثلاث السابقة ضمن رُقاقة واحدةٍ تحمل الاسم "‘ACCEL/GYRO/MAG" على لوحة سنس هات. حساس رطوبة، الذي يقيس كمية بخار الماء في الهواء وهذا ما يُعرف بالرطوبة النسبية relative humidity، التي تبدأ بالقيمة 0% (لا رطوبة في الهواء) وصولًا إلى 100% (الهواء مشبعٌ تمامًا ببخار الماء). يمكن استخدام بيانات الحساس لتوقع هطول الأمطار مثلًا. حساس ضغط بارومتري Barometric، الذي يقيس الضغط الجوي. وعلى الرغم من اعتقاد الكثيرين بارتباطه فقط بنشرات الطقس إلا أن له استخدامٌ آخر غير معروف، إذ يمكنه تعقبك إن كنت صاعدًا إلى تلة أو جبل أو نازلًا عنه نظرًا لتغيُّر الضغط الجوي للأرض عند الارتفاع أو الانخفاض عن مستوى سطح البحر. حساس درجة الحرارة لقياس درجة حرارة الوسط المحيط، وقد يتأثر بحرارة لوحة سنس هات، وبالتالي قد تحصل على حرارة أدنى أو أعلى من القراءة الصحيحة إذا كنت تضع باي ضمن حاضنة. لا يوجد حساس حرارة مستقل في سنس هات بل تستخدم حساسا الحرارة المدمجان مع حساسي الرطوبة والضغط، ويمكن لبرنامجك استخدام حساس أو حساسين فقط من هذه المجموعة. تثبيت سنس هات إذا اشتريت لوحة سنس هات، فابدأ بإخراجها من علبتها وتأكد من وجود جميع الأجزاء، وهي اللوحة نفسها وأربعة دعائم معدنية أو بلاستيكية تُعرف باسم المباعدات Spacers وثمانية براغي Screws. قد تجد أيضًا بعض الأرجل المعدنية المشابهة لأرجل GPIO على باي مثبتة على شريط بلاستيكي أسود، ادفع الشريط أسفل لوحة سنس هات في هذه الحالة والأرجل متجهة للأعلى حتى تسمع صوت إطباق. صُممت المباعدات لحماية سنس هات من الانحناء عند استخدام مقبض الألعاب، ورغم أن سنس هات ستعمل دون تثبيت المباعدات، إلّا أنّ استخدامها سيحمي لوحة سنس هات ولوحة راسبيري باي والمنصة GPIO من الضرر. ثبِّت المباعدات بدفع أربعة براغي من أسفل لوحة راسبيري باي إلى الأعلى عبر الثقوب الأربعة في كل زاوية، ثم لُف المباعدات فوق البراغي. ادفع سنس هات بعد التأكد من تطابق موقعها فوق منصة GPIO تمامًا نحو المنصة وحاول أن تجعلها مستويةً قدر الإمكان. ثبِّت سنس هات بواسطة البراغي الأربعة الباقية بإدخالها ضمن الثقوب الموجودة على زوايا سنس هات لتدخل ضمن المباعدات التي ثبتّها مسبقًا. ينبغي أن تكون سنس هات مستويةً تمامًا إن ثبّتها جيدًا ولن تنحني عندما تضغط على أزرار مقبض الألعاب. أعِد وصل باي إلى التغذية الكهربائية وسترى مصفوفة الأضواء على سنس هات وقد أضاءت بنمط ألوان قوس قزح ثم انطفأت. (شكل 1- ظهور نمط شكل قوس قزح عند وصل التغذية الكهربائية) فك البراغي العلوية الأربعة إذا أردت إزالة سنس هات، ثم ارفعها بحذر كي لا تثني أرجل GPIO كونها مرتبطةٌ بإحكام معها (قد تضطر إلى زحزحتها قليلًا بالمفك). أزِل المباعدات عن باي بعد ذلك لتتحرر البراغي السفلية الأربعة. مرحبا سنس هات سنبدأ مثل معظم المشاريع البرمجية بعرض رسالة ترحيب بمستخدمي سنس هات من خلال المصفوفة الضوئية، فإذا كنت ستستخدم مقلّد سنس هات، فعليك تشغيله بالنقر على أيقونة راسبيان والانتقال إلى فئة "برمجة Programming" ثم النقر على مقلّد سنس هات "Sense HAT Emulator". سكراتش ترحب بك شغّل سكراتش 2 من قائمة راسبيان ثم انقر على الفئة "كتل إضافية More Blocks" ضمن لوحة الكتل البرمجية، ثم انقر على زر "إضافة موسّع Add an Extension". اختر الموسّع "Pi SenseHAT"، ثم انقر "OK". ستظهر لك الآن جميع الكتل البرمجية التي تساعدك على التحكم بمختلف ميزات سنس هات بما في ذلك المصفوفة الضوئية وستجد هذه الكتل ضمن الفئة "كتل إضافية More Blocks". شكل 2-7 إضافة الموّسع "Pi SenseHAT" إلى سكراتش 2 اسحب الكتلة إلى منطقة بناء البرنامج، ثم ضع الكتلة تحتها مباشرةً وعدِّل النص، لتقرأ الكتلة عبارة "!Hello World" مع قيمة دوران مساوية 0 وبلونٍ أبيض وخلفية مُطفأة off. هناك طبعًا العديد من النقاط الواجب شرحها في الكتلة السابقة، لكننا سنكتفي الآن بالنقر على الراية الخضراء لتشغيل البرنامج ومراقبة سنس هات أو المقلّد. ستمر أحرف العبارة "!Hello, World" التي تكوّنها الأضواء البيضاء للمصفوفة تباعًا وببطء، كما هو موضح في الشكل التالي. تهانينا، نجح برنامجك في العمل. شكل 3-7 ستتحرك رسالتك خلال مصفوفة المؤشرات الضوئية بعد أن نجحت في عرض الرسالة لا بدّ من إلقاء نظرة على بقية خصائص الكتلة ، فبالإضافة إلى إمكانية تغيير الرسالة، يمكنك تغيير القيمة rotation التي تتحكم بطريقة عرض الرسالة على سنس هات. انقر على السهم الصغير بجوار rotation وغيِّر القيمة إلى 90 لتصبح الكتلة بالصيغة "Hello, World! at rotation 90 in colour white background off". شغِّل البرنامج وستلاحظ أنّ الرسالة ستتحرك من الأسفل إلى الأعلى وليس من اليسار إلى اليمين. شكل 4-7 ستتحرك الرسالة عموديًا الآن أعِد قيمة rotation إلى 0 وغيِّر لون الأضواء التي تعرض الرسالة بالنقر على السهم الصغير بجوار "in colour white"، ثم اختر لونًا من القائمة: أحمر red، أزرق blue، أصفر yellow، سماوي cyan، أرجواني magenta، أبيض white، إضافةً لخيار off لإطفاء الأضواء بدلًا من تشغيلها، وهو مكافئ للون الأسود. اختر حاليًا اللون الأصفر وانقر الراية الخضراء ولاحظ تغيّر لون النص. شكل 5-7 تغيير لون الرسالة المعروضة انقر أخيرًا على السهم الصغير بجوار الخيار background لترى قائمة الألوان السابقة نفسها. لن يتغير لون المؤشرات الضوئية التي تعرض الرسالة هذه المرة بل ألوان مجموعة المؤشرات التي لا تعرضها والتي تُسمى خلفية Background. غيِّر ألوان النص والخلفية لتصل إلى التشكيلة المثالية، فلن تتماشى بعض الألوان مع البعض الآخر. وطالما أنك قادر على تحريك رسالتك عبر الشاشة، يمكنك مشاهدة الحروف كلٌ على حدى. اسحب الكتلة خارج منطقة بناء البرنامج لحذفها واستبدلها بالكتلة ثم انقر الراية الخضراء وسترى الفرق. تعرض المصفوفة حرفًا واحدًا كل مرة في المكان نفسه حتى نغيّر ذلك دون أن تتحرك الحروف عبر المصفوفة أو تختفي. يُطبَّق على هذه الكتلة نفس النظام اللوني المطبَّق على الكتلة السابقة، لذلك حاول تغيير لون الحرف إلى الأحمر. شكل 6-7 يظهر على الشاشة حرف واحد بايثون ترحب بك حمّل أيًا من نمطي بيئة العمل ثوني Thonny البسيط، أو القياسي بالنقر على أيقونة راسبيان، ثم انتقل إلى فئة "برمجة Programming"، ثم انقر أخيرًا على أي من اختصاري ثوني. ستغطي واجهة ثوني واجهة المقلّد إذا كنت تستخدمه، لذلك غيِّر موقع النافذتين حتى تتمكن من عرضهما معًا على الشاشة. ستحتاج إلى إدراج مكتبة SenseHat، إذا كنت ستستخدم بايثون لكتابة برنامجك سواءٌ لتجهيزة سنس هات، أم للمقلّد. اكتب ما يلي في نافذة الشيفرة: from sense_hat import SenseHat sense = SenseHat() للمكتبة دالةٌ بسيطة تقرأ الرسالة وتنسِّقها لتظهر على مصفوفة الأضواء ومن ثم تحرِّكها بلطف. اكتب الشيفرة التالية الآن: sense.show_message("Hello, World!") احفظ برنامجك باسم "Hello Sense HAT"، ثم انقر أيقونة التشغيل "Run"، ستتحرك الرسالة ببطء على شاشة المصفوفة الضوئية. تهانينا، نجح برنامجك في العمل. from sense_hat import SenseHat إلى: from sense_emu import SenseHat وبالعكس. شكل 7-7 تحريك الرسالة عبر شاشة المصفوفة الضوئية. يوجد للدالة ()show_message ميزاتٌ أخرى، لذلك عُد إلى برنامجك وعدّل الدالة لتصبح على النحو التالي: sense.show_message("Hello, World!", text_colour=(255, 255, 0), back_colour=(0, 0, 255), scroll_speed=(0.05)) تُعرف هذه التعليمات التي تفصل بينها فاصلة "," داخل قوسي الدالة باسم المعاملات Parameters، وهي تتحكم بعمل الدالة من نواحٍ عدة، ويُعد ()=scroll_speed أبسط هذه المعاملات، إذ يتحكم بسرعة عرض الرسالة على الشاشة؛ فلو كانت قيمته 0.05، فستتحرك الرسالة بسرعة مضاعفة عن السرعة الاعتيادية، وكلما زادت القيمة كلما قلت السرعة. أما المعاملان ()=text_colour و ()=back_colour (مكتوبان وفق التهجئة البريطانية على خلاف تعليمات بايثون الأخرى) فيحددان لون النص ولون الخلفية، لكنهما لا يستخدمان أسماء الألوان بل يستخدمان النظام اللوني الثلاثي الذي تحدد فيه نسب الألوان الأساسية الأحمر ثم الأخضر ثم الأزرق واختصارًا RGB، إذ يمثل الرقم الأول من الثلاثية كمية اللون الأحمر في اللون المحدد والتي تأخذ القيم من 0 (لا لون أحمر) حتى 255 (الحد الأقصى للون الأحمر)، ويمثل الرقم الثاني كمية اللون الأخضر، والثالث كمية اللون الأزرق. انقر على أيقونة التشغيل "Run" وراقب سنس هات. لاحظ كيف تتحرك الرسالة التي تظهر بلون أصفر على خلفية زرقاء بسرعة أكبر. بدِّل قيم المعاملات السابقة لتحصل على طريقة العرض الملائمة. شكل 8-7 تغيير لون النص والخلفية. يمكنك استخدام المتغيرات لإعطاء أسماء مناسبة للون الذي تريده بدلًا من استخدام نظام RGB. لتجربة ذلك اكتب الشيفرة التالية قبل سطر الدالة ()sense.show_message: yellow = (255, 255, 0) blue = (0, 0, 255) ثم عدًل سطر الدالة نفسها ليصبح على النحو التالي: sense.show_message("Hello, World!", text_colour=(yellow), back_ colour=(blue), scroll_speed=(0.05)) إذا نقرت على أيقونة التشغيل مجددًا فلن تلحظ أية تغيرات، وستبقى رسالتك بلون أصفر وخلفية زرقاء وكل ما هناك أنك استخدمت المتغيرات لجعل اللون الذي اخترته مقروءًا بدلًا من استخدام مجموعة أرقام؛ وهكذا يمكن تعريف العدد الذي تشاء من الألوان ومنحها أسماءً، فيمكنك مثلًا تسمية اللون (255,0,0) باسم "أحمر red" واللون (255,255,255) باسم "أبيض white" وسيكون "الأسود black" هو حتمًا اللون (0,0,0). يمكنك كذلك عرض الرسالة مثل حروف متلاحقة واحدًا تلو الآخر بدل تحريكها، ولتنفيذ ذلك احذف سطر التعليمة: sense.show_message() واستبدله بالشيفرة التالية: sense.show_letter("Z") انقر على أيقونة التشغيل لترى الحرف "Z" على شاشة سنس هات، إذ سيبقى الحرف مكانه هذه المرة، فلا تتحرك الحروف المفردة بحد ذاتها على الشاشة. يمكنك كذلك التحكم في لون وخلفية الحرف من خلال الدالة ()sense.show_letter وباستخدام معاملات مشابهةٍ لمعاملات الدالة ()sense.show_message، جرّب ذلك. شكل 9-7 إظهار حرف وحيد الرسم بالأضواء لا تُستخدم المصفوفة الضوئية في سنس هات لعرض الرسائل فقط، بل يمكنك عرض الصور أيضًا، إذ يُعامل كل مؤشر ضوئي في المصفوفة مثل بكسل pixel (بكسل= عنصر-صورة أو بكسل كما هو شائع) مفرد في الصورة التي تختارها، وبالتالي ستكون قادرًا على إحياء برامجك بالصور وحتى الرسوم المتحركة. ولكي تتمكن من إظهار الرسوميات والصور، لا بدّ أن تكون قادرًا على تغيير كل مؤشر ضوئي على حدى، لذلك علينا أولًا فهم طريقة تنظيم المؤشرات الضوئية في مصفوفة سنس هات لكتابة البرنامج الصحيح الذي يضيء ويطفئ المؤشر الضوئي المطلوب. شكل 10-7 نظام الإحداثيات الخاص بالمصفوفة الضوئية. تضم المصفوفة ثمانية مؤشرات ضوئية في كل صف وثمانية في كل عمود، وتُعَد المؤشرات كما هو الحال في معظم لغات البرمجة إذ تبدأ من 0 وتنتهي عند الرقم 7، وسيكون المؤشر الضوئي في الزاوية اليسارية العليا في الصف 0 والعمود 0 أي إحداثياته (0,0)، إذ يمثِّل الإحداثي الأول قيمة X التي تشير إلى الأعمدة والإحداثي الثاني قيمة Y التي تشير إلى الأسطر. وستكون إحداثيات المؤشر في الزاوية اليمينية السفلية بناء على هذه المنظومة (7,7) وهكذا. يمكنك ملاحظة المؤشر الضوئي الأزرق مثلًا المبين في الشكل السابق عند الإحداثيات (0,2) والأحمر عند الإحداثيات (4,7). قد يفيدك رسم مخطط للمؤشرات الضوئية على ورقة مقسمة عندما تخطط لعرض صورة ما على شاشة سنس هات، كما يمكنك الاستعانة بالجداول الإلكترونية spreadsheets لتخطيط طريقة عرض الصورة مثل برنامج ليبر أوفيس كالك LibreOffice Calc. عرض الصور باستخدام سكراتش ابدأ مشروعًا جديدًا في سكراتش بعد حفظ مشروعك السابق إن أردت. حمّل الموسِّع "PI Sense HAT" من خلال الفئة "كتل إضافية More Blocks"، ولا تنس أن تعيد هذه الخطوة في كل مرة تنشئ فيها مشروعًا جديدًا يستخدم سنس هات وإلا لن تظهر الكتل التي تتحكم بهذه التجهيزة. اسحب الكتلة إلى منطقة بناء البرنامج، ثم ضع تحتها مباشرةً الكتلة . انقر على الراية الخضراء دون أن تنظر مباشرةً إلى المصفوفة الضوئية لأن المؤشرات ستضيء بلون أبيض لامع قد لا يكون النظر إليها مباشرة أمرًا مريحًا. شكل 11-7 لا تنظر مباشرةً إلى مصفوفة الأضواء عندما تضيء بلون أبيض لامع انقر على السهم الصغير بجوار الخيار white واختر لونًا مختلفًا، ثم أعد تشغيل البرنامج. اختر من جديد الخيار off بدلًا من اختيار لون محدد، ثم شغِّل البرنامج مجددًا لتُطفأ كل الأضواء في هذه الحالة. يمكنك استخدام نظام RGB لمزج اللون المطلوب إذا أردت لونًا خاصًا بك. لهذا اسحب الكتلة خارج منطقة بناء البرنامج واستبدلها بالكتلة انقر على الراية الخضراء وستضيء المؤشرات بلون أبيض لامع من جديد. يمكنك الآن تصميم اللون الذي تريد بتحديد كميات اللون الأحمر والأخضر والأزرق في الكتلة السابقة بعد الخيارات R و G و B على التوالي. يمكن أن تحمل أي كمية قيمًا من 0 حتى 255. عدّل الكتلة لتصبح ثم انقر الراية الخضراء لتضيء المصفوفة الآن بلون أخضر لامع. شكل 12-7 ستضيء المصفوفة كلها باللون الأخضر اللامع. جرب قيمًا مختلفة لمنظومة RGB لتحصل على اللون الذي تريده وسجل هذه القيم لاستخداماتك المستقبلية. ولكي تتمكن من عرض صورةٍ ما، لا بدّ أن تكون قادرًا على التحكم بكل مؤشر ضوئي على حدى. لتنشئ مثلًا نسختك عن البرنامج الذي يعرضه الشكل 10-7، الذي يُضاء فيه مؤشرين ضوئيين لبيكسلين باللون الأحمر والأزرق، غيِّر الكتلة إلى ، ثم اسحب كتلتي لتكونا تحتها مباشرةً وغير قيمهما لتكونا كما في الشكل التالي: انقر على الراية الخضراء لتشاهد الضوئين الأحمر والأزرق كما في الشكل 10-7. تهانينا، تستطيع الآن التحكم بكل مؤشر ضوئي على نحوٍ مستقل. عدّل الكتل السابقة كما في التسلسل التالي وأضف الكتل المناسبة لتحصل على البرنامج التالي: حاول أن تتوقع الصورة التي ستظهر على المصفوفة الضوئية بناءً على الإحداثيات التي استخدمتها في كتل التسلسل السابق قبل أن تنقر على الراية الخضراء، ثم شغّل البرنامج لترى إن كنت على حق. على الرغم من إمكانية استخدام كتل في عرض الصور البسيطة، لكن موسِّع سنس هات الموجود في النسخة سكراتش 2 لن يكون مناسبًا لعرض صور معقدة أو رسوميات متحركة. لذلك فكِّر في الانتقال إلى بايثون عند كتابة برنامجك. عرض الصور باستخدام بايثون ابدأ برنامجًا جديدًا في ثوني واحفظه باسم "Sense HAT Drawing" ثم اكتب الشيفرة التالية في نافذة الشيفرة وانتبه إلى استبدال sense_hat بمقابلتها sense_emu إذا كنت ستستخدم المقلّد: from sense_hat import SenseHat sense = SenseHat() وتذكر أنك ستحتاج كلا سطري الشيفرة السابقين لاستخدام سنس هات. أضف بعد ذلك السطر التالي: sense.clear(255, 255, 255) انقر على أيقونة التشغيل Run دون النظر مباشرةً إلى المصفوفة الضوئية لأنها ستضيء بأكملها باللون الأبيض اللامع عند تشغيل البرنامج. شكل 13-7 لا تنظر مباشرة إلى مصفوفة الأضواء عندما تضيء بلون أبيض لامع صُممت الدالة ()sense.clear لإلغاء برمجة كل المؤشرات الضوئية لكنها تقبل أيضًا معاملات لونية وفق نظام RGB، أي يمكنك تغيير لون المصفوفة إلى أي لون تريد. عدّل الشيفرة في السطر الأخير على النحو التالي: sense.clear(0, 255, 0) انقر على أيقونة التشغيل Run وسيتحول لون سنس هات إلى الأخضر اللامع. جرِّب ألوانًا مختلفة أو استخدم المتغيرات التي سمّيتها سابقًا بأسماء الألوان في برنامجك "Hello World" لتبسيط الأمر أكثر. شكل 14-7 ستضيء المصفوفة الضوئية باللون الأخضر اللامع. لإطفاء الأضواء، استخدم قيمة RGB الموافقة للون الأسود وهي (0,0,0)، كما يمكنك تنفيذ ذلك بطريقة أسهل وذلك بتعديل السطر الأخير من برنامجك ليصبح على النحو التالي: sense.clear() ستطفئ الدالة ()sense.clear أضواء سنس هات إن كانت أقواسها فارغة، وهذا ما ستحتاجه لإلغاء برمجة المؤشرات الضوئية بأكملها. شكل 15-7 استخدم الدالة sense.clear لإطفاء أضواء مصفوفة سنس هات. لتنشئ نسختك عن البرنامج الذي يعرضه الشكل 10-7 والمكوّن من مؤشرين ضوئيين محددين يضيئان باللونين الأحمر والأزرق، أضِف الشيفرة التالية مباشرةً بعد الدالة ()sense.clear: sense.set_pixel(0, 2, (0, 0, 255)) sense.set_pixel(7, 4, (255, 0, 0)) يمثِّل المعامل الأول من الدالة ()sense.set_pixel الإحداثي X (رقم العمود) لمنظومة إحداثيات المصفوفة، ويمثِّل المعامل الثاني الإحداثي Y، بينما يحدد الإحداثي الثالث لون المؤشر الضوئي بطريقة RGB. انقر على أيقونة التشغيل Run لترى تنفيذ الشيفرة، ولاحظ كيف ستضيء المصفوفة على نحوٍ مشابه لما يعرضه الشكل 10-7. احذف الآن السطرين السابقين واكتب الشيفرة التالية: sense.set_pixel(2, 2, (0, 0, 255)) sense.set_pixel(4, 2, (0, 0, 255)) sense.set_pixel(3, 4, (100, 0, 0)) sense.set_pixel(1, 5, (255, 0, 0)) sense.set_pixel(2, 6, (255, 0, 0)) sense.set_pixel(3, 6, (255, 0, 0)) sense.set_pixel(4, 6, (255, 0, 0)) sense.set_pixel(5, 5, (255, 0, 0)) تأمل إحداثيات المؤشرات الضوئية في الشيفرة السابقة وتوقع نتيجتها قبل تشغيل البرنامج، ثم تحقق من ذلك بعد التشغيل. وكما ترى سيكون رسم أي لوحة بتكرار استدعاء واحد للدالة ()sense.set_pixel بطيئًا، ومن الأفضل تغيير عدة بكسلات في الوقت نفسه. لهذا احذف كل الأسطر التي تستدعي الدالة ()sense.set_pixel واكتب الشيفرة التالية: g = (0, 255, 0) b = (0, 0, 0) creeper_pixels = [ g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, b, b, g, g, b, b, g, g, b, b, g, g, b, b, g, g, g, g, b, b, g, g, g, g, g, b, b, b, b, g, g, g, g, b, b, b, b, g, g, g, g, b, g, g, b, g, g ] sense.set_pixels(creeper_pixels) سنشرح الشيفرة السابقة لاحقًا لكن ابدأ بتشغيل البرنامج لنرى إن استطعت تمييز الشكل الذي ستعرضه سنس هات. لاحظ كيف يُنشئ أول سطرين متغيرين نسند إليهما قيم RGB المحددة للونين الأخضر g والأسود b لتسهيل كتابة وقراءة الشيفرة؛ وتنشئ كتلة الشيفرة التي تليهما متغيرًا يضم بين قوسين مربعين ألوان جميع بكسلات الشاشة الضوئية تفصل بينها الفاصلة ",". لاحظ كيف استخدمنا المتغيرين السابقين g و b بدلًا من الأرقام في تحديد الألوان وسيظهر حلزون نتيجة تنفيذ الشيفرة كما في الشكل 16-7. تقبل الدالة (sense.set_pixels(creeper_pixels المتغير creeper_pixels مثل معامل، ثم ترسم المصفوفة كاملةً في اللحظة نفسها، وهذا أسهل طبعًا من رسم كل بكسل لوحده. شكل 16-7 عرض صورة على المصفوفة الضوئية. من الممكن أيضًا تدوير أو قلب الصورة لعرض الصورة بالشكل الصحيح عند تدوير سنس هات، أو لتصميم رسم متحرك بسيط انطلاقًا من صورة غير متناظرة. ابدأ بتعديل قيم المتغير creeper_pixels لنغمض عين الحلزون على النحو التالي: creeper_pixels = [ g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, g, b, b, g, g, g, g, g, g, b, b, g, g, g, g, b, b, g, g, g, g, g, b, b, b, b, g, g, g, g, b, b, b, b, g, g, g, g, b, g, g, b, g, g ] انقر على Run وسترى عين الحلزون وقد أغمضت كما هو موضح في الشكل التالي. ولإنشاء رسمٍ متحرك انتقل إلى بداية برنامجك وأضِف السطر التالي: from time import sleep عُد إلى آخر البرنامج وأضف ما يلي: while True: sleep(1) sense.flip_h() انقر على زر التشغيل Run وسترى الحلزون وهو يغلق ويفتح عينيه بالتناوب. شكل 17-7 رسم متحرك من إطارين تقلب الدالة ()flip_h الصورة وفق محورها الأفقي، بينما تقلبها الدالة ()flip_v وفق محورها العمودي؛ وتستطيع أيضًا تدوير الصورة بزوايا 0 و 90 و 180 و 270 ثم العودة إلى 0 درجة باستخدام الدالة (sense.set_rotation(90 بعد استبدال 90 بالزاوية المطلوبة. حاول أن تستخدم هذه الدالة ليدور الحلزون بدلًا من إغماض عينيه> تحسس العالم من حولك من الممتع العمل مع المصفوفة الضوئية لسنس هات، لكن تظهر قوتها الحقيقية عند استخدام حساساتها المختلفة، إذ تتيح لك تلك الحساسات استشعار المحيط من درجة الحرارة إلى الحركة ومن ثم استخدام هذه المعلومات في برامجك بالطريقة التي تريد. تحسس البيئة المحيطة تأخذ حساسات الضغط والحرارة والرطوبة لسنس هات البيانات من البيئة المحيطة بها، لذلك فهي حساسات بيئية. استشعار البيئة المحيطة باستخدام سكراتش ابدأ برنامجًا جديدًا في سكراتش بعد حفظ البرنامج السابق إن أردت، ثم أضف الموّسع "Sense HAT" إلى فئة "كتل إضافية More Blocks". اسحب الكتلة إلى منطقة بناء البرنامج، وضع تحتها الكتلة . من المفيد تنفيذ هاتين الخطوتين في بداية برنامجك لتتأكد من عدم عرض أي شيء على المصفوفة الضوئية قد يكون عالقًا من برنامج سابق. اسحب بعد ذلك الكتلة الموجودة في الفئة "مظهر Look"، وضعها مباشرةً تحت الكتل السابقة. لقراءة الضغط الجوي، ابحث عن الكتلة في فئة "كتل إضافية More Blocks"، ثم اسحبها وأفلتها مكان الكلمة "!Hello" في الكتلة . انقر على الراية الخضراء، وستبلغك شخصية القط القراءة الحالية للضغط الجوي من حساس الضغط بالميلي بار، وستختفي الرسالة بعد ثانيتين. حاول أن تنفخ فوق سنس هات (أو تزيد قيمة الضغط عبر المحاكي) وأن تشغل البرنامج بالتوازي فسترى قراءة أعلى هذه المرة. شكل 18-7 عرض قراءة حساس الضغط ولكي نعرض مستوى الرطوبة بدلًا من الضغط، احذف الكتلة واستبدلها بالكتلة . شغِّل البرنامج الآن وسترى قيمة مستوى الرطوبة في الغرفة. جرّب كذلك أن تنفخ فوق سنس هات (أو تزيد قيمة الرطوبة عبر المحاكي) وأن تشغّل البرنامج بالتوازي فسترى قراءة أعلى هذه المرة لأن نفسك رطبٌ جدًا. شكل 19-7 عرض قراءة حساس الضغط إذا أردت الحصول على درجة الحرارة احذف الكتلة واستبدل بها الكتلة ، ثم شغِّل البرنامج مجددًا وستظهر درجة الحرارة بالدرجات المئوية (سلزيوس). قد لا تكون الدرجة المعروضة نفسها درجة حرارة الغرفة الفعلية، إذ تنتج راسبيري باي حرارةً أثناء عملها فتسخِّن سنس هات وحساساتها. شكل 20-7 عرض قراءة حساس الحرارة تحسس البيئة المحيطة باستخدام بايثون أنشئ برنامجًا جديدًا في ثوني واحفظه باسم "Sense HAT Sensors"، ثم اكتب الشيفرة التالية منتبهًا إلى استخدام المكتبة sense_emu بدلًا عن sense_hat عند استخدام المقلِّد: from sense_hat import SenseHat sense = SenseHat() sense.clear() من المفيد تنفيذ الأمر ()sense.clear في بداية برنامجك لتتأكد من عدم عرض أي شيء على المصفوفة الضوئية قد يكون عالقًا من برنامجٍ سابق. اكتب الأمر التالي لقراءة بيانات حساس الضغط: pressure = sense.get_pressure() print(pressure) انقر على أيقونة التشغيل Run وسترى قراءة الحساس مطبوعةً في نافذة المفسِّر بالميلي بار. حاول أن تنفخ فوق سنس هات، أو تزيد قيمة الضغط عبر المحاكي، وأن تشغِّل البرنامج بالتوازي فسترى قراءة أعلى هذه المرة. شكل 21-7 إظهار قراءة أعلى للضغط للانتقال إلى قراءة حساس الرطوبة، احذف السطرين السابقين ثم اكتب ما يلي: humidity = sense.get_humidity() print(humidity) انقر على أيقونة التشغيل Run، وسترى قراءةً أخرى في نافذة المفسّر تمثِّل الرطوبة النسبية بالنسبة المئوية. جرّب كذلك أن تنفخ فوق سنس هات (أو تزيد قيمة الرطوبة عبر المحاكي) وأن تشغل البرنامج بالتوازي فسترى قراءةً أعلى هذه المرة، فنفسك رطبٌ جدًا. شكل 22-7 إظهار قراءة حساس الرطوبة. ولتعرض قراءة حساس الحرارة، أزِل آخر سطرين واستبدلهما بالشيفرة التالية: temp = sense.get_temperature() print(temp) شغِّل البرنامج مجددًا وستظهر درجة الحرارة بالدرجات المئوية (سلزيوس). قد لا تكون الدرجة المعروضة نفسها درجة حرارة الغرفة الفعلية، إذ تنتج راسبيري باي حرارةً أثناء عملها فتسخن سنس هات وحساساتها. شكل 20-7 عرض قراءة حساس الحرارة تعطي سنس هات درجة الحرارة عادة بناءً على قراءة حساس الحرارة المدمج ضمن حساس الرطوبة، لكن إذا أردت قراءة الحساس الآخر المُدمج مع حساس الضغط استعمل الدالة ()sense.get_temperature_from_pressure، وقد تستخدم القراءتين معًا ثم تأخذ متوسطهما لدقة أفضل، لهذا احذف السطرين الأخيرين واكتب: htemp = sense.get_temperature() ptemp = sense.get_temperature_from_pressure() temp = (htemp + ptemp) / 2 print(temp) انقر على أيقونة التشغيل Run، وسترى قيمة درجة الحرارة المأخوذة مثل متوسطٍ لقراءتي الحساسين ضمن نافذة المفسِّر، وإذا كنت تستخدم المقلّد فستحصل على النتيجة نفسها في الحالات الثلاث. شكل 24-7 درجة الحرارة بناء على قراءتي كلا الحساسين استشعار الحركة يُشكّل الجيروسكوب وحساسا التسارع والحقل المغناطيسي ما يُسمى بوحدة قياس العطالة inertial measurement unit -أواختصارًا IMU-. وعلى الرغم من أنّ قراءة هذه الحساسات ستُؤخذ تقنيًا من البيئة المحيطة، مثل شدة الحقل المغناطيسي في الجوار، إلا أنها تُستخدم عادةً لاستشعار حركة سنس هات، إذ تظهر قيمة IMU مثل مجموعة قراءات لعدّة حساسات تسمح لك بعض لغات البرمجة بقراءة كل منها بصورةٍ مستقلة، بينما تعطيك بعضها الآخر قراءةً مشتركةً لكل الحساسات. ولكي تتعامل مع IMU، لا بدّ من فهم طبيعة حركة الأشياء. تتحرك سنس هات وباي المتصلة معها في فراغ ثلاثي الأبعاد يحدده معلم إحداثي ثلاثي المحاور كما يلي: المحور X وتُحدد عليه الحركة الجانبية من طرف إلى طرف. المحور Y وتُحدد عليه الحركة للأمام والخلف. المحور Z وتُحدد عليه الحركة للأعلى والأسفل. ويمكن لباي الدوران حول هذه المحاور، لكن وصف هذه الحركات سيتغير قليلًا؛ إذ يُدعى الدوران حول المحور X "تدحرج roll" وحول المحور Y "تقلّب pitch" وحول المحور Z "فتل Yaw". فعندما تدوّر سنس هات حول محورها القصير "Y" فأنت تُقلّبها، وعندما تدور حول المحور الطولي "X" تدحرجها، وتفتلها عندما تدور بوضعها الأفقي على الطاولة. فكّر بالأمر مثل طائرة، إذ تتقلَّب الطائرة بحلقة دائرية وهي تقلع حتى تصل إلى الارتفاع المطلوب وتتدحرج عندما تدور دوران النصر، وتفتل عندما تريد الدوران لتغيير الاتجاه. شكل 25-7 المحاور الفراغية لتحديد قيمة MUI لسنس هات استشعار الحركة باستخدام سكراتش ابدأ برنامجًا جديدًا وحمّل موسِّع سنس هات، ثم اسحب الكتلة إلى منطقة بناء البرنامج، وضع تحتها الكتلة ، ثم غيّرها بالنقر على الزر الصغير بجوار الكلمة "white" إلى . اسحب الكتلة إلى أسفل التسلسل السابق وضع داخلها الكتلة . ستحتاج إلى كتل ضم join blocks لإظهار قراءات المحاور الثلاث (تدحرج- تقلب- فتل)، إضافةً إلى كتل سنس هات الموافقة. تذكر إضافة فواصل ومسافات فارغة أثناء ترتيب كتل الضم لتسهيل قراءة النتيجة. انقر على الراية الخضراء لتشغيل البرنامج، ثم حاول تدوير سنس هات وباي بحذر كي لا تزيح الكابلات. ستظهر قيم المحاور الثلاث وتتغير باستمرار مع تغير وضع سنس هات. شكل 26-7 عرض قيم التقلب pitch والتدحرج roll والفتل yaw استشعار الحركة باستخدام بايثون ابدأ برنامجًا جديدًا في ثوني واحفظه باسم "Sense HAT Movement"، ثم اكتب الشيفرة التالية منتبهًا إلى استخدام المكتبة sense_emu بدلًا عن sense_hat عند استخدام المقلد: from sense_hat import SenseHat sense = SenseHat() sense.clear() لاستخدام معلومات عن IMU في تحديد الوجهة الحالية لسنس هات وفقًا لمحاورها الثلاث، اكتب الشيفرة التالية: orientation = sense.get_orientation() pitch = orientation["pitch"] roll = orientation["roll"] yaw = orientation["yaw"] print("pitch {0} roll {1} yaw {2}".format(pitch, roll, yaw)) انقر على أيقونة التشغيل Run وسترى قراءات اتجاه سنس هات على المحاور الثلاث. حاول تدوير سنس هات ثم انقر على أيقونة التشغيل مجددًا وستلاحظ تغيُّر القراءات بما يعكس الوجهة الجديدة. عرض قيم التقلب pitch والتدحرج roll والفتل yaw يمكن أن يسهم قياس MUI بأكثر من تحديد وجهة سنس هات فهو قادرٌ على اكتشاف الحركة. وللحصول على قراءة دقيقة للحركة، لا بدّ من قراءة MUI باستمرار من خلال حلقات، فلن تعطيك قراءة واحدة أية فائدة تُذكر في استشعار الحركة على خلاف تحديد الوجهة. احذف كل ما يأتي بعد الدالة ()sense.clear واكتب التالي: while True: acceleration = sense.get_accelerometer_raw() x = acceleration['x'] y = acceleration['y'] z = acceleration['z'] لدينا الآن ثلاثة متغيرات لتخزين قراءات مقياس التسارع على المحاور الثلاث: X للحركة يمينًا ويسارًا، Y للحركة أمامًا وخلفًا، Z للأعلى والأسفل. من الصعب أحيانًا قراءة بيانات مقياس التسارع، لذلك اكتب الشيفرة التالية لتدوير الرقم إلى أقرب عدد صحيح وبذلك يسهل فهمها: x = round(x) y = round(y) z = round(z) اطبع النتائج بعد ذلك كما يلي: print("x={0}, y={1}, z={2}".format(x, y, z)) انقر على أيقونة التشغيل وسترى قراءات مقياس التسارع مطبوعةً على شاشة المفسِّر، لكنه سيستمر في طباعة الأرقام بلا توقُّف وعليك النقر على أيقونة "Stop" لإيقاف البرنامج. شكل 28-7 قراءات مقياس التسارع مقرّبة إلى أقرب رقم صحيح. نلاحظ أن مقياس التسارع يعطي القراءة 1.0 للجاذبية (1G) على أحد المحاور (المحور Z إذا كانت باي وسنس هات أفقيتان على الطاولة) على الرغم من أن سنس هات لا تتحرك، والسبب وراء ذلك هو أن الحساس يستشعر الجاذبية الأرضية التي تشد سنس هات نحو مركز الأرض. حاول رفع سنس هات مع باي للأعلى بحذر أثناء عمل البرنامج، لكن انتبه كي لا تُزاح الكابلات. أمِل اللوحتان بحيث يتجّه منفذا الشبكة المحلية والناقل USB نحو الأرض فستتغير القراءة لتصبح 0G على Z و 1G على X، وستتحول القراءتان على X و Z إلى 0G وعلى Y إلى 1G عندما تميل اللوحتان بحيث يتجه منفذ HDMI لباي نحو الأرض. إذا حاولت أن تميلها بحيث يتجه منفذ HDMI نحو السقف ستتغير القراءة على Y لتصبح 1G-. وبمعرفة أن الجاذبية الأرضية هي تقريبًا 1G وفهم المحاور الفراغية بالطريقة التي عرّفناها سابقًا، ستتمكن من استعمال قراءات مقياس التسارع لتحديد توجّه اللوحة نحو الأسفل والأعلى، وستتمكن أيضًا من اكتشاف الحركة. حاول أن تهزّ اللوحتين وراقب الأرقام في نافذة المفسِّر، وكلّما زادت شدة الاهتزاز كلما زادت قراءة مقياس التسارع. عندما تستخدم الدالة ()sense.get_accelerometer_raw، فأنت تخبر سنس هات في هذه الحالة أن تعطِّل الحساسين الباقيين في IMU (الجيروسكوب ومقياس الحقل المغناطيسي) وتعيد قراءات مقياس التسارع فقط، ويمكن طبعًا فعل نفس الشيء عند استخدام أي حساسٍ آخر. استبدل السطر: acceleration = sense.get_accelerometer_raw() بالسطر: orientation = sense.get_gyroscope_raw() غيّر الكلمة acceleration في الأسطر الثلاثة داخل الحلقة إلى orientation، ثم انقر أيقونة التشغيل لترى قيم توجه سنس هات على المحاور الثلاث مدوّرةً إلى أقرب عدد صحيح. ستأتيك البيانات هذه المرة من الجيروسكوب فقط دون استخدام مقياسي الحقل المغناطيس والتسارع، ويفيد ذلك في تحديد وجهة سنس هات إن تحركت على ظهر روبوت مثلًا دون الحاجة لأخذ تعقيدات الحركة بالحسبان أو استخدامها في جوار مصدر قوي للإشعاع المغناطيسي. لاستخدام مقياس الحقل المغناطيسي، أوقف البرنامج ثم احذف كل أسطر برنامجك ما عدا الأربعة الأولى منه، ثم اكتب الشيفرة التالية تحت بداية الحلقة while True: north = sense.get_compass() print(north) شغِّل برنامجك وسترى اتجاه الشمال المغناطيسي وقد طُبع في نافذة المفسِّر. دوّر سنس هات بلطف وستلاحظ تغيرات القراءة نظرًا لانحراف توجهها بالنسبة للشمال المغناطيسي. لقد نجحت في صناعة بوصلة. قرِّب مغناطيسًا (يمكنك استخدام المغانط التي تُلصق على البرادات) من سنس هات وراقب تغيّر قراءة مقياس الحقل المغناطيسي. التحكم بمقبض الألعاب يتواجد في الزاوية اليمينية السفلية لسنس هات، وقد تراه صغيرًا لكنه فعّال جدًا وقادرٌ على تمييز إشارات الدخل من أربعة جهات (أمام وخلف ويمين ويسار)، كما يمتلك قناة دخل خامسة تصل إليها بالضغط على المقبض في منتصفه وكأنه زر الكبس في المنتصف. تحذير: لا ينبغي استخدام مقبض سنس هات ما لم تستخدم المباعدات التي تحدثنا عن تثبيتها سابقًا، لأن الضغط على المقبض سيثني سنس هات مما يسبب في تضررها وتضرر منصة GPIO معها. التحكم بمقبض الألعاب باستخدام سكراتش ابدأ برنامجًا جديدًا وحمّل موسِّع سنس هات، ثم اسحب الكتلة إلى منطقة بناء البرنامج وضع تحتها الكتلة واضبط الخيار "white" على "off". يرتبط مقبض سنس هات في سكراتش scratch مع مفاتيح الأسهم في لوحة المفاتيح، فعندما تضغط زر "أمام" في المقبض فهذا أمرٌ مماثل لضغط مفتاح السهم "أعلى" وكذلك الأمر عند ضغط زر المقبض اليساري فهذا مماثلٌ لضغط مفتاح السهم اليساري في لوحة المفاتيح وهكذا، بينما يطابق ضغط المقبض في منتصفه مثل زر الكبس ضغط المفتاح "Enter" في لوحة المفاتيح. تحذير: لا يتوفر مقبض الألعاب سوى على سنس هات الفيزيائية، فإذا كنت تستخدم المقلِّد فعليك بمفاتيح الأسهم على لوحة المفاتيح لمحاكاة المقبض. نظرًا للارتباط السابق، سنستعمل كتل الأحداث نفسها التي نستخدمها لقراءة مُدخلات لوحة المفاتيح. اسحب الآن الكتلة إلى منطقة بناء البرنامج، ثم غيّر الخيار فيها إلى "up arrow" بدلًا من "space". اسحب الكتلة وضعها تحت الكتلة السابقة حتى نرى نتيجة هذا البرنامج. تحرك إلى الأمام من خلال المقبض وستشاهد القط يحييك بالعبارة "!Hello". عدّل العبارة السابقة لتصبح "!Joystick Up" ثم أضف كتل أحداث Events وكتل مظهر Looks إلى برنامجك حتى يعطي الضغط على أي زر من أزرار المقبض الخمسة نتيجة على النحو التالي: اضغط على أزرار المقبض بكل الاتجاهات لكي ترى نتيجة عملك. التحكم بمقبض الألعاب باستخدام بايثون ابدأ برنامجًا جديدًا في ثوني واحفظه باسم "Sense HAT Joystick"، ثم اكتب الأسطر الثلاث التي تهيئ سينس هات وتطفئ أضواء المصفوفة: from sense_hat import SenseHat sense = SenseHat() sense.clear() استخدم تاليًا حلقةً لا نهائية while True وأخبر بايثون أن ينصت ضمنها إلى أحداث الدخل الناتجة عن الضغط على أزرار المقبض. سيزيح ثوني الشيفرة تلقائيًا بمسافة بادئة داخل الحلقة: while True: for event in sense.stick.get_events(): أضِف أخيرًا الشيفرة التي تنفذ شيئًا عند ضغط زر المقبض المحدد داخل حلقة for، وسيزيحها ثوني تلقائيًا أيضًا بمسافة بادئة: print(event.direction, event.action) انقر على أيقونة التشغيل Run، واضغط على الأزرار المختلفة لمقبض سنس هات وسترى أسماء الجهات التي تحركت نحوها قد طُبعت في نافذة المفسِّر. وستلاحظ أيضًا أن هناك حدثان مرتبطان بكبسةٍ واحدةٍ على أحد أزرار المقبض الأول عند الضغط على الزر والآخر عند تحريره. يمكن الاستفادة من هذا برمجيًا كما لو كنت تبرمج حركةً لشخصيةٍ في لعبة، بحيث تتقدم باتجاه محدد عند الضغط على زر ثم تتوقف بمجرد أن تحرره. يمكن استخدام المقبض لتفعيل دوال بدلًا من أن يكون استخدامها محدودًا ضمن حلقة "for". احذف كل الأسطر التي تلي الدالة ()sense.clear واكتب الشيفرة التالية: def red(): sense.clear(255, 0, 0) def blue(): sense.clear(0, 0, 255) def green(): sense.clear(0, 255, 0) def yellow(): sense.clear(255, 255, 0) تحوّل هذه الدوال المصفوفة الضوئية إلى لون وحيد (أحمر أو أزرق أو أخضر أو أصفر) لتسهيل طريقة عرض برنامجك. ولكي تستدعي هذه الدوال لا بُد من تحديد أي دالة تتوافق مع أي زرٍ للمقبض، لذلك اكتب الشيفرة التالية: sense.stick.direction_up = red sense.stick.direction_down = blue sense.stick.direction_left = green sense.stick.direction_right = yellow sense.stick.direction_middle = sense.clear يحتاج البرنامج الآن إلى حلقة لا نهائية تُعرف بالحلقة الأساسية التي تُبقي البرنامج مستمرًا في عمله لمراقبة الدخل القادم إلى باي عبر مقبض سنس هات بدلًا من تنفيذ الشيفرة مرةً واحدةً ثم توقف البرنامج. اكتب الشيفرة التالية: while True: pass انقر على أيقونة التشغيل وحاول التحكم بالمقبض وستشاهد تألق المصفوفة الضوئية بألوان مختلفة، ولإطفاء الأضواء اضغط على المقبض ككل لأن الضغط على منتصفه سيستدعي الدالة ()sense.clear التي تطفئ المصفوفة. تهانينا، أصبحت قادرًا على التقاط إشارات مقبض سنس هات. مشروع سكراتش: جهاز أضواء راقصة يتعلق بالحرارة طالما أنك انطلقت في مسيرتك في عالم سنس هات فقد حان الوقت لتضع كل ما تعلمته في تصميم جهاز أضواء راقصة حساس للحرارة، وهو جهاز يكون في أوج لمعانه عندما يكون باردًا ثم يبطئ تدريجيًا عندما يسخن. ابدأ مشروعًا جديدًا في سكراتش وحمّل موّسع سنس هات من فئة "كتل إضافية More Blocks". اسحب كما جرت العادة الكتلتين و . ولا تنسَ تغيير الخيار "white" إلى "off" في الكتلة الأخيرة. سنبدأ بتصميم الجهاز البسيط بحرفية، لذلك اسحب الكتلة إلى منطقة بناء البرنامج، ثم ضع بداخلها الكتلة ثم املأ جميع فراغاتها بكتلة المعامل . يمثِّل أول مربعين فارغين الإحداثيين X و Y لموقع المؤشر الضوئي في المصفوفة لذلك لا بُد من تعديل كتلتي اختيار الرقم العشوائي في كلا الفراغين لتصبح من 0 إلى 7 بدلًا من 1 إلى 10؛ وكذلك الأمر بالنسبة للفراغات الثلاث التالية التي تمثِّل كمية اللون الأحمر ثم الأخضر ثم الأزرق، فلا بُد من تغيير مجال المتغير العشوائي ضمنها ليكون من 0 إلى 255 بدلًا من 1 إلى 10. انقر على الراية الخضراء وسترى المصفوفة الضوئية في سنس هات تضيء بألوان عشوائية. شكل 29-7 ضاءة المؤشرات الضوئية بألوان عشوائية تهانينا، لقد صنعت جهاز بريق الكتروني. لا يتفاعل هذا الجهاز مع محيطه حتى اللحظة، لذلك اسحب الكتلة وضعها تحت الكتلة ضمن الكتلة . اسحب كتلة عامل القسمة وضعها مكان الرقم 1 في كتلة الانتظار، ثم اسحب الكتلة وضعها في فراغ كتلة عامل القسمة الأول وضع 10 في الفراغ الثاني. انقر الراية الخضراء مجددًا وستلاحظ أن حدة اللمعان قد انخفضت بوضوح، إلا إذا كنت تعيش في مكان بارد جدًا، ويعود السبب وراء ذلك إلى تصميمك تأخير زمني متعلِّق بالحرارة، إذ ينتظر برنامجك عددًا من الثواني تساوي قيمة درجة الحرارة مقسومةً على 10 قبل تنفيذ ما هو موجود داخل الحلقة؛ فلو كانت درجة الحرارة 20 مئوية سينتظر البرنامج ثانيتين، وينتظر ثانية إذا كانت درجة الحرارة 10 مئوية وأقل من ثانية إذا كانت تحت 10 درجات مئوية؛ أما إن كانت القراءة سالبة (الحرارة تحت الصفر المئوي)، فلن يكون هناك تأخير زمني إطلاقًا وستُنفذ الحلقة دون تأخير. تهانينا، لقد أنجزت بنفسك برنامجًا يُكامل بين مختلف ميزات سنس هات. للاطلاع على مشاريع أخرى تستخدم سنس هات، عليك بالملحق "D" (اطلع أكثر) مشروع بايثون: مسبار ترايكوردر طالما أنك انطلقت في مسيرتك في عالم سنس هات فقد حان الوقت لتضع كل ما تعلمته في تصميم جهاز ترايكوردر Tricorder، وهو جهاز يعرفه جيدًا محبي بعض أفلام الخيال العلمي (ستار ترك تحديدًا) بأنه مسبارٌ قادرٌ على تحليل بيانات الحساسات التي يضمها. ابدأ مشروعًا جديدًا في ثوني واحفظه باسم "Tricorder" ثم اكتب الشيفرة التالية: from sense_hat import SenseHat sense = SenseHat() sense.clear() علينا في الخطوة الثانية تعريف دوال لكل حساس من حساسات سنس هات، وسنبدأ بحساسات IMU: def orientation(): orientation = sense.get_orientation() pitch = orientation["pitch"] roll = orientation["roll"] yaw = orientation["yaw"] وطالما أننا سنحرك نتائج قراءة الحساسات على شاشة المصفوفة الضوئية، فمن الأفضل تدوير القراءات إلى رقمٍ عشري واحد بعد الفاصلة حتى لا ننتظر مرور عشرات الأرقام قبل أن ننتهي من عرض أحد النتائج: pitch = round(pitch, 1) roll = round(roll, 1) yaw = round(yaw, 1) سنحتاج أخيرًا إلى تحريك النتائج على المصفوفة لأن الترايكوردر مسبارٌ محمولٌ باليد، ولا حاجة لوصله إلى شاشة. sense.show_message("Pitch {0}, Roll {1}, Yaw {2}". format(pitch, roll, yaw)) لقد انتهينا الآن من إنشاء دالةٍ تقرأ وتُظهر وجهة سنس هات بناءً على مقياس IMU، وعلينا الآن إنشاء دوال مماثلة لبقية الحساسات. لنبدأ بحساس الحرارة: def temperature(): temp = sense.get_temperature() temp = round(temp, 1) sense.show_message("Temperature: %s degrees Celsius" % temp) انتبه إلى السطر الذي يعرض النتيجة على المصفوفة الضوئية ولاحظ وجود الرمز s%، ويُدعى هذا الرمز "محدد مكان placeholder" ويُستبدل بمحتوى المتغير temp، ويساعدك ذلك على تنسيق الخرج بطريقة جميلة تظهر فيها القراءة بين عنوان "Temperature" ووحدة القياس "degrees Celsius". سننشئ الآن دالةً لحساس الرطوبة: def humidity(): humidity = sense.get_humidity() humidity = round(humidity, 1) sense.show_message("Humidity: %s percent" % humidity) ثم لحساس الضغط البارومتري: def pressure(): pressure = sense.get_pressure() pressure = round(pressure, 1) sense.show_message("Pressure: %s millibars" % pressure) وأخيرًا للبوصلة التي تعتمد على قراءة حساس الحقل المغناطيسي: def compass(): for i in range(0, 10): north = sense.get_compass() north = round(north, 1) sense.show_message("North: %s degrees" % north) استخدمنا في الدالة السابقة حلقةً قصيرةً ومحدودةً لتأخذ عدة قراءات متلاحقة من مقياس الحقل المغناطيسي للتأكُّد من كفاية البيانات لإظهار قراءة دقيقة. عدِّل مجال الحلقة إلى 20 أو 30 وحتى 100 إن شعرت بأن القراءة غير مستقرة وذلك لتحسين الدقة. يتكون برنامجك الآن من خمس دوال تقرأ كلٌ منها بيانات أحد حساسات سنس هات ثم تحرِّك هذه البيانات على المصفوفة الضوئية. بقي علينا إيجاد طريقة لنختار الحساس الذي سنعرض بياناته ومن المؤكد أن مقبض سنس هات هو الحل الأمثل. اكتب الشيفرة التالية إذًا: sense.stick.direction_up = orientation sense.stick.direction_right = temperature sense.stick.direction_down = compass sense.stick.direction_left = humidity sense.stick.direction_middle = pressure تربط الشيفرة السابقة كل حساس بأحد أزرار الاتجاه لمقبض سنس هات؛ إذ يكون الزر الأعلى لقراءة الوجهة والأسفل لقراءة مقياس الحقل المغناطيسي (البوصلة) واليمين لقراءة حساس الحرارة واليسار لقراءة الرطوبة والأوسط لقراءة الضغط. لا بُدّ أخيرًا من وضع برنامجك بأكمله ضمن حلقةٍ لا نهائية رئيسية تصغي إلى أحداث الضغط على أزرار المقبض دون أن تنهي البرنامج مباشرةً. اكتب ما يلي: while True: pass انقر على أيقونة التشغيل Run وجرِّب الضغط على أزرار المقبض لقراءة أحد الحساسات. اضغط زرًا آخر حالما ينتهي عرض القراءة السابقة وراقب النتيجة. تهانينا، لقد صممت مسبار ترايكوردر محمول باليد مكتمل الوظائف. شكل 30-7 ستتحرك كل نتيجة عبر المصفوفة الضوئية للاطلاع على مشاريع أخرى تستخدم سنس هات، عليك بالملحق "D" (اطلع أكثر). ترجمة -وبتصرف- للفصل السابع "Physical computing with Sense HAT" من كتاب The official Raspberry Pi beginner's guide. اقرأ أيضًا المقال السابق: ربط راسبيري باي بعناصر إلكترونية وبرمجتها باستخدام سكراتش وبايثون ما هو حاسوب راسبيري باي Raspberry Pi؟ التعامل مع بيئة سطر الأوامر في راسبيري باي إعداد Raspberry Pi للعمل تجميع راسبيري باي والتحضير لاستعماله
  20. هل تجذبك فكرة تصميم تجربة المستخدم؟ هل كانت معرفتك بتصاميم تجربة المستخدم عبر قراءة عابرة؟ أم أنك بذلت وقتًا في الاطلاع عليها؟ إن تصميم تجربة المستخدم هي صناعة ديناميكية متداخلة التخصصات تتطور باستمرار. لن تجد أنسب من هذه الفترة لتحترف تصميم تجربة المستخدم، فهو عمل مطلوب عالميًا، مع عدد لا يُحصى من الفرص التي لن تجد عوائق كبيرةً في الحصول عليها، كما يمكنك الوصول إلى موارد هذه الصناعة من خلال الإنترنت، وستجد الكثير من الجهات التي تمنحك شهادات في تصميم تجربة المستخدم، والأهم من ذلك ما يتقاضاه مصمم تجربة المستخدم من مرتبات تفوق المتوسط بكثير. هل استرعى ما قلناه اهتمامك؟ اغتنم فرصة دمج طاقاتك الإبداعية مع إمكاناتك التحليلية لتطوير عالمنا بأفكار تصميمية جيدة. وإليك مجموعة أسباب تدفعك لتصبح مصمم تجربة مستخدم. لتترك أثرا ستعمل بصفتك مصممًا لتجربة مستخدم، على حل مشاكل حقيقية تواجه الناس في واقعهم، إضافةَ إلى بعض المنغصات الصغيرة التي تظهر يومًا بعد يوم (والتي تسبب الكثير بمجموعها). وكما يوحي الاسم "تصميم تجربة المستخدم"، فأساس هذا المجال هو المستخدم واحتياجاته، سواء أكان ما يريده تطبيقًا، أو موقع ويب، أو خدمات مالية، أو مخطط متجر. قد يعطينا سماع عبارة "تصميم تجربة مستخدم" انطباعًا عن عملاء أو تصميم وبيع منتجات، لكن ما يحدث في الواقع هو أن هذا المستخدم قد يكون مريضًا في مستشفى أو طبيبًا، وقد تكون جدتك أو حتى أنت نفسك في الكثير من المسارات. لقد امتلأ العالم بالتصاميم الجيدة والسيئة، فتخيل إذًا كيف ستتغير حياتنا إلى الأفضل إن سادت التصاميم الجيدة؟ هنا ستظهر قيمة ميزتين مهمتين لتصميم تجربة المستخدم: الشمولية inclusivity وسهولة الوصول accessibility. لقد أبدى "دون نورمان" عرّاب تصميم تجربة المستخدم ومؤلف الكتاب الذي اتسم بتصميمه القريب من المستخدم "تصميم الأشياء التي نحتاجها في حياتنا اليومية The Design of Everyday Things"، انزعاجه من عدم مراعاة المتقدمين في السن في تصميم تجارب المستخدم بعد أن أمضى 60 عامًا في المهنة. ففي مقالة لمجلة فاست كومباني Fast Company، ناقش "نورمان" -عضو مجلس إدارة IxDF ونائب رئيس شركة آبل السابق- التوجه العالمي نحو تصاميم لا تراعي المسنين إطلاقًا، خاصةً وأن البشر يُعمر في هذا العصر لفترة أطول، ويزداد متوسط أعمارهم عالميًا. صحيح أن حواس البشر تتراجع مع تقدمهم في السن وتتناقص قدراتهم الحركية، إلا أن الكثيرين منهم لا يزالون أصحاء ونشيطين. ستغدو الحياة أصعب كلما تقدمنا في العمر ابتداءً من صعوبة قراءة الخطوط الصغيرة تحت عنوان مهم أو داخل دليل استخدام، إلى غاية الحاجة إلى سكاكين وكماشات لفتح صندوقٍ يضم أدوات منزلية. وحتى عندما تُصمَّم المنتجات خصيصًا لكبار السن، إلا أنها تبدو قبيحةً وبلا معنى. أقامت الكلية الملكية للفنون معرضًا في متحف لندن للتصميم عام 2017 بعنوان "المسنون الجدد New Old"، وقد وُصف المعرض لاحقًا بمقالة كتبها أيضًا "دون نورمان" في نفس المجلة السابقة عنوانها "لماذا عليك التصميم لنفسك وكأنك في 73 من العمر Why you should be designing for your 73-year-old self". لقد أظهر المعرض أهمية التصميم الجيد وقدرته على تحسين حياتنا في آخر المطاف. ومن بين ما عرض "سكوتر لحياة بأكملها Scooter for Life" بثلاث عجلات لزيادة الاستقرار من تصميم PriestmanGoode، وقد زوّد بسلة عصرية في مقدمته لوضع البقالة، خلافًا للسكوتر التقليدي الذي نراه حولنا. "تشاهد إلى اليسار Scooter for Life من تصميم PriestmanGoode والذي يساعد كبار السن على التنقل وشراء حاجاتهم بطريقة عصرية وفعّالة أكثر. كما تشاهد إلى اليمين السكوتر التقليدي الذي لا يكاد يتسع له الممشى الجانبي للطريق، فما بالك بممرات التسوق" ينطبق الكلام السابق على المنتجات الرقمية أيضًا. فعندما تصمم تطبيقًا أو موقع ويب ليستخدمه كبار السن، لا بدّ حينها من أخذ بعض الأمور الخاصة بالحسبان، مثل الخطوط الكبيرة وأدوات التنقل الواضحة والبسيطة؛ والأهم أن يتمكن مستخدم المنتج من فهم الغاية منه بسهولة، فلن تريد لجدتك مثلًا أن تقضي ساعات محتارةً في أمر هذا التطبيق. يُوجِّه موقع الويب Ageist محتواه -الذي يهتم بنمط الحياة- إلى الأشخاص الذين تجاوزوا سن الخمسين، ويُحدَّث هذا الموقع باستمرار لتحسين تجربة المستخدم. يستخدم الموقع ألوانًا لامعةً ويمتلك أدوات تنقل بسيطة وعناصر قائمة واضحة وسهلة العرض في أعلى الصفحة، كما يعرض أيقونة بحث كبيرة. وبالإضافة إلى ذلك، لن يتطلب الوصول إلى نهاية الصفحة أكثر من دحرجتين لعجلة الفأرة. ستجني من تصميم تجربة المستخدم الشيء الكثير، وستكتشف الفرص التي لا تنتهي لتحسين وابتكار منتجات قد تحسّن حياة الملايين. لأنه عمل إبداعي ومنطقي من أكثر الأمور جاذبيةً وتفردًا في تصميم تجربة المستخدم هو التكامل بين الإبداع والمنطق. لنقل أنك شخص يصنع ما يحتاجه بيديه (إعادة استخدام وصناعات يدوية) ولديك أيضًا مدوّنة عن كيفية صناعة الأشياء بنفسك (فأنت من محبي الكتابة أيضًا). لا بد أنك شخص مبدع بالفطرة، لكنك لا تمتلك الخبرات التقنية، فسماع عبارة " كتابة شيفرة" قد تخيفك. لكن لا بأس، إذ ليس عليك أن تكون تقنيًا لتنخرط في مجال تصميم تجربة المستخدم. والأمر ذاته إن كان العكس، أي إن كانت نقاط قوتك تكمن في الرياضيات أو في كتابة الشيفرات، فسيمنحك مجال تصميم تجربة المستخدم الفرصة لاستخدام هذه القدرات وأنت تستغل ما لديك من إبداع فطري (نعم، فأنت مبدع أيضًا). ستستخدم الجانب المنطقي من تفكيرك عندما تدخل عالم تصميم تجربة المستخدم لكي تُبدع حلولًا عملية لمشاكل المستخدمين. ولن تكفي العملانية في الحلول وحسب، بل عليك أن تكون مبدعًا في الجوانب الوظيفية ونواحي الاستخدام وليس من النواحي الجمالية فقط. فكّر مثلًا بهاتفك الذكي، فهو يخدم عدة غايات عملية، أهمها الاتصالات؛ لكن ذلك ليس كافيًا للوصول إلى منتج ناجح، فما هو شعور المستخدم تجاهه؟ هل يشعر بالسعادة عند النظر إليه؟ وما الذي يجعل شخصًا ما يفضله على غيره من الهواتف الذكية؟ لنأخذ مثالًا هاتف آيفون من آبل، فهو يوازن باحتراف بين الناحيتين الجمالية والوظيفية. فقد تصادف هواتف ذكيةً بلا طرائق إعداد مفهومة وتقضي وقتك وأنت تقلب في دليل الاستخدام لفهم وظائفها، بينما تجد أن آيفون واضح الاستخدام من اللحظة التي تخرجه فيها من علبته، ويقودك بكل متعة خلال عملية الإعداد. لا تساوم إذًا بين الجمالية وسهولة الاستخدام والعكس بالعكس، فالتوازن هو الأساس. لتصبح محترفا مطلوبا في صناعة نامية متعددة الاختصاصات لا يتطلب دخولها الكثير لقد زاد عدد الموظفين المهتمين بتصميم تجربة المستخدم بما يقارب 289% عام 2020 في المملكة المتحدة. وقد وجد تقرير بعنوان "الانتباه إلى الهوة Mind the Gap " في المجلة الرقمية "Hired.com"، أن تصميم تجربة السمتخدم كانت من المهارات التي تعاني فجوةً بين العرض والطلب. وقد قدّر موقع "لينكد إن" أن تصميم تجربة المستخدم ستكون من المهارات الخمسة الأكثر طلبًا في عام 2020، كما قدّر تقرير لقناة "سي إن إن" الأمريكية عن الوظائف الأفضل مدخولًا عام 2015، أن تصميم تجربة المستخدم سينمو بمقدار 18% ما بين عامي 2015 و 2025. ستجد آلاف الوظائف المدرجة في "إنديد" و"لينكد إن" في الولايات المتحدة والمملكة المتحدة وكندا خصوصًا، مع خيارات لا تُحصى للعمل عن بعد. وستزداد بلا شك فرص العمل في تصميم تجربة المستخدم، أكثر كما سيزداد عامل الأمان فيها مع اعتناق معظم المؤسسات والمنظمات لأفكارها. رأينا أن تصميم تجربة المستخدم يُعَد مهارةً تحليليةً وإبداعية، لكنها تمتد لأبعد من ذلك حتى. يضم مجال تصميم تجربة المستخدم عددًا هائلًا من الاختصاصات المختلفة مثل علم النفس والتكنولوجيا والتصميم البصري وعلم الاجتماع، وهذا في الواقع مفهوم الاختصاصات المتنوعة multidisciplinary. تجعل هذه الميزة من العمل أكثر إثارةً ومردودًا وتحديًا ولن تقف في طريق من يريد الخوض فيه عوائق كبيرة. فلو كنت عالم نفس خلال مرحلة التدريب أو امتلكت خبرة سنوات، فستكون قادرًا على تطبيق خبراتك في مجال تصميم تجارب المستخدم، إذ لديك بالفعل الإمكانيات والمعرفة لتنطلق بقوة عندما يتعلق الأمر بفهم سلوك المستخدم، وحتى لو ابتعد مجال عملك الحالي عن تصميم تجربة المستخدم أو عن الاختصاصات التي أشرنا إليها سابقًا، فسيساعدك ما تملكه من مهارات وقدرات على البدء في مسيرتك المهنية كمصمم تجارب مستخدم. الانتقال إلى مهنة تصميم تجربة المستخدم ليس أمرا صعبا لم تتأخر بعد لتغيّر مهنتك، إذ تظهر مهن جديدة أكثر إثارةً باستمرار مع تقدم المجتمع؛ فلم يأت "دون نورمان" بمصطلح "تجربة المستخدم UX" في الواقع حتى عام 1995، ولم يتحول إلى عمل حقيقي حتى العقد الأول من هذا القرن. هنالك أسباب عديدة لتمتهن تصميم تجربة المستخدم، وستجد الكثير من الطرق التي تتبعها في سبيل ذلك. لا تجعل خلفيتك العلمية أو المهنية عائقًا في رحلتك، بل استخدمها لتنهض وتتعلم ما يلزمك لتخطو أولى خطواتك في هذا المجال، فالكثير من المهارات التي يحتاجها مصمم تجربة المستخدم الناجح قابلة للنقل من مهنة إلى أخرى، وستكون خبراتك السابقة مصدر دعم لك دائمًا. لنلق نظرة على أمثلة محددة عن كيفية الانتقال إلى مهنة تصميم تجربة المستخدم: إن كنت مصمم جرافيك فأنت محظوظ، لأن مهاراتك في التصميم الشعوري والتفكير الإبداعي وإنشاء النماذج الأولية ستخدمك جيدًا. عليك فقط التركيز على بناء أدوات فكرية تتمحور حول حاجة المستخدم، وأن تتعلم العمل على مهام متكررة ضمن فريق متعدد الاختصاصات. إن كنت مختصًا في التسويق وأردت أن تصبح مصمم تجربة مستخدم، فستساعدك مهاراتك في البحث وقدرتك على فهم علم نفس العملاء. وستجني فوائد خبراتك السابقة التي تجعل منتجًا ما مقبولًا ومرغوبًا من قِبل العميل، لكن عليك أن تغير أدواتك الفكرية التي تُركز على نسبة تحول الزوار إلى عملاء إلى أدوات تركز على تجربة المستخدم، كما عليك الاطلاع أكثر على السلوك الفردي للأشخاص. إن كنت مصمم ويب، فلا بد أنك قد اعتدت على العمل مع فريق متعدد الاختصاصات، وستتلاءم مباشرةً مع أجواء العمل. إضافةً إلى ذلك، لديك مهارات كثيرة في حل المشاكل المختلفة، وهي مهارات سهلة النقل إلى مهنة تصميم تجربة المستخدم. وكل ما عليك فعله هو تحويل تركيزك من التكنولوجيا إلى تجربة المستخدم، ولا بد من الانتباه إلى أحاسيس المستخدم عندما يتعامل مع منتج ما، إضافةً إلى التأكد من عمله من الناحية التقنية والوظيفية. إن كنت مدير أعمال، فستستفيد بالتأكيد من طريقة تفكيرك الواسعة في اتخاذ قرارات أفضل لصالح المستخدم. وما عليك فعله هو بناء أدوات فكرية تركّز على المستخدم وأن تألف عمليات ومراحل التصميم. إن كنت مطوّر برمجيات/ فهذا يعني أنك خبير في إيجاد حلول إبداعية للمشاكل واختبار هذه الحلول، كما أنك تتمتع بعقلية قابلة للتعلم باستمرار. ستساعدك هذه المهارات لتصبح مصممًا بارعًا لتجارب المستخدم. وينبغي عليك نقل تركيزك من التكنولوجيا نفسها إلى أحاسيس المستخدم عندما يتعامل معها. فإن استطعت بناء أدوات فكرية تركّز على المستخدم، فستكون ناجحًا إن امتهنت تصميم تجربة المستخدم. إن أردت تغيير مهنتك لتصبح مصمم تجربة مستخدم، وكان ما تمتهنه مختلفًا عن المهن التي ذكرناها في أمثلتنا السابقة، فلا تقلق. فكّر بالنقاط المشتركة بين مهنتك وتصميم تجربة المستخدم واستخدمها للانطلاق. وحالما تألّف أفكار تصميم تجربة المستخدم، ستمتلك وجهة نظرك الخاصة والفريدة وستبدأ في بناء مهنتك الجديدة بنجاح. ستجد الكثير من الخيارات لاكتساب المعرفة التي تحتاجها وتناسب مجالك الذي تعمل به حاليًا، وتأكد أنك تتخذ خطواتك الأولى نحو مهنة تصميم تجربة المستخدم بسلاسة وذكاء. ليس عليك أن تحترف العمل على أية أدوات صدق أو لا تصدق أن أدوات تجربة المستخدم أقل أهمية مما تعتقد، فعلى الرغم من أنها مرغوبة للمحترفين في هذا المجال ويتابعون إصداراتها الجديدة كل عام، إلا أنه من الصعب متابعتها باستمرار لتبقى على اطلاع بكل جديد. فأدوات تجربة المستخدم مثل "سكيتش Sketch" و"إن فيجين InVision" و"أدوبي إكس دي Adobe XD" مثلًا، تتطور باستمرار (بتحديثات شهرية أو أقل)/ وبالتالي سيصعب متابعتها، وسيفقدك ذلك التركيز على جوهر عملك، لكن ما تفعله وما تعرفه والخبرات التي تمتلكها وكيف تطبقّها، هي النقاط الأكثر أهميةً، فالأدوات تسطع وتخبو، لكن مبادئ تجربة المستخدم والعمليات المرتبطة بها ستبقى، ولن تضمن بقاء الأدوات التي تستخدمها حاليًا أو التي ستستخدمها مستقبلًا نفسها في مشروعك القادم أو في الشركة التي ستنتقل إليها. أخيرًا لا بد أن نشير إلى أن العديد من تقنيات تجربة المستخدم الأساسية لا تتطلب استخدام أية أدوات مثل التقنيات التي تضمن اختبارات سهولة الاستخدام والمقابلات مع العملاء. ومن أكثر المفاهيم المضللة الشائعة في مضمار تصميم تجربة المستخدم هي ضرورة معرفتك بكتابة الشيفرة. فعلى الرغم من فائدتها الواضحة للمصممين لفهم عمل التكنولوجيا التي تدعم تصميماتهم وبالتالي استخدامها باحتراف في منتجاتهم، إلا أنها ليست ضرورية. مهنة تصميم تجربة المستخدم تتيح فرصا لتطور مهنتك ومهاراتك وتخصصك تتبنى تصاميم تجربة المستخدم المهارات الفكرية والفيزيائية على حد سواء. إليك بعض المهارات التي قد تتطور عند التحول إلى مهنة تصميم تجربة المستخدم، وذلك من خلال الحصول على شهادات في تصميم تجربة المستخدم والتعلم عبر إنجاز المشاريع (هذه القائمة ليست حصرية، فهناك الكثير من المهارات المتعلقة بتصميم تجربة المستخدم والتي يمكن تعلمها): معرفة الآخرين. التفكير الناقد. البحث. التواصل البصري. الكتابة. التشفير وتطوير المنتجات الرقمية. وتمامًا كما تمكّنت من استخدام أدواتك المهارية في تصميم تجربة المستخدم، ستتمكن أيضًا من نقل مهاراتك التي ستكتسبها من تصميم تجربة المستخدم إضافةً إلى مهاراتك السابقة إلى تخصص جديد أو مجال جديد. قد يتضمن تصميم تجربة المستخدم أدورًا أو اختصاصات فرعية بما في ذلك: مصمم تجربة مستخدم. مصمم منتجات. معماري تقانة معلومات. مصمم بصري. مصمم تجربة عملاء. باحث في مجال تجربة المستخدم. محلل لاستراتيجيات المحتوى. مصمم خدمات. إن تصميم تجربة المستخدم هي مجال ابتكاري يقدّم إمكانات لا متناهية للتعلم والنمو والتطور. الحصول على شهادات في تصميم تجربة المستخدم ممكن وسهل المنال إليك المزيد من الأخبار الجيدة، ليس عليك دخول الجامعة أو أن تحصل على درجة علمية لتدخل عالم تصميم تجربة المستخدم. يمكنك أن تبدأ بالتعلم الذاتي بمساعدة بعض الموارد المتوفرة على شبكة الإنترنت. ابدأ بالبحث عن مصادر مفتوحة المصدر ومفتوحة الوصول تتحدث عن تصميم تجربة المستخدم. تساعدك الشهادات كثيرًا في مسيرتك لتحترف تصميم تجربة المستخدم، فمعرض أعمالك العصري وخبراتك أمران أساسيان لتحصين عملك الطموح كمصمم تجارب مستخدم. وتقدِم الدورات التعليمية تدريبات على إنجاز معرض أعمالك وتكسِبك خبرات من خلال تنفيذ مشاريع تطبيقية وبالتالي ستكون قادرًا على بناء معرض أعمالك أثناء تعلمك. قد يكون اختيارك لشهادة تصميم تجربة مستخدم أمرًا صعبًا لوجود خيارات كثيرة واختلاف تقييم هذه الشهادات وتضارب المعلومات حولها. ويُعَد الحل المثالي لهذا الأمر هو البحث الذاتي والتساؤل المستمر للتأكد من أن ما تختاره سيحقق أهدافك ومتطلباتك. هل أنت مستعد لتبدأ رحلتك في تصميم تجربة المستخدم؟ تحقق من الدورات التعليمية المعترف بها في هذه الصناعة، وكذلك الدروس الاحترافية ومعسكرات التدريب التي يشرف عليها مختصون. يمكنك الاختيار ما بين العديد من المواد التعليمية والمبنية بطرق مختلفة لتلائم أسلوبك الخاص في التعلم، وستتعمق في تفاصيل مفاهيم تجربة المستخدم عبر الشهادات المعترف بها في هذه الصناعة. وإن كان الوقت هو ما يقيّدك، فالدروس الاحترافية Master Classes التي لا تستغرق أكثر من ساعة هي وسيلتك لتخوض غمار تجربة المستخدم دون أن تلتزم بفترة زمنية محددة. بإمكانك أن تعمل عن بعد لقد أجبرت ظروف الجائحات التي ظهرت في السنوات الأخيرة، وأبرزها جائحة كوفيد 19، الكثيرين على العمل عن بعد. وقد شجعت التداعيات الاقتصادية للوباء والحاجة الملحة لاستمرار العمل، الكثير من الهيئات على تقليل نفقاتها العامة وتوفير الوقت والموارد بتبني العمل الافتراضي تمامًا. وقد خطى بعضها خطوات متقدمة جدًا بالتخلص من مكاتبها الحقيقية بالكامل. لقد جعلت الكثير من مواقع الويب مثل Zoom وSlack وMicrosoft Teams العمل عن بعد مباشرًا وأكثر تطورًا عما كان عليه، ولا حاجة فيما يخص مصممي تجارب المستخدم التواجد فيزيائيًا في مكان محدد، فكل ما يحتاجونه هو حاسوب واتصال بالإنترنت وورقة وقلم للبدء بالتصميم، ويمكنهم التواصل مع الزملاء أو العملاء أو ينفّذوا أية مهام مطلوبة من خلال تلك المنصات. لا ضمانة طبعًا أن تنتقل لشركة تصميم تجربة المستخدم التي قد تعمل لحسابها إلى العمل عن بعد، لكن فرص حدوث ذلك في الواقع تزداد أكثر في كل سنة. وإن كنت تعمل مستقلًا، فسيعود إليك خيار انتقاء الطريقة المناسبة لإنجاز أعمالك. ستحصل على مرتب كاف إن أحد الأسباب التي تجعلك مقتنعًا بعملك هو أن يكون عملًا ذو معنى (إن لم يكن السبب الرئيسي)، كما أن ما تتقاضاه ماديًا أمر مهم أيضًا، فإن لم تشعر بأن عملك الجاد قد آتى ثماره، ستبدأ البحث عن فرص أخرى حتى لو كنت مستمتعًا بما تفعله. يزداد الطلب على مصممي تجربة المستخدم بشدة، وهنالك نقص في أعدادهم، وبالتالي سيزداد متوسط مرتبات المصممين. تختلف المرتبات غالبًا تبعًا للدول والشركات ومستوى الخبرة وعوامل أخرى، إذ يبلغ المتوسط السنوي في الولايات المتحدة قرابة 105,122 دولار أمريكي و 48,755 جنيه استرليني في المملكة المتحدة و 77,090 دولار كندي في كندا و 1,389,256 روبية في الهند. سيزداد الطلب على مصممي تجربة المستخدم في اﻷعوام القادمة عالميًا، وبالتالي ستزداد مرتباتهم. تدفع شركات تصميم تجارب المستخدم أكثر للخبراء، لذلك توّقع أن يزداد ما تتقاضاه مع نمو خبراتك. خلاصة القول تقدم لك مهنة مصمم تجارب المستخدم فرصًا مهمةً ومستمرةً في النمو وجميعها في متناول يديك. ومع النقص في أعداد المصممين عالميًا سترتفع المرتبات وتنخفض متطلبات دخول المهنة. ومع حرية العمل في أي مكان تفضّله، سيكون المستقبل مثاليًا لتجرب هذا الطريق. لا تقلق إن لم تمتلك خلفيةً في التصميم أو بأنظمة المعلومات، إذ ستجد الكثير من الدورات ومعسكرات التدريب والمناهج المعترف بها في هذه الصناعة بانتظارك لتبدأ رحلتك في عالم تصميم تجربة المستخدم. ومع المشكال العصرية التي ظهرت وستظهر دائمًا فهي التجارة الرابحة في هذا العصر، ويمكنك التنقل ضمن قسم التصميم من أكاديمية حسوب ترجمة -وبتصرف- للمقال 10 Reasons To Become A UX Designer in 2022 لصاحبته Molly Fitz-Patrick. اقرأ أيضًا مهام مصممي تجربة المستخدم مخرجات تصميمية يجب على كل مصمم تجربة مستخدم أن يتقنها دليلك الشامل لفهم المسارات المهنية لمجال تجربة المستخدم
  21. يستخدِم المتصفح خيطًا واحدًا افتراضيًا لتنفيذ شيفرة جافاسكربت في صفحتك، إضافةً إلى تخطيط الصفحة وإعادة ضبط العناصر وتجميع الموارد المستهلكة، ويعني هذا أنّ التنفيذ الطويل لدوال جافاسكربت قد يعيق خيط التنفيذ، والذي يقود بدوره إلى صفحة ضعيفة الاستجابة، وبالتالي تجربة مستخدِم سيئة، كما تستطيع استخدام أداتَي تحليل الأداء Waterfall وFrame rate الموضحتين في مقال المكونات الرئيسية للأداة Performance لتحليل أداء صفحات الويب لمراقبة تنفيذ جافاسكربت والمشاكل التي تسببها في الأداء والإشارة إلى دوال محددة تستدعي الانتباه. سنستخدِم في هذا المقال مثالًا لموقع يسبب فيه التنفيذ الطويل لجافاسكربت عدم الاستجابة، وسنقدِّم بعد ذلك مقاربتين مختلفتين لحل هذه المشكلة، بحيث تقتضي الأولى ضرورة فصل الدوال التي تستغرق وقتًا طويلًا في التنفيذ إلى أجزاء واستخدام الدالة ()requestAnimationFrame لجدولة تنفيذ هذه القطع؛ أما الثانية، فهي تنفيذ الدالة كلها في خيط مستقل مستخدِمين عمّال ويب، ولتجريب المثال التطبيقي يمكنك إيجاده في المستودع الخاص به على جيت هاب، إذ سيبدو هذا الموقع بالصورة التالية: يتضمن الموقع ثلاث أدوات تحكم: مجموعة أزرار اختيار للتحكم بطريقة تنفيذ شيفرة جافاسكربت: على أساس كتلة واحدة ضمن الخيط الرئيسي. على أساس سلسلة من عمليات أصغر ضمن الخيط الرئيسي باستخدام ()requestAnimationFrame. ضمن خيط مستقل باستخدام عمّال ويب. زر لتنفيذ شيفرة جافاسكربت عنوانه "!Do pointless computations". زر لتشغيل وإيقاف بعض رسوم CSS المتحركة لكي ينفِّذ المتصفح بعض الأعمال خلف الستار. ابقي الخيار على التنفيذ على أساس كتلة واحدة ضمن الخيط الرئيسي Use blocking call in main thread، واستعد لتسجيل ملف أداء عبر الأداة Performance. انقر على زر Start animations. ابدأ بتسجيل ملف الأداء. انقر على زر Do pointless computations!‎ مرتين أو ثلاث مرات. أوقف تسجيل الملف. سيختلف ما تراه ضمن نافذة الأداة Performance تبعًا لحاسوبك، لكنه يبدو مشابهًا للقطة الشاشة التالية: يعرض القسم الأعلى من اللقطة نظرة عامة للأداة Waterfall يخبرنا عن نوع العمليات التي يجريها المتصفح خلال فترة التسجيل، حيث يدل اللون الزهري على أنّ أغلب ما ينفذه المتصفح هي حسابات خاصة بتنسيق CSS وقد تجد بعض عمليات تخطيط الصفحة وإعادة تدفقها وجمع البيانات المهملة، إذ ينتج ذلك عن رسوميات CSS المتحركة التي تُنفَّذ خلال فترة تسجيل ملف الأداء، وسترى أيضًا كتلًا برتقالية اللون تمثِّل شيفرة جافاسكربت التي تُنفَّذ في كل مرة ننقر فيها الزر، في حين نشاهد في القسم السفلي معدل الإطارات المرتبط بالمسار الزمني للتسجيل، إذ يمكننا رؤية أنّ معدل الإطارات سليم طيلة فترة التسجيل، لكنه ينهار تمامًا عند النقر على الزر، كما سنختار إحدى هذه الفترات ونلقي نظرةً عن قرب على ما يجري من خلال نافذة التفاصيل التي تعرض بيانات الأداة Waterfall: يُنفِّذ المتصفح دالة جافاسكربت أو سلسلة من الدوال الأصغر عندما نضغط الزر، مما يعيق التنفيذ ضمن الخيط الرئيسي مدة 71.73 ميلي ثانية، إذ يُعَدّ هذا الزمن أعلى بأربع مرات من الزمن المفترض لتنفيذ الإطار أي 16.7 ميلي ثانية، فما الدالة التي سببت المشكلة إذًا؟ لننتقل إلى الأداة Flame Chart لنرى تفاصيلًا أكثر ضمن نافذة التفاصيل: تعرض لنا الأداة مكدس استدعاء جافاسكربت في لحظة التنفيذ هذه، إذ تتوضع الدالة ()calculatePrimes في قمة المكدس، كما يمكننا من خلال التفاصيل المعروضة معرفة اسم الملف الذي يضمها والسطر الذي عُرّفت فيه، وإليك شيفرة الدالة، بالإضافة إلى الدالة التي تستدعيها مباشرةً: const iterations = 50; const multiplier = 1000000000; function calculatePrimes(iterations, multiplier) { var primes = []; for (var i = 0; i < iterations; i++) { var candidate = i * (multiplier * Math.random()); var isPrime = true; for (var c = 2; c <= Math.sqrt(candidate); ++c) { if (candidate % c === 0) { // not prime isPrime = false; break; } } if (isPrime) { primes.push(candidate); } } return primes; } function doPointlessComputationsWithBlocking() { var primes = calculatePrimes(iterations, multiplier); pointlessComputationsButton.disabled = false; console.log(primes); } ما تنفذه الشيفرة هو اختبار -غير فعال إطلاقًا- لأوّليِّة primality عدد عشوائي كبير ويُكرَّر الاختبار 50 مرة. استخدام الدالة requestAnimationFrame سنقسم الدالة إلى عدد من الدوال الأصغر والمستقلة بذاتها على أساس محاولة أولى لحل المشكلة، وسنستخدِم بعد ذلك الدالة ()requestAnimationFrame لجدولة تنفيذ هذه الأجزاء، إذ تطلب هذه الدالة من المتصفح تنفيذ دالة محددة في كل إطار قبل عملية إعادة رسم الصفحة مباشرةً. وطالما أن الدوال المجتزأة صغيرة بما يكفي، فسيتمكن المتصفح من تنفيذ العمل ضمن الزمن المفترض لكل إطار، كما أنه من السهل تجزئة الدالة ()calculatePrimes بحيث تحسب أوّليّة كل عدد في دالة مستقلة: function doPointlessComputationsWithRequestAnimationFrame() { function testCandidate(index) { // finishing condition if (index == iterations) { console.log(primes); pointlessComputationsButton.disabled = false; return; } // test this number var candidate = index * (multiplier * Math.random()); var isPrime = true; for (var c = 2; c <= Math.sqrt(candidate); ++c) { if (candidate % c === 0) { // not prime isPrime = false; break; } } if (isPrime) { primes.push(candidate); } // schedule the next var testFunction = testCandidate.bind(this, index + 1); window.requestAnimationFrame(testFunction); } var primes = []; var testFunction = testCandidate.bind(this, 0); window.requestAnimationFrame(testFunction); } انتقل إلى الخيار Use requestAnimationFrame لاختبار هذا الحل، ثم ابدأ تسجيلًا جديدًا، إذ سيبدو التسجيل هذه المرة مشابهًا للقطة الشاشة التالية: ما نراه في اللقطة هو ما نتوقعه تمامًا، فبدلًا من ظهور كتلة برتقالية واحدة في كل مرة ننقر فيها على الزر، سنجد سلسلةً طويلةً مكونةً من كتل برتقالية قصيرة جدًا تبدو منفصلة عن بعضها بمقدار إطار -أي زمن تنفيذ إطار- وتمثِّل كل منها تنفيذ دالة واحدة من الدوال التي تستدعيها ()requestAnimationFrame، كما يتخلل الكتل البرتقالية كتلًا زهرية اللون تمثِّل عمليات CSS، وسيتمكن المتصفح من تنفيذ عمليات الإطار جميعها في الوقت المفترض دون انخفاضات مفاجئة عند نقر الزر -عند تنفيذ جافاسكربت- نظرًا لصغر فترة تنفيذ الدوال المجزَّأة. حسّن استخدام الدالة ()requestAnimationFrame استجابة الموقع، لكن هناك مشكلتَين محتملتَين: من الصعب أحيانًا تقسيم الدالة التي تتطلب وقتًا كبيرًا في التنفيذ إلى دوال مستقلة أصغر، فقد ولَّدت هذه العملية في مثالنا البسيط شيفرةً أعقد. تستغرق الدوال المجزأة وقتًا أطول حتى تُنفَّذ جميعها، إذ يمكن في مثالنا تحديد الوقت الذي استغرقته بدقة: إذ تُكرَّر العملية 50 مرة، ويولّد المتصفح 60 إطار في الثانية، وبالتالي سيستغرق تنفيذ التكرارات الخمسين قرابة الثانية، وهذا الزمن ملحوظ سواء في ملف الأداء أو من قبل المستخدِم. استخدام عمال ويب سنحاول حل المشكلة الآن باستخدام تقنية عمَّال الويب التي تمكّنك من تنفيذ شيفرة جافاسكربت في خيط مستقل، ولا يمكن بالطبع استدعاء دوال تُنفَّذ ضمن الخيط الرئيسي من خيط العامل أو العكس مباشرةً، وإنما يمكنها التواصل من خلال واجهة برمجية تضمن تراسلًا غير متزامن، وتبدو الشيفرة التي تُنفَّذ ضمن الخيط الرئيسي كما يلي: const iterations = 50; const multiplier = 1000000000; var worker = new Worker("js/calculate.js"); function doPointlessComputationsInWorker() { function handleWorkerCompletion(message) { if (message.data.command == "done") { pointlessComputationsButton.disabled = false; console.log(message.data.primes); worker.removeEventListener("message", handleWorkerCompletion); } } worker.addEventListener("message", handleWorkerCompletion, false); worker.postMessage({ "multiplier": multiplier, "iterations": iterations }); } إنّ الاختلاف الرئيسي في هذه الحالة موازنةً بالسابقة هو الحاجة إلى: إنشاء عامل. إرسال رسالة عندما يحين وقت الحسابات. الإنصات إلى رسالة نصها "done" تشير إلى انتهاء العامل. نحتاج بعد ذلك إلى ملف يُدعى calculate.js ويضم الشفرة التالية: self.addEventListener("message", go); function go(message) { var iterations = message.data.iterations; var multiplier = message.data.multiplier; primes = calculatePrimes(iterations, multiplier); self.postMessage({ "command":"done", "primes": primes }); } function calculatePrimes(iterations, multiplier) { var primes = []; for (var i = 0; i < iterations; i++) { var candidate = i * (multiplier * Math.random()); var isPrime = true; for (var c = 2; c <= Math.sqrt(candidate); ++c) { if (candidate % c === 0) { // not prime isPrime = false; break; } } if (isPrime) { primes.push(candidate); } } return primes; } لا بد في شيفرة العامل أن ننصت إلى الرسالة التي تخبرنا ببدء التنفيذ، ومن ثم نرسل الرسالة "done" عندما ننهي الحسابات. لاحظ أنّ الشيفرة التي تنفّذ الحسابات هي نفسها تمامًا الشيفرة الأصلية دون تعديل، فكيف سيتغير الأداء الآن؟ انتقل إلى الخيار Use a worker وأنشئ تسجيلًا جديدًا، إذ سيبدو التسجيل مشابهًا للقطة الشاشة التالية: نقرنا الزر في هذا التسجيل ثلاث مرات، حيث تبدو كل نقرة موازنةً بالملف الأول كتلتَين برتقاليتَي اللون وقصيرتين جدًا هما: الدالة ()doPointlessComputationsInWorker التي تتعامل مع حدث النقر وتبدأ تنفيذ شيفرة عامل الويب. الدالة ()handleWorkerCompletion التي تُنفَّذ عندما ينتهي استدعاء العامل. سينفِّذ العامل اختبارات الأوّليّة في الفترة الفاصلة بين تنفيذ الدالتين السابقتين ولم يلاحظ أيّ تأثير على استجابة الخيط الرئيسي، وقد يبدو هذا الأمر مستبعدًا بعض الشيء، لكن قد تستغل تقنية عمال الويب إيجابيات المعالجات متعددة النوى كونها تعمل على خيط مختلف، في حين لا يمكن للمواقع التي تعتمد خيطًا واحدًا استغلال هذه الناحية في تحسين الأداء، وتبقى المحدودية الرئيسية لاستخدام عمال ويب هي عدم توفر واجهة برمجية لشجرة DOM لدعم عملياتها. ترجمة -وبتصرف- للمقال Intensive Javascript. اقرأ أيضًا المقال السابق: تأثير رسوم CSS المتحركة على أداء مواقع الويب خطوات أساسيّة لتحسين أداء المواقع
  22. قد ترغب في نشر صفحة الويب البسيطة التي بنيتها ليزورها الجميع وذلك برفعها إلى خادم ويب، لهذا سنناقش في هذا المقال طريقة تنفيذ الأمر مستخدِمين عدة خيارات وأدوات متاحة، مثل عميل SFTP وRSync وGitHub وGoogle App Engine، كما يُنصح قبل متابعة القراءة بالاطلاع على مفهوم خادم الويب وآلية عمل أسماء النطاقات، كما ينبغي أن تكون على دراية بطريقة إعداد بيئة عمل بسيطة من أجل تطوير الويب وكيفية كتابة صفحات ويب. بروتوكول نقل الملفات الآمن SFTP ستجد العديد من الأدوات التي تخدم مثل عميل لبروتوكول SFTP، وسنغطي في مقالنا FileZilla كونها أداةً مجانيةً متاحةً للاستخدام في ويندوز وماك ولينوكس، ولتثبيت الأداة FileZilla، انتقل إلى صفحة التنزيل الرئيسية الخاصة بها، ثم انقر الزر الكبير الذي يحمل العنوان تنزيل Download، بعد ذلك ثبتها من خلال ملف التثبيت الذي نزّلته بالطريقة الاعتيادية. افتح تطبيق FileZilla وسترى نافذةً تشبه النافذة في الصورة التالية: تسجيل الدخول سنفترض في مثالنا أنّ مزود خدمة الاستضافة -أي الخدمة التي تستضيف خادم ويب HTTP الخاص بنا- هي الشركة الوهمية "Example Hosting Provider" التي تعطي لمواردها عناوين URL. لنفترض أننا أنشأنا حسابًا وتلقينا المعلومات التالية: لنلق نظرةً في البداية على العنوان /http://demozilla.examplehostingprovider.net، وبالطبع لن تجد شيئًا فيه. اتبع الآن الخطوات التالية لتتصل بالخادم البعيد عبر عميل SFTP الذي ثبتّه: اختر من القائمة الرئيسية: ملف File > مدير الموقع Site Manager. انقر على الزر "موقع جديد New Site" في نافذة "مدير الموقع Site Manager" وسمِّ الموقع "demozilla" ضمن المساحة المخصصة لذلك. ضع في حقل "المضيف Host" اسم خادم SFTP الذي زودتك به الشركة. اختر "عادي Normal" من قائمة نمط تسجيل الدخول Logon Type المنسدلة، ثم اكتب اسم المستخدِم وكلمة المرور في الأماكن المخصصة لذلك. ضع رقم المنفذ وبقية المعلومات المطلوبة في أماكنها المخصصة. انقر الآن على زر "اتصال Connect" لتتصل بالخادم. العرض المشترك للموارد على حاسوبك وعلى الخادم ستبدو نافذة التطبيق كما يلي عند نجاح الاتصال بالخادم، والصورة التالية ما هي إلا مثال خاص لإيضاح الفكرة فقط: لنلق نظرةً على ما تعرضه الصورة: ستجد في القسم اليساري نافذة الملفات المحلية، حيث تستطيع من خلالها الانتقال إلى المجلد الذي تخزّن فيه موقعك. ستجد في القسم اليميني اليساري نافذة الملفات الموجودة على الخادم -أي البعيدة- بعد دخولنا إلى المجلد الخاص بالموقع على الخادم عبر بروتوكول SFTP. يمكنك تجاهل الأقسام العليا والسفلى حاليًا، وهي بالترتيب نافذة سجل الرسائل التي تعرض حالة الاتصال بين حاسوبك وخادم SFTP، وتمثل الأخرى سجلًا آنيًا لمعلومات التفاعل بين عميل SFTP الخاص بك والخادم. رفع الموارد إلى الخادم تخبرنا إرشادات خادم الاستضافة في مثالنا أنه علينا وضع الموارد في المجلد البعيد Public/htdocs حتى تُنشَر على الويب، إذًا لا بدّ من الانتقال إلى المجلد المحدَّد ضمن القسم اليساري من نافذة العميل. ويمثِّل هذا المجلد جذر موقع الويب، إذ ينبغي وجود الملف الرئيسي للموقع index.html، وبقية الموارد الداعمة له ضمن هذا المجلد، وعندما تصل إلى المجلد الجذر، اسحب الملفات والموارد التي تريد رفعها إلى الخادم من القسم الأيسر لنافذة العميل إلى القسم الأيمن من النافذة. التحقق من وجود الملفات على ويب بعد رفعها يمكنك التحقق من وجود الملفات التي رفعتها بطلب عنوان موقعك عبر المتصفح في مثالنا. /http://demozilla.examplehostingprovider.net وبهذا تكون العملية قد اكتملت بنجاح. استخدام الأداة Rsync تُستخدَم الأداة Rsync لمزامنة الملفات المحلية والبعيدة، وتتوفر الأداة عمومًا في معظم الأنظمة المبنية على يونكس مثل ماك ولينوكس، كما تتواجد نسخ تعمل على ويندوز أيضًا، ويُنظَر إلى هذه الأداة على أنها أكثر تقدمًا من عملاء SFTP لأنها تستخدَم في سطر الأوامر افتراضيًا، إذ يبدو الأمر الأساسي كما يلي: rsync [-options] SOURCE user@x.x.x.x:DESTINATION ‎-options‎‎‎: وهي عبارة عن شرطة - يتبعها حرف أو أكثر مثل v- لإظهار رسائل الخطأ الطويلة وb- لإجراء نسخ احتياطي، كما يمكنك الاطلاع على قائمة الخيارات ضمن الصفحة الرئيسية للأداة Rsync. SOURCE: يمثِّل المسار إلى الملف أو المجلد المحلي الذي تريد نسخ الملفات منه. @user: يمثِّل ثبوتيات المستخدِم على الخادم البعيد الذي تريد نسخ الملفات إليه. x.x.x.x: عنوان IP الخاص بالخادم البعيد. DESTINATION: يمثِّل المسار أو الموقع على الخادم البعيد الذي تريد نسخ الملفات أو المجلدات إليه. عليك الحصول على المعلومات السابقة من مزود خدمة الاستضافة، كما من الجيد دائمًا استخدام اتصال آمن كما هو الحال مع FTP، لذلك يمكن تحديد التفاصيل الخاصة ببروتوكول SSH لتنفيذ الاتصال باستخدامه من خلال الخيار e-، وإليك المثال التالي: rsync [-options] -e "ssh [هنا SSH ضع تفاصيل]" SOURCE user@x.x.x.x:DESTINATION واجهات رسومية للأداة Rsync أدوات الواجهات الرسومية متوفرة لهؤلاء الذين لا يرتاحون بالتعامل مع سطر الأوامر مثل الأداة Acrosync المتاحة في نظامَي التشغيل ويندوز وماك، وتذكَّر أنه عليك الحصول على الثبوتيات اللازمة للوصول إلى موقعك من خادم الاستضافة، إذ سيكون دور الواجهة الرسومية تسهيل إدخال هذه الثبوتيات. نشر موقع ويب على جيت هاب GitHub يُعَدّ جيت هاب GitHub موقع ويب لكتابة الشيفرة بصورة جماعية، حيث يمكّنك من رفع الشيفرة وتخزينها في مستودعات منظومة إدارة النُسخ الخاصة بالموقع، كما يتيح لك هذا الموقع المفتوح المصدر لاحقًا إمكانية التعاون مع أطراف أخرى للعمل على شيفرتك، حيث يمكن لأيّ كان الوصول إلى شيفرتك واستخدامها والتعلم منها وتطويرها أيضًا، كما يمكنك بالطبع فعل الأمر ذاته مع أيّ شيفرة ضمن الموقع، وسيرشدك هذا المقال إلى كيفية نشر المحتوى على الويب باستخدام الميّزات التي تقدمها صفحات جيت هاب GitHub-pages. نشر المحتوى يُعَدّ جيت هاب مجتمعًا غايةً في الأهمية والفائدة، كما تُعَدّ جيت Git منظومة إدارة نُسخ شعبيةً جدًا تستخدِمها معظم الشركات حاليًا أثناء تطوير برمجياتها، كما يمتلك جيت هاب ميزةً هامةً تُدعى صفحات جيت هاب تتيح لك نشر شيفرة المواقع على الويب مباشرةً. الإعدادات الأساسية ثبّت جيت أولًا على حاسوبك، فهي البنية البرمجية التحتية لمنظومة إدارة النسخ ويعمل جيت هاب اعتمادًا عليها. سجّل بعد ذلك حسابًا جديدًا على جيت هاب، وهذه العملية بسيطة وسهلة. سجّل دخولك إلى الموقع عندما يكتمل حسابك الجديد باستخدام كلمة السر واسم المستخدِم الخاصَّين بك. تحضير الشيفرة لرفعها يمكنك تخزين الشيفرة التي تريد في مستودعات جيت هاب، لكن لا بدّ من تنظيم شيفرتك على أساس شيفرة موقع ويب تقليدي حتى تستفيد من ميزة صفحات جيت هاب بكامل طاقتها، إذ ينبغي مثلًا وجود نقطة دخول إلى موقعك على شكل ملف HTML يحمل الاسم index.html، كما يجب أيضًا تهيئة مجلد الشيفرة ليصبح مستودع جيت قبل متابعة العمل، واتبع الخطوات التالية لتنفيذ الأمر: انتقل من خلال سطر الأوامر إلى المجلد الذي يحتوي على موقعك مستخدِمًا تعليمة تغيير المجلد cd وسنفترض أنه يحمل الاسم test-site وموجود على سطح المكتب: cd Desktop/test-site نفّذ التعليمة التالية عندما تصل إلى داخل المجلد المطلوب، والتي تطلب من الأداة git تحويل مجلدك إلى مستودع جيت: git init واجهات سطر الأوامر ستكون أفضل الطرق لرفع الشيفرة إلى جيت هاب هي عبر سطر الأوامر، إذ سيظهر على صورة نافذة تكتب فيها التعليمات التي تنفذ وظائف معينة مثل إنشاء ملفات أو تنفيذ برنامج معيّن، بدلًا من النقر على أزرار واجهة مستخدِم ما، وستبدو نافذة سطر الأوامر مشابهةً للصورة التالية: يحتوي أي نظام تشغيل على أداة سطر الأوامر: ويندوز: وتُدعى موجِّه الأوامر Command Prompt، ويمكن الوصول إلى الأداة بالضغط على المفتاح Windows ثم كتابة Command Prompt واختياره من القائمة التي ستظهر، وتذكّر أنّ سطر أوامر ويندوز مختلف عن مثلائه في لينوكس وماك، لذلك قد تختلف التعليمات التي ستراها تاليًا وفقًا لنظام التشغيل. OS X: وتُدعى طرفية Terminal، وللوصول إليها انتقل إلى تطبيقات Applications، ثم مرافق Utilities. لينوكس: وتُدعى طرفية Terminal أيضًا، ويمكن الوصول إليها عادةً بضغط المفاتيح Ctrl + Alt + T، وإذا تعذر ذلك، فابحث عنها ضمن شريط التطبيقات أو في القائمة. قد يخيفك الأمر في البداية، لكنك ستعتاد على هذه المهام الروتينية، فكل ما عليك فعله هو إخبار الحاسوب بما تحتاج من خلال كتابة الأمر المناسب ثم الضغط على المفتاح Enter. بناء مستودع خاص بشيفرتك لا بدّ من إنشاء مستودع جديد لملفاتك على أساس خطوة ثانية. انقر على زر الإضافة (+) في أعلى يمين صفحة جيت هاب الرئيسية، بعد ذلك اختر مستودعًا جديدًا. اكتب اسم المستودع المناسب لشيفرتك في صندوق اسم المستودع Repository name عندما تنتقل إلى صفحة إنشاء مستودع جديد، ليكون مثلًا my-repository. اكتب معلومات عن المحتويات التي ستضعها في المستودع في حقل الوصف Description كما في الصورة التالية: انقر على زر إنشاء مستودع Create repository وستظهر لك الصفحة التالية: رفع الملفات إلى جيت هاب سترى سطرين من الشيفرة في صفحة المستودع الجديد وفق القسم الذي يحمل العنوان "… أو ادفع مستودعًا موجودًا عبر سطر الأوامر or push an existing repository from the command line…"؛ انسخ السطر الأول بالكامل والصقه في نافذة سطر الأوامر، ثم اضغط المفتاح Enter، إذ سيبدو الأمر مشابهًا للصورة التالية: git remote add origin https://github.com/chrisdavidmills/my-repository.git اكتب سطرَي الأوامر التاليين ثم اضغط المفتاح Enter بعد كل سطر، حيث تحضِّر التعليمات السابقة الشيفرة للرفع إلى جيت هاب وتطلب من جيت إدارة ملفات الشيفرة. git add --all git commit -m 'adding my files to my repository' ادفع الشيفرة في النهاية إلى جيت هاب بالانتقال إلى صفحة الويب جيت هاب التي كنا فيها، ثم أدخل السطر الثاني من الشيفرة الموجودة في القسم "… أو ادفع مستودعًا موجودًا عبر سطر الأوامر or push an existing repository from the command line…" إلى الطرفية أو موجِّه سطر الأوامر واضغط المفتاح Enter. git push -u origin main علينا الآن تفعيل ميزة صفحات جيت هاب في المستودع الجديد الذي رفعت إليه ملفات الشيفرة، لذلك اختر الأمر "إعدادات Setting" في صفحة الويب الخاصة بمستودعك ثم الأمر "صفحات Pages" من الشريط الجانبي على يسار الصفحة، واختر بعد ذلك الفرع "رئيسي Main" أسفل الأمر مصدر Source، إذ سيسبب ذلك تحديث الصفحة. انتقل إلى قسم صفحات جيت هاب مجددًا، وسترى سطرًا جديدًا مفاده أنّ موقعك أصبح جاهزًا ليُنشر على العنوان https://xxxxxx. إذا نقرت على عنوان URL السابق، فستنتقل إلى نسخة حية لموقعك تُعرض فيها محتويات الصفحة التي تُدعى index.html، والتي تُعرض افتراضيًا؛ لكن إذا كانت الصفحة الرئيسية لموقعك لا تحمل الاسم السابق وإنما myPage.html مثلًا، فعليك حينها الانتقال إليها بنفسك بطلب عنوانها https://xxxxxx/myPage.html. معلومات أكثر عن جيت هاب إذا أردت إجراء تعديلات أكثر على موقعك ومن ثم رفع الشيفرة المعدَّلة إلى جيت هاب، فعليك تطبيق التغييرات التي أجريتها سابقًا على ملفات موقعك كما فعلت سابقًا، ثم إدخال الأوامر التالية مع الضغط على المفتاح"Enter" بعد كل أمر لدفع التعديلات إلى جيت هاب: git add --all git commit -m 'another commit' git push ضع مكان العبارة another commit أيّ رسالة أخرى تراها مناسبة لوصف التعديلات التي أجريتها. يُعَدّ ما قدمناه عن جيت بدايةً متواضعةً جدًا، ولتتعمق أكثر عليك الاطلاع على المزيد من المقالات والدورات التعليمية حول جيت وجيت هاب. استضافة مواقع ويب على محرك جوجل آب يُعَدّ محرك جوجل آب Google App Engine منصةً فعالةً لبناء وتشغيل التطبيقات بالاستفادة من البنية التحتية لجوجل، سواءً أردت بناء موقع ويب من الصفر، أو استضافة موقع ويب ساكن static website، كما سنرشدك فيما يأتي إلى طريقة استضافة موقعك على جوجل آب خطوةً بخطوة. إنشاء مشروع على منصة جوجل السحابية لا بدّ من إنشاء مشروع جديد على منصة جوجل السحابية Google Cloud Platform قبل البدء باستخدام أدوات جوجل، ويتطلب ذلك بالطبع امتلاك حساب على جوجل. انتقل إلى لوحة محرك التطبيقات App Engine dashboard ضمن طرفية منصة جوجل السحابية، وانقر زر إنشاء Create. إذا لم تنشئ مشروعًا من قبل، فعليك تحديد ما إذا أردت استقبال بريد إلكتروني عن آخر التحديثات أم لا، ثم الموافقة على شروط الخدمة. ويفترض بعدها أن تكون قادرًا على متابعة العمل. اختر اسمًا للمشروع ثم اعدل على معرفه ID، واحفظه، إذ سنستخدِم القيم التالية في هذه الإرشادات: اسم المشروع: GAE Sample Site. معرّف المشروع: gaesamplesite. انقر على زر إنشاء Create لإنشاء مشروعك. إنشاء تطبيق يمكن أن يضم كل مشروع سحابي تطبيقًا واحدًا وهذا ما سنفعله الآن: نحتاج إلى تطبيق تجريبي لننشره، فإذا لم يكن لديك تطبيق لاستخدامه، فنزِّل التطبيق التجريبي الذي أعددناه لهذا الغرض وفك ضغطه. لنلق نظرةً على هيكلية التطبيق التجريبي، حيث يحتوي المجلد website على ملفات المشروع بالإضافة إلى ملف الإعدادات app.ymal. لا بدّ أن تكون محتويات موقعك ضمن المجلد website وأن تحمل الصفحة الرئيسية للموقع الاسم index.html وما عدا ذلك يمكنها أخذ الشكل الذي تريد. يخبر ملف الإعدادات app.yaml محرك التطبيقات عن كيفية ربط العناوين التي تقود إلى ملفاتك الساكنة، ولا حاجة لتعديل أيّ شيء فيه. نشر التطبيق سنحاول نشر التطبيق التجريبي الآن بعد تجهيزنا إياه: افتح مفسّر أوامر أو صدفة سحابة جوجل Google Cloud Shell. اسحب المجلد sample-app وافلته في لوحة محرر الشيفرة. نفِّذ الأمر التالي لاختيار مشروعك: gcloud config set project gaesamplesite نفّذ الأمر التالي للانتقال إلى مجلد تطبيقك: cd sample-app بهذا تكون قد أصبحتَ جاهزًا الآن لنشر التطبيق، أي لرفع تطبيقك إلى محرك تطبيقات جوجل: gcloud app deploy أدخِل رقمًا ليدل على المنطقة التي ستضع فيها تطبيقك. اضغط المفتاح Y لتأكيد ما اخترته. انتقل إلى تطبيقك عبر المتصفح بكتابة عنوانه على الصورة your-project-id.appspot.com لمشاهدة موقعك على الإنترنت، وسنستبدل your-project-id في تطبيقنا التجريبي بمعرِّف التطبيقgaesamplesite ليصبح العنوان على الصورة gaesamplesite.appspot.com. طرق أخرى لرفع الملفات يّعَدّ بروتوكول FTP من البروتوكولات المعروفة جيدًا لنشر مواقع الويب، لكنه بالطبع ليس الوحيد في هذا المضمار، وإليك بعض الخيارات الأخرى: واجهات ويب Web interfaces: وهي واجهة مكتوبة بلغة HTML تعمل على أساس واجهة أمامية لخدمة رفع ملفات عن بعد موجودة على خادم الاستضافة. WebDAV: وهو توسعة لبروتوكول HTTP يسمح بإدارة أوسع للملفات. اقرأ أيضا اطلع على توثيق محرك تطبيقات جوجل عبر صفحته الرسمية. لابد من الإشارة إلى إمكانية استضافة المواقع على جيت هاب مستخدمًا اسم النطاق الذي تريده، كما يمكنك الاطلاع على معلومات أكثر عن الموضوع من خلال ملفات المساعدة الإلكترونية الخاصة بموقع جيت هاب. ترجمة -وبتصرف- للمقالات التالية: ?How do you upload your files to a web server. ?How do I use GitHub Pages. ?How do you host your website on Google App Engine. اقرأ أيضًا مساعدة المبتدئين في فهم كيفية رفع الموقع على الإنترنت مدخل إلى أسماء النطاقات في شبكة الإنترنت الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث المدخل الشامل لتعلم تطوير الويب
  23. لا تستهن بالتفكير التصميمي Design thinking، فقد يغير مسار شركات ومنظمات وحتى حياة الأشخاص، لكنه قد يسبب في انهيار كل شيء إن مارسناه بطريقة سطحية أو دون فهم عميق لأسسه. ستقابل مصطلح "التفكير التصميمي" في كل مكان، وهذا ما يجعل استخدامه وفهمه محفوفًا بالمخاطر. لكن إن كنت على دراية بالعقلية التي يفكر بها المصممون، فلن تخطئ معنى التفكير التصميمي وستجني ثماره بكل تأكيد. تتضمن عقلية المصمم Designer's mindset مجموعة أدوات مثل التعاطف والخيال والغموض والتكرارية والإبداع وحل المشاكل. ويُعَد حال الفكر مشابهًا لحال المصمم، فقد يفشل مبكرًا، وغالبًا ما يتعلّم من أخطائه ويبدأ من جديد مهما استغرق الأمر. إذًا لا بد أن يكون المصمم متفائًلا عندما يجرب أفكارًا جديدةً، وأن يكون قادرًا على الاستفادة من هذه الأفكار، وعندها فقط قد تبصر الحلول التي تختمر في مخيلته النور لتُقيّم وتُجرّب. وهكذا، نرى أن التفكير التصميمي هو توازن مثالي بين التحليل والخيال. ما ستكتشفه لاحقًا، هو أنّ التفكير التصميمي يحمل أبعادًا أوسع من كونه مصطلحًا محيّرًا، وستلمس أهمية النقاط الثمانية التي نستعرضها في مقالنا إن أردت إتقان التفكير التصميمي وتطبيق مبادئه في أعمالك وفي حياتك اليومية أيضًا. 1. تقبل حقيقة أن التفكير التصميمي لا يحدده تعريف معين على الرغم من عدم وجود تعريف محدد للتفكير التصميمي، لكنك ستتمكن من استيعاب التفسيرات المختلفة للمصطلح والطريقة التي تُطبق بها عندما تمتلك معرفة جيدة بعقلية المصمم وأدواتها. لا تعريف محدد للتفكير التصميمي، لكن التفسيرات المختلفة للمصطلح تعتمد المبادئ نفسها طوّرت الشركات والمصممون أساليبهم الخاصة في التفكير التصميمي وكيّفوها لتلبي احتياجاتهم. لنلقِ نظرةً على التعريف الذي تبناه المدير التنفيذي لشركة IDEO "تيم براون" للتفكير التصميمي: إنّ التفكير التصميمي كما تقدّمه IDEO هو أسلوب لاستشعار العالم وحل المشاكل من خلال الإبداع. مع ذلك ستجد في أيامنا هذه تنوّعًا كبيرًا في إطارات العمل التي تُعنى بالتفكير التصميمي وتقديمه بطريقة بصرية، ويضم كل إطار ما بين ثلاث إلى سبع مراحل مستقلة، لكنها جميعًا تعتمد على المبادئ ذاتها. فما تفعله خلال التفكير التصميمي سيتضمن: مقاربة المشكلة بشيء من التعاطف: فلا بدّ لفريق التفكير التصميمي أن يضع حاجة المستخدم في مركز العملية. إعادة صياغة المشكلة أو التحدي مرارًا: لا بد لفريق التفكير التصميمي أن يعيد تحديد المشكلة أو التحدي مرارًا حتى يقف على السبب الجذري للمشكلة. استخدام أنماط تفكير متشعبة في البداية: فالنوعية تأتي من الكثرة في حالتنا. استخدام أنماط تفكير متقاربة في النهاية: يختار الفريق الفكرة التي سيعمل عليها من بين الأفكار التي حصلوا عليها. بناء واختبار نماذج أولية: يطوّر الفريق نموذجًا أوليًا لنقل الأفكار إلى أشياء ملموسة يمكن اختبارها. التكرار: يمكن للفريق تكرار جميع المراحل السابقة وبأي ترتيب وفي أي وقت لتحسين نتائج العمل. 2. التفكير التصميمي ليس حكرًا على المصممين قد تستخدم أي منظمة أو أي فرد مهما كان مجال عمله التفكير التصميمي إن كان المطلوب مقاربةً فعالةً لدفع عجلة الابتكار التي تجعل حاجات الناس مركز عملية التطوير. وقد اعتمدت طرائق التفكير التصميمي واستراتيجياته في عالم الأعمال وعلى مختلف مستوياته. لقد ازدادت شعبية التفكير التصميمي خلال العقود الماضية لأنه كان سببًا رئيسيًا في نجاح العديد من الشركات العالمية المرموقة. وتدرّس الآن طريقة التفكير المنفتحة هذه في الكثير من الجامعات المشهورة، كما يُشجّع على استخدامها في عالم الأعمال وعلى مختلف المستويات. وتجدر الإشارة إلى ضرورة العمل مع فريق متعاون ومتعدد الاختصاصات، يضم أشخاصًا من خلفيات ومهارات مختلفة. بيل جيلبرت، مؤسس شريك في فريق IBM للتفكير التصميمي لقد تبنى العديد من الأشخاص الذي تعلّموا مبادئ التفكير التصميمي أساليبه في حل مشاكلهم، وللحصول على نتائج أو منتجات أفضل. وعلى الرغم من سهولة انخراط المتعلمين الجدد في مسارات التفكير التصميمي، إلا أنّ احترافه سيتطلب أساسًا معرفيًا قويًا والكثير من الوقت والتدريب. ولا ينطبق ذلك على المستويات الفردية فحسب، بل على مستوى المنظمات أيضًا. ولا بد من اعتناق مبادئ التفكير التصميمي في ثقافة المؤسسة حتى يحقق النجاح بما في ذلك تقبل الإخفاق كجزء أساسي من عملية التعلّم وتقبل المجازفة. 3. يبدأ كل شيء عند تحديد المشكلة الحقيقية يبدأ أي مشروع عادة بمشكلة ينبغي حلها، وستكون الخطوة الأولى لنجاح التفكير التصميمي هي إعادة النظر في الافتراضات التي قُدمّت إليك في موجز المشروع كي تتأكد من وقوفك على المشكلة الحقيقية. يميل البشر إلى الاهتمام بالأعراض دون الاهتمام بالمسبب أو المشكلة الجذرية. تخيل أنك توجهت إلى الطبيب لأنك تعاني من الغثيان؛ قد تكون هناك العديد من الأسباب التي تقود إلى الغثيان ابتداءً من التسمم الغذائي وانتهاءً بالحمل. ولكي يعالج الطبيب حالتك بالشكل الصحيح لا بدّ له من إيجاد المسبب الذي لن تتمكن أنت من تحديده لأنك لست متمرسًا في ذلك مثل الطبيب؛ فما تختبره أنت من أعراض يساعد الطبيب بناءً على خبرته في تحديد السبب الكامن خلفها، ثم يصف لك العلاج وفقًا لذلك. وهذا ما عليك فعله كمصمم، إذ عليك إيجاد المشكلة الحقيقية التي يريد العميل حلها. إن تبني هذه المقاربة هو ما سيميزك عن أقرانك في العمل وينقلك إلى مستوى أكثر تقدمًا. اجعل من عملية الاستكشاف صديقك المقرّب، فليس من السهل إيجاد الأسباب الحقيقية للمشكلة مباشرةً حتى على المصمم ولا يعود سبب ضبابيتها إلى معلومات خاطئة قد تحصل عليها من الآخرين عمدًا أو من غير قصد، لهذا عليك استخدام كل أدواتك للوقوف على المشكلة الجذرية، ابتداءً باستطلاعات الرأي والاستبيانات، وصولًا إلى تتبع الأسباب بنفسك ومعاكسة قرارتك وقرارات زملائك وافتراضاتكم. وتذكر دائمًا هذه القاعدة الذهبية: "اكتشف حقيقة ما يقصده العملاء والمستخدمون". وعندها ستكون قادرًا على حل المشكلة الحقيقية. لن يكون الطريق إلى حل المشكلة مستقيمًا، لذا كن مستعدًا للعودة مرارًا وتكرارًا، وشعِّب البحث، مع تحديد صيغ مختلفة للمشكلة، وحاول تكرار البحث واختبار الأفكار. قد يختلف ما نشير إليه عن الأفكار التي تبناها الآخرون مسبقًا عن عملية إيجاد المشكلة الحقيقية، والتي قد تبدو عمليةً مباشرةً لا تشعبات فيها، مثل خط مستقيم من المشكلة A إلى الحل B، فالحقيقة هي أن الطريق سيبدو نوعًا ما كما في الشكل التالي: "عملية التصميم ليست خطًا مستقيمًا، بل هي عملية متشعبة لا بدّ من خوضها لتتضح الأمور" وبمجرد أن ترتاح إلى هذا التمثيل المجازي الذي يعبّر عن عملية التفكير التصميمي بأفضل حالاته، فسيخف شعورك بالغضب وستنجز عملك بجودة أكبر. قد يكون من الصعب نقل هذه الأفكار إلى الثقافة التقليدية للكثير من المنظمات، لكن عدّ نفسك سفيرًا للتفكير التصميمي ضمنها. 4. تقبل الطبيعة الكسيرية لعملية التفكير التصميمي لنتأمل أحد أكثر أطر عمل التفكير التصميمي شعبيةً، والذي صاغته مدرسة "ستانفورد" على أنه عملية لاخطية قابلة للتكرار وتتألف من خمس مراحل هي: التعاطف (تخيل نفسك مكان العميل). تعريف المشكلة. وضع تصورات لها. وضع نماذج أولية. الاختبار. تبدو المراحل مثل خط مستقيم أليس كذلك؟ إذ تكمن المشكلة الحقيقية في فهم وتنفيذ هذه المراحل بتتابع لاخطّي وبأسلوب تكراري، فقد تكون هاتين المفردتين هما الوصفة السرية لنجاح التفكير التصميمي. يتصوّر معظم البشر الزمن على شكل مسار مستقيم إلى حد ما، ولهذا نفضل العمليات المرتبة التي تتجه إلى الأمام مباشرةً أو إلى الخلف مباشرةً، وبإرشادات واضحة كي لا نضيع. توقّف لبرهة وتأكد من فهمك أو عدم فهمك لأهمية اللاخطية والتكرارية. تخيل الأمر مثل عنصر كُسيري fractal، ودعنا نَعُد الكُسيريات في مجالنا على أنها أنماط تتكرر إلى ما لانهاية. ما الذي سيحدث لو فكّرت بالمراحل الخمسة السابقة كأنماط تتكرر إلى ما لا نهاية؟ سيعني ذلك أن كل مرحلة ستتضمن المراحل الخمسة ذاتها وهكذا. فإن استوعبت وتقبلت مرونة التفكير التصميمي واستطعت رؤيته مثل عملية مستمرة، فستحصد نتائج أفضل وتستمتع بما تفعل، إذ سيتطور النموذج الأولي الذي تبنيه على سبيل المثال مع كل تكرار، وذلك ابتداءً بالرسم الأولي البسيط إلى النسخة الرقمية الكاملة الجاهزة للاختبار. سيتطور أيضًا تحديدك للمشكلة، وقد يختلف الأمر تمامًا في النهاية؛ ولا بد إذًا من إتقان لعبة التقارب والتباعد عن المشكلة لتحترف التفكير التصميمي، لكن إن كانت العملية لا متناهية، فكيف سنقدم الحل النهائي؟ وكيف سينتهي الأمر؟ 5. تعلم متى تنهي عملية التفكير التصميمي إليك الحقيقة المُرّة: يبدو أن النتائج لا تظهر عادةً إلا قبل 24 ساعة من الموعد النهائي للتسليم، أيًا كان الوقت المتاح أمام المصمم كي ينجز تصميمه. هذه هي طبيعة العملية، فلن تصل إلى مرحلة الكمال أبدًا، لكن كلما كررت العملية أكثر، ستقترب من الإتقان. ويتطلب الأمر قائدًا خبيرًا للفريق ليقرر أنّ حلًا ما هو الأفضل، وذلك بناءً على ميزانية المشروع والوقت المتاح. ولكي تبدأ بتنفيذ عملية التفكير التصميمي بالأسلوب الصحيح، لا بد أن تتأكد أولًا من إمكانية تطبيق هذه العملية، فلن يكون الحل جيدًا إن لم يعتمد على الموارد المتوفرة. وحتى لو تمكنت من بناء الحل، فلن يُنتج مردودًا كافيًا للعمل، كما لن يكون حلًا مستدامًا قابلًا للتجديد. مع تنامي خبراتك، ستتعلم متى تنتقل من عملية التفكير التصميمي إلى عملية تطوير المُنتج، ومع ذلك لن تنتهي عملية التفكير التصميمي بإطلاق منتجك أو الحل الذي تعمل عليه، فقد تتابع البحث والاطلاع لتحسين حلولك ومنتجاتك باستمرار. إن أحد جوانب المتعة في المنتجات الرقمية، هي الإضافات المستمرة لتحسين تجارب مستخدميك حتى بعد حصولهم على منتجاتك. 6. يتعارض التفكير التصميمي مع التحيز البشري يتميز التفكير التصميمي بأنه منهجية أساسية ينبغي استعمالها بحكمة. وما يجعل التفكير التصميمي أحد الأدوات الأساسية في الإبداع الذي يستند إلى الحاجة البشرية، هو تعارضه مع التحيز البشري الصريح أو المخفي تحت الرغبات اللاواعية، فإن أدركت هذه الحقيقة، فعندها ستمتلك ناصية هذه المنهجية وستضع نفسك في مكان مرموق لتقديم أفضل النتائج. نتعلم -بصفتنا بشر- من تجاربنا الماضية. ومن أنماط محددة من التفكير، قد لا ندرك في الواقع أننا نتبناها. وما يحتاجه الابتكار كما ندرك جميعًا تفكيرًا منفتحًا، فلا بدّ إذًا من كسر تلك الأفكار التي تبنيناها مسبقًا كي ننجز تلك الابتكارات. وبكلمات أخرى، لا بد من التخلص من الأحكام المسبقة. سيمنحك التفكير التصميمي إطار عمل يساعدك في تجاوز تلك العقبات ضمن بيئة تعاونية مريحة. إنّ البعد التعاوني هو ما يمنح التفكير التصميمي القوة الحقيقية، وهو الوصفة السرية للابتكار الذي يجعل الحاجات البشرية مركز اهتمامه. لا تعتقد أبدًا أن التفكير التصميمي عملية مريحة وخالية من التعب، فهي ستدفعك وفريقك لإيجاد أفضل الحلول وليس أسهلها. ومن زاوية فلسفية، هي أسلوب يدفعك إلى تحدي أفكارك ذاتها وتقييم كل خطوة في مسيرة عملك لتصل في النهاية إلى ابتكار قد يغير العالم. 7. يهيئ لك التفكير التصميمي إطارا لعملية الابتكار لقد أصبح التفكير التصميمي المقاربة المشتركة في جميع الابتكارات التي تتمحور حول حاجات الناس، ويُعَد الابتكار هو المنتج الرئيسي. نعيش جميعًا في عالم لا شيء ثابت فيه سوى "التغيير"، ووفق هذه الرؤية، سيكون الابتكار جوهريًا لمعالجة التحديات الجديدة التي تواجه المجتمع. فكّر في طفولتك، ما الذي احتجته حينها؟ هل لا زلت تحتاج تلك الأشياء الآن؟ على الأرجح لا، فقد ساعدتك تجاربك خلال مسيرة حياتك في تعلم مهارات جديدة لتخطي العقبات الجديدة، وقد يحدد الاكتفاء الذاتي الذي تشعر به قدرتك على تجاوز هذه العقبات بنجاح. يمكننا توسيع هذا المنطق إلى مجالات أوسع، فبصفتنا مجتمعًا، سنحتاج إلى الابتكار للتغلب على التحديات الطارئة، مثل الشيخوخة والنمو السكاني وتغيرات المناخ وهكذا، لذا لا بدّ أن نبتكر لنبقى. يساعدنا التفكيرالتصميمي على الابتكار، ولهذا السبب لا بدّ من أن نبدي جدية أكثر في تعميمه. يمثّل الشكل السابق منحنيًا بيانيًا يشير إلى تفوق بعض الشركات التي اعتمدت التفكير التصميمي مثل آبل ووالت ديزني وغيرها بمقدار 219% موازنةً مع غيرها من الشركات الخمسمائة الكبرى وفق تصنيف ستاندرد آند بورز S&P 500، فقد تقدّمت الشركات والمنظمات التي طبقت مقاربة التفكير التصميمي بالشكل الصحيح في عالم الابتكار كما تأقلمت مع العالم المتغير الذي يحيط بنا وبقيت محافظةً على مكانتها. وتحاول هذه الشركات تكرار منتجاتها وتحسينها أكثر فأكثر للتأكد من تحقيق حاجات مستخدميها باستمرار 8. يتطلب التفكير التصميمي وقتا لإتقانه لا يمكن تعلم التفكير التصميمي بين يوم وليلة، وهذا أمر طبيعي. ومن المحتمل أنك تابعت العديد من ورشات عمل ليوم واحد تتحدث عن التفكير التصميمي وهي بلا شك بداية تعريفية ممتازة، لكن تذكر دومًا أن التفكير التصميمي يتطلب وقتًا وجهدًا. فقد تتدرب ليوم كامل مثلًا على الجري، لكن لا تتوقع أن تربح مارثونًا بعدها مباشرةً، خاصةً إذا كنت بدون خبرة سابقة. وهذا ما يحدث تمامًا مع التفكير التصميمي الذي قد يستغرق وقتًا أطول حتى في إتقان منهجيته. لا ينحصر التفكير التصميمي بفئة المصممين، وقد يسيء المبتدئون استخدامه لأنه منهجية تُتقن بالمران. لذلك خذ وقتًا كافيًا لفهم حقيقة التفكير التصميمي، وأسباب استخدامه، والغاية منه؛ وهكذا ستكون قادرًا على تقديم إضافات جديدة للعملية عندما تقدم وجهة نظرك وتصل إلى حلول ناجحة. ترجمة وبتصرف للمقال: 8 Must-Know Insights to Conquer Design Thinking لصاحبته Laia Tremosa. اقرأ أيضًا المرحلة الأولى من عملية التفكير التصميمي: التعاطف مع المستخدمين المرحلة الثالثة في عملية التفكير التصميمي: مرحلة التفكير المرحلة الرابعة في عملية التفكير التصميمي: مرحلة بناء النماذج الأولية استخدام التفكير التصميمي لتخطي مشاكل رائد الأعمال
  24. يصف المقال طريقة إعداد خادم اختبار محلي على حاسوبك وكيفية استخدامه، كما ننصحك بدايةً بالاطلاع على كيفية عمل الإنترنت والتعرُّف على خادم الويب. الملفات على الخادم المحلي موازنة بالملفات على خادم بعيد يمكنك بكل بساطة فتح ملف HTML أو صفحة ويب على حاسوبك بالنقر المزدوج عليه، أو من خلال سحبه ثم إفلاته داخل المتصفح، أو من خلال قائمة ملف File ثم فتح Open، ومن ثم الانتقال إلى الملف المطلوب، ولاحظ أنّ أيّ ملف موجود على القرص الصلب لحاسوبك سيبدأ عنوانه بالشكل //:file يلي ذلك مسار الملف، بينما إذا استعرضت ملفًا على جيت هاب GitHub أو على أيّ خادم آخر، فستلاحظ بدء عنوانه بـ //:http أو //:https للدلالة على حصولنا عليه عبر بروتوكول HTTP. مشكلة اختبار الملفات المحلية لن تتمكن من فتح بعض الأمثلة إذا عاملتها على أنها ملفات محلية، إذ يعود ذلك إلى أسباب مختلفة أهمها: قد تمثل هذه الملفات ردودًا لطلبات غير متزامنة asynchronous requests: لن تنفِّذ بعض المتصفحات -بما فيها جوجل كروم- الطلبات غير المتزامنة إذا جرى طلبها عن طريق ملف محلي لأسباب تتعلق بقيود أمنية. قد تستخدم هذه الملفات شيفرة لغات تعمل على الخادم: مثل PHP أو بايثون، والتي تتطلب خوادم خاصة لتفسير الشيفرة وإيصال النتائج. تعامل المتصفحات الطلبات التي تحمِّل موارد محلية عبر بروتوكول file://‎ على أنها طلبات ذات أصل مختلط cross-origin requests، لذا إن حمَّلت ملفًأ محليًا يحوي يطلب ملفات محلية أخرى، فقد يولد هذا خطأ CORS (اختصارٌ إلى سياسة مشاركة الموارد ذات الأصول المختلطة). تشغيل خادم HTTP محلي بسيط لا بدّ من اختبار الأمثلة المشابهة على خادم ويب محلي لتجاوز مشكلة الطلبات غير المتزامنة، إذ سيكون استخدام وحدة خادم HTTP لبايثون http.server من أسهل طرق تنفيذ ذلك. اتبع الخطوات التالية لإعداد الخادم: ثبِّت بايثون: من المفترض أن تكون حزمة بايثون مثبتةً على جهازك مسبقًا إذا كنت تستخدِم لينوكس Linux أو ماك أو إس macOS‎، بينما إذا كنت تستخدِم ويندوز Windows، فعليك زيارة الصفحة الرسمية لبايثون والحصول على المُثبِّت الخاص بويندوز من خلال الخطوات التالية: انتقل إلى العنوان python.org. انقر على الرابط "Python "3.xxx الموجود ضمن قسم التنزيل Download. انقر على رابط مُثبِِّت ويندوز Windows Installer الموجود أسفل الصفحة لتنزيل ملف التثبيت. شغّل ملف التثبيت عند انتهاء التنزيل. تأكد من تفعيل مربع التحقق الذي يشير إلى إضافة بايثون إلى المسار Add Python 3.xxx to PATH. انقر على تثبيت Install، ثم انقر على إغلاق Close عند انتهاء العملية. افتح موجه سطر الأوامر Command Prompt في ويندوز أو الطرفية Terminal في لينوكس أو ماك لتتحقق من تثبيت بايثون. نفذ الأمر التالي: python -V # إن فشلت التعليمة السابقة استخدم التعليمة python3 -V # إن كان متاحًا "py" أو حاول استخدام الأمر py -V سيعيد إليك الأمر السابق رقم إصدار بايثون الذي ثُبِّت، ثم انتقل بعد ذلك إلى المجلد الذي يحتوي على المثال الذي تريد اختباره باستخدام الأمر cd إذا كان المثال على سطح المكتب أو في مكان آخر، فجرّب الانتقال إليه وفق أحد الأسلوبين التاليين: # ضع عنوان المجلد الذي يحوي المثال الذي تريد اختباره cd Desktop # استخدم النقطتين للانتقال إلى مجلد أعلى بمستوى واحد cd .. استخدم الأمر التالي لتشغيل الخادم ضمن المجلد المحدد: # إذا كان إصدار بايثون 3 # حاول ما يلي على ويندوز # "python -m http.server" # أو # "py -3 -m http.server" python3 -m http.server # إذا كان إصدار بايثون 2 python -m SimpleHTTPServer ستنفِّذ التعليمة السابقة محتوى المجلد على خادم ويب محلي ورقم المنفذ الخاص به 8000، كما يمكن الوصول إلى هذا الخادم من خلال كتابة العنوان localhost:8000 ضمن المتصفح الذي سيعرض لك محتويات المجلد، وانقر على ملف HTML الذي تريد تشغيله. # بايثون 3 python3 -m http.server 7800 # بايثون 2 python -m SimpleHTTPServer 7800 ستتمكن من الوصول إلى الخادم على هذا المنفذ بكتابة العنوان localhost:7800 ضمن المتصفح. تنفيذ شيفرة لغة تعمل على الخادم لن تستطيع وحدتَي بايثون http.server أو SimpleHTTPServer التي تعمل على الإصدار 2 على الرغم من فائدتهما من تنفيذ شيفرة مكتوبة بلغات مثل بايثون أو PHP أو جافاسكربت، فهي تقدِّم بالكاد خادم ملفات ساكن static file server، ولتنفيذ شيفرات مثل هذه، فلا بدّ من عمل إضافي يتعلق بطبيعة اللغة التي تستخدِمها، وإليك بعض الأمثلة: لتنفيذ شيفرة بايثون، لا بدّ من استخدام إطار عمل بايثون خاص بالويب Python web framework، وستجد الكثير من إطارات العمل هذه مثل Django أو Flask أو Pyramid. لتنفيذ شيفرة Node.js -جافاسكربت-، لا بدّ من استخدام Node الأساسي أو أيّ إطار عمل مبني على أساسه مثل إكسبرس Express الذي يمثِّل خيارًا جيدًا. لتنفيذ شيفرة PHP، شغّل خادم PHP المدمج كما يلي: $ cd path/to/your/php/code $ php -S localhost:8000 ترجمة -وبتصرف- للمقال ?How do you set up a local testing server. اقرأ أيضًا دليل إعداد خادم ويب محلي خطوة بخطوة الفرق بين صفحة الويب وموقع الويب وخادم الويب ومحرك البحث
  25. يختلف أثر رسوم CSS المتحركة الناتجة عن التغيير التدريجي لخصائص التنسيق من خاصية إلى أخرى، وقد تؤدي عمليات التحريك المكثفة إلى جمود المتصفح وهو يحاول تحقيق معدل إطارات مناسب لعرض أكثر نعومةً، كما تساعدك الأداتين Frame rate وWaterfall في الإضاءة على عمل المتصفح أثناء تنفيذه هذه الرسوميات لتشخيص مشاكل الأداء التي تنتج عنها. تحدِّد عدد الإطارات عندما تستخدِم رسوم CSS المتحركة، إذ تستخدِم CSS كل إطار لتعريف مظهر العنصر خلال مراحل الحركة، ويعرض المتصفح الحركة بالانتقال من إطار إلى آخر، كما تُعَدّ رسوميات CSS المتحركة أسهل تنفيذًا من رسوميات جافاسكربت، كما تقدم أداءً أفضل أيضًا، وذلك لأنها تمنح المتصفح قدرًا أكبر من التحكم بتوقيت تصيير الإطارات، وإمكانية تجاوز بعضها إذا كان ذلك ضروريًا. يختلف تأثير التعديلات التي نُحدثها على خصائص CSS تبعًا للخاصية المستهدفة. فتحريك العناصر باستخدام خصائص تستهلك موارد أعلى، سيفضي إلى عرقلة أداء المتصفح الذي يحاول جاهدًا بلوغ معدل إطارات مرتفع. تسلسل تصيير رسوميات CSS يُحدِّث المتصفح صفحة ويب عندما تتغير خاصية CSS عبر عملية متسلسلة تتضمن الخطوات التالية: إعادة ضبط التنسيق Recalculating Style: لا بدّ للمتصفح من إعادة ضبط التنسيق في كل مرة تتغير فيها خاصية CSS لعنصر. تخطيط الصفحة Layout: يستخدِم المتصفح التنسيق الجديد في الخطوة الثانية لضبط موقع وهندسة العنصر، وتدعى هذه المرحلة تخطيط الصفحة أو إعادة الانسياب reflow. رسم الصفحة Paint: لا بدّ للمتصفح في النهاية من إعادة رسم العناصر على الشاشة، ولم نعرض في التسلسل السابق خطوةً أخيرةً تقتضي بتقسيم الصفحة أحيانًا إلى طبقات يُعاد رسمها بصورة مستقلة، ثم تُدمج مجددًا بعملية تدعى التركيب Composition. لا بدّ من اتساع إطار واحد للتسلسل السابق طالما أنّ الشاشة لن تُحدِّث حتى اكتمال سلسلة التنفيذ السابقة، ومن المعروف أنّ معدل 60 إطار في الثانية كافٍ لإظهار الرسوميات المتحركة بصورة سلسة وناعمة على الشاشة، ويتطلب هذا من المتصفح تنفيذ السلسلة السابقة خلال 16.7 ميلي ثانية. تأثير الخاصية على الأداء يؤثر تحريك بعض خاصيات CSS أكثر من غيرها على أداء صفحة الويب إليك بعض الأمثلة: 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; } نوع الخاصية Cost مثال ستتسبب الخصائص التي تتحكم تغيراتها بموقع وهندسة العنصر في وقوع أحداث إعادة ضبط التنسيق وتخطيط الصفحة وإعادة رسمها left max-width border-width margin-left font-size لن تتسبب الخصائص التي لا تتحكم تغيراتها بموقع وهندسة العنصر ولا تُصيّر في طبقة مستقلة في وقوع حدث تخطيط الصفحة. color لا تتسبب الخصائص التي تُصيّر في طبقة مستقلة في وقوع حدث إعادة الرسم أيضًا، لأن تحديث الصفحة سيُنفَّذ في خطوة التركيب.. transform opacity يمكنك الاطلاع على تأثير كل خاصية من خاصيات CSS على ملف الأداء وفقًا للمتصفح المستخدَم عبر الموقع CSS Triggers. مثال تطبيقي: موازنة بين أثر الخاصيتين margin وtransform سترى خلال هذه الفقرة كيف تشير الأداة إلى الفرق بين تحريك الكائنات من خلال الخاصية margin والخاصية transform، كما لا يهدف هذا السيناريو إلى إقناعك بأنّ استخدام الخاصية فكرة سيئة دومًا، وإنما لتوضيح فائدة أدوات تحليل الأداء في الإضاءة على عمل المتصفح أثناء تصيير موقعك وكيفية استخدام هذه الإضاءات لتشخيص وتصحيح مشاكل الأداء، فإذا أردت تجريب الأمر، فانتقل إلى صفحة المثال التطبيقي، والتي تبدو بالشكل التالي: تملك الصفحة أداتَي تحكم: زر تشغيل/ توقف: لتشغيل وإيقاف تشغيل الحركة. مجموعة أزرار اختيار: لاختيار أسلوب الحركة باستخدام transform أو margin. ستجد في الصفحة مجموعةً من العناصر أضفنا لها خلفيةً بألوان متدرجة باستخدام الخاصية linear-gradient وظلال حولها بتطبيق الخاصية shadow لأنّ كلتا الخاصيتين السابقتين شديدتا التأثير على الأداء. تحريك العناصر باستخدام margin ابقي الخيار على Use margin وابدأ الحركة، ثم افتح الأداة Performance وأنشئ تسجيلًا جديدًا، فليس عليك في الواقع سوى تسجيل بضعة ثوان. افتح التسجيل الأول، إذ سيعتمد ما تراه على حاسوبك وحمولة نظام التشغيل، لكنه سيبدو قريبًا من الشكل التالي: تظهر في الشكل ثلاثة مشاهد مختلفة: (a): نظرة عامة للأداة Waterfall. (b): معدل الإطارات. (c): تفاصيل الشريط الزمني. نظرة عامة للأداة Waterfall تُظهِر اللوحة مشهدًا مضغوطًا للأداة Waterfall يسيطر عليه اللون الأخضر الذي يوحي بقضاء المتصفح معظم وقته في عمليات الرسم. معدل الإطارات يُظهِر الشكل السابق معدّل الإطارات الذي يشير إلى وسطي قدره 46.67 إطار في الثانية، وهو أقل من المعدل المستهدَف البالغ 60 إطار في الثانية، والأسوأ من ذلك التعرجات الشديدة والانخفاضات المتكررة التي تصل بالوسطي إلى العشرينات والعشرات، فمن غير المحتمل رؤية حركة ناعمة في هذه الحالة وخاصةً عندما تضيف إليها العمليات الناتجة عن تفاعل المستخدِم مع الصفحة. تفاصيل الأداة Waterfall يعرض باقي التسجيل تفاصيل الأداة Waterfall، فإذا تنقَّلت خلال التفاصيل، فستجد نمطًا متكررًا كما يلي: يُظهِر الشكل السابق تسلسل عملية تصير الصفحة، إذ يُعاد ضبط تنسيق كل عناصر الصفحة في كل إطار، ثم تجري عملية تخطيط واحدة للصفحة، ومن ثم إعادة رسم الصفحة، إذ تُخفّض عملية الرسم كما تلاحظ من أداء الصفحة. سلطنا الضوء في لقطة الشاشة السابقة على عملية رسم، إذ يخبرنا امتدادها أنها استغرقت 13.11 ميلي ثانية من أصل 16.7 ثانية وهو زمن تنفيذ عمليات الإطار بكاملها إذا أردنا أداءً سلسًا وناعمًا، وهذا هو السبب وراء انخفاض معدل الإطارات وعدم استقراره، كما من الممكن تعديل الاختبار بإزالة الظلال حول العناصر، ومن ثم ترى أثر ذلك على الأداء، وسنحاول تاليًا استخدام الخاصية transform بدلًا من margin وسنرى النتيجة. تحريك العناصر باستخدام الخاصية transform اختر الآن زر Use transform ضمن خيارات التشغيل في صفحة المثال التطبيقي السابقة وأنشئ تسجيلًا ثانيًا، إذ سيبدو شكل لوحة النظرة العامة للأداة Performance كما يلي: نظرة عامة للأداة Waterfall لاحظ وجود علامات خضراء أقل بكثير من المشهد نفسه عند استخدام الخاصية margin والكثير من اللون الزهري، والذي يوحي بعمليات تخطيط كثيرة أو عمليات إعادة ضبط تنسيق الصفحة كثيرة. معدل الإطارات Frame Rate يبدو الوضع أفضل موازنةً مع الحالة السابقة، فقد حققت الصفحة معدلًا قريبًا من 60 إطار في الثانية، كما يبدو معدل الإطارات في تزايد مستمر بغض النظر عن الانخفاض الملموس في معدل الإطارات في البداية. تفاصيل الأداة Waterfall تدل التفاصيل على سبب التحسن في معدل الإطارات موازنةً بالحالة السابقة، إذ لا يقضي المتصفح وقتًا طويًلا في تخطيط الصفحة أو في عملية الرسم وهي الناحية الأهم في حالتنا. حسَّن استخدام الخاصية transform أداء الموقع بصورة واضحة، وقد أرشدتنا الأداة Performance إلى طبيعة التحسن وسببه. ترجمة -وبتصرف للمقال Animating CSS Properties. اقرأ أيضًا المرجع الشامل إلى التحريك عبر CSS أساسيات التحريك: إنشاء صفحات ويب تفاعلية متجاوبة المكونات الرئيسية للأداة Performance لتحليل أداء صفحات الويب التحريك عبر CSS
×
×
  • أضف...