محمد أحمد العيل

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

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

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

  • Days Won

    25

السُّمعة بالموقع

132 Excellent

المعلومات الشخصية

  • النبذة الشخصية مهندس نظم معلومات، أكتب في مدونتي (تلميحات تقنية) عن البرامج الحرة ومفتوحة المصدر. لدي خبرة في التطوير بلغة جافا وإدارة قواعد بيانات MySQL و Oracle، إضافة إلى إدارة أنظمة لينوكس (دبيان ومشتقاتها).
  1. يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها. كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL كيف تشخّص أخطاء المقابس Sockets في MySQL يُدير خادوم MySQL الاتّصالات القادمة إلى قاعدة البيانات اعتمادًا على ملفّ مقبس Socket، وهو نوعٌ خاصّ من الملفّات يسهّل التواصل بين عمليّات Processes مختلفة. يحمل الملفّ المقبس الخاصّ بخادوم MySQL اسمَ mysqld.sock ويوجد عادةً - بالنسبة للخواديم العاملة بتوزيعة أوبنتو – في المجلّد ‎/var/run/mysqld/‎. تُنشئ خدمة MySQL هذا الملفّ تلقائيّا. تتسبّب التعديلات على نظام التشغيل أو على إعدادات MySQL في عدم تمكّن MySQL من قراءة الملفّ المقبس، ممّا يمنع الوصول إلى قواعد البيانات على الخادوم. يظهر خطأ المقبس الشائع على النحو التالي: ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2) توجد بضعة أمور تتسبّب في الخطأ أعلاه، وخيّارات محدودة لإصلاحه. أحد الأسباب الشائعة هي توقيف خدمة MySQL أو الإخفاق في تشغيلها؛ بمعنى أنّ الخدمة لم تستطع إنشاء الملفّ المقبس ابتداءً. حاول تشغيل الخدمة بالأداة systemctl لمعرفة ما إذا كان هذا هو سبب ظهور الخطأ: sudo systemctl start mysql ثم حاول الوصول إلى سطر أوامر MySQL من جديد. تأكّد - إن استمرّ الخطأ في الظهور – من المسار الذي يبحث فيه MySQL عن الملفّ المقبس. يمكن معرفة هذا المسار من خلال ملفّ الإعداد mysqld.cnf: sudo nano /etc/mysql/mysql.conf.d/mysql.cnf ابحث عن المُعامل socket ضمن المقطع [mysqld] من الملفّ. يبدو المقطع المذكور كالتالي: . . . [mysqld] user = mysql pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock port = 3306 . . . أغلق الملفّ ثم تأكّد من وجود الملفّ mysqld.sock بتنفيذ الأمر ls على المسار الذي يتوقّع MySQL وجودَ الملفّ فيه: ls -a /var/run/mysqld/ إذا كان الملفّ المقبس موجودًا فسيظهر في مُخرجات الأمر: . .. mysqld.pid mysqld.sock mysqld.sock.lock إذا لم يكن الملفّ موجودًا فربما يكون السبب هو أنّ MySQL يحاول إنشاءه دون أن تكون لديه الصلاحيّات المناسبة لذلك. يمكن التأكّد صحّة الصلاحيّات بتغيير ملكيّة المجلّد إلى المستخدم والمجموعة mysql: sudo chown mysql:mysql /var/run/mysqld/ ثم تأكّد بعد ذلك من أنّ المستخدم mysql لديه الصلاحيّات المناسبة على المجلّد. تصلُح الصلاحيّات 755 لأغلب الحالات: sudo chmod -R 755 /var/run/mysqld/ أخيرًا؛ أعد تشغيل MySQL لترى ما إذا كان يستطيع إنشاء الملفّ المقبس من جديد: sudo systemctl restart mysql ثم حاول الوصول إلى سطر أوامر MySQL. إن استمرّ خطأ المقبس في الظهور، فقد يشير ذلك إلى وجود مشكلة أعمق في خادوم MySQL، وفي هذه الحالة تجب مراجعة سجلّات الأخطاء بحثًا عن ما يقود إلى معرفة سبب المشكلة. ترجمة – بتصرّف – للمقال How To Troubleshoot Socket Errors in MySQL لصاحبه Mark Drake. اقرأ أيضًا كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL
  2. فلنفترض أنّ لديك مقطع فيديو طويلًا تريد قطع جزء من وسطه دون أن تكلّف نفسك عناء استيراد المقطع إلى محرّر فيديو، وقطع أجزاء منه، ثم تصديره من جديد. هذه الطريقة مملّة، وعلاوةص على ذلك تغيّر ترميز (Transcoding) الفيديو لغير حاجة. توجد طريقة سهلة لقصّ مقاطع الفيديو من سطر الأوامر باستخدام برنامج avconv عن طريق تنفيذ الأمر التالي في سطر الأوامر: avconv -i [input file] -ss [start time] -t [duration] -codec copy [output file] سنعطي مثالًا على كيفيّة تنفيذ الأمر أعلاه. فلنفترض أنّ لدينا مقطع فيديو يبدأ بـ 42 ثانية لا نرغب فيها. نحتاج لتعيين المعامل ‎-ss إلى القيمة 00:00:42. يقبل هذا المعطى رمزًا زمنيًّا بصيغة "ثوان:دقائق:ساعات". يخبر المعامل البرنامج أنّنا نريد الإبقاء على محتوى الفيديو الموجود بعد 42 ثانية. ماذا لو كانت لدينا 12 ثانيّة أخرى غير مرغوب بها في آخر الفيديو؟. في هذه الحالة يمكننا استخدام المعامل ‎-t لتحديد المدّة التي نريد الاحتفاظ بها من الفيديو. يوجد إشكال بسيط هنا، فقيمة المعامل ‎-t هي مدّة زمنيّة وليست نقطة زمنيّة محدّدة، وهذه المدّة هي الطول الإجمالي للمقطع الناتج. يعني هذا أنّ ما كان يوجد عند النقطة الزمنيّة 00:00:42 سيصبح عند 00:00:00 في الملفّ الناتج عن القصّ. وبالتالي إنْ أردنا قصّ 12 ثانيّة من آخر الفيديو فسنحتاج لعمليّة حسابيّة بسيطة. توجد طريقة سهلة تتمثّل في طرح قيمة المعامل ‎-ss من النقطة الزمنيّة التي تريد التوقّف عندها، واستخدام هذه القيمة في المعامل ‎-t. إذا كنّا نريد التوقّف عند النقطة 00:04:08 فإنّ قيمة ‎-t ستكون 00:03:26. نحصُل في النهاية على الأمر التالي: avconv -i input.mkv -ss 00:00:42 -t 00:03:26 -codec copy output.mkv لدينا الآن مقطع فيديو بطول 3 دقائق و26 ثانيّة. هذه هي طريقة قصّ الفيديو باستخدام avconv نظريّا. عمليًّا، قد تحتاج لتغيير بسيط. لسبب مّا لا يُنسَخ الصوت إلى الفيديو الناتج بطريقة جيّدة، لذا قد تحتاج لإعادة ترميز الصوت. إنْ واجهت هذه المشكلة فيمكنك التغلّب عليها بسهولة باستخدام الأمر التالي: avconv -i input.mkv -ss 00:00:42 -t 00:03:26 -c:v copy -c:a flac output.mkv يطلُب الأمرُ من البرنامج بنسخ ترميز الفيديو من المصدر، وفي نفس الأثناء إعادة ترميز الصوت إلى flac، الذي هو ترميز يضغط الصوت بدون فقد للمعلومات. ترجمة – بتصرّف – للمقال How to Trim Videos with the Command Line Using AVConv.
  3. يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها. كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL كيف تشخّص أخطاء المقابس Sockets في MySQL يحدُث أحيانًا أن تُصاب جداول MySQL بأعطاب سببها أخطاء أدّت إلى استحالة قراءة البيانات الموجودة بها. تؤدّي محاولة قراءة بيانات من جداول معطوبة – عادةً - إلى انهيّار الخادوم. في ما يلي بعضٌ من الأسباب الشائعة لعطب الجداول: توقّف خادوم MySQL أثناء عمليّة كتابة في جدول. التعديل، من طرف برنامج خارجي، على جدول يُعدِّل عليه الخادوم في نفس الوقت. إيقاف الخادوم دون سابق إنذار. إخفاق في عتاد الحاسوب. وجود علّة في برمجة MySQL. إذا كنت تظنّ أنّ أحد جداول قاعدة البيانات معطوب، فيجب أخذ نسخة احتيّاطيّة من مجلّد البيانات قبل تشخيص عطب الجدول أو محاولة إصلاحه.يُساعد هذا الإجراء في التقليل من خطر فقد البيانات. أول ما يجب عليك فعلُه هو إيقاف خدمة MySQL: sudo systemctl stop mysql ثم نقل جميع بيانات MySQL إلى مجلّد جديد. يوجد المجلّد المبدئي لبيانات MySQL بالنسبة للخواديم العاملة بتوزيعة أوبونتو في المسار ‎/var/lib/mysql/‎: cp -r /var/lib/mysql /var/lib/mysql_bkp تصبح جاهزًا – بعد إنشاء نسخة احتيّاطيّة – للبدء في التحقيق لمعرفة ما إذا كان الجدول معطوبًا أم لا. إذا كان الجدول يستخدم محرّك التخزين (MyISAM) فيمكن التحقّق من عطب الجدول باستخدام التعليمة CHECK TABLE من سطر أوامر MySQL: CHECK TABLE table_name; ستظهر رسالة في مُخرجات الأمر تخبرك ما إذا كان الجدول معطوبًا أم لا. إذا كان جدول MyISAM معطوبًا فيمكن عادةً إصلاحه بتنفيذ التعليمة REPAIR TABLE: REPAIR TABLE table_name; ستُظهرمخرجات التعليمة - بافتراض أنّ عمليّة الإصلاح ناجحة – رسالة تشبه التالي: +--------------------------+--------+----------+----------+ | Table | Op | Msg_type | Msg_text | +--------------------------+--------+----------+----------+ | database_name.table_name | repair | status | OK | +--------------------------+--------+----------+----------+ أما إذا لم تنجح العمليّة وبقي الجدول معطوبًا فإنّ توثيق MySQL يقترح بضعة طرق بديلة من أجل إصلاح الجداول المعطوبة. بالنسبة للجداول التي تستخدم محرّك التخزين InnoDB، فعمليّة الإصلاح مختلفة. بدأت قواعد بيانات MySQL باستخدام محرّك InnoDB - الذي يتميّز بتوفّرعمليّات التحقّق التلقائي من الأعطال وإصلاحها - مبدئيًّا منذ الإصدر 5.5. يتحقّق InnoDB من وجود أعطال في الصفحات بحساب مجموع تحقّق (Checksum) لكلّ صفحة يقرأها؛ وفي حال وجود اختلاف بين مجموعات التحقّق فإنّه يوقف خادوم MySQL تلقائيّا. نادرًا مّا توجد حاجة لإصلاح الأعطاب في الجداول التي تستخدم InnoDB، إذ أنّ InnoDB لديه آليّة يمكنها حلّ أغلب الأعطاب عند إعادة تشغيل الخادوم. على الرغم من ذلك، ينصح توثيق MySQL باستخدام طريقة "الطرح وإعادة التحميل" Dump and reload. يعني هذا إعادة الوصول إلى الجدول المعطوب باستخدام الأداة mysqldump، لإنشاء نسخة احتيّاطيّة منطقيّة من الجدول يُحتَفظ فيها ببُنيته وبياناته؛ ثم إعادة تحميل الجدول إلى قاعدة البيانات. حاول إعادة تشغيل خدمة MySQL لترى إن كنت ستتمكّن من الوصول إلى الخادوم، مع استحضار آلية عمل طريقة "الطرح وإعادة التحميل: sudo systemctl restart mysql إنْ استمرّ انهيّار الخادوم أو استحال الوصول إليه لسبب آخر، فربّما يكون من المفيد تفعيل الخيّار force_recovery ضمن عدادات InnoDB. يمكن فعلُ ذلك بسهولة عبر تحرير الملفّ mysqld.cnf: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf أضف السّطر التالي في المقطع [mysqld] من الملفّ: . . . [mysqld] . . . innodb_force_recovery=1 احفظ الملفّ ثم أغلقه، ثم جرّب إعادة تشغيل MySQL من جديد. إذا استطعت النجاح في الوصول إلى الجدول المعطوب فاستخدم الأداة mysqldump لطرح بيانات الجدول في ملفّ جديد. يمكنك تسميّة الملفّ بما يحلو لك. في ما يلي اخترنا الاسم out.sql: mysqldump database_name table_name > out.sql الخطوة المواليّة هي حذف الجدول من قاعدة البيانات. يمكنك استخدام الصيغة التاليّة لتفادي فتح سطرأوامر MySQL من جديد: mysql -u user -p --execute="DROP TABLE database_name.table_name" أخيرًا، استعد الجدول بالاعتماد على ملفّ الطرح الذي أنشاته للتو: mysql -u user -p < out.sql فليكن في علمك أن محرّك التخزين InnoDB – في العموم – أكثر مقاومةً للأخطاء من محركّ التخزين القديم MyISAM. لا يعني هذا أنّ جداول InnoDB غير معرَّضة للأخطاء، لكن وجود ميزات التغلّب على الأخطاء تلقائيّا يجعل احتمال عطب الجداول وما ينتج عنه من انهيّارات أقلّ بكثير. ترجمة - بتصرّف - للمقال How To Fix Corrupted Tables in MySQL لصاحبه Mark Drake. اقرأ أيضًا المقال التالي: كيف تشخّص أخطاء المقابس Sockets في MySQL
  4. يمكن أنْ يكون تطوير موقع ويب بدون الأدوات المناسبة مدعاة للكثير من الإحباط. ستجد أحيانًا أنّك تعمل على برنامج متقدّم جدًّا بالنسبة لمستواك، أو يمكن أن تكون بحاجة للانتقال إلى برنامج موجّه للمحترفين. يتعلّق الأمر بمستوى قدراتك بوصفك مصمّم مواقع، إلّا أنّ برامج التصميم للويب هي - مجملًا - نفسُها سواءٌ كنت مبتدئًا أو مستخدمًا متقدّمًا. الفرقُ الوحيد هو أنّك قد لا تستخدم جميع الميزات المتوفّرة في أداة معيّنة إنْ كنت مستخدمًا مبتدئًا أو بخبرة متوسّطة. تحتاج لاستكشاف ما يستخدمه المحترفون ومتابعة دورات وقراءة مقالات لمعرفة الطريقة التي تجعل تصميماتك أفضل ما يمكن أن تصل إليه. لذا، سنلخّص في هذا المقال تسعةً من برامج التصميم التي تحتاجها أكثر من غيرها، ونشرح مالذي يُستخدَم فيه كلّ واحد منها خلال عمليّة التطوير. ووردبريس ووردبريس هو نظام إدارة محتوى وتدوين بلغت شهرته ومرونته حدًّا جعل ثُلث مواقع الويب الموجودة تستخدمه. تمكن استضافة ووردبريس ذاتيًّا (وبالتالي يكون لديك التحكّم الكامل في موقعك). علاوة على ذلك، فإنّ المنحى التعلّمي لووردبريس سهلٌ مقارنة بمنصّات مثل Weebly وShopify. يتوفّر برنامج ووردبريس مجانًا، لكنْ ستحتاج للدفع مقابل أمور من قبيل اسم النطاق (Domain name)، الاستضافة (Hosting) والقوالب. بالمختصر، تهدف هذه المنصّة الرائعة لبناء مواقع الويب إلى العمل في الخلفيّة وإعطائك فرصة إنشاء صفحات، وتدوينات، وقوالب وغيرها بسهولة. فوتوشوب يشتهر فوتوشوب بتحرير الصوّر والتعديل عليها، إلّا أنّ هذا المحرّر الضخم يصلُح لأي نوع من مشاريع التصميم. يُستخدَم فوتوشوب لإنشاء شعارات لمواقع الويب أو لتصميم نماذج أوليّة لها. ليس غريبًا أن تجد من يستخدم فوتوشوب لإنشاء مخطّط تصميم كامل لموقع ويب، اعتمادًا على نظام الطبقات (Layers) والتصدير الذي يتوفّر عليه فوتوشوب ويوفّر الكثير من الميزات. Sketch يُنظَر إلى برنامج Sketch غالبًا على أساس أنّه إصدار مُبسَّط من فوتوشوب. يعود السبب في ذلك إلى أنّ Sketch يركّز كثيرًا على التصميم للويب، في حين يمكن استخدام فوتوشوب لأي مشروع تصميم. الميزة الأساسيّة لبرنامج Sketch هي آليّة عمله مع التصاميم المتجهيّة (Vectors)، ممّا يجعله رائعًا لتوسعة التصاميم أو تقليصها بدون فقد أي بيانات أثناء العمليّة. علاوةً على ذلك، يمكن اختبار التصميم على الأجهزة الجوّالة مباشرةً من البرنامج. GIMP توجد في GIMP تقريبًا نفس الميزات الموجودة في فوتوشوب. الفرق الأساسي هو أنّ GIMP مجانيّ تماما. يحاجج بعض المصمّمين بالقول إنّ GIMP معقّد الفهم قليلًا، إلّا أنّه منتَج مجانيّ رائع يوفّر ميزات ضروريّة للعمل على تصميم المواقع وتحرير الصوّر. Adobe Dreamweaver يعدّ Dreamweaver مصنعًا لتصميم المواقع، حيث يوجد محرّر شفرة برمجيّة على جانب الشاشة ومعاينة لموقع الويب على الجانب الآخر. يمكنك بهذه الطريقة التعديل على الشفرات البرمجيّة ورؤية النتيجة مباشرة. في حين يركّز فوتوشوب على إنشاء عناصر موقع الويب أو النماذج الأوليّة، فإنّ Dreamweaver ينشئ موقع ويب جاهزًا للعمل. يمكن بنهاية العمليّة تصدير ملفات موقع الويب ووضعها على الخادوم. WAMP الخطوة المواليّة لتصميم موقع باستخدام برنامج مثل ووردبريس أو Dreamweaver هي اختباره، ثم تعديله وفقًا لنتيجة الاختبارات. قد لا ترغب في الدفع مقابل خادوم، فقط لعرض موقع نصف مكتمل على الجمهور. توجد طريقة أفضل، وهي الحصول على خادوم محلّي مثل WAMP. بالمختصر، تشغّل الخادوم على حاسوبك الشخصيّ، وتنشئ أو تختبر موقع الويب كما لو كان موجودًا على الشبكة، وأخيرًا تنقل الملفات إلى الخادوم المتاح للعموم. يعمل برنامج WAMP على أنظمة التشغيل وندوز، ولكن يوجد بديل يعمل على حواسيب Mac وهو MAMP. عجلة الألوان (Color Wheel) من المهمّ جدًّا أن تكون لديك أداة ألوان أثناء تصميم موقع ويب. عجلة الألوان أداة مجانيّة توفّر طريقة لبناء مخطّطات ألوان ذات مظهر متناسق لاستخدامها ضمن موقع الويب. قد تكون لديك فكرة باستخدام لون معيّن في جزء من الموقع، إلّا أنّ المشكلة هي أنّ ألوانًا كثيرة لن تظهر متناسقة مع اللون الرئيسي لموقعك. تأتي عجلة الألوان للتغلّب على هذه المشكلة، إضافة إلى أنّها تساعد في تحديد الرمز الدقيق للون مّا، بدلًا من تخمينه. Adobe Spark أو Canva ظهر برنامج Canva قبل Adobe Spark، لكنّ الاثنين يعملان جيّدًا لتصميم البصريّات الاحترافيّة بأنواعها للاستخدام في شبكات التواصل الاجتماعي، أو منصّات التدوين، أو البطاقات المهنيّة، وغيرها. تختصر الأداتان العمليّة الطويلة لإنشاء موادّ بصريّة من الصفر على فوتوشوب. كما توفّر قوالب احترافيّة كثيرة للاختيّار بينها. بالمختصر، تمكّن غير المصمّمين من إنشاء موادّ بصريّة جميلة للاستخدام على شبكات التواصل الاجتماعي أو على مواقع الويب دون اللجوء إلى فوتوشوب. ترجمة – بتصرّف – للمقال ‎9 Must-Have Web Design Tools and Alternatives لصاحبه Brenda Stokes Barron.
  5. يشرح هذا المقال كيفيّة إنشاء صور متحرّكة بصيغة GIF انطلاقًا من مجموعة صور بصيغة PNG عبر سطر الأوامر على لينكس (توزيعة أوبونتو). أدناه مثال على تجميع صور لإنشاء صورة متحرّكة تُستخدم لشدّ الانتباه. نبدأ أوّلًا بتثبيت الأداة ImageMagick التي سنستعملها خلال هذا الدرس: sudo apt install imagemagick الخطوة التاليّة لتثبيت الأداة هي الانتقال إلى المجلّد الذي يحوي مجموعة الصوّر التي نريد استخدامها لإنشاء الصورة المتحرّكة. بالنسبة لهذا المثال فمسار المجلّد هوDesktop/shebang : cd Desktop/shebang من السهل جدًّا استخدام ImageMagick وفهمُ آليّة عمله. يوفّر ImageMagick برنامجًا يُسمّى convert، هو الذي سنستخدمه لتحويل الصور. يمكن عبر الأمر التالي إظهار صفحة التوثيق الخاصّة بالبرنامج، والتي تشرح آليّة عمله: man convert تُظهر صفحة التوثيق السطر التالي، والذي يوضح طريقة استخدام البرنامج: convert [input-option] input-file [output-option] output-file نمرّر للبرنامج convert خيّارًا للإدخال، وملفًّا مُدخلًا، ونحدّد خيّارات عمليّة التحويل وأخيرًا اسم الملفّ الناتج عن عمليّة التحويل. نفّذ الأمر التالي في سطر الأوامر: convert -delay 2 -loop 0 *.png -scale 480x270 shebang.gif فلنمرّ على الأمر أعلاه خطوة خطوة. الخيّار الأوّل هو ‎-delay. يعيّن هذا الخيّار مدّة التوقّف بين إطارات الصورة المتحرّكة، بالأجزاء المئويّة من الثانيّة. أعطيناه هنا القيمة 2 (أي جزئيْن مئويّين من ثانيّة). نحدّد بعد ذلك عدد مرات تكرار التحريك عبر الخيّار ‎-loop. نريد ألّا يتوقّف التحريك، لذا نعطي القيمة 0 للخيّار. إنْ أردنا تحريك الصورة لمرّة واحدة فقط، فستكون القيمة 1، وإنْ أردنا تحريكها مرتين فالقيمة المناسبة هي 2. نريد أن يكون مُدخَل البرنامج مجموعةً من الصوّر، لذا نستخدم حرف البدل * لإخبار برنامج convert أنّنا نريد استخدام جميع الصوّر الموجودة في مجلّد العمل التي تنتهي بـpng. لدينا صوّرPNG مُصدَّرة من برنامج Blender، وتبلغ أبعادها ‎1920 x 1080، وهو قيّاس كبير جدًّا ولا يناسب صوّر GIF المتحرّكة، فنحدّد أبعاد الملفّ الناتج عن التحويل عبر الخيّار ‎-scale لتكون الأبعاد ‎.480×270 أخيرًا، ندخل اسم الملفّ الناتج وصيغته (shebang.gif). ترجمة – بتصرّف – للمقال How To Create Animated GIFs from a PNG Sequence with ImageMagick and the Command Line.
  6. ربّما تكون شاشات اللّمس أحد الأسباب التي جعلت الأجهزة الجوّالة ذات شعبيّة كبيرة جدّا. تحذف شاشات اللمس المسافة بين الشخص والجهاز التفاعليّ، ونتيجةً لذلك، يحسّ الأشخاص بأنّ شاشات اللمس بديهيّة وسهلة الاستخدام. لهذا السبب، يمكن إدماج المنزلقات (Sliders) بسهولة في الأجهزة الجوّالة. تشجّع المنزلقات المستخدمين على استكشاف محتوى موقع بسهولة عن طريق إجراء حركات أفقيّة على الشاشة. رغم ذلك، فإنّ المنزلقات خيار قليل الاستخدام للتصفّح على الجوّال. تقدّم المنزلقات خيّار تصفّح رائعًا للمواقع والتطبيقات التي لديها عناصر قليلة لاستكشافها. تبدو المنزلقات طبيعيّة للمستخدمين، وتوفّر طريقة مرحة لتعديل الإعدادات أو استكشاف الميزات. يسهُل على الزوّار التعرّف على المنزلقات، ممّا يجعلها سهلة الاستخدام؛ وبالتالي، خيّارًا عمليًّا جدًّا ليستغلّه المصمّمون. ما لذي تصلُح له المنزلقات المنزلقات سهلة الفهم والاستكشاف، وهو ما يجعلها بديهيّة. تمثّل المنزلقات - نظرًا لكونها لا تأخذ مساحة كبيرة - خيّارًا جيّدًا في الأجهزة التي تستخدم شاشات لمس، التي هي شاشات صغيرة. كما أنّ المنزلقات مناسبة لما تمثّله من إضافة لتصميم واجهات المستخدم. تساعد المنزلقات المستخدمين في التحرّك جيئة وذهابًا، أو زيّادة السرعة أو الصوت، وتمنح حسَّا نسبيًّا للأنشطة (جعل مستوى الصوت أرفع ممّا هو عليه الآن). مصاعب عند استخدام المنزلقات النظر إلى التصميم من زاويّة المستخدم أمر مهمّ في سبيل التأكد من قابليّة الاستخدام (Usability). مستخدمو الجوّال – في الغالب – مستعجِلون أو مشتّتو الانتباه عند استخدام أجهزتهم. يمكن أنْ يستخدموا أجهزتهم وهم يتجوّلون في مركز تسوّق، أو يتناولون الطعام، أو يتنزهون في الحديقة. عندما يمرّ المستخدمون على منزلق، فهم يفعلون ذلك في الغالب مشتّتي الانتباه أو مستعجِلين. يعني هذا غالبًا دفع المنزلق كثيرًا إلى أحد الجانبيْن أثناء محاولة إبعاد أصابعهم عن الشاشة. يمكن أن تكون المنزلقات كذلك صعبة الاستخدام بالنسبة للأشخاص الذين لديهم صعوبات حركيّة. قد يكون من الصعب جعل المنزلق يعمل بالطريقة التي تفضّل أن يعمل بها إذا تلقّى ضغطًا زائدًا قليلًا على الشاشة. قد تكون المنزلقات كذلك صعبة الاستخدام بالنسبة للمستخدمين المتقدّمين في السنّ الذين ترتعش أيديهم؛ وهو ما يجعل ضمان نتيجة محدّدة صعبًا أثناء استخدام المنزلق. ربّما يفقد المستخدمون في مثل هذه الحالات الأمل في إمكانيّة تصفّح الموقع. ضع الجمهور المستهدَف من الموقع بالحسبان. إنْ كنت تستهدف زوّارًا متقدّمين في السن، أو أشخاصًا لديهم صعوبات حركيّة أو صحيّة، فلن يكون المنزلق خيّارك الأمثل. فكّر في مشاكل قابليّة الاستخدام بعد التأكّد من ملاءمة استخدام المنزلقات لجمهورك المستهدَف، يأتي الوقت للتفكير في قابليّة استخدام التصميم. يعتمد مستخدمو شاشات اللمس – غالبًا – الأصابع عند العمل على أجهزتهم. بما أنّك تريد أن يكون تصميمك قابلًا للاستخدام، فمن المهمّ استكشاف أماكن شاشة اللمس التي سيشغلها الأصبع أو اليد عند استخدام الجهاز الجوّال. سيساعد ذلك في وضع المنزلق بحيث يمكن استخدامه والتعامل معه. يختلف التصميم لسطح المكتب، حيث تُستخدَم الفأرة لتحريك المنزلق، عن الأجهزة بشاشات لمس. يجب أن تسعى في حالة شاشة لمس إلى التقليل من إمكانيّة الخطأ، أو الضغط على روابط أخرى، أو تغطيّة التعليمات أثناء وضع المستخدمين أصابعهم على الشاشة. يجب أن تظهر جميع اللافتات (Labels) والقيّم التي تفسّر المنزلق بجانب أصابع المستخدم وزرّ التمرير، أو فوقهما. استخدم المنزلقات لترك انطباع بصريّ واضح يفيد غالبًا استخدام المنزلق لتقديم متتاليّة من الصوّر البصريّة للمستخدمين إذا كان لديك محتوى مهمّ لعرضه، ولكنّ به معلومات كثيرة جدًّا، يصعُب استكشافها أو استيعابها على زوّار الموقع. على سبيل المثال، إنْ رغبت في عرض سلسلة من الأحداث التي يمكن للمستخدم متابعتها بهدف شراء منتَج من موقع تجارة إلكترونيّة، فإنّ مجموعةَ صوّر واضحة تقود المستخدم عبر خطوات متتاليّة يمكن أن تكون مفيدة ولا تتطلّب الكثير من العمل. تقتصد الطريقة السابقة أعلاه من وقت الزائر وتجعل الموقع سهل التصفّح. يمكن استخدام هذه العمليّة في حالات كثرة لمساعدة المستخدم في تصفّح موقع أو تطبيق للجوّال. أنواع المنزلقات التي يمكنك استخدامها توجد أنواع عدّة يمكن استخدامها عند تصميم موقع أو تطبيق: المنزلقات المنفردة (Single sliders): مناسبة للعمل مع قيمة وحيدة في كلّ مرة. المنزلقات المزدوجة (Double sliders): مناسبة للعمل مع مجال من القيم (مثلًا، منزلق للقيمة الدنيا وآخر للقيمة القُصوى). المنزلقات المتواصلة (Continuous sliders): تسمح المنزلقات المتواصلة بتحديد موقع نسبي على مجال مُحدَّد بقيمتين دنيا وقُصوى. المنزلقات المتقطّعة (Discrete sliders): تتميّز بنقاط توقّف يمكن للمستخدم استعمالها لإعطاء قيمة دقيقة. الدقة أم التخمين؟ قد يكون صعبًا أو معقّدًا بالنسبة للزائر استخدامُ منزلق بصورة دقيقة. يتأكّد هذا الأمر على شاشات اللمس. من الصعب جدًّا الحصول على الدقّة في التحديد إذا كنت أمام مؤشّر تمرير صغير على شاشة لمس. يكون استخدام المنزلقات – غالبًا – أسهل عندما لا تكون دقّة القيمة المُختارة مهمّة. إنْ كان المستخدم يستطيع استخدام المنزلق لمشاركة قيمة تقريبيّة، فسيكون ذلك – غالبا – كافيّا. مالعمل إنْ احتجت لقيمة دقيقة؟ يمكن إنشاء منزلق بقيم عدديّة قابلة للتعديل إذا كان من اللازم على المستخدم إدخال قيمة مضبوطة. يعني هذا أنّه سيكون باستطاعة المستخدم لمس المنزلق ثم إدخال عدد في صندوق نصّيّ. يمكن أن يُصبح الصندوق قابلًا للتعديل كلّ ما لمس الأصبعُ المنزلق. رغم ذلك، إنْ كانت واجهة المستخدم تتطلّب قيمة دقيقة من أجل قابليّة الاستخدام، فسيكون من الأفضل عدم استخدام المنزلقات. عرض مجال قِيم تسخدم بعض المنزلقات قيمًا عدديّة بحيث يمكن للزائر تحديد اختيّارات. يمكن لتطبيق تجارة إلكترونيّة أن يوفّر مجموعة من المنتجات تبدأ أسعارها من دولار واحد، لكنّها تصل إلى 999 دولار. يكون من المفيد في هذه الحالة – غالبًا – عرضُ مجال القيّم المتوفّرة على المتجر بدقّة. تمنح هذه الطريقة المستخدم إمكانيّة إنشاء مجال مخصَّص للعناصر التي يريدون استكشافها. تتجنّب بتخصيص مجال من القيّم حصول الزائر على إجابة بمجموعة عناصر فارغة. ستوفّر مجموعة قليلة من قيّم البحث نتيجة بعناصر أقلّ، في حين يوفّر مجال بحث أوسع عناصر أكثر. على الرغم من ذلك، لن يحدّد المستخدمون مجموعةً من القيّم إلّا لسبب، ولن يزعجهم غياب مجموعة من الخيّارات لا يمكنهم دفع ثمنها. أعط للمستخدمين القدرة على استكشاف التطبيق، حتى ولو لم يكونوا يفهمون مغزى المنزلق والمجالات التي يتيحها للمستخدم. وفّر تغذيّة راجعة بصريّة للمستخدمين أضف تغذيّة راجعة بصريّة لتفاعلات المستخدمين مع المنزلق، فتلك هي طريقة العمل التي يتوقّعها المستخدم. وفّر إجابة بصريّة فوريّة للمستخدم عند استخدامه لمنزلق أو عندما يُدخل معلومات في صندوق إدخال. يمكن استخدام التحريكات (Animations)، حالات الحومان (Hover)، والتأشير فوق العناصر (Rollover) للتواصل مع المستخدم. تجذب هذه الميزات انتباه المستخدم وتخلُق بالتالي قناة اتّصال معه. مواقع الويب التفاعليّة جذّابة دائما. عندما تمدّ المستخدم بتغذيّة راجعة بصريّة فإنّه يشعُر بالتقدير، ممّا ينتُج عنه إحساس بالثقة في قدرته على تصفّح الموقع. خاتمة تبدو المنزلقات بديهيّة وسهلة الاستخدام في تطبيقات الويب؛ كما أنّها خيّار جمالي، إلّا أنّها ليست دائمًا الأداة الأفضل للاستخدام. إنْ كنت تبحث عن قيم نسبيّة، وتعلم أنّ الجمهور المستهدَف لديه قدرة حركيّة جيّدة، فإنّ المنزلقات قد تكون خيّارًا جيّدا. أمّا إذا كنت تبحث عن قيّم دقيقة، فسيكون من المفيد توفير خيّارات لإدخال تلك القيّم. اعمل، بوصفك مصمِّمًا، على إنشاء شرائط تمرير يمكن للمستخدم من خلالها اختيار مجال من القيّم يمكن استغلاله على الموقع. يساعد هذا الأمر المستخدمين الذين قد يجدون صعوبة في تحديد قيم دقيقة عند استخدام المنزلق. ترجمة – بتصرّف – للمقال How to Create a Good UI Slider in Mobile Design لصاحبه Bogdan Sandu.
  7. يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها. كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL كيف تشخّص أخطاء المقابس Sockets في MySQL يعدّ التوقّف عن العمل، أو الإخفاق في تشغيل الخدمة بسبب نقص حجم الذاكرة، أكثرَ أسباب الانهيّارات التي تواجهها MySQL شيوعا. ستحتاج – من أجل التحقّق من الأمر – إلى مراجعة سجل أخطاء MySQL بعد الانهيار. أوّلًا، ابدأ بمحاولة تشغيل خادوم MySQL بكتابة الأمر: sudo systemctl start mysql ثم راجع سجلّات الأخطاء لمعرفة سبب انهيّار MySQL. يمكن استخدام الأمر less لمراجعة السجلّات صفحةً صفحة: sudo less /var/log/mysql/error.log رسالتا الخطأ Out of memory و mmap can’t allocate من الرسائل الشائعة التي تنمّ عن نقص في الذاكرة. في ما يلي بعضٌ من الحلول المحتملة لنقص حجم الذاكرة: تحسين إعدادات MySQL. الأداة مفتوحة المصدر MySQLtuner رائعة لهذا الغرض. يؤدّي تنفيذ سكربت MySQLtuner إلى إظهار مجموعة من التعديلات الموصى بإجرائها على ملف إعدادات MySQL‏ (mysqld.cnf). يُرجى الانتباه إلى أنّه كل ما طالت مدّة تشغيل خادوم MySQL قبل استخدام MySQLTuner كانت اقتراحات السكريبت أحسن. استخدم حاسبة MySQL هذه لتقدير حجم الذاكرة المطلوب بالنسبة لكلّ من إعداداتك الحاليّة وتلك التي يقترحها MySQLtuner. التقليل من اعتماد تطبيق الويب على MySQL في تنزيل الصفحات. إضافة نظام تخزين مؤقّت (Cache) إلى التطبيق هو الوسيلة المعتادة لهذا الأمر. من أمثلة استخدام هذه الطريقة نظامُ Joomla الذي يتضمّن وظيفة تخبئة مُضمَّنة يمكن تفعيلها، والإضافة WP Super Cache التي تضيف خاصيّة التخبئة إلى ووردبريس. الترقيّة إلى خادوم افتراضي ذي قدرات أكبر. يُنصَح بخادوم لا تقلّ ذاكرة الوصول العشوائي فيه عن 1GB مهما كانت نوعيّة استخدام قاعدة البيانات MySQL، إلّا أنّ حجم البيانات ونوعيّتها يمكن أن يؤثر كثيرًا على متطلّبات الذاكرة. يُرجى الانتباه إلى أنّ ترقيّة الخادوم، رغم أنّها من المرجّح أن تحلّ المشكلة، إلّا أنه حلّ لا يُنصَح به إلّا بعد التحقّق من الخيّارات الأخرى ومعرفة احتمالات نجاحها. تكلّف إضافة قدرات أكبر إلى الخادوم سعرًا أعلى ويجدر بك اعتماد هذا الخيّار إلّا إذا كان الحلّ الأمثل في نهاية المطاف. انتبه أيضًا إلى أنّ توثيق MySQL يتضمّن اقتراحات أخرى لتشخيص الانهيّارات ومنع حدوثها. ترجمة – بتصرّف – للمقال How To Address Crashes in MySQL لصاحبه Mark Drake. اقرأ أيضًا المقال التالي: كيف تصلح الجداول المعطوبة في MySQL
  8. ليس لدينا وقتٌ كثير. حتى وأنت تستقطع وقتًا لقراءة هذا المقال، فإنّ إشعارات سطح المكتب بدأت فعلًا في التراكم؛ فترى رسائل سلاك (Slack) تزداد، وتسمع الهاتف يهتزّ؛ ممّا يعني التزاماتٍ أكثر ومهامّ أخرى تحتاج لإضافتها إلى قائمة المهامّ التي لا تنتهي. يتسبّب هذا الكمّ المتزايد من الضّغط في جعل مهامّ مثل تقويم تجربة المستخدم (User eXperience) على موقعك تبدو استغلالًا تافهًا للوقت. بينما الواقع أنّ كلّ ما قمت به من تصميم رسومات، وإنشاء محتوى، وتطوير ويب، وتحسين لمحرّكات البحث، وتسويق عبر شبكات التواصل الاجتماعي، وإعلانات مموَّلة يمكن أن يذهب أدراج الرياح إنْ لم تحسّن تجربة المستخدم. تقع الكثير من الشركات في فخّ التركيز المبالغ فيه على المبيعات وحركة البيانات، دون تدعيم الموقع الذي ترسل إليه الزوّار. السقوط في شَرَك لعبة الأرقام طريقة مؤكَّدة لتحطيم سمعتك الإلكترونيّة، والإضرار بتماسك الهويّة التجاريّة (Brand). ستجد أنّ النجاح في مشهد رقميّ تُخصِّص فيه الكثير من الشركات موارد مهمّة لإرضاء الزوّار أمرٌ صعبٌ جدًّا، إنْ لم تكن تدرك قيمة زوّار موقعك (زبنائك). تدرك – إذن – أهميّة تجربة المستخدم. تدرك كذلك ألّا وقت كثيرًا لديك. كيف يمكنك الرفع لأقصى حد من مستوى الاستفادة من تحليل تجربة المستخدم، في وقت قصير؟ إنْ كنت تعرف هويّتك التجاريّة جيّدًا وتفهم مالذي تبحث عنه، فيمكنك إكمال تقويم تجربة المستخدم في ما لا يتجاوز خمس دقائق. سواءٌ أخذت خمس دقائق مرّةً في الشهر، أو مرّةً في الأسبوع، فتستطيع إجراء تحسينات كبيرة في معدّل الارتداد (Bounce rate)، ومعدّلات التحويل (Conversion rates)، و – عمومًا - العائد على الاستثمار (Return on investment, ROI) من حملاتك التسويقيّة. الجانب البصري (دقيقتان) تشبه ردّةُ فعل شخصٍ يزور موقع ويب لأوّل مرة ردّةَ فعله عند أوّل لقاء بشخص لا يعرفه، إذْ ستنبني ردّة الفعل هذه على الجانب البصريّ. تضع الطبيعة البشريّة وزنًا كبيرًا للانطباع الأوّل، فالبشر يرغبون في الشعور بأنّهم محقّون في حكمهم، حتى وإنْ لم يجدوا الفرصة لإلقاء نظرة أخرى. مهما قيل، فلن يكون ذلك كافيًّا لوصف أهميّة الانطباعات الأولى لزوّار موقع ويب، في ظلّ وجود هذا العدد المَهول من الشركات على الشبكة للاختيّار بينها. يكفي زرّ خارج عن موقعه، أو فقرة بمحاذاة خاطئة، أو خطأ مطبعي، لكي يرتدّ الزوّار إلى موقع منافس. حتى إنّ موقعًا خاليًّا من الأخطاء يمكن أن يتسبّب في انطباع سيّئ إنْ لم يتمسّك بما فيه الكفاية بالهويّة التجاريّة، والهدف العام للرسائل التي يريد تمريرها. خصّص دقيقتيْن لمراجعة الجانب البصري للموقع من وجهة نظر الزائر، وتأكّد من تسجيل أي اختلالات، أو محتوى خارج الإطار المخصّص له، أو ترتيب غير مناسب لمخطّطات الصفحة. ركّز – خصوصًا – على العناصر البصريّة التاليّة عند إجراء تحليل تجربة المستخدم في خمس دقائق: الألوان: هل هي متوافقة مع الهويّة التجاريّة؟ هل اختير الرمز السداسي العشري بما يتوافق مع هدف الفقرة أو الصفحة؟ هل الألوان ناعمة جدًّا أم خشنة جدّا؟ سهولة القراءة: هل الموقع سهلُ القراءة على كلّ من الأجهزة الجوّالة وأجهزة سطح المكتب؟ هل يُميَّز المحتوى المناسب على كلّ صفحة؟ الخطأ في المحاذاة: حتى الاختلالات البسيطة يمكنها إبداءُ الكثير عن عمل شركتك وأخلاقيّاتها. إنْ لم يكن بمقدورك إتقانُ موقعك الخاصّ فكيف ستتمكّن من توفير خدمات أو منتجات جيّدة لزبنائك المحتملين؟ التأثير العامّ: ما مدلول الموقع، أو صفحة منه، من وجهة نظر بصريّة؟ هل يتماشى موقعك ومحتواه مع الشخصيّة التي تعكسها هويّتك التجاريّة؟ التفاعل (دقيقتان) اطمأننتَ على أنّ الانطباع الأوّل للزوّار جيّد. يأتي الدّور الآن على الأمور الأكثر جدّيّة. هل أنت جاهز لإكمال العمل؟ هل أنت جادّ؟ تحتاج لأن تجعل تجربة المستخدم متناسقةً تمامًا من وجهة نظر بصريّة وتفاعليّة، حتى يقتنع الزوّار فعليًّا بما تقدّمه. وفّر لزوّارك العمق الذي ينتظرونه من موقع بميزات بصريّة فريدة. بدون الوظائف المناسبة لتكملة التعديلات البصريّة على الموقع، لن يبقى الزوّار طويلًا، ولن يستمرّوا بالتصفّح إنْ لم يجدوا الإجابات التي يحتاجونها على نحو أسهل أو أسرع من المواقع المنافسة. إنْ كان الجانب الوظيفي من الموقع يحتوي على أخطاء، أو بطيئًا، أو مخادعًا فقد يتسبّب ذلك في إبعاد المستخدِم عن التجربة الغامرة التي تحاول إنشاءها عبر التصميم البصري والمحتوى. خذ الوقت لتقويم العناصر التقنيّة التاليّة بهدف الرفع من مستوى تجربة المستخدم: الأيقونات: هل تلبّي الأيقونات حاجات هويّتك التجاريّة أو المجال الذي تعمل فيه؟ هل الرسومات واضحة ومناسبة للمعايير التي حدّدتها؟ هل يمكن للمستخدمين النقر على الأيقونات للحصول على معلومات أكثر إنْ كانوا يريدون ذلك؟ الأزرار: تأكّد من حصول المستخدمين على نفس القابليّة للتفاعل عبر الموقع، سواءٌ تعلّق الأمر بنصوص الدعوات إلى إجراء (Call-to-action)، أو ألوان الأزرار وأحجامها. الروابط: هل تعمل الروابط جميعًا على النحو المرجو؟ هل تُميَّز الروابط التشعبيّة بنفس اللون، وهل تسهُل رؤيتها؟ النوافذ المنبثقة (Pop-ups) والقوائم المنسدلة (Drop-downs): هل تعمل العناصر البصريّة المُجمَّعة، سواءٌ كانت عناصر قائمة بذاتها أم جزءًا من قائمة، بطريقة مناسبة؟ وهل تندمج في مساحة معيَّنة دون أن تتجاوزها أو تحجُب محتوى مهمًّا آخر؟ المؤشّر: كيف يتغيّر مؤشّر الفأرة عند التفاعل مع الموقع؟ تأكّد أنّ كلّ تغيير متناسق ومتناسب مع الهدف المُراد منه. الزيارة (دقيقة واحدة) تحتاج للقيّام بإجراءات الدقيقة الأخيرة، والانتباه إلى كلّ تفصيل للتأكّد من أن تكون إجابة المستخدم على السؤال هل أنت راضٍ هي "نعم". من المحتمل جدًّا أن يتحوّل الزوّار إلى زبناء، إنْ خصّصت وقتًا لتقويم تجربة المستخدم من الجانب البصري والوظيفي. رغم ذلك، تبقى خطوة أخيرة تتمثّل في تقمّص شخصيّة زوّارك للتأكّد من فاعليّة تجربة المستخدم وجاهزيّتها للرّفع من مداخيلك. يجب أن تسجّل - أثناء النظر في العناصر البصريّة والوظيفيّة - ملاحظات بالتعديلات التي يمكن إجراؤها. إنْ كانت لديك دقيقة إضافيّة فتصفّح موقعك، كما لو كنت زائرًا، منذ لحظة دخولك الموقع وإلى الخروج منه. هل يستطيع زائر جديد تصفّح الموقع بسهولة من أجل العثور على معلومات يحتاجها، أو البحث عن خدمات تقدّمها، أو تقرير شراء منتج؟ فكّر أثناء تحليل زيّارة مستخدم لموقعك، أنّ الموقع عبارة عن جسر وكلّ صفحة عبارة عن مركبة تنقل المستخدمين من جهة (شخص في حاجة لشيء مّا) إلى أخرى (زبون راض). إنْ لم تكن المركبات موجودة، أو كانت غير صالحة، فسيكون احتمال الانتقال من طرف إلى آخر ضئيلًا جدّا. اجعل تصفّح الموقع سلِسًا للمستخدم كلّ ما تعلّق الأمر بعمليّة شراء. الهدف من تجربة المستخدم هو نقل المستخدمين من النقطة "أ" إلى النقطة "ب" بدون المرور عبر حواجز، أو طرق مسدودة، أو حتى تشقّقات. قوّم تجربة المستخدم على موقعك، حتى ولو لم تكن لديك سوى خمس دقائق، من أجل الحصول على تدفّق مستمرّ من الزوّار المهتمين، والزبناء الراضين. ترجمة – بتصرّف – للمقال How to Evaluate Your UX in Under 5 Minutes لصاحبه Kayla Naab.
  9. الحوسبة خفيّة الخوادم (Serverless computing) في طريقها لإحداث ثورة في طرق تطوير البرمجيّات المتعارف عليها. ستساعدك المنصّات المفتوحة المصدر التي نقدّمها هنا في التعرّف على هذا المجال. كثُر الحديث في الآونة الأخيرة عن خفاء الخوادم (Serverless)، فلنوضّح المعنى المقصود بهذا المصطلح، والمصطلحات المرتبطة به، مثل الحوسبة خفيّة الخوادم (Serverless computing) والمنصّات خفيّة الخوادم (Serverless platform). يُستخدَم مصطلح خفاء الخوادم عادةً على أنّه مرادف لتقديم الوظائف بصيغة خدمات (Functions-as-a-Service, FaaS)؛ إلّا أنّ المصطلح لا يعني غيّاب الخادم، عكس ما قد يوحي به الاسم. في الواقع، توجد خوادم عدّة لأنّ مزوّدي الخدمات السحابيّة للعموم يوفّرون خوادم تنشُر، وتشغّل ، وتدير تطبيقك. تعدّ الحوسبة خفيّة الخوادم قسمًا جديدًا يمثّل تحوّلًا في الطريقة التي يبني بها المطوّرون ويوزّعون الأنظمة البرمجية. يمكن أن يؤدّي عزلُ البنية التحتيّة للتطبيقات عن الشفرة البرمجيّة إلى تسهيل عمليّة التطوير مع الحصول على فوائد أخرى من حيث التكلفة والفاعليّة. يرى عدد من المتخصّصين أنّ الحوسبة خفيّة الخوادم وFaaS ستلعبان دورًا أساسيًّا في تحديد أبعاد الحقبة القادمة من تقنيّة المعلومات في المؤسسّات، جنبًا لجنب مع خدمات السحابة الأصيلة Cloud-native والخدمات السحابيّة الهجينة (Hybrid cloud). توفّر المنصّات خفيّة الاسم واجهات تطبيقات برمجيّة (API) تتيح للمستخدمين تشغيل دوالّ برمجيّة (تُسمّى أيضًا إجراءات (Actions)) وتُرجِع نتيجة تشغيل كلّ دالة. توفّر المنصّات خفيّة الخادم كذلك نهايات HTTPS لتمكين المطوّر من الحصول على نتائج الدالّة. يمكن استخدام هذه النهايات (Endpoints) لتكون مُدخلًا Input لدوالّ أخرى؛ وبالتالي توفير متتاليّة (أو سلسلة) من الدوالّ المترابطة. تعمل أغلب المنصّات خفيّة الاسم بحيث ينشُر المستخدم (أو يُنشئ) الدوالّ قبل تنفيذها. يتوفّر لدى المنصّة بعد ذلك كلّ ما يلزم لتنفيذ الشفرة البرمجيّة حالما يُطلب منها ذلك. يُمكن طلب تنفيذ الدالّة خفيّة الخادم يدويًّا بتنفيذ أمر، أو يمكن التسبّب في تنفيذها عبر حدث مرجعي مُعدّ لتنشيط الدالّة للإجابة على أحداث مثل إشعار Cron، وتحميل ملفّ، وأحداث أخرى كثيرة. سبع منصّات مفتوحة المصدر للتعرّف على الحوسبة خفيّة الخوادم Apache OpenWhisk: منصّة مفتوحة المصدر تمكّنك من تنفيذ شفرة برمجيّة استجابةً للأحداث مهما كان عددها. كُتبت المنصّة بلغة Scala، ويمكنها معالجة مُدخلات انطلاقًا من طلبات HTTP ثم تشغيل شفرات برمجيّة مكتوبة بلغة جافاسكريبت أو سويفت Swift. Fission: إطار عمل للحوسبة خفيّة الخوادم يمكّن المطوّرين من إنشاء دوالّ باستخدام Kubernetes. يتيح إطار العمل هذا للمبرمجين كتابة دوالّ تدوم لمدّة قصيرة بأيّة لغة برمجة، وربطها بأي حدث مثل طلبات HTTP. IronFunctions: إطار عمل للحوسبة خفيّة الخوادم يوفّر منصّة للخدمات الصغيرة (Microservices) المترابطة، عن طريق دمج الخدمات الموجودة والاستفادة من Docker. يكتُب المطوّرون الدوالّ بلغة Go. FnProject: منصّة خفيّة الخوادم مُوجَّهة أساسًا للحاويّات يمكن تشغيلها في أي مكان على السحابة أو في البنية التحتيّة الداخليّة. استخدام المنصّة سهل، كما أنّها عاليّة الأداء، و تدعم لغات البرمجة جميعًا، ويمكن توسعتها. OpenLambda: مشروع حوسبة خفيّة الخوادم مُرخص برخصة Apache، ومكتوب بلغة Go، ويعتمد على حاويّات لينكس. يهدف OpenLambda في المقام الأول إلى التمكين من استغلال المقاربات الجديدة للحوسبة خفيّة الخوادم. Kubeless: إطار عمل يعتمد على Kubernetes ويسمح للمطوّر بنشر شفرات برمجيّة قصيرة دون التفكير في البنية التحتيّة المستخدمة. يعتمد Kubeless على موارد Kubernetes لتوفير قابليّة التوسّع الذاتيّة، وتوجيه واجهات التطبيقات البرمجية، والمراقبة، والتشخيص وغيرها. OpenFaas: إطار عمل لبناء دوالّ خفيّة الخوادم باستخدام Docker وKubernates؛ يوفّر دعمًا مدمجًا للقيّاسات والإحصاءات. يُمكن تحزيم أي عمليّة Process على هيئة دالّة، ممّا يسمح باستغلال مجموعة من أحداث الويب دون الحاجة لكتابة شفرات مُكرَّرة. يعدّ Kubernates المنصّة الأكثر انتشارًا لإدارة أحمال العمل في المنصّات خفيّة الخوادم، وحاويّات التطبيقات ذات الخدمات الصغيرة. يستخدم Kubernates نموذج نشر معدًّا بدقّة لمعالجة أحمال العمل بسرعة أكبر وسهولة أكثر. يمكّن Knative Serving من بناء خدمات وتطبيقات خفيّة الخوادم ونشرها على Kubernates، مع استخدام Istio للتوسّع ودعم سيناريوهات عمل متقدّمة، مثل: النشر السريع لحاويات خفيّة الخوادم التوسع والتقلّص التلقائيّيْن (Scaling up and down) التوجيه وبرمجة الشبكات بالنسبة لعانصر Istio أخذ لقطات (Snapshots) من الشفرة المنشورة والإعدادات في نقاط زمنيّة محدّدة. يركّز Knative على المهامّ الاعتيّاديّة من بناءٍ للتطبيقات وتشغيلها على منصّات السحابة الأصليّة (Cloud-native)؛ بهدف تنسيق عمليّات البناء من الشفرة البرمجيّة إلى الحاويّة، وربط الخدمات بأحداث النظام، وتوجيه حركة البيانات وإدارتها أثناء النشر، والتوسّع التلقائي حسب حمل العمل. أمّا Istio، فهو منصّة مفتوحة للاتّصال بالخدمات الصغيرة وتأمينها (وهو في الواقع مستوى تحكّم بنسيج الخدمة Service mesh في الوسيط Envoy) صُمِّم ليتناسب مع تفاعل أشخاص مختلفين مع إطار العمل بما في ذلك المطوّرون، عمّال الصيّانة ومزوّدو الخدمات. يمكن – على سبيل المثال – نشر جافاسكريبت خفيّة الخادم باستخدام Knative Serving على منصّة Minishift محليّة باتّباع الشفرة التاليّة: ## Dockerfile FROM bucharestgold/centos7-s2i-nodejs:10.x WORKDIR /opt/app-root/src COPY package*.json ./ RUN npm install COPY . . EXPOSE 8080 3000 CMD ["npm", "start"] ## package.json { "name": "greeter", "version": "0.0.1", "private": true, "scripts": { "start": "node app.js" }, "dependencies": { "express": "~4.16.0" } } ## app.js var express = require("express"); var app = express(); var msg = (process.env.MESSAGE_PREFIX || "") + "NodeJs::Knative on OpenShift"; app.get("/", function(req, res, next) { res.status(200).send(msg); }); app.listen(8080, function() { console.log("App started in port 8080"); }); ## service.yaml apiVersion: serving.knative.dev/v1alpha1 kind: Service metadata: name: greeter spec: configuration: revisionTemplate: spec: container: image: dev.local/greeter:0.0.1-SNAPSHOT أنشئ تطبيق Node.js وانشره على منصّة Kubernates المحليّة. ستحتاج لتثبيت متطلّبات المنصّة (Knative، و Istio، و Knative Serving على Kubernetes (أو Minishift)). اربط المنصّة بخدمة Docker بالأمر التالي: (minishift docker-env) && eval(minishift oc-env) أنشئ نسخة من حاوية خفيّة الخادم باستخدام Jib عبر الأمر التالي: ./mvnw -DskipTests clean compile jib:dockerBuild انشر خدمة خفيّة الاسم مثل Minishift على عنقود Kubernates بالأمر التالي: kubectl apply -f service.yaml خاتمة يوضّح المثال أعلاه أين وكيف يمكن البدء في تطوير تطبيقات خفيّة الخادم باستخدام منصّات سحابة أصليّة مثل Kubernates، و Knative Serving وIstio. ترجمة - بتصرّف - للمقال 7 open source platforms to get started with serverless computing لصاحبه Daniel Oh.
  10. يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها. كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL كيف تشخّص أخطاء المقابس Sockets في MySQL تبدأ الكثير من المواقع والتطبيقات بوضع خادوم الويب وقاعدة البيانات على نفس النظام؛ إلّا أنّ هذا الإعداد يصبح مع الوقت ثقيلًا وغير قابل للتوسيع.. من الشائع التغلّب على هذا الإشكال بفصل الوظيفتيْن بضبط قاعدة بيانات منفصلة ممّا يسمح لخادوم الوِيب وقاعدة البيانات بالنموّ على الأجهزة الخاصّة بها، كلّ حسب حاجته. يعدّ الإعداد المبدئيّ لـ MySQL الذي لا يسمح سوى بالاتّصالات القادمة من نفس الجهاز، وبالتالي يمنع الاتّصالات القادمة من نظام آخر، أحد المشاكل الشائعة التي يواجهها المستخدمون أثناء محاولة إعداد الوصول إلى MySQL عن بعد. يمكن تعديل السلوك المبدئيّ لـ MySQL بتحرير الملف mysqld.cnf: sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf انتقل إلى السطر الذي يبدأ بالتوجيه bind-address. يبدو الملفّ على النحو التالي: . . . lc-messages-dir = /usr/share/mysql skip-external-locking # # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. bind-address = 127.0.0.1 . . . يأخذ التوجيه مبدئيًّا القيمة 127.0.0.1، ممّا يعني أنّ الخادوم سيبحث عن الاتّصالات المحليّة فقط. ستحتاج لتعديل هذه القيمة لتكون عنوان IP خارجي (عنوان الجهاز الذي تريد التواصل معه). كما يمكن استخدام حرف بدل (Wildcard) لأغراض التشخيص والبحث عن الأخطاء. مثلًا: *، أو ::، أو 0.0.0.0: . . . lc-messages-dir = /usr/share/mysql skip-external-locking # # Instead of skip-networking the default is now to listen only on # localhost which is more compatible and is not less secure. bind-address = 0.0.0.0 . . . ملحوظة: لا يحتوي الملف mysqld.cnf في الإصدار 8 وما بعده من MySQL – مبدئيًّا – على التوجيه bind-address؛ لذا تجب إضافة التوجيه أسفل آخر سطر من الملفّ على النحو التالي: [mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error = /var/log/mysql/error.log bind-address = 0.0.0.0 احفظ الملفّ بعد تعديله، ثم أغلقه وأعد تشغيل خدمة MySQL: sudo systemctl restart mysql حاول بعد ذلك الوصول إلى قاعدة البيانات من جهاز آخر كما يلي (حيث database_server_ip عنوان IP الخاص بخادوم قاعدة البيانات): mysql -u user -h database_server_ip -p إن استطعت الاتّصال بقاعدة البيانات، فهذا يؤكّد أن التوجيه bind-address كان السبب في تعذّر الاتّصال عن بعد بقاعدة البيانات. يُرجى ملاحظة أن القيمة 0.0.0.0 غير آمنة وتتيح الاتّصال بقاعدة البيانات من جميع عناوين IP. أمّا إن لم تستطع الاتّصال بقاعدة البيانات بعد ضبط إعداد bind-address، فهذا يعني أن السبب أمر آخر. قد ترغب - في الحالتين – في التعرّف على كيفيّة إعداد اتّصال بعيد أكثر أمانًا، والتي يشرحها المقال كيفية إعداد قاعدة بيانات بعيدة لتحسين أداء موقع يستخدِم MySQL. ترجمة – بتصرّف – للمقال How To Allow Remote Access to MySQ لصاحبه Mark Drake. اقرأ أيضًا المقال التالي: كيف تعالج انهيار خادوم MySQL
  11. لا يشبه تصميمُ موقع تجارة إلكترونيّة أيّ مشروع ويب آخر، إذ يجب أن تفكّر في الهويّة التجاريّة (Brand) إلى جانب تجربة المستخدم (User experience) والتسويق المعتمد على التصميم. أقلّ ما يُقال هو أنّ الأمر يمكن أن يكون صعبًا. رغم ذلك، توجد مصادر مجانيّة كثيرة يمكن استخدامها لجعل العمل أسهل. مجموعات الأيقونات تعني – بالتأكيد – الكثير من الأشياء لتصميمها. يمكنك اقتصادُ ساعات عملٍ طويلة، وربّما أيّام، باستخدام حزمة أيقونات مجانيّة بدلًا من تصميم أيقونات جديدة. توفّر المجموعات المجانيّة أدناه تعدّدًا في الأنماط، وستجد من خلالها الكثير ممّا يمكن النظر فيه. حزمة 54 أيقونة مجانيّة للتجارة الإلكترونيّة تتضمّن هذه الحزمة الشاملة 54 أيقونة تتميّز بخطوطها البسيطة التي تصلُح للوظائف الشائعة في مواقع التجارة الإلكترونيّة. صمّم Virgil Pana الحزمة ووفّرها مجانًا على موقع Dribbble. تأتي الحزمة كاملةً بصيغة ملفّات PSD، وهي – حقًّا – من أفضل الحزم الموجّهة لمواقع التجارة الإلكترونيّة. خصوصيّة الحزمة في أنّه يمكن تضمينها في أي موقع. النمط التقليلي (Minimalist) مستخدَم كثيرًا، لذا فهو يستحق التجربة، بغض النظر عن المشروع الذي تعمل عليه. مجموعة أيقونات خضراء بسيطة هذه حزمة مجانيّة أخرى موجودة على Dribbble، تركّز على أيقونات خضراء أنيقة. فنيًّا، يمكن تغيير المخطّط اللوني بسهولة عن طريق Illustrator. أنشأ المصمّم Pavel Kozlov هذه الحزمة التي تضمّ 40 أيقونة، وجعلها في المتناول قبل سنوات. رغم ذلك، ما زالت الحزمة قابلةً للاستخدام، تمامًا كما كانت من قبل. زر صفحة Gumroad التاليّة لتنزيل المجموعة. عادةً، يُدفَع مقابل العناصر الموجودة على موقع Gumroad، إلّا أنّ هذه الحزمة مجانيّة بالكامل. يمكن - لمن يرغب في ذلك – إرسال مكافأة صغيرة للمصمّم على جهوده، إلّا أنّه ليس شرطًا للحصول على هذه الأيقونات الخضراء الجذّابة. أيقونات تبضّع (Shopping) متجهيّة مسطَّحة (Flat vector) التصميم المسطَّح (Flat design) توجّه في التصميم يحظى بالشعبيّة. طُبِّق التصميم المسطَّح في كلّ مكان، بدءًا من تطبيقات الجوّال إلى مواقع الويب، بل وحتى الأيقونات. ألق نظرة على هذه المجموعة من أيقونات التبضّع المتجهيّة التي تضمّ 80 أيقونة مختلفة. بعض أيقونات المجموعة ملوَّنة، وأخرى أيقونات بخطوط بسيطة، إلّا أنّها جميعًا سهلة الاستخدام والتخصيص. يمكن تنزيل الحزمة بصيغة PNG أو بصيغتي AI و EPS المتجهيّتيْن، كما أنّه يُسمَح باستخدامها ضمن مشاريع تجاريّة. انتبه إلى أنّ رخصة الأيقونات تطلُب وضعَ رابط إحالة إلى الموقع الأصلي. أيقونات شحن وتجارة إلكترونيّة يتضمّن سوق EpicPxls الإلكتروني موارد عاليّة الجودة. يعدّ هذا السوق مكانًا رائعًا للمصمّمين لينشروا فيه منتجاتهم المجانيّة والمدفوعة، وبالتالي بناء سمعة لأعمالهم. ألق نظرة على مجموعة الأيقونات هذه التي يقدّمها فريق EpicCoders. جاوزت المجموعة أكثر من ألفيْ تنزيل، وهي حقَّا فريدة. بنظرة خاطفة على المجموعة يمكن فهمُ مصدر فرادتها، إذ تبدو نابضة، وشبيهة بالأيقونات الكرتونيّة، لكن دون مبالغة. تناسب الحزمة كثيرًا المواقع التقليليّة (minimalist sites)، إلى جانب أي موقع تجاري يوافق مخطّط ألوان الحزمة. مجموعة أيقونات مرسومة يدويّا قد يكون صعبًا تصميمُ صفحة بعناصر مرسومة يدويّا، إلّا أنها تُضيف لمسة إبداع لكلّ موقع تُضمَّن فيه، وهو ما ينطبق بالتأكيد على هذه الأيقونات المجانيّة. تُركّز هذه الحزمة لأيقونات التجارة الإلكترونيّة بالكامل على العناصر المرسومة يدويّا. توجد جميع الرسومات التي قد تحتاج إليها بدءًا من صناديق الهدايا إلى سلّات التبضّع الصغيرة وميزات تسديد المدفوعات. يُنصَح باستخدام هذه المجموعة أثناء تصميم صفحة هبوط، وليس في واجهات المستخدم الخاصّة بتسديد المدفوعات. يمكن أن تواجه مشاكل في جعل هذه الأيقونات تمتزج طبيعيًّا في واجهات التسديد، لكن يمكنها أن تجلب الانتباه في الصفحة الرئيسيّة لموقع تجاري. حزمة بطاقات دفع لا يكتمل موقع التجارة الإلكترونيّة بدون وجود أيقونات لبطاقات الدفع. إنْ كنت تصمّم متجرًا يقبل بطاقات الدفع الإلكتروني فيجدُر بك إلقاء نظرة على هذه الأيقونات المتاحة للملك العام (رخصة CC0)، والمنشورة على موقع Dribbble. صمّم Guy Levin تسع أيقونات مختلفة لبطاقات دفع، وجمعها كلّها في ملف Illustrator واحد. الأيقونات أنيقة، سهلة التخصيص ويمكنها وضعها في أي مكان من الصفحة. أيقونات خطيّة للتجارة إلكترونيّة نشر موقع Pixlov حزمته الخاصّة من أيقونات مواقع التجارة الإلكترونيّة، وهي حزمة تعتمد على نمط الأيقونات الخطيّة. قد لا تجد أنّ 33 أيقونة عدد كبير، إلّا أنّ تصاميم عدّة توجد في هذه المجموعة للاختيار بينها. لا يُنصَح باستخدام هذه الأيقونات لصفحة تسديد المدفوعات، إذ أنّها مناسبة أكثر لصفحات الهبوط أو صفحات "ميزات المتجر". يمكن أن تناسب المجموعة كذلك النشرة البريديّة وتساعد في زيادة نسبة المبيعات. مشروع Noun للتجارة الإلكترونيّة إنْ لم تكن تعرف مشروع Noun فيجدر بك التعرّف عليه. يجمّع الموقع الكثير من حزم الأيقونات المجانيّة من أماكن مختلفة على الشبكة ومن مصمّمين كثر عبر العالم. يوجد الكثير ممّا يمكن اكتشافه، إلّا أننا في هذا المقال ننصح بمجموعة الأيقونات الخاصّة بالتجارة الإلكترونيّة التي صمّمها Anton Scherbik. هذه المجموعة من الأيقونات من أبسط أيقونات الخطوط، وتتضمّن خيّارات رائعة مثل السلّات والحقائب بأنماط مختلفة. أيقونات الدّفع والتسليم تقوم مدوّنة Codrops بعمل رائع. تنشُر المدوَّنة دوريًّا مقالات عاليّة الجودة تتضمّن موادّ مجانيّة يمكن استخدامها في مشاريعك الخاصّة. من أمثلة ذلك، هذه المجموعة من أيقونات تسديد المدفوعات التي صمّمها EpicPxls. تحوي المجموعة 35 أيقونة فريدة بتأثير حشو لن يمكنك العثور عليه في مكان آخر. تمتد ألوان الحشو دائمًا إلى الخارج قليلًا، وهو أوّل شيئ – ربما – تلاحظه. تقدّم المجموعة بلا شك لمسةً خاصّة. مجموعة أيقونات مُخصَّصة أخيرًا – وليس الأقل أهميّة – هذه المجموعة الرائعة من الأيقونات بواسطة Graphicboat. قد لا تناسب هذه المجموعة جميع الاستخدامات، إلّا أنّها يمكن أن تجذب الانتباه بسرعة وتثير فضول الناس لمعرفة المزيد عن متجرك. يمكن القول إنّ هذه الأيقونات ستتناسب أكثر مع خلفيّة ترويسة، أو في صفحة "ميزات المتجر"، أو ربما في مكان قريب من زرّ الدعوة لإجراء ( CTA). كانت تلك قائمتنا من الأيقونات المجانيّة. إنْ لم تجد ما تبحث عنه، فيمكنك استخدام محرّك بحث للعثور على خيّارات أكثر. تظهر مجموعات مجانيّة جديدة كلّ شهر، لذا يمكن أن تجد ضالتك فيها. ترجمة – بتصرّف – للمقال ‎10 Free Icon Sets for Ecommerce UI Design لصاحبه Jake Rocheleau.
  12. قال الناقد السينمائي روغر إيبر (Roger Eber): "ربّما تتشوّش قدراتك العقليّة مرّة، إلّا أنّ مشاعرك لن تكذب عليك أبدا". تنطبق المقولة السابقة على أبحاث التسويق والدّعاية. إنْ استطعت فهم ردّ الفعل الشعوريّ الحقيقيّ لشخص على مقطع فيديو، أو منتج، أو موقع ويب، أو أيّ محتوى آخر، فسيمكنك التنبّؤ على نحو أدقّ بكيفيّة تحوّل تلك المشاعر إلى أفعال. مالذي يجعل المشاعر بهذه الخصوصيّة؟ تؤكّد دراسات كثيرة على أنّ المشاعر تؤدّي دورًا حيويًّا في قدرتنا على على حفظ المشاعر وتذكّرها. المشاعر هي آليّة بقاء حسب مفهوم نظريّة التطوّر: تحمي مشاعر الخوف من المخاطر في حين تعزّز المشاعر الإيجابيّة سلوك التجرأ على الأخطار، المفيد للبقاء على قيد الحياة. كما أوضح باحثون أنّ البشر فطريًّا أكثر ميلًا إلى الأحداث أو الصوّر الشعوريّة منهم إلى الأحداث أو الصوّر المحايدة. ليس مفاجئًا، من هذا المنطلق، وجودُ اتّجاه تسويقيّ ودعائيّ يجرّب وينشئ محتوى مثيرًا شعوريّا. سواء تعلّق الأمر بالميمة (Meme) التي ألهمت إعلان Sarah McLachlan لمحاربة العنف ضدّ الحيوانات الذي اشتهر بتأثر المشاهدين به حدّ البكاء، أو إعلانات السوبر بول (Super Bowl) الهيستيريّة التي أصبحت حدثًا في ذاتها؛ فإنّ الهويّات التجاريّة التي تثير ردود أفعال شعوريّة جارفة أسهلُ تذكّرًا – بالنسبة اللمشاهدين – كثيرًا من غيرها، وفي آخر المطاف هم أكثر تجاوبًا معها. لكن، كيف يمكننا إثبات الأمر؟ وكيف يمكن – بسرعة - قيّاس التأثير الشعوريّ الذي يحدثه المحتوى؟ استخدمنا أداة Sticky لمعرفة ذلك. تسمح هذه الأداة لفرق التسويق برؤية ما يراه المستخدمون فعليًّا، وفهم ما يشعرون به. وجدنا تلازُمًا (Correlation) بين تذكّر الهويّة التجاريّة وأوج الإجابة الشعوريّة للمشاهدين. تهدف الدراسة إلى معرفة كيف تؤثّر المشاعر ووجود مشاهير في إعلانات العودة إلى المدارس على تذكّر الهويّة التجاريّة لخمس شركات كبرى وهي: Target، و Walmart، و GAP، و Old Navy (تظهر فيه الممثّلة Amy Schumer)، و Old Navy، و Staples. اتّبعنا المنهجيّة التاليّة: استهدفنا 461 مشاركًا تتراوح أعمارهم بين 25 و60 سنة، وهم آباء أو أمّهات يعدّون المنفقين الأساسيّين على عائلاتهم. أرسُلت الدراسة إلى المشاركين عبر الشبكة، وأجروها عن بعد. طُلِب من المشاركين مشاهدةُ واحد من إعلانات العودة إلى المدارس الستة التي تبلغ مدّة كلّ واحد منها 30 ثانيّة، وتتشابه من حيث قدر ظهور الهويّات التجاريّة (الشعار والحوارات). قبل المشاركون استخدام المنصّة لكاميرات أجهزتهم من أجل تتبّع حركات العين وتعابير الوجه خلال الدراسة. سُئل المشاركون ثلاثة أسئلة خلال استبيان تكميلي، بعد مشاهدة مقاطع الفيديو وهي: عن أي شركة يتحدّث الفيديو؟ ما احتمال أن تشتري منتجًا من هذه الشركة لابنك أثناء فترة العودة إلى المدارس؟ ما مدى استحسانك لهذا الفيديو؟. أظهرت النتائج التوجّهات التاليّة: وجود تلازُم بين قدرة المشاركين على تذكّر الهويّة التجاريّة في الإعلان وأوج الإجابة الشعوريّة للمشاهدين. نتج عن مقاطع الفيديو ذات الأوج الشعوريّ المتشابه نسب تذكّر متقاربة (Walmart و Target). أدّى إشراك شخصيّة مشهورة إلى إحداث دفعة لتذكّر الهويّة التجاريّة (Old Navy مقابل Staples). ليس ضروريًّا أن يثير الإعلان مشاعر إيجابيّة ليكون له تأثير على تذكّر الهويّة التجاريّة (أثار إعلان GAP "الاشمئزاز" في أوج الإجابة الشعوريّة). الأوج الشعوري (Peak emotion) هو النقطة التي عبّر عندها أغلب المشاركين عن نفس الشعور. تذكّر الهويّة التجاريّة (Brand recall) هو التذكّر غير الموجّه للهويّة التجاريّة المعروضة في الإعلان. تأثير الضحك يوجد أدناه مقطع من إعلان Staples في فترة العودة إلى المدارس، الذي يبرز أغنيّة عيد الميلاد الشهيرة "إنّها أجمل أيّام السنة" (It’s The Most Wonderful Time of the Year). يُظهر الإعلان أبًا يرقُص بفرح في ممرّات المتجر في حين يتثاقل أبناؤه خلفه، يظهر عليهم الإحباط والفتور. ليس مفاجئًا أن تكون ردّة فعل الآباء إيجابيّة على الفيديو الذي يجمع بين ما قد يشعر به الآباء من تحمّس لعودة أبنائهم للمدارس، وفتور الأطفال. يظهر الأوج الشعوري مبكّرًا في الإعلان، مع أوج شعوري قيمته 9% بعد 8 ثوان فقط، ممّا يؤثّر على مشاعر المشاهدين ويؤدّي إلى نسبة تذكّر تبلغ 91%. لاحظ في المقطع المُصوّر أعلاه كيف يتغير مركز الانتباه خلال إعلان Staple. تأثير المشاهير توجد أدناه صورة متحرّكة لإعلان Old Navy الذي تظهر فيه الممثّلة Amy Schumer. استخدم الإعلان الكوميديا للوصول إلى المشاهد، ليس هذا فقط، بل إنّ 89% من المشاهدين تتبّعوا الممثّلة خلال مقطع الفيديو. حدث ذلك كثيرًا عندما تكون الممثّلة داخل إطار الصورة، ممّا يؤكّد أن شهرتها كانت سببًا أساسيًّا للفت الانتباه البصري. تتماشى هذه الملاحظة مع التوقّع بأنّ إبراز شخصيّة مشهورة يُشعِر بالثقة والألفة تُجاه الهويّة التجاريّة، ممّا يزيد من احتمالات تذكّرها، وبالتالي نيّات الشراء. رغم أنّ إعلان Staples حقّق أوجًا شعوريًّا أعلى، إلّا أنّ حضور Amy Schumer منح إعلان Old Navy دفعة لتذكّر تمكن ملاحظتها في النتائج (96 % مقابل 91 %). كان بمقدورنا كذلك ملاحظة تأثير الشهرة بالتمعّن في إعلانيْن من Old Navy، أحدهما توجد فيه شخصيّة مشهورة، وأخرى لا توجد به. بوجود الشخصيّة المشهورة أدّى الأوج الشعوريّ الأعلى عند 7.5 % ووجود الشخصيّة إلى الوصول لنسبة تذكّر بلغت 96 %. في غيّاب الشخصيّة المشهورة، أدّى الأوج الشعوريّ الأدنى قليلًا (7 %) إلى نسبة تذكّر بلغت 86 %. يُظهرالمقطع المُصوّر أعلاه كيف يتغير مركز الانتباه خلال إعلان Old Navy بوجود الممثّلة. لقطة شاشة تظهر الانتباه البصري الأعلى (اللون الأبيض والأزرق) ضمن منطقة الانتباه. يمكننا الاستنتاج، انطلاقًا من هذه الدراسة، أنّ الجمع بين إثارة شعوريّة معتبرة، وحضور شخصيّة مشهورة يمكن أن يرفع من إمكانيّة تذكّر الهويّة التجاريّة إلى الحدّ الأقصى، وبالتالي احتمال شراء منتجاتها. وفّرت الدراسة إثباتات حيويّة على هذه المبادئ الدعاية المتعارف عليها. على الرغم من أنّ النتائج المعروضة هنا ليست ثوريّة، إلّا أنّها تذكير جيّد لكلّ مسوِّق، أو مُعلن، أو مدير تجاري أو باحث تسويق أنّه يتعامل مع كائنات بشريّة تتفاعل مع المحتوى طوال اليوم على الشاشات وفي الواقع الملموس؛ سواء تعلّق الأمر باللوحات الإعلانيّة في الشوارع، أو إعلانات إنستاغرام المُوجَّهة، أو الإعلانات التجاريّة على التلفزيون أو غيرها. لا يتذكّر الناس أشياء، وبالتالي يتجاوبون معها، إلّا إذا أثارت لديهم إجابة شعورية. ترجمة – بتصرّف – للمقال Leveraging emotions and celebrity to increase brand recall لصاحبه Joey Goldberg.
  13. يهدف هذا الدليل إلى أن يكون مصدرًا ونقطة بداية لتشخيص واستكشاف مشاكل وإعدادات MySQL للتمهيد لحلها. سنتناول بعضًا من المشاكل التي يتعرّض لها كثيرون من مستخدمي MySQL ونوفّر إرشادات لكيفية تشخيصها وحلها. سيشتمل الدليل كذلك على روابط لمقالات من أكاديميّة حسوب ومن التوثيق الرسمي للاستفادة منها. فهرس مقالات السلسلة: كيف تعرض سجلّات الأخطاء وتشخّص الاستعلامات في MySQL كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL كيف تعالج انهيّار خادوم MySQL كيف تصلح الجداول المعطوبة في MySQL كيف تشخّص أخطاء المقابس Sockets في MySQL يمكن في كثير من الأحيان التعرّف على السبب وراء بطء، أو انهيار، أو أي سلوك غير متوقّع من قاعدة قاعدة البيانات MySQL بتحليل سجلات الأخطاء. توجد هذه السجلات مبدئيًّا في المسار ‎/var/log/mysql/error.log‎، بالنسبة للخواديم التي تعمل بتوزيعة أوبونتو. يعدّ برنامج less، وهو أداة تعمل على سطر الأوامر تتيح قراءة الملفّات دون إمكانيّة تعديلها، الوسيلة الأسهل في كثير من الأحيان، لقراءة سجلات الأخطاء: $ sudo less /var/log/mysql/error.log يمكن الحصول على معلومات أكثر عن مصدر المشاكل في حال سلوك غير متوقّع من MySQL عبر تنفيذ الأمر أعلاه وتشخيص الخطأ بناءً على محتويات السجلّات. تشخيص استعلامات MySQL قد يواجه المستخدمون، فور بدئهم في تنفيذ الاستعلامات Queries، مشاكل بطء في قاعدة بيانات MySQL. يجب عند تنفيذ استعلامات في بعض من أنظمة قواعد البيانات، بما فيها MySQL، إنهاء الاستعلام بفاصلة منقوطة (;) من أجل إتمام الاستعلام؛ كما في المثال التالي : SHOW * FROM table_name; إن لم تضف فاصلة منقوطة في نهاية الاستعلام، فإن سطر الأوامر سيستمر في الانتقال إلى سطر جديد ما لم تكتب الفاصلة المنقوطة وتضغط بعدها على زر الإدخال Enter. قد يجد بعضٌ من المستخدمين أن استعلاماتهم بطيئة إلى حد بعيد. يعدّ تمكين سجلّ الاستعلامات البطيئة في MySQL ومراجعته. إحدى الطرق الناجعة لمعرفة سبب البطء. لفعل ذلك، افتح الملف mysqld.cnf الذي يُستخدَم لضبط خيارات خادوم MySQL. يوجد هذا الملف عادةً في المسار ‎/etc/mysql/mysql.conf.d/‎ : sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf تَنقّل في الملف إلى أن تبلغ الأسطر التالية : . . . #slow_query_log = 1 #slow_query_log_file = /var/log/mysql/mysql-slow.log #long_query_time = 2 #log-queries-not-using-indexes . . . تضبُط التوجيهات المُعلّقة أعلاه (توجد علامة # قبلها) خيّارات الإعداد المبدئيّة لسجلّ الاستعلامات البطيئة. في ما يلي شرحٌ لعمل كلّ منها : slow-query-log: إعطاء القيمة 1 لهذا التوجيه يفعّل سجلّ الاستعلامات البطيئة. Slow-query-log-file: يعرّف الملفّ الذي سيسجّل فيه MySQL الاستعلامات البطيئة. يشير التوجيه في المثال أعلاه إلى الملف ‎/var/log/mysql-slow.log. long_query_time : يؤدي إعطاء القيمة 2 لهذا التوجيه إلى ضبط MySQL لتسجيل جميع الاستعلامات التي تتجاوز مدة تنفيذها الثانيتين. log_queries_not_using_indexes : يخبر MySQL أن يسجّل أي استعلام لا يستخدم فهارس Indexes ضمن الملف ‎/var/log/mysql-slow.log. ليس مفروضًا استخدامُ هذا الإعداد لكي يعمل سجل الاستعلامات البطيئة إلا أنه مفيد جدًّا في التعرّف على الاستعلامات غير الفعّالة. انزع تعليق الأسطُر بحذف علامة # من أوّلها. سيبدو المقطع أعلاه على النحو التالي بعد نزع التعليقات: . . . slow_query_log = 1 slow_query_log_file = /var/log/mysql-slow.log long_query_time = 2 log_queries_not_using_indexes . . . ملحوظة: إن كنت تسخدم الإصدار 8 وما تلاه من MySQL، فلن يحتوي الملف mysqld.cnf مبدئيًّا على الأسطُر المعلّقة التي تحدّثنا عنها آنفًا، لذا أضف توجيهات الإعداد أسفل الملف على النحو التالي : . . . slow_query_log = 1 slow_query_log_file = /var/log/mysql-slow.log long_query_time = 2 log_queries_not_using_indexes احفظ الملف بعد تمكين سجلّ الاستعلامات البطيئة ثم أغلقه. أعد تشغيل خدمة MySQL كما يلي : sudo systemctl restart mysql سيمكن بعد هذه الإعدادات العثور على الاستعلامات التي تسبّب مشاكل بطء الخادوم. استخدم الأمر less لعرض الملف كما يلي : sudo less /var/log/mysql_slow.log الخطوة التالية بعد فرز الاستعلامات البطيئة هي البحث عن طريقة لتحسينها؛ مقال كيف تحسّن الاستعلامات والجداول في MySQL و MariaDB مفيد لهذا الغرض. علاوة على ذلك؛ يتضمّن MySQL التعليمة EXPLAIN التي توفّر معلومات عن كيفيّة تنفيذ MySQL للاستعلامات. تقدّم هذه الصفحة من التوثيق الرسمي لـ MySQL أفكارًا حول كيفيّة استخدام EXPLAIN لتسليط الضوء على الاستعلامات غير الفعّالة. راجع المقال أساسيّات لغة SQL من أجل التعرّف على البنية الأساسيّة لتعليمات MySQL. ترجمة – بتصرّف – للمقالين How to Access MySQL Error Logs و How To Troubleshoot MySQL Queries لصاحبهما Mark Drake. اقرأ أيضًا المقال التالي: كيف تسمح بالاتّصال عن بعد بقاعدة بيانات MySQL
  14. مقدّمة نظرية كائن جافاسكريبت هو كيان لديه خاصيّات. كلّ خاصيّة عبارة عن زوج مفتاح وقيمة. المفتاح هو اسم الخاصيّة. يمكن أن تكون قيمة الخاصيّة بيانات (عددا، سلسلة محارف، …إلخ.) أو دالة. يُطلَق على الخاصيّة عندما تكون قيمتها دالة الاسم تابع Method. يُنشَأ كائن حرفي Object literal في جافاسكريبت بتحديد خاصيّاته ضمن زوج من الأقواس المعكوفة. const myObject = { property1: value1, property2: value2, // ... , method1(/* ... */) { // ... }, method2(/* ... */) { // ... } // ... }; myObject.property1 = newValue; // يعيّن القيمة الجديدة للخاصيّة property1 في الكائن myObject console.log(myObject.property1); // يعرض قيمة الخاصيّة property1 في الكائن myObject myObject.method1(...); // استدعاء التابع method1 في myObject تمثّل الكلمة المفتاحية this في تابع الكائن الذي يُستدعَى فيه التابع. تعرّف لغة البرمجة سلفا كائنات عدّة للاستفادة منها مثل console و Math. مقدّمة ما هو الكائن؟ انظر إلى الكائنات في معناها غير البرمجي، مثل قلم. يمكن أن يكون للقلم ألوان عدّة، يصنعه أشخاص متعدّدون، أطراف متنوّعة وخاصيّات أخرى كثيرة. على نحو مشابه، الكائن في البرمجة هو كيان لديه خاصيّات. تعرّف كل خاصيّة ميزة في الكائن. يمكن أن تكون الخاصيّة بيانات مرتبطة بالكائن (لون القلم) أو إجراء (قدرة القلم على الكتابة). ما علاقة هذا بالشفرة؟ البرمجة كائنية التوجّه Object-oriented programming (أو OOP اختصارا) هي طريقة لكتابة البرامج باستخدام الكائنات. يكتُب المبرمج - عند اتّباع هذه الطريقة - الكائنات، ينشئها ويعدّل عليها؛ تشكلّ الكائنات البرنامج. ** تغيّر البرمجة كائنية التوجّه الطريقة التي تُكتَب وتُنظَّم بها البرامج. كتبنا في الفصول السابقة برامج تعتمد على الدوالّ، وهي طريقة برمجيّة تُسمَّى البرمجة الإجرائية Procedural programming. فلنكتشف الآن كيف نكتب شفرة كائنية التوجّه. جافاسكريبت والكائنات تدعم جافاسكريبت، مثل لغات برمجة أخرى، البرمجة بالكائنات. كما توفّر كائنات معرَّفة مسبقا مع إتاحة الفرصة لإنشاء كائنات جديدة. إنشاء كائن في ما يلي تمثيل جافاسكريبت لقلم حبر جاف أزرق اللون علامته التجارية Bic. const pen = { type: "حبر جاف", color: "أزرق", brand: "Bic" }; يمكن إنشاء كائنات جافاسكريبت، كما ذكرنا سابقا، بسهولة بتعيين خاصيّات الكائن ضمن زوج أقواس معكوفة {...}. كلّ خاصيّة هي زوج من المفاتيح والقيم. يُسمَّى الكائن المعرَّف سابقا بالكائن الحَرْفي Object literal. ملحوظة: النقطة الفاصلة ; بعد زوج الأقواس اختيارية، إلا أنه من الآمن إضافتها على كلّ حال. تعرِّف الشفرةُ أعلاه متغيّرا يُسمَّى pen قيمته كائن، يمكننا القول إذن إن pen كائن. لهذا الكائن ثلاث خاصيّات هي: type (النوع)، color (اللون) وbrand (العلامة التجارية). لكلّ خاصيّة اسمٌ وقيمة، كما أنها متبوعة بفاصلة لاتينية , (ما عدا الخاصيّة الأخيرة) الوصول إلى خاصيّات الكائن يمكن الوصول إلى قيم الخاصيّات بعد إنشاء الكائن بالتنويت النقطي Dot notation مثل myObject.myProperty. const pen = { type: "حبر جاف", color: "أزرق", brand: "Bic" }; console.log(pen.type); // "حبر جاف" console.log(pen.color); // "أزرق" console.log(pen.brand); // "Bic" الوصول إلى خاصيّة كائن هو عبارة Expression تنتج قيمة. يمكن تضمين هذه العبارة في عبارات أكثر تعقيدا. يوضّح المثال التالي كيفية عرض خاصيّات القلم السابق في تعليمة واحدة: const pen = { type: "حبر جاف", color: "أزرق", brand: "Bic" }; console.log(`أكتب بقلم ${pen.type} لونه ${pen.color} وعلامته التجارية ${pen.brand}`); التعديل على كائن يمكن تعديل قيم الخاصيّات في كائن بعد إنشائه بالصيغة myObject.myProperty = newValue. const pen = { type: "حبر جاف", color: "أزرق", brand: "Bic" }; pen.color = "أحمر"; // تغيير لون القلم console.log(`أكتب بقلم ${pen.type} لونه ${pen.color} وعلامته التجارية ${pen.brand}`); توفّر جافاسكريبت إمكانية الإضافة الديناميكية لخاصيّات جديدة لكائن أنشأته قبْلا: const pen = { type: "حبر جاف", color: "أزرق", brand: "Bic" }; pen.price = "2.5"; // تعيين خاصية لسعر القلم console.log(`يبلغ سعر قلمي ${pen.price}`); البرمجة بالكائنات تعلّم الكثير من الكتب والدورات البرمجة كائنية التوجّه عبر أمثلة عن الحيوانات، السيّارات أو الحسابات المصرفية. فلنجرّب أمرا ألطف ولننشئ لعبة تقمّص أدوار Role playing game مصغَّرة باستخدام الكائنات. تُعرَّف كلّ شخصية في ألعاب تقمّص اﻷدوار بصفات مميَّزة عدّة مثل القوّة، القدرة على التحمّل والذكاء. في ما يلي لقطة شاشة للعبة تقمّص أدوار شهيرة على الإنترنت. سيكون للشخصيّات - في مثالنا الأبسط كثيرا - ثلاثُ صفات مميّزة: الاسم Name، الصّحة Health (عدد نقاط الحياة)، القوة Strength. مثال ساذج فلنقدّم أورورا، الشخصيّة الأولى في لعبتنا لتقمّص الأدوار: const aurora = { name: "أورورا", health: 150, strength: 25 }; للكائن aurora ثلاث خاصيّات: health، name وstrength. ملاحظة: يمكن - كما ترى في المثال أعلاه - إسناد أعداد، سلاسل محارف وحتى كائنات أخرى إلى خاصيّات الكائنات. تستعدّ أورورا للبدء في سلسلة من المغامرات العظيمة التي ستحدّث بعض منها خاصيّات الشخصيّة. تأمل المثال التالي: const aurora = { name: "أورورا", health: 150, strength: 25 }; console.log(`يوجد لدى ${aurora.name} نقاط قوة قدرها ${aurora.health} وقوة تبلغ ${aurora.strength}`); // أصاب سهم أورورا وبالتالي تقل نقاط الحياة aurora.health -= 20; // تتجهّز أورورا بقلادة قوة aurora.strength += 10; console.log(`يوجد لدى ${aurora.name} نقاط قوة قدرها ${aurora.health} وقوة تبلغ ${aurora.strength}`); التعريف بالتوابع احتجنا في الأمثلة السابقة إلى كتابة تعليمات console.log طويلة في كلّ مرة نريد عرض حالة الشخصية. توجد طريقة أنسب للوصول إلى هذا الغرض. إضافة تابع لكائن تأمل المثال التالي: const aurora = { name: "أورورا", health: 150, strength: 25 }; // ترجع وصف الشخصية function describe(character) { return `يوجد لدى ${character.name} نقاط صحة قدرها ${character.health} وقوة تبلغ ${character.strength}`; } console.log(describe(aurora)); معامل الدالة describe() هو كائن. تصل الدالة إلى خاصيّات الكائن وتنشئ سلسلة المحارف التي تصف الشخصية. أدناه مقاربة بديلة تستخدم الدالة describe() داخل الكائن. const aurora = { name: "أورورا", health: 150, strength: 25, // ترجع وصف الشخصية function describe(character) { return `يوجد لدى ${character.name} نقاط صحة قدرها ${character.health} وقوة تبلغ ${character.strength}`; } }; console.log(aurora.describe()); يتوفّر الكائن الآن على خاصيّة جديدة: describe(). قيمة هذه الخاصيّة دالة تُرجِع وصفا نصيًّا للكائن. نتيجة التنفيذ مطابقة تماما لما سبق. تُسمّى خاصيّة كائن عندما تكون قيمتها دالة بالتابع. تُستخدَم التوابع لتعريف إجراءات على كائن. يضيف التابع سلوكا إلى الكائن. استدعاء تابع في كائن فلنتأمل السطر الأخير من المثال السابق: console.log(aurora.describe()); نستخدم العبارة aurora.describe() لعرض وصف الشخصية بدلا من describe(aurora)، وهنا فرق جوهري. تستدعي العبارة describe(aurora) الدالة describe() مع تمرير الكائن aurora في المعطيات. الدالة خارجة عن الكائن. هذا مثال على البرمجة الإجرائية. تستدعي العبارة aurora.describe() الدالة describe() في الكائن aurora. الدالة خاصيّة من خاصيّات الكائن: تابع. هذا مثال على البرمجة كائنية التوجه. صيغة استدعاء التابع myMethod() في myObject هي myObject.myMethod(). تنبيه: تذكّر الأقواس، حتى وإن كانت خاوية، عند استدعاء تابع. الكلمة المفتاحية this تأمل جيّدا متن التابع describe() في المثال التالي: const aurora = { name: "أورورا", health: 150, strength: 25, // ترجع وصف الشخصية describe() { return `يوجد لدى ${this.name} نقاط صحة قدرها ${this.health} وقوة تبلغ ${this.strength}`; } }; سترى كلمة مفتاحية جديدة: this. تُعيَّن هذه الكلمة المفتاحية تلقائيا داخل تابع في جافاسكريبت وتمثّل الكائن الذي استُدعِي فيه التابع. لا يستقبل التابع describe() أي معاملات. يستخدم التابع this للوصول إلى خاصيّات الكائن الذي استُدعِي فيه. الكائنات المعرَّفة مسبقا في جافاسكريبت تتوفّر جافاسكريبت على كائنات عدّة معرَّفة مسبقا تخدم أغراضا متفرّقة. رأينا في ما مضى بعضا منها: يمنح الكائن console الوصول إلى بيئة الطرفية. التعليمة console.log() هي في الواقع استدعاء لتابع. يحوي الكائن Math خاصيّات رياضية كثيرة. على سبيل المثال، تُرجع الخاصيّة Math.PI قيمة تقريبية للعدد π، ويرجع التابع Math.random() عددا عشوائيا بين 0 و1. حان وقت كتابة الشفرة! إضافة تجربة الشخصية حسّن برنامج لعبة تقمّص الأدوار بإضافة خاصيّة التجربة؛ على أن يكون اسمها xp وقيمتها الابتدائية 0. يجب أن تظهر التجربة ضمن وصف الشخصية. // للإنجاز: إنشاء الكائن character هنا. // أصاب سهم أورورا وبالتالي تقل نقاط الحياة aurora.health -= 20; // تتجهّز أورورا بقلادة قوة aurora.strength += 10; // تعلّمت أورورا مهارة جديدة aurora.xp += 15; console.log(aurora.describe()); نمذجة Modeling كلب أكمل البرنامج التالي لإضافة تعريف بالكائن dog (كلب). // للإنجاز: أنشئ الكائن dog هنا console.log(`${dog.name} كلب نوعه ${dog.species} يبلغ طوله ${dog.size}`); console.log(`انظر هرّة! ${dog.name} ينبح: ${dog.bark()}`); نمذجة دائرة أكمل البرنامج التالي لإضافة تعريف الكائن circle (دائرة). يُدخل الزائر قيمة شعاع الدائرة const r = Number(prompt("أدخل قيمة شعاع الدائرة:")); // للإنجاز: أنشئ تعريف الدائرة هنا console.log(`يبلغ محيط الدائرة ${circle.circumference()}`); console.log(`تبلغ مساحة الدائرة ${circle.area()}`); نمذجة حساب مصرفي أنشئ برنامجا ينشئ كائن account يمثّل حسابا مصرفيا لديه الميزات التالية: خاصيّة name قيمتها “أحمد”. خاصيّة balance قيمتها 0. تابع credit تضيف القيمة (سالبة أو موجبة) المُمرَّرة في المعطى إلى رصيد الحساب balance. تابع describe يُرجع وصف الحساب. استخدم هذا الكائن لعرض وصف حساب مصرفي، أضف 250 إلى رصيده، اسحب منه 80 ثم اعرض وصفه مرة أخرى. تحصُل على الآتي عند عرض وصف البرنامج في المرة الأولى: “المالك: أحمد، الرصيد: 0” وعلى ما يلي في المرة الثانية: “المالك: أحمد، الرصيد: 170” ترجمة - بتصرّف - للفصل Create your first objects من كتاب The JS Way.
  15. لغة C# هي لغة برمجة أنيقة، كائنيّة التوجه Object-oriented بأنواع بيانات سليمة Type-safe تمكّن المطورين من بناء تطبيقات آمنة ومتينة تعمل على إطار العمل NET. // تبدأ التعليقات وحيدة السطر بشريطين مائلين هكذا // /* توضع التعليقات متعدّدة الأسطر بين العلامة أعلاه والعلامة أسفله */ هذا تعليق xml يُستخدَم لتوليد توثيق خارجي أو لتقديم مساعدة حسب السياق في بيئة تطوير مندمجة IDE. /// <param name="firstParam"> لتوثيق الدالة Parameter الذي هو معامل firstParam هذا تعليق</param> /// <returns>معلومات عن القيمة المُرجَعة للدالة/returns> //public void MethodOrClassOrOtherWithParsableHelp(string firstParam) {} يحدّد فضاءات اﻷسماء Namespaces التي ستستخدمها هذه الشفرة فضاءات الأسماء أدناه هي كلّها جزء من مكتبة الأصناف Classes المعيارية في إطار العمل NET. Framework Class Library using System; using System.Collections.Generic; using System.Dynamic; using System.Linq; using System.Net; using System.Threading.Tasks; using System.IO; فضاء الأسماء هذا ليس مُتضمّنا في المكتبة المعيارية: using System.Data.Entity; لكي تتمكّن من استخدام المكتبة أعلاه فستحتاج لإضافة مرجع إلى ملف dll وهو ما يمكن لمدير الحزم NuGet فعلُه: Install-Package EntityFramework تعرّف فضاءات الأسماء مجالات لتنظيم الشفرات ضمن حزم Packages أو وِحْدات Modules لاستخدام فضاء الأسماء المُعرّف أدناه في شفرة أخرى نضيف العبارة Learning.CSharp إلى فضاءات الأسماء المستخدمة namespace Learning.CSharp { يجب أن يحوي كل ملف cs. على الأقل على صنف Class له نفس اسم الملف. يمكنك لك عدم التقيّد بهذا الشرط، إلا أنه أفضل لصحة الشفرة المصدرية public class LearnCSharp { صياغة أساسية: يمكنك التجاوز إلى “ميزات مثيرة للاهتمام” إن سبق لك كتابة شفرات بجافا أو سي++ public static void Syntax() { // للكتابة في سطر جديد Console.WriteLine استخدم Console.WriteLine("Hello World"); Console.WriteLine( "Integer: " + 10 + " Double: " + 3.14 + " Boolean: " + true); // لكتابة عبارات على نفس السطر Console.Write استخدم Console.Write("Hello "); Console.Write("World"); أنواع البيانات Types والمتغيّرات Variables عرّف المتغيّرات على النحو التالي <type> <name> Sbyte - عدد صحيح (سالب أو موجب) على 8 بتات (محصور بين 128- و127) sbyte fooSbyte = 100; Byte - عدد طبيعي (موجب فقط) على 8 بتات (محصور بين 0 و255) byte fooByte = 100; Short - عدد صحيح أو طبيعي طوله 16 بتات صحيح short محصور بين -32,768 و32,767 طبيعي ushort محصور بين 0 و65,535 short fooShort = 10000; ushort fooUshort = 10000; عدد صحيح fooInt أو طبيعي fooUint طوله 32 بت int fooInt = 1; // (-2,147,483,648 <= int <= 2,147,483,647) uint fooUint = 1; // (0 <= uint <= 4,294,967,295) Long عدد صحيح fooLong أو طبيعي fooUlong طوله 64 بت long fooLong = 100000L; // (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807) ulong fooUlong = 100000L; // (0 <= ulong <= 18,446,744,073,709,551,615) النوع المبدئي default للأعداد هو int أو uint حسب طول العدد. والحرف L وراء العدد يشير إلى أن نوع العدد هو long أو ulong Double - فاصلة عائمة مزدوجة الدقة حسب المعيار 64-bit IEEE 754 double fooDouble = 123.4; // الدقة: 15-16 رقما Float - فاصلة عائمة وحيدة الدقة 32-bit IEEE 754 Floating Point float fooFloat = 234.5f; // الدقة: 7 أرقام يشير الحرف f وراء العدد إلى أن نوع العدد هو Float Decimal - نوع بيانات بطول 128 بت، ودقّة أعلى من بقية أنواع البيانات ذات الفاصلة العائمة مناسب للحسابات المالية والنقدية decimal fooDecimal = 150.3m; // Boolean - true & false bool fooBoolean = true; // or false Char - نوع بيانات بطول 16 بت يرمز لمحرف يونيكود `char fooChar = 'A'; Strings – على النقيض من جميع أنواع البيانات السابقة التي هي أنواع لقيم البيانات فإن النوع String - سلسلة محارف - هو نوع لمرجع Reference بمعنى أنه يمكنه أخذ القيمة null string fooString = "\"escape\" quotes and add \n (new lines) and \t (tabs)"; Console.WriteLine(fooString); يمكن الوصول إلى كل محرف من سلسلة المحارف عن طريق ترتيبه في السلسلة char charFromString = fooString[1]; // => 'e' لا يمكن التعديل على سلاسل المحارف؛ التعليمة fooString[1] = X خاطئة مقارنة سلاسل محارف مع قيمة الخاصيّة CurrentCulture المعرّفة في المكتبة المعيارية لتمثيل اللغة المستخدمة في النظام، مع تجاهل حالة الأحرف IgnoreCase string.Compare(fooString, "x", StringComparison.CurrentCultureIgnoreCase); تهيئة سلسلة المحارف اعتمادا على sprintf string fooFs = string.Format("Check Check, {0} {1}, {0} {1:0.0}", 1, 2); التاريخ والتهيئة DateTime fooDate = DateTime.Now; Console.WriteLine(fooDate.ToString("hh:mm, dd MMM yyyy")); سلاسل المحارف الأصلية Verbatim String يمكنك استخدام العلامة @ أمام سلسلة محارف لتخليص جميع المحارف الموجودة في السلسلة string path = "C:\\Users\\User\\Desktop"; string verbatimPath = @"C:\Users\User\Desktop"; Console.WriteLine(path == verbatimPath); // => true يمكنك توزيع سلسلة محارف على أكثر من سطر بالرمز @ لتخليص العلامة " ضع مكانها "" (" مرتين) string bazString = @"Here's some stuff on a new line! ""Wow!"", the masses cried"; استخدم الكلمة المفتاحية const لجعل المتغيّر ثابتًا غير قابل للتعديل وتُحسب القيم الثابتة أثناء تصريف البرنامج compile time const int HoursWorkPerWeek = 9001; بنى البيانات المصفوفات - يبدأ العنصر الأول عند الترتيب 0 ويجب تحديد قياس المصفوفة عند تعريفها صيغة تعريف المصفوفة هي كالتالي: ;<datatype>[] <var name> = new <datatype>[<array size>] المصفوفة intArray في المثال التالي تحوي 10 أعداد int[] intArray = new int[10]; طريقة أخرى لتعريف مصفوفة وتهيئتها int[] y = { 9000, 1000, 1337 }; ترتيب عناصر المصفوفة - الوصول إلى عنصر Console.WriteLine("intArray @ 0: " + intArray[0]); المصفوفات قابلة للتعديل. intArray[1] = 1; القوائم تُستخدَم القوائم أكثر من المصفوفات لما توفّره من مرونة وصيغة تعريف قائمة هي على النحو التالي: ;List<datatype> <var name> = new List<datatype>() List<int> intList = new List<int>(); List<string> stringList = new List<string>(); List<int> z = new List<int> { 9000, 1000, 1337 }; // تحديد القيم الابتدائية لعناصر القائمة تُستخدَم الإشارتان <> للأنواع العميمة Generics - راجع فقرة ميزات رائعة ليست للقوائم قيم مبدئية ويجب أولا إضافة قيمة قبل إمكانية الوصول إلى العنصر intList.Add(1); Console.WriteLine("intList @ 0: " + intList[0]); بنى تحتية أخرى يجدر بك مراجعتها: قوائم الانتظار Queues/ الرصوص Stacks القواميس Dictionaries HashSet تجميعاـ القراءة فقط Read-only collections الأزواج المُرتّبة Tuples (الإصدار 4 من .NET. فما فوق) العوامل Console.WriteLine("\n→Operators"); int i1 = 1, i2 = 2; // اختصار لتعريف متغيّرات عدة في آن واحد العمليات الحسابية واضحة Console.WriteLine(i1 + i2 - i1 * 3 / 7); // => 3 المقياس Modulo Console.WriteLine("11%3 = " + (11 % 3)); // => 2 عوامل المقارنة Console.WriteLine("3 == 2? " + (3 == 2)); // => false Console.WriteLine("3 != 2? " + (3 != 2)); // => true Console.WriteLine("3 > 2? " + (3 > 2)); // => true Console.WriteLine("3 < 2? " + (3 < 2)); // => false Console.WriteLine("2 <= 2? " + (2 <= 2)); // => true Console.WriteLine("2 >= 2? " + (2 >= 2)); // => true عوامل المقارنة البتّية Bitwise ~ عامل التكملة الأحادي (إن كان البت يحوي 0 يحوله إلى 1، وإن كان يحوي واحد يحوّله إلى صفر) >> إزاحة البتات إلى اليسار << إزاحة البتات إلى اليمين & عامل “و” المنطقي ^ عامل “أو” المنطقي غير الشامل exclusive OR | عامل “أو” المنطقي الشامل inclusive OR التزايد Incrementation int i = 0; Console.WriteLine("\n->Inc/Dec-rementation"); Console.WriteLine(i++); //Prints "0", i = 1. تزاد بعدي Console.WriteLine(++i); //Prints "2", i = 2. تزايد قبلي Console.WriteLine(i--); //Prints "2", i = 1. تناقص بعدي Console.WriteLine(--i); //Prints "0", i = 0. تناقص قبلي بنى التحكّم Console.WriteLine("\n->Control Structures"); تتبع بنية التحكم if else طريقة كتابة بنى التحكم في C int j = 10; if (j == 10) { Console.WriteLine("I get printed"); } else if (j > 10) { Console.WriteLine("I don't"); } else { Console.WriteLine("I also don't"); } العوامل الثلاثية بنية تحكّم if else بسيطة تمكن كتابتها على النحو التالي: <condition> ? <true> : <false> int toCompare = 17; string isTrue = toCompare == 17 ? "True" : "False"; حلقة While التكرارية int fooWhile = 0; while (fooWhile < 100) { //تتكرّر الحلقة مئة مرة، من القيمة 0 إلى القيمة 99 fooWhile++; } حلقة Do.. While التكرارية int fooDoWhile = 0; do { الحلقة معدّة للتكرار مئة مرة، من القيمة 0 إلى القيمة 99 Start iteration 100 times, fooDoWhile 0->99 if (false) continue; // تجاوز التكريرة الحالية fooDoWhile++; if (fooDoWhile == 50) break; // توقيف الحلقة تماما، والخروج منها } while (fooDoWhile < 100); حلقة for التكرارية ذات الصيغة: (<for(<start_statement>; <conditional>; <step for (int fooFor = 0; fooFor < 10; fooFor++) { // تتكرّر الحلقة عشر مرات، من القيمة 0 إلى القيمة 9 } حلقة For Each يمكن استخدام حلقة التكرار foreach للمرور عبر أي كائن Object يُنفّذ الصنف IEnumerable أو <IEnumerable<T تنفّذ جميع الأنواع التجميعية (المصفوفات، القوائم، القواميس…) في إطار العمل .Net واجهة أو أكثر من الأصناف المذكورة (يمكن حذف ()ToCharArray من التعليمة أدناه، لأن String تنفّذ الواجهة IEnumerable) foreach (char character in "Hello World".ToCharArray()) { // تمرّ على جميع المحارف في السلسلة } تعليمة Switch تعمل Switch مع أنواع البيانات byte, short, char, وint تعمل كذلك مع أنواع البيانات Enum (نتعرّض لها أدناه)، الصنف String وبضعة أصناف خاصّة تغلّف أنواع بيانات أساسية: Character,Byte,Short, و Integer. int month = 3; string monthString; switch (month) { case 1: monthString = "January"; break; case 2: monthString = "February"; break; case 3: monthString = "March"; break; يمكن تنفيذ أكثر من إجراء في كل حالة case، إلا أنه لا يمكن إضافة إجراء ضمن حالة دون إضافة تعليمة توقيف break; قبل الحالة الموالية (إن أردت فعل هذا الأمر، فستحتاج لإضافة تعليمة goto case x بعد الإجراء) case 6: case 7: case 8: monthString = "Summer time!!"; break; default: monthString = "Some other month"; break; } التحويل بين أنواع البيانات وجبْر الأنواع Typecasting تحويل البيانات تحويل سلسلة محارف String إلى عدد Integer سيظهر استثناء Exception في حالة إخفاق عملية التحويل int.Parse("123");// نحصُل على النسخة العددية من سلسلة المحارف "123" عند استخدام الدالة TryParse لتحويل نوع البيانات فإن قيمة التحويل ستكون القيمة المبدئية لنوع البيانات وفي حالة الأعداد فإن القيمة المبدئية هي 0 int tryInt; if (int.TryParse("123", out tryInt)) // ترجع الدالة قيمة منطقية Console.WriteLine(tryInt); // 123 تحويل الأعداد إلى سلاسل محارف String يتضمّن الصنف Convert عددا من التوابع Methods لتسهيل التحويل Convert.ToString(123); أو tryInt.ToString(); جبر أنواع البيانات جبر العدد العشري 15 للحصول على قيمة من النوع int ثم جبر القيمة المُتحصَّل عليها ضمنيا لنحصُل على النوع long long x = (int) 15M; } الأصناف راجع التعريفات في آخر الملف public static void Classes() { انظر تعريف الكائنات في آخر الملف استخدم الكلمة المفتاحية new لاستهلال صنف Bicycle trek = new Bicycle(); استدعاء توابع الكائن trek.SpeedUp(3); // يجب دائما المرور عبر المعدّلات والمسترجعات Setter and getter methods trek.Cadence = 100; يُستخدم التابع ToString لعرض قيمة الكائن Console.WriteLine("trek info: " + trek.ToString()); استهلال كائن جديد من الصنف PennyFarthing PennyFarthing funbike = new PennyFarthing(1, 10); Console.WriteLine("funbike info: " + funbike.ToString()); Console.Read(); } // نهاية التابع الرئيس Main method مَدخل الكونسول Console entry. التطبيقات التي تعمل عبر الطرفية يجب أن يكون لديها مدخل عبارة عن تابع رئيس public static void Main(string[] args) { OtherInterestingFeatures(); } ميزات مثيرة للاهتمام التوقيعات المبدئية للتوابع public // مجال الرؤية static // يسمح بالاستدعاء المباشر من الصنف دون المرور بكائنات int // نوع البيانات المُرجَعة, MethodSignatures( int maxCount, // المتغيّر الأول عددي int count = 0, // القيمة المبدئية هي 0، تُستخدَم إن لم يُمرَّر متغير إلى التابع int another = 3, params string[] otherParams // يستقبل بقية المتغيّرات المُمررة إلى التابع جميعا ) { return -1; } يمكن أن تكون أسماء التوابع متطابقة، ما دامت التوقيعات مختلفة وكل تابع لا يختلف عن آخر سوى في نوع البيانات المُرجَع ليس وحيدا public static void MethodSignatures( ref int maxCount, // تمرير المعاملات حسب المرجع، وليس القيمة out int count) { المعامل المُمرر في المتغيّر count سيحوي القيمة 15 خارج هذه الدالة count = 15; // معامل الخروج out يجب أن يُسنَد قبل الانتهاء من التابع } أنواع البيانات العميمة Generics الأصناف TKey وTValue يحدّدها المستخدم الذي يستدعي هذه الدالة ويحاكي هذا التابع عمل SetDefault في بايثون public static TValue SetDefault<TKey, TValue>( IDictionary<TKey, TValue> dictionary, TKey key, TValue defaultItem) { TValue result; if (!dictionary.TryGetValue(key, out result)) return dictionary[key] = defaultItem; return result; } يمكنك تقييد الكائنات التي يمكن تمريرها إلى الدالة public static void IterateAndPrint<T>(T toPrint) where T: IEnumerable<int> { بما أن الصنف T ينفّذ IEnumerable فإنه يمكننا المرور على عناصره باستخدام foreach foreach (var item in toPrint) // العنصر هو من النوع int Console.WriteLine(item.ToString()); } الكلمة المفتاحية “yield” يدلّ استخدام yield أن التابع الذي تظهر فيه هذه الكلمة المفتاحية لديه خاصيّة التكرار (أي أنه يمكن استخدام التابع مع الحلقة foreach) public static IEnumerable<int> YieldCounter(int limit = 10) { for (var i = 0; i < limit; i++) yield return i; } نستطيع استدعاء التابع أعلاه على النحو التالي public static void PrintYieldCounterToConsole() { foreach (var counter in YieldCounter()) Console.WriteLine(counter); } يمكن استخدام yield return أكثر من مرّة في نفس التابع public static IEnumerable<int> ManyYieldCounter() { yield return 0; yield return 1; yield return 2; yield return 3; } كما يمكنك استخدام “yield break” لتوقيف التكرار التابع التالي يُرجِع نصف القيم الموجودة بين 0 وlimit public static IEnumerable<int> YieldCounterWithBreak(int limit = 10) { for (var i = 0; i < limit; i++) { if (i > limit/2) yield break; yield return i; } } public static void OtherInterestingFeatures() { المعاملات الاختيارية MethodSignatures(3, 1, 3, "Some", "Extra", "Strings"); MethodSignatures(3, another: 3); // تعيين قيمة المعامل مباشرة، مع تجاوز المعاملات الاختيارية تمرير المعاملات بالمرجع By reference، والقيمة المُرجعة Out parameter BY REF AND OUT PARAMETERS int maxCount = 0, count; // المعاملات المُمررة بالمرجع يجب أن تحوي قيمة MethodSignatures(ref maxCount, out count); توابع التمديد Extension methods int i = 3; i.Print(); // مُعرَّفة أدناه الأنواع التي تقبل قيمة فارغة Nullable types، مناسبة للتخاطب مع قواعد البيانات والقيم المُرجَعة وأي نوع بيانات قيمي (أي ليس صنفا) يمكن جعله يقبل قيما فارغة بكتابة ? بعده <type>? <var name> = <value> int? nullable = null; // اختصار لـ Nullable<int> Console.WriteLine("Nullable variable: " + nullable); bool hasValue = nullable.HasValue; // قيمة منطقية صحيحة true إن لم يكن يساوي null علامتا الاستفهام المتلاصقتان ?? هما اختصار لتحدد قيمة مبدئية في حال كان المتغيّر فارغا نعطيه 0 قيمة مبدئية int notNullable = nullable ?? 0; // 0 ?. هذه العلامة عي عامل للتحقّق من القيمة الفارغة null nullable?.Print(); // استخدم تابع التمديد Print() إذا كان المتغيّر nullable مختلفا عن null المتغيّرات ضمنية النوع - يمكنك ترك المُصرّف Compiler يحدّد نوع المتغيّر: var magic = "magic is a string, at compile time, so you still get type safety"; ;magic = 9 لن تُسنَد القيمة 9 إلى المتغيّر magic لأنه يحوي سلسلة محارف الأنواع العميمة var phonebook = new Dictionary<string, string>() { {"Sarah", "212 555 5555"} // إضافة عنوان إلى دفتر العناوين }; استدعاء الدالة SetDefault المُعرَّفة أعلاه Console.WriteLine(SetDefault<string,string>(phonebook, "Shaun", "No Phone")); // No Phone يمكنك عدم تحديد TKey و TValue بما أنه يمكن استنتاجهما تلقائيا Console.WriteLine(SetDefault(phonebook, "Sarah", "No Phone")); // 212 555 5555 الدوال مجهولة الاسم Lambda expressions - تتيح كتابة شفرات على نفس السطر Func<int, int> square = (x) => x * x; // آخر عنصر من T هو القيمة المُرجعة Console.WriteLine(square(3)); // 9 التعامل مع الأخطاء try { var funBike = PennyFarthing.CreateWithGears(6); لن تُنفَّذ لأن CreateWithGears تتسبّب في استثناء Exception string some = ""; if (true) some = null; some.ToLower(); // تتسبّب في الاستثناء NullReferenceException } catch (NotSupportedException) { Console.WriteLine("Not so much fun now!"); } catch (Exception ex) // التقاط جميع الاستثناءات الأخرى { throw new ApplicationException("It hit the fan", ex); // throw; // التقاط آخر يحافظ على ركام النداء callstack } // catch { } // التقاط كل شيء دون التعامل مع الاستثناءات finally { // try أو catch تُنفّذ بعد } إدارة الموارد يمكنك إدارة الموارد المتوفّرة بسهولة حيث تنفّذ أغلب الكائنات التي تستعمل الموارد غير المستغلة (الملفات، سياق الأجهزة الطرفية، …إلخ) تُنفّذ الواجهة IDisposable تتولّى التعليمة using التخلّص من كائنات IDisposable using (StreamWriter writer = new StreamWriter("log.txt")) { writer.WriteLine("Nothing suspicious here"); } يُتخلَّص من جميع الموارد بعد الانتهاء من تنفيذ هذه الشفرة حتى ولو تسبّبت في استثناء البرمجة المتوازية var words = new List<string> {"dog", "cat", "horse", "pony"}; Parallel.ForEach(words, new ParallelOptions() { MaxDegreeOfParallelism = 4 }, word => { Console.WriteLine(word); } ); تشغيل هذه الشفرة سينتُج عنه مُخرجات متعدّدة لأن كلّ تشعّب thread يُكمل في وقت مختلف عن الآخر. أدناه أمثلة على المُخرجات cat dog horse pony dog horse pony cat الكائنات الديناميكية (رائعة للعمل مع لغات برمجة أخرى) dynamic student = new ExpandoObject(); student.FirstName = "First Name"; لا تحتاج لتعريف صنف أولا بل إنه يمكنك إضافة توابع (يُرجع التابع أدناه سلسلة محارف ويتلقّى سلسلة محارف) student.Introduce = new Func<string, string>( (introduceTo) => string.Format("Hey {0}, this is {1}", student.FirstName, introduceTo)); Console.WriteLine(student.Introduce("Beth")); تنفّذ أغلب التجميعات Collections الواجهة <IQUERYABLE<T التي توفّر الكثير من التوابع المفيدة var bikes = new List<Bicycle>(); // دراجات هوائية bikes.Sort(); // يرتّب القائمة bikes.Sort((b1, b2) => b1.Wheels.CompareTo(b2.Wheels)); // يرتّب القائمة بناءً على عدد العجلات var result = bikes .Where(b => b.Wheels > 3) // الترشيج والفلترة .Where(b => b.IsBroken && b.HasTassles) .Select(b => b.ToString()); // var sum = bikes.Sum(b => b.Wheels); يجمع عدد العجلات في كامل القائمة وينشئ قائمة من الكائنات الضمنية Implicit objects بالاعتماد على بعض خواص الدراجة الهوائية var bikeSummaries = bikes.Select(b=>new { Name = b.Name, IsAwesome = !b.IsBroken && b.HasTassles }); من الصعب توضيح الأمر هنا، إلا أنك تحصُل على نوع البيانات قبل الانتهاء من التعليمات، إذ أن المصرّف يمكنه العمل ضمنا على الأنواع أعلاه foreach (var bikeSummary in bikeSummaries.Where(b => b.IsAwesome)) Console.WriteLine(bikeSummary.Name); التوازي مع ASPARALLEL نخلط عمليّات LINQ والعمليّات المتوازية var threeWheelers = bikes.AsParallel().Where(b => b.Wheels == 3).Select(b => b.Name); سيحدث الأمر بالتوازي. تُنشَأ التشعبات تلقائيا وستُقسَّم النتائج بينها طريقة رائعة للعمل مع مجموعة بيانات ضخمة إن كانت لديك الكثير من الأنوية Cores LINQ تربط بين مخزن بيانات وكائنات من الصنف <IQueryable<T مثلا: LinqToSql تربط الكائنات مع قاعدة بيانات، LinqToXml تربط الكائنات مع مستند XML var db = new BikeRepository(); يؤجَّل التنفيذ، وهو أمر جيّد عند التعامل مع قواعد البيانات var filter = db.Bikes.Where(b => b.HasTassles); // no query run if (42 > 6) // يمكنك الاستمرار في إضافة المرشحات، حتى تلك المشروطة؛ مناسبة لميزة "البحث المتقدّم" filter = filter.Where(b => b.IsBroken); // no query run var query = filter .OrderBy(b => b.Wheels) .ThenBy(b => b.Name) .Select(b => b.Name); // still no query run يعمل الاستعلام الآن، إلا أنك لا تحصُل على نتائج الاستعلام إلا عند المرور عليها foreach (string bike in query) Console.WriteLine(result); } } // نهاية الصنف LearnCSharp يمكنك إضافة أصناف أخرى في ملف cs. public static class Extensions { توابع الصنف Extensions public static void Print(this object obj) { Console.WriteLine(obj.ToString()); } } التفويض والأحداث public class DelegateTest { public static int count = 0; public static int Increment() { // زيادة العدّاد ثم إرجاع النتيجة return ++count; } التفويض delegate هو مرجع لتابع لجعل مرجع على التابع Increment نبدأ بتعريف تفويض بنفس التوقيع أي أنه لا يأخذ أية معطيات ويُرجع عددا من النوع int public delegate int IncrementDelegate(); يمكن أيضا استخدام حدث Event لتحريك التفويض أنشئ حدثا بنوع التفويض public static event IncrementDelegate MyEvent; static void Main(string[] args) { نحيل إلى التابع Increment باستهلال التفويض وتمرير معطى هو التابع نفسه IncrementDelegate inc = new IncrementDelegate(Increment); Console.WriteLine(inc()); // => 1 يمكن تركيب التفويضات بالعامل + IncrementDelegate composedInc = inc; composedInc += inc; composedInc += inc; سينفّذ التفويض composedInc التابع Increment ثلاث مرات Console.WriteLine(composedInc()); // => 4 الاشتراك في الحدث باستخدام التفويض MyEvent += new IncrementDelegate(Increment); MyEvent += new IncrementDelegate(Increment); تحريك الحدث، أي تنفيذ كل التفويضات المشترِكة في هذا الحدث Console.WriteLine(MyEvent()); // => 6 } } صيغة تعريف صنف: <public/private/protected/internal> class <class name>{` // حقول البيانات، المشيّدات، الدوالّ.. كلّها في الداخل //تُستدعى الدوال بنفس طريقة استدعاء التوابع في جافا } public class Bicycle { // حقول/متغيّرات صنف الدراجات الهوائية Bicycle public int Cadence // عمومي public : يمكن استدعاء من أي مكان { get // مسترجع - نعرّف تابعا للوصول إلى قيمة خاصيّة من الكائن { return _cadence; } set // معدّل - نعرّف تابعا لتعيين قيمة خاصيّة { _cadence = value; // القيمة value هي المعطى المُمرّر إلى المعدّل } } private int _cadence; protected virtual int Gear // يمكن استدعاءه فقط من هذا الصنف أو الأصناف المتفرّعة منه Protected:محميّ { get; // تُنشأ خاصيّة تلقائية بحيث لا تحتاج لإضافة حقل بيانات set; } internal int Wheels // داخليّ Internal: يُمكن الوصول إليه من نفس الملف التنفيذي { get; private set; // يمكن تغيير مجال المسترجعات والمعدّلات } int _speed; // ولا يمكن الوصول إليها إلا من داخل الصنف Private كل الخاصيّات هي مبدئيا خاصّة // يمكن أيضا استخدام الكلمة المفتاحية private public string Name { get; set; } للخاصيّات صياغة استثنائية عندما نريد خاصية متاحة للقراءة فقط بمعنى أنها تعيد فقط نتيجة عبارة public string LongName => Name + " " + _speed + " speed"; النوع enum هو نوع بيانات قيمية يتمثّل في مجموعة من المتغيّرات ثابتة القيمة هذا النوع هو في الواقع مجرّد ربط اسم بقيمة (عددية، إن لم يحدد نوع آخر) أنواع البيانات الموثوقة في قيم الثوابت هي byte, sbyte, short, ushort, int, uint, long, و ulong ولا يمكن أن توجد نفس القيمة مرتين في متغيّر من النوع enum public enum BikeBrand { AIST, BMC, Electra = 42, // مباشرة enum يمكن تعيين قيمة المتغيّر في Gitane // 43 } عرّفنا هذا النوع داخل الصنف Bicycle لذا فهو نوع داخلي وعندما نريد استخدامه خارج الصنف فسيتوجّب أن نكتُب Bicycle.Brand public BikeBrand Brand; بعد تعريف نوع enum يصبح بإمكاننا تعريف متغيّر من هذا النوع تستطيع التعليم على وجود قيم عدّة يمكن الاختيار بينها بإضافة الصنف FlagsAttribute قبل تعريف النوع enum يمكن استخدام أي صنف متفرّع عن الصنف Attribute لتعليم أنواع البيانات، التوابع والمعاملات…إلخ يمكن استخدام العوامل المنطقية & و | لإجراء عمليّات منطقية داخل القيمة [Flags] public enum BikeAccessories { None = 0, Bell = 1, MudGuards = 2, // نحتاج لتعيين القيم يدويا Racks = 4, Lights = 8, FullPackage = Bell | MudGuards | Racks | Lights } الاستخدام: aBike.Accessories.HasFlag(Bicycle.BikeAccessories.Bell) في الإصدارات السابقة على الإصدار الرابع من إطار العمل NET (aBike.Accessories & Bicycle.BikeAccessories.Bell) == Bicycle.BikeAccessories.Bell public BikeAccessories Accessories { get; set; } تنتمي الخاصيّات المُعلمة بالكلمة المفتاحية static للصنف نفسه، وليس لكائن عكس بقية الخاصيّات يمكن الوصول إلى هذه الخاصيّات دون الرجوع إلى كائن محدّد ;Console.WriteLine("Bicycles created: " + Bicycle.bicyclesCreated) public static int BicyclesCreated { get; set; } عيّن القيم غير القابلة للتعديل أثناء التشغيل ولا يمكن إسناده إلا عند تعريفها أو داخل مشيّد readonly bool _hasCardsInSpokes = false; // خاصيّة خاصّة وللقراءة فقط المشيّدات Constructors هي طريقة لإنشاء الأصناف أدناه المشيّد المبدئي public Bicycle() { this.Gear = 1; // يمكن الوصول إلى خاصيّات الصنف بالكلمة المفتاحية this Cadence = 50; // إلا أنك لا تحتاجها في كل الحالات _speed = 5; Name = "Bontrager"; Brand = BikeBrand.AIST; BicyclesCreated++; } هذا مشيّد مُعيّن (يحوي معطيات) public Bicycle(int startCadence, int startSpeed, int startGear, string name, bool hasCardsInSpokes, BikeBrand brand) : base() // أولا base يستدعي { Gear = startGear; Cadence = startCadence; _speed = startSpeed; Name = name; _hasCardsInSpokes = hasCardsInSpokes; Brand = brand; } يمكن وضع المشيّدات بالتسلسل public Bicycle(int startCadence, int startSpeed, BikeBrand brand) : this(startCadence, startSpeed, 0, "big wheels", true, brand) { } صيغة كتابة الدوال (<public/private/protected> <return type> <function name> <args>) يمكن للأصناف أن تعيّن مسترجعات ومعدّلات لحقولها كما يمكنها تنفيذ الخاصيّات عبر دوال (وهي الطريقة المفضّلة في Csharp) ويمكن لمعاملات التابع أن تحوي قيما مبدئية، في هذه الحالة، يمكن استدعاء التوابع بدون تمرير معطيات عن هذه العوامل public void SpeedUp(int increment = 1) { _speed += increment; } public void SlowDown(int decrement = 1) { _speed -= decrement; } تعيّن الخاصيّات القيم وتسترجعها. إن كان غرضك الوصول إلى البيانات فقط دون تعديلها فالخاصيّات أنسب. يمكن أن يكون للخاصيّة مسترجع أو معدّل أو كلاهما private bool _hasTassles; // متغيّر خاص public bool HasTassles // مسترجع عام { get { return _hasTassles; } set { _hasTassles = value; } } كما يمكنك تعريف خاصيّة تلقائية في سطر واحد ستُنشئ هذه الصيغة حقلا داعما تلقائيا يمكنك الحد من مجال الرؤية على المسترجع أو المعدّل أو كليهما public bool IsBroken { get; private set; } يمكن للخاصيّات أن تكون تلقائية التنفيذ public int FrameSize { get; // يمكنك الحد من مجال الرؤية على المسترجع أو المعدّل //Framesize يمكنه استدعاء معدّل Bicycle يعني هذا أن الصنف private set; } يمكن تعريف فهرس على الكائنات يمكنك مثلا كتابة bicycle[0] التي ترجع القيمة “chris” للحصول على أول راكب أو كتابة “bicycle[1] = "lisa لتعيين الراكب الثاني (دراجة رباعية المقاعد!) private string[] passengers = { "chris", "phil", "darren", "regina" }; public string this[int i] { get { return passengers[i]; } set { passengers[i] = value; } } تابع لعرض قيم حقول الكائن public virtual string Info() { return "Gear: " + Gear + " Cadence: " + Cadence + " Speed: " + _speed + " Name: " + Name + " Cards in Spokes: " + (_hasCardsInSpokes ? "yes" : "no") + "\n------------------------------\n" ; } يمكن للتوابع أن تكون ثابتة (الكلمة المفتاحية static). مناسبة للدوال المساعدة public static bool DidWeCreateEnoughBicycles() { داخل التابع الثابت لا يمكن إجراء عمليات سوى على الحقول الثابتة return BicyclesCreated > 9000; } إن كان الصنف لا يحتاج إلا إلى حقول ثابتة فربما يكون من الأفضل أن يكون الصنف نفسه ثابتا } // نهاية الصنف Bicycle PennyFarthing هو صنف متفرّع من الصنف Bicycle class PennyFarthing : Bicycle { (يمثّل هذا الصنف تلك الدراجات الهوائية التي لديها عجلة أمامية كبيرة جدا، وليست لديها مسنّنات Gears لتعديل السرعة) . نستدعي مشيّد الصنف الأب public PennyFarthing(int startCadence, int startSpeed) : base(startCadence, startSpeed, 0, "PennyFarthing", true, BikeBrand.Electra) { } protected override int Gear { get { return 0; } set { throw new InvalidOperationException("You can't change gears on a PennyFarthing"); } } public static PennyFarthing CreateWithGears(int gears) { var penny = new PennyFarthing(1, 1); // عمليا لا توجد دراجة من نوع PennyFarthing بمسنّنات penny.Gear = gears; return penny; } public override string Info() { string result = "PennyFarthing bicycle "; result += base.ToString(); // نستدعي التابع الأصلي الموجود في الصنف الأب return result; } } تحتوي الواجهات على التوقيعات فقط interface IJumpable { void Jump(int meters); // جميع الأعضاء في الواجهة هي مبدئيا عمومية } interface IBreakable { bool Broken { get; } // يمكن للواجهات أن تحوي خاصيّات كما يمكنها أن تتضمّن واجهات وأحداثا } يمكن للأصناف أن ترث Inherit من صنف واحد آخر على الأكثر، إلا أنه يمكنها تنفيذ أي عدد من الواجهات ويجب أن يكون الصنف الأب الأول في لائحة الأصناف تليه الواجهات كلّها class MountainBike : Bicycle, IJumpable, IBreakable { int damage = 0; public void Jump(int meters) { damage += meters; } public bool Broken { get { return damage > 100; } } } صنف للاتصال بقاعدة البيانات، نستخدمه مثالا لعمل LinqToSql يعمل إطار العمل EntityFramework Code First لربط الكائنات بسجلات جداول البيانات (بنفس طريقة ActiveRecord في روبي، إلا أنه ثنائي الاتجاه) public class BikeRepository : DbContext { public BikeRepository() : base() { } public DbSet<Bicycle> Bikes { get; set; } } يمكن تقسيم الأصناف على ملفات cs. عدّة A1.cs public partial class A { public static void A1() { Console.WriteLine("Method A1 in class A"); } } A2.cs public partial class A { public static void A2() { Console.WriteLine("Method A2 in class A"); } } يستخدم الصنف Program أدناه الصنف A المُقسّم على ملفي cs. Program using the partial class "A" public class Program { static void Main() { A.A1(); A.A2(); } } يمكن الإداراج في سلاسل المحارف String interpolation بكتابة $ أمام السلسلة ثم إحاطة المتغيّر المُدرج بقوسين معكوفين { }. يمكنك أيضا تجميع السلسلتين، الأصلية والمُعدّلة، بالعلامة @ public class Rectangle { public int Length { get; set; } public int Width { get; set; } } class Program { static void Main(string[] args) { Rectangle rect = new Rectangle { Length = 5, Width = 3 }; Console.WriteLine($"The length is {rect.Length} and the width is {rect.Width}"); string username = "User"; Console.WriteLine([email protected]"C:\Users\{username}\Desktop"); } } ميزات جديدة في الإصدار C# 6 class GlassBall : IJumpable, IBreakable { تمهيد الخاصيّات التلقائية public int Damage { get; private set; } = 0; تمهيد الخاصيّات التلقائية المقتصرة على المسترجعات public string Name { get; } = "Glass ball"; تمهيد الخاصيّات التلقائية المقتصرة على المسترجعات في المشيّد public string GenieName { get; } public GlassBall(string genieName = null) { GenieName = genieName; } public void Jump(int meters) { if (meters < 0) العبارة nameof() مستحدثة وينتُج عنها التحقّق من وجود المعرّف "nameof(x) == "x تحول على سبيل المثال دون بقاء أسماء المتغيّرات القديمة في رسائل الخطأ بعد تحديثها throw new ArgumentException("Cannot jump negative amount!", nameof(meters)); Damage += meters; } الخاصيّات المعرَّفة ضمن هيكل العبارة public bool Broken => Damage > 100; نفس الشيء بالنسبة للتوابع public override string ToString() // سلسلة محارف تُدرج ضمنها متغيّرات => $"{Name}. Damage taken: {Damage}"; public string SummonGenie() العوامل المشترطة بالقيمة الفارغة null ترجع العبارة x?.y القيمة null بمجرد كون x مساوية ل null، بدون تقييم y => GenieName?.ToUpper(); } static class MagicService { private static bool LogException(Exception ex) { /* سجّل الاستثناءات في مكان ما */ log exception somewhere */ return false; } public static bool CastSpell(string spell) { try { // API نفترض هنا أننا نستدعي واجهة تطبيقات برمجية throw new MagicServiceException("Spell failed", 42); // نجح الاستدعاء return true; } يلتقط استثناء في حالة إخفاق استدعاء واجهة التطبيقات، أي أن قيمة Code تساوي 42 Only catch if Code is 42 i.e. spell failed catch(MagicServiceException ex) when (ex.Code == 42) { // أخفق الاستدعاء return false; } استثماءات أخرى أو الاستثناء MagicServiceException عندما تكون قيمة المتغير Code مختلفة عن 42 catch(Exception ex) when (LogException(ex)) { // لا يصل التنفيذ إلى هذه الكتلة } return false; } لاحظ أن التقاط الاستثناء MagicServiceException وإعادة إطلاقه عندما يكون المتغير Code لا يساوي القيمة 42 أو 117 هو أمر مختلف، إذ أن كتلة catch-all الأخيرة لن تلتقط الاستثناء المُعاد public class MagicServiceException : Exception { public int Code { get; } public MagicServiceException(string message, int code) : base(message) { Code = code; } } الخاصية Obsolete public static class PragmaWarning { [Obsolete("Use NewMethod instead", false)] public static void ObsoleteMethod() { /*شفرة برمجية قديمة هنا */ } public static void NewMethod() { /* شفرة برمجية جديدة */ } public static void Main() { ObsoleteMethod(); تحذير يظهر عند استخدام شفرة برمجية قديمة، ناتج عن الوسم Obsolete أعلاه CS0618: 'ObsoleteMethod is obsolete: Use NewMethod instead' تعطّل التعليمة التالية إظهار التحذير السابق #pragma warning disable CS0618 ObsoleteMethod(); // لا تحذير #pragma warning restore CS0618 ObsoleteMethod(); // CS0618: 'ObsoleteMethod is obsolete: Use NewMethod instead' } } } // نهاية فضاء الأسماء using System; ميزة في C# 6: إمكانية استخدام static مع using using static System.Math; namespace Learning.More.CSharp { class StaticUsing { static void Main() { // using مع static بدون استخدام Console.WriteLine("The square root of 4 is {}.", Math.Sqrt(4)); // using مع static باستخدام Console.WriteLine("The square root of 4 is {}.", Sqrt(4)); } } } ميزة جديدة في C# 7 ثبّت آخر إصدار من Microsoft.Net.Compilers باستخدام Nuget ثبّت آخر إصدار من System.ValueTuple باستخدام Nuget using System; namespace Csharp7 { الأزواج المرتبة Tuples، التفكيك DECONSTRUCTION والإلغاءات Discards class TuplesTest { public (string, string) GetName() { // Item1، Item2 .... تُسمى الحقول في الأزواج المرتبة مبدئيا بـ var names1 = ("Peter", "Parker"); Console.WriteLine(names1.Item2); // => Parker يمكن تخصيص أسماء الحقول تعريف النوع الأول (string FirstName, string LastName) names2 = ("Peter", "Parker"); تعريف النوع الثاني var names3 = (First:"Peter", Last:"Parker"); Console.WriteLine(names2.FirstName); // => Peter Console.WriteLine(names3.Last); // => Parker return names3; } public string GetLastName() { var fullName = GetName(); يمكن تفكيك الأزواج المرتبة (string firstName, string lastName) = fullName; يمكن إلغاء حقول من الزوج المرتب بعد تفكيكه بالعلامة _ Fields in a deconstructed tuple can be discarded by using _ var (_, last) = fullName; return last; } يمكن تفكيك أي نوع بيانات على نفس المنوال باستخدام التابع Deconstruct public int randomNumber = 4; public int anotherRandomNumber = 10; public void Deconstruct(out int randomNumber, out int anotherRandomNumber) { randomNumber = this.randomNumber; anotherRandomNumber = this.anotherRandomNumber; } static void Main(string[] args) { var tt = new TuplesTest(); (int num1, int num2) = tt; Console.WriteLine($"num1: {num1}, num2: {num2}"); // => num1: 4, num2: 10 Console.WriteLine(tt.GetLastName()); } } مطابقة الأنماط Pattern matching class PatternMatchingTest { public static (string, int)? CreateLogMessage(object data) { switch(data) { // when ترشيح إضافي باستخدام case System.Net.Http.HttpRequestException h when h.Message.Contains("404"): return (h.Message, 404); case System.Net.Http.HttpRequestException h when h.Message.Contains("400"): return (h.Message, 400); case Exception e: return (e.Message, 500); case string s: return (s, s.Contains("Error") ? 500 : 200); case null: return null; default: return (data.ToString(), 500); } } } الإحالة إلى الموارد المحلية Reference locals تعطيك إمكانية إرجاع مرجع Reference كائن بدلا من قيمته class RefLocalsTest { لاحظ الكلمة المفتاحية ref في تعليمة الإرجاع return public static ref string FindItem(string[] arr, string el) { for(int i=0; i<arr.Length; i++) { if(arr[i] == el) { // إرجاع المرجع return ref arr[i]; } } throw new Exception("Item not found"); } public static void SomeMethod() { string[] arr = {"this", "is", "an", "array"}; //في كل مكان ref لاحظ ref string item = ref FindItem(arr, "array"); item = "apple"; Console.WriteLine(arr[3]); // => apple } } الدوال المحليّة Local functions class LocalFunctionTest { private static int _id = 0; public int id; public LocalFunctionTest() { id = generateId(); لا يمكن الوصول إلى الدالة المحلية خارج هذا المجال int generateId() { return _id++; } } public static void AnotherMethod() { var lf1 = new LocalFunctionTest(); var lf2 = new LocalFunctionTest(); Console.WriteLine($"{lf1.id}, {lf2.id}"); // => 0, 1 int id = generateId(); // خطأ // error CS0103: The name 'generateId' does not exist in the current context } } } ترجمة -وبتصرّف- للمقال Learn C# in Y Minutes