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

إبراهيم البحيصي

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

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

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

  • عدد الأيام التي تصدر بها

    5

آخر يوم ربح فيه إبراهيم البحيصي هو يناير 2 2019

إبراهيم البحيصي حاصل على أكثر محتوى إعجابًا!

10 متابعين

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

  • النبذة الشخصية
    مبرمج, وكاتب تقني, لدي معرفة جيدة في أنظمة قواعد البيانات مثل Oracle و MySql. محب للبايثون.
    "بايثونات" مدونتي وأكتب عليها من فترة لأخرى.
  • الموقع

آخر الزوار

لوحة آخر الزوار معطلة ولن تظهر للأعضاء

إنجازات إبراهيم البحيصي

عضو مساهم

عضو مساهم (2/3)

56

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

1

إجابات الأسئلة

  1. تأتي وحدة التسجيل (logging) مبدئيا توزيعة بايثون المعيارية وتقدم حلا لمتابعة الأحداث التي تحصُل أثناء عمل البرمجية. تستطيع إضافة استدعاءات التسجيل للشيفرة البرمجية الخاصة بك للإشارة لما تحقق من أحداث. تسمح لك وحدة التسجيل بإعداد كل من التسجيلات التشخيصية التي تسجل الأحداث المقترنة بعمليات التطبيق، بالإضافة إلى تسجيلات التدقيق التي تسجل الأحداث الخاصة بحركات المستخدم بهدف تحليلها. وحدة التسجيل هذه مختصة في حفظ السجلات في ملفات. لماذا نستخدم وحدة التسجيل؟ تحافظ وحدة التسجيل على سجل الأحداث التي تحدث خلال عمل البرنامج، مما يجعل من رؤية مخرجات البرنامج المتعلقة بأحداثه أمراً متاحاً. قد يكون استخدام الأمرprint أمرا مألوفا لك خلال الشيفرة البرمجية لفحص الأحداث. يقدم الأمر print طريقة بدائية لإجراء عملية التنقيح الخاصة بحل المشاكل خلال عمل البرمجية. بينما يعد تضمين تعليمات print خلال الشيفرة البرمجية طريقة لمعرفة مسار تنفيذ البرنامج والحالة الحالية له، إلا أن هذه الطريقة اُثبت أنها أقل قدرة على الصيانة من استخدام وحدة التسجيل في بايثون، وذلك للأسباب التالية: باستخدام تعليمات print يصبح من الصعب التفرقة بين مخرجات البرنامج الطبيعية وبين مخرجات التنقيح لتشابههما. عندما تنتشر تعليمات print خلال الشيفرة البرمجية، فإنه لا توجد طريقة سهلة لتعطيل التعليمات الخاصة بالتنقيح. من الصعب إزالة كافة تعليمات print عندما تنتهي من عملية التنقيح. لا توجد سجلات تشخيصية للأحداث. من الجيد البدء بالتعود على استخدام وحدة التسجيل المعيارية في بايثون خلال كتابة الشيفرة البرمجية بما أنها طريقة تتلاءم أكثر مع التطبيقات التي يكبر حجمها عن سكريبتات بايثون بسيطة، وكذلك بما أنها تقدم طريقة أفضل للتنقيح. طباعة رسائل التنقيح في وحدة التحكم إذا كنت متعودا على استخدام تعليمات print لرؤية ما يحدث في برنامجك خلال العمل، فمن المحتمل مثلا أنك تعودت على رؤية برنامج يُعرف صنفًاClass وينشئ منه عناصر كما في المثال التالي: class Pizza(): def __init__(self, name, price): self.name = name self.price = price print("Pizza created: {} (${})".format(self.name, self.price)) def make(self, quantity=1): print("Made {} {} pizza(s)".format(quantity, self.name)) def eat(self, quantity=1): print("Ate {} pizza(s)".format(quantity, self.name)) pizza_01 = Pizza("artichoke", 15) pizza_01.make() pizza_01.eat() pizza_02 = Pizza("margherita", 12) pizza_02.make(2) pizza_02.eat() توجد في الشيفرة السابقة الدالة__init__ التي تستخدم لتعريف خصائصname وprice للصنفPizza. كما تحتوي على الدالتين make لصنع البيتزا، وeat لأكلها وتأخذان المعطى quantity ذا القيمة الافتراضية 1. لنشغل البرنامج: >> python pizza.py وسنحصل على المخرج التالي: Output Pizza created: artichoke ($15) Made 1 artichoke pizza(s) Ate 1 pizza(s) Pizza created: margherita ($12) Made 2 margherita pizza(s) Ate 1 pizza(s) تسمح لنا تعليمات print برؤية أن البرنامج يعمل، ولكننا نستطيع أن نستخدم وحدة التسجيل لذات الغرض بدلا من ذلك. لنقم بإزالة تعليمات print من الشيفرة البرمجية، ونستورد الوحدة باستخدام الأمر import logging: import logging class Pizza(): def __init__(self, name, value): self.name = name self.value = value ... المستوى التلقائي للتسجيل في وحدة التسجيل هو مستوى التحذير (WARNING)، وهو مستوى فوق مستوى التنقيح (DEBUG). بما أننا سنستخدم الوحدة بغرض التنقيح في هذا المثال، سنحتاج الى تعديل إعدادات التسجيل لتصبح بمستوى التنقيح logging.DEBUG بحيث تعود معلومات التنقيح لنا من خلال لوحة التحكم. ونقوم بإعداد ذلك بإضافة ما يلي بعد تعليماتة الاستيراد: import logging logging.basicConfig(level=logging.DEBUG) class Pizza(): ... هذا المستوى المتمثل بlogging.DEBUG يشير لقيد رقمي قيمته 10. سنستبدل الآن جميع تعليمات print بتعليمات logging.debug()، (logging.DEBUG ثابت بينما logging.debug() دالة). نستطيع أن نمرر لهذه الدالة نفس المدخلات النصية لتعليماتة print كما هو موجود بالأسفل: import logging logging.basicConfig(level=logging.DEBUG) class Pizza(): def __init__(self, name, price): self.name = name self.price = price logging.debug("Pizza created: {} (${})".format(self.name, self.price)) def make(self, quantity=1): logging.debug("Made {} {} pizza(s)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Ate {} pizza(s)".format(quantity, self.name)) pizza_01 = Pizza("artichoke", 15) pizza_01.make() pizza_01.eat() pizza_02 = Pizza("margherita", 12) pizza_02.make(2) pizza_02.eat() لهذا الحد، نستطيع تشغيل البرنامج عبر تنفيذ الأمر python pizza.py وسنحصل على المخرج التالي: Output DEBUG:root:Pizza created: artichoke ($15) DEBUG:root:Made 1 artichoke pizza(s) DEBUG:root:Ate 1 pizza(s) DEBUG:root:Pizza created: margherita ($12) DEBUG:root:Made 2 margherita pizza(s) DEBUG:root:Ate 1 pizza(s) لاحظ أن مستوى التسجيل في المخرج السابق هو DEBUG بالإضافة لكلمة root والتي تشير لمستوى المُسجل (logger) الذي يتم استخدامه. يعني ما سبق أن وحدة التسجيل logging من الممكن أن يتم استخدامها لإعداد أكثر من مُسجل بأسماء مختلفة. فمثلا، نستطيع إنشاء مسجلين باسمين مختلفين ومخرجات مختلفة كما هو موضح بالأسفل: logger1 = logging.getLogger("module_1") logger2 = logging.getLogger("module_2") logger1.debug("Module 1 debugger") logger2.debug("Module 2 debugger") Output DEBUG:module_1:Module 1 debugger DEBUG:module_2:Module 2 debugger بعد أن أصبحت لدينا المعرفة اللازمة لكيفية استخدام الوحدة logging لطباعة الرسائل على وحدة التحكم، دعونا نكمل شرح الوحدة ونتعرف على كيفية استخدام الوحدة في طباعة الرسائل إلى ملف خارجي. التسجيل في ملف الغرض الأساسي للتسجيل هو حفظ البيانات في ملف وليس إظهار معلومات التسجيل على وحدة التحكم. يتيح لك التسجيل في ملف حفظ بيانات التسجيل مع مرور الوقت واستخدامها في عملية التحليل والمتابعة ولتحديد ما تحتاجه من تغيير على الشيفرة البرمجية. لجعل عملية التسجيل تحفظ التسجيلات في ملف، علينا أن نعدّل logging.basicConfig() بحيث تحتوي على معطى لاسم الملف (filename)، وليكن مثلا test.log: import logging logging.basicConfig(filename="test.log", level=logging.DEBUG) class Pizza(): def __init__(self, name, price): self.name = name self.price = price logging.debug("Pizza created: {} (${})".format(self.name, self.price)) def make(self, quantity=1): logging.debug("Made {} {} pizza(s)".format(quantity, self.name)) def eat(self, quantity=1): logging.debug("Ate {} pizza(s)".format(quantity, self.name)) pizza_01 = Pizza("artichoke", 15) pizza_01.make() pizza_01.eat() pizza_02 = Pizza("margherita", 12) pizza_02.make(2) pizza_02.eat() الشيفرة البرمجية هنا هي نفسها الموجودة سابقا عدا أننا أضفنا اسم الملف الذي سنقوم بحفظ التسجيلات فيه. بمجرد تشغيلنا للشيفرة السابقة، سنجد في نفس المسار الملف test.log. لنفتحه باستخدام محرر النصوص nano (أو أي محرر نصوص من اختيارك): $ nano test.log وسيكون محتويات الملف كالتالي: DEBUG:root:Pizza created: artichoke ($15) DEBUG:root:Made 1 artichoke pizza(s) DEBUG:root:Ate 1 pizza(s) DEBUG:root:Pizza created: margherita ($12) DEBUG:root:Made 2 margherita pizza(s) DEBUG:root:Ate 1 pizza(s) المخرج السابق هو نفسه الذي حصلنا عليه في القسم السابق من المقال، غير أنه الآن في ملف باسم test.log وليس على الطرفية. لنغلق المحرر، ونجر بعض التعديلات التالية على المتغيرين pizza_01 و pizza_02: ... # Modify the parameters of the pizza_01 object pizza_01 = Pizza("Sicilian", 18) pizza_01.make(5) pizza_01.eat(4) # Modify the parameters of the pizza_02 object pizza_02 = Pizza("quattro formaggi", 16) pizza_02.make(2) pizza_02.eat(2) عند تنفيذ الشيفرة بعد حفظ التعديلات، ستُضاف التسجيلات الجديدة للملف وسيكون محتواه كالتالي: DEBUG:root:Pizza created: artichoke ($15) DEBUG:root:Made 1 artichoke pizza(s) DEBUG:root:Ate 1 pizza(s) DEBUG:root:Pizza created: margherita ($12) DEBUG:root:Made 2 margherita pizza(s) DEBUG:root:Ate 1 pizza(s) DEBUG:root:Pizza created: Sicilian ($18) DEBUG:root:Made 5 Sicilian pizza(s) DEBUG:root:Ate 4 pizza(s) DEBUG:root:Pizza created: quattro formaggi ($16) DEBUG:root:Made 2 quattro formaggi pizza(s) DEBUG:root:Ate 2 pizza(s) تُعد البيانات الموجودة في الملف مفيدة، ولكننا نستطيع جعلها أكثر إعلاماً بإضافة بعض الإعدادات. بشكل أساسي، فإننا نريد أن نجعل السجلات مفصلة أكثر بإضافة الوقت الذي أنشئ السجل فيه. نستطيع إضافة المعطى المسمى format ونضيف له النص %(asctime)s الذي يشير للوقت، كذلك، للإبقاء على ظهور مستوى التسجيل في السجلات، لابد أن نضيف النص %(levelname)s بالإضافة للسجل نفسه %(message)s. لابد من الفصل بين كل خيار في المعطى format بالعلامة : كما هو موضح بالأسفل: import logging logging.basicConfig( filename="test.log", level=logging.DEBUG, format="%(asctime)s:%(levelname)s:%(message)s" ) ....... عندما ننفذ الشيفرة السابقة، سنحصل على تسجيلات جديدة في ملف test.log تتضمن الوقت الذي أنشئ فيه التسجيل بالإضافة لمستوى التسجيل ورسالة التسجيل: Output DEBUG:root:Pizza created: Sicilian ($18) DEBUG:root:Made 5 Sicilian pizza(s) DEBUG:root:Ate 4 pizza(s) DEBUG:root:Pizza created: quattro formaggi ($16) DEBUG:root:Made 2 quattro formaggi pizza(s) DEBUG:root:Ate 2 pizza(s) 2017-05-01 16:28:54,593:DEBUG:Pizza created: Sicilian ($18) 2017-05-01 16:28:54,593:DEBUG:Made 5 Sicilian pizza(s) 2017-05-01 16:28:54,593:DEBUG:Ate 4 pizza(s) 2017-05-01 16:28:54,593:DEBUG:Pizza created: quattro formaggi ($16) 2017-05-01 16:28:54,593:DEBUG:Made 2 quattro formaggi pizza(s) 2017-05-01 16:28:54,593:DEBUG:Ate 2 pizza(s) تبعا لاحتياجاتك، من الممكن أن تضيف إعدادات أخرى للمسجل بحيث تجعل التسجيلات التي يتم حفظها في الملف مرتبطة بك نوعا ما. التنقيح بواسطة التسجيل في ملفات خارجية يتيح لك فهما شاملا لبرنامج بايثون مع مرور الوقت، معطيا الفرصة لحل المشاكل التي تظهر وتغيير ما تحتاج تغييره في الشيفرة البرمجية استنادا لما لديك من بيانات تسجيلات تاريخية وأحداث وحركات تمت خلال عمل البرنامج. جدول بمستويات التسجيل تستطيع نسب مستوى الأهمية للحدث الذي يتم تسجيله بواسطة المُسجل وذلك بإضافة مستوى الخطورة (Severity Level). مستويات الخطورة موضحة في الجدول الذي بالأسفل. تتمثل مستويات التسجيل تقنيا بأرقام (ثوابت)، بفرق قيمة بين كل مستوى ب 10، تبدأ من المستوىNOTEST ذي القيمة 0. تستطيع أن تُعرف مستويات خاصة بك مرتبطة بالمستويات المعرفة مسبقا. إذا عَرَّفْتَ مستوى بنفس القيمة الرقمية، فإنك تستبدل اسم المستوى المرتبط بتلك القيمة. المستوى القيمة الرقمية الدالة الاستخدام CRITICAL 50 ()logging.critical اظهار الأخطاء الخطيرة، البرنامج قد لا يستمر بالعمل ERROR 40 ()logging.error إظهار مشكلة خطيرة WARNING 30 ()logging.warning الإشارة لحدث غير متوقع حصل أو قد يصحل INFO 20 ()logging.info الإشارة أن الحدث حصل كما هو متوقع DEBUG 10 ()logging.debug فحص المشاكل، وإظهار معلومات تفصيلية خاتمة الوحدة logging هي وحدة ضمن التوزيعة المعيارية لبايثون، وتقدم حلا لمتابعة الأحداث التي تحدث خلال عمل البرمجية مع إمكانية تسجيل هذه الأحداث في ملفات خارجية أو إظهارها على الطرفية. وهذا يتيح لك فهما شاملا لبرنامج بايثون مع مرور الوقت. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة – بتصرّف – للمقال How To Use Logging in Python 3 لصاحبته Lisa Tagliaferri. اقرأ أيضًا المقالة التالية: كيفية ترحيل شيفرة بايثون 2 إلى بايثون 3 المقالة السابقة: كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي المرجع الشامل إلى تعلم لغة بايثون كتاب البرمجة بلغة بايثون
  2. نعني بالتنقيح Debugging في مجال تطوير البرمجيات، عملية إيجاد وحل المشاكل التي تمنع البرمجية من العمل على نحو سليم. يُقدم مُنقح بايثون بيئة تنقيح لبرامج بايثون، ويدعم إعداد نقاط الفصل (Breakpoints)، التدرج خلال الشيفرة البرمجية (Stepping) سطرًا بسطر والعديد من المزايا. التفاعل مع مُنقح بايثون يأتي مُنقح بايثون مرفقًا مع توزيعة بايثون المعيارية على هيئة وحدة بايثون باسم pdb، ومن الممكن أن يُستخدم في الشيفرة البرمجية كعنصر من الصنف Pdb، ولمزيد من المعلومات تستطيع قراءة التوثيق الرسمي للوحدة pdb. سوف نبدأ العمل باستخدام برنامج صغير يحتوي على متغيرين ودالة تحتوي على حلقة تكرار بالإضافة لسطر استدعاء الدالة من خلال التركيبة if __name__ == '__main__':. num_list = [500, 600, 700] alpha_list = ['x', 'y', 'z'] def nested_loop(): for number in num_list: print(number) for letter in alpha_list: print(letter) if __name__ == '__main__': nested_loop() نستطيع الآن تشغيل البرنامج السابق من خلال مُنقح بايثون في الطرفية باستخدام الأمر التالي: python -m pdb looping.py يستورد الخيار m- في الأمر أي وحدة بايثون وتشغيلها كبرنامج. في هذه الحالة نقوم باستيراد الوحدة pdb وتمريرها كما هو مكتوب في الأمر. عند تنفيذ الأمر السابق سوف تحصل على المُخرج التالي: > /Users/sammy/looping.py(1)<module>() -> num_list = [500, 600, 700] (Pdb) يحتوي السطر الأول في المُخرج على اسم الملف الحالي الذي نقوم بتنقيحه – بالمسار الكامل -، ومن ثم يوجد رقم سطر الشيفرة التي يقف عليها مؤشر المُنقح (في هذه الحالة 1، ولكن في حالة وجود تعليق أو سطر غير تنفيذي سيكون الرقم أكبر من ذلك). السطر الثاني عبارة عن سطر الشيفرة الذي يتم تنفيذه. يُقدم مُنقح بايثون وحدة تحكم (Console) تفاعلية لإجراء عملية التنقيح وتستطيع استخدام أمر المساعدةhelp للتعرف على الأوامر المتاحة في المُنقح، وأيضا من الممكن أن تستخدم صيغة المساعدة مع الأمرhelp command للتعرف أكثر على تفاصيل أمر معين. سيعيد المُنقح عمله مرة أخرى تلقائيا عندما يصل لنهاية البرنامج. إذا أردت الخروج من وحدة تحكم المُنقح، أدخل الأمرquit أوexit. إذا أردت إعادة تشغيل عملية التنقيح مرة أخرى وفي أي مكان من البرنامج، أدخل الأمرrun. استخدام المُنقح للتدرج خلال البرنامج عند العمل على تنقيح البرامج باستخدام مُنقح بايثون، فإنك غالبا ستستخدم أوامر step، list وnext للمرور على الشيفرة البرمجية. خلال هذا الجزء من المقال سنتناول هذه الأوامر. من خلال نافذة الأوامر، نستطيع إدخال الأمرlist للحصول على السياق المحيط للسطر الحالي. فمثلا، من السطر الأول في البرنامج looping.py الذي عرضناه في الأعلى — num_list = [500, 600, 700] — سيكون تنفيذ الأمرlist معه بالشكل التالي: (Pdb) list 1 -> num_list = [500, 600, 700] 2 alpha_list = ['x', 'y', 'z'] 3 4 5 def nested_loop(): 6 for number in num_list: 7 print(number) 8 for letter in alpha_list: 9 print(letter) 10 11 if __name__ == '__main__': (Pdb) السطر الحالي يشار إليه بالعلامة -> في بدايته وهو في حالتنا هذه السطر الأول من البرنامج. بحكم أن البرنامج الذي نستخدمه هنا صغير نسبيا، فإننا تقريبا نحصل على كافة الأسطر في البرنامج عند استخدامالأمر list. بدون تزويد معطيات مع الأمر list، نحصل من استخدام الأمر على 11 سطراً من الشيفرة البرمجية محيطة بالسطر الحالي في المُنقح، ولكننا نستطيع تحديد الأسطر التي نريد عرضها بالشكل التالي: (Pdb) list 3, 7 3 4 5 def nested_loop(): 6 for number in num_list: 7 print(number) (Pdb) في الأمر السابق قمنا بعرض الأسطر 3-7 باستخدام الأمر list 3,7. للمرور خلال البرنامج سطرا بسطر، نستخدم الأمرstep أو next. (Pdb) step > /Users/sammy/looping.py(2)<module>() -> alpha_list = ['x', 'y', 'z'] (Pdb) (Pdb) next > /Users/sammy/looping.py(2)<module>() -> alpha_list = ['x', 'y', 'z'] (Pdb) الفرق بين الأمرstep والأمرnext أن الأمرstep سوف يتوقف مع استدعاء دالة، بينما الأمر next يُنفذ الدالة عند استدعائها. يتجلى الفرق بين الأمرين عند التعامل مع الدوال. في مثالنا المستخدم، سيقوم الأمرstep بالتعداد خلال حلقات التكرار بمجرد الدخول في استدعاء الدالة nested_loop() بحيث يظهر تماما ما تقوم به حلقة التكرار من طباعة رقم ومن ثم الدخول في حلقة تكرار طباعة الحروف المقترنة بالرقم ومن ثم العودة لطباعة رقم جديد وهكذا. (Pdb) step > /Users/sammy/looping.py(5)<module>() -> def nested_loop(): (Pdb) step > /Users/sammy/looping.py(11)<module>() -> if __name__ == '__main__': (Pdb) step > /Users/sammy/looping.py(12)<module>() -> nested_loop() (Pdb) step --Call-- > /Users/sammy/looping.py(5)nested_loop() -> def nested_loop(): (Pdb) step > /Users/sammy/looping.py(6)nested_loop() -> for number in num_list: (Pdb) step > /Users/sammy/looping.py(7)nested_loop() -> print(number) (Pdb) step 500 > /Users/sammy/looping.py(8)nested_loop() -> for letter in alpha_list: (Pdb) step > /Users/sammy/looping.py(9)nested_loop() -> print(letter) (Pdb) step x > /Users/sammy/looping.py(8)nested_loop() -> for letter in alpha_list: (Pdb) step > /Users/sammy/looping.py(9)nested_loop() -> print(letter) (Pdb) step y > /Users/sammy/looping.py(8)nested_loop() -> for letter in alpha_list: (Pdb) الأمرnext، بدلا من ذلك، سيستدعي الدالة دون الدخول في خطوات تنفيذها خطوة-بخطوة. لنخرج من المُنقح ونعد تشغيله مرة أخرى: python -m pdb looping.py الآن لنستخدم الأمرnext: (Pdb) next > /Users/sammy/looping.py(5)<module>() -> def nested_loop(): (Pdb) next > /Users/sammy/looping.py(11)<module>() -> if __name__ == '__main__': (Pdb) next > /Users/sammy/looping.py(12)<module>() -> nested_loop() (Pdb) next 500 x y z 600 x y z 700 x y z --Return-- > /Users/sammy/looping.py(12)<module>()->None -> nested_loop() (Pdb) أثناء عملك في تنقيح الشيفرة البرمجية الخاصة بك، قد تريد فحص قيمة متغير، وهو ما تستطيع تنفيذه باستخدام الأمرpp والذي يقوم بطباعة القيمة باستخدام وحدة pprint: (Pdb) pp num_list [500, 600, 700] (Pdb) أغلب الأوامر في مُنقح pdb لديها اختصارات، فمثلا، الأمرstep له اختصار هوs ولأمرnext يوجدn. يسرد أمر المساعدة help كافة الاختصارات لكل الأوامر. بالإضافة لذلك، تستطيع استدعاء الأمر الأخير بالضغط على زر الإدخال (Enter) في لوحة المفاتيح. نقاط الفصل من المؤكد أنك ستعمل على برامج أكبر من المثال المستخدم هنا، لذلك، غالبا ستحتاج أن تتوقف عند وظيفة معينة أو سطر محدد أثناء تنقيحك للشيفرة البرمجية، وذلك بدلا من المرور على كافة أسطر البرنامج. ستتمكن باستخدام الأمرbreak لإعداد نقاط الفصل من تشغيل البرنامج حتى نقطة معينة مسبقا فيه تـسمى نقطة فصل Break point. عندما تضيف نقطة فصل، سيعطيها المُنقح رقما خاصا بها. الأرقام المُعطاة لنقاط الفصل تكون أرقاماً متعاقبة وتبدأ من 1، وتستطيع الإشارة لنقاط الفصل باستخدام أرقامها أثناء عملك في المُنقح. تُضاف نقاط الفصل في أسطر معينة باستخدام الصيغة التالية <program_file>:<line_number> كما هو موضح بالأسفل: (Pdb) break looping.py:5 Breakpoint 1 at /Users/sammy/looping.py:5 (Pdb) اكتب الأمرclear ومن ثم y لإزالة نقاط الفصل الحالية. تستطيع بعد ذلك إضافة نقطة فصل في مكان تعريف الدالة: (Pdb) break looping.nested_loop Breakpoint 1 at /Users/sammy/looping.py:5 (Pdb) تستطيع كذلك إضافة شرط لنقطة الفصل: (Pdb) break looping.py:7, number > 500 Breakpoint 1 at /Users/sammy/looping.py:7 (Pdb) لو أدخلنا الآن الأمرcontinue، فإن البرنامج سيتوقف عندما تكون قيمة المتغيرnumber أكبر من 500. (Pdb) continue 500 x y z > /Users/sammy/looping.py(7)nested_loop() -> print(number) (Pdb) للحصول على قائمة بنقاط الفصل المُعدة حاليا للعمل، استخدم الأمرbreak فقط (دون معطيات) وسوف تحصل على معلومات نقاط الفصل التي قمت بإعدادها. (Pdb) break Num Type Disp Enb Where 1 breakpoint keep yes at /Users/sammy/looping.py:7 stop only if number > 500 breakpoint already hit 2 times (Pdb) نستطيع تعطيل نقطة فصل من البرنامج باستخدام الأمرdisable ومن ثم ندخل رقم نقطة الفصل. في هذه الجلسة (المثال المشروح) قمنا بإضافة نقطة فصل أخرى ومن ثم عطلنا النقطة الأولى: Pdb) break looping.py:11 Breakpoint 2 at /Users/sammy/looping.py:11 (Pdb) disable 1 Disabled breakpoint 1 at /Users/sammy/looping.py:7 (Pdb) break Num Type Disp Enb Where 1 breakpoint keep no at /Users/sammy/looping.py:7 stop only if number > 500 breakpoint already hit 2 times 2 breakpoint keep yes at /Users/sammy/looping.py:11 (Pdb) لتفعيل نقطة الفصل نستخدم الأمرenable، ولإزالة نقطة الفصل نستخدم الأمرclear: (Pdb) enable 1 Enabled breakpoint 1 at /Users/sammy/looping.py:7 (Pdb) clear 2 Deleted breakpoint 2 at /Users/sammy/looping.py:11 (Pdb) تقدّم لك نقاط الفصل في pdb قدرة كبيرة في التحكم، فمثلا، من الإضافات أنك تستطيع تجاهل نقطة الفصل خلال الدورة الحالية من البرنامج باستخدام الأمرignore أو تنفيذ حدث معين عند الوصول لنقطة فصل معينة باستخدام الأمرcommand. تستطيع كذلك إضافة نقاط فصل مؤقتة بواسطة الأمرtbreak، بحيث يقوم المُنقح بحذفها تلقائيا عند الوصول إليها وتنفيذها للمرة الأولى (لإضافة نقطة فصل مؤقتة في السطر رقم 3، ندخل الأمرtbreak 3 ). تضمين المُنقح في الشيفرة البرمجية تستطيع تشغيل جلسة تنقيح في الشيفرة البرمجية مباشرة وذلك باستيراد الوحدة pdb إضافة الدالة pdb.set_trace قبل السطر الذي تريد أن تبدأ الجلسة من عنده. في مثالنا المستخدم خلال هذا المقال، سوف نقوم باستيراد الوحدة pdb واضافة الدالة المذكورة قبل البدء بحلقة التكرار الداخلية في الدالة nested_loop: # Import pdb module import pdb num_list = [500, 600, 700] alpha_list = ['x', 'y', 'z'] def nested_loop(): for number in num_list: print(number) # Trigger debugger at this line pdb.set_trace() for letter in alpha_list: print(letter) if __name__ == '__main__': nested_loop() بإضافة المُنقح في الشيفرة البرمجية الخاصة بك، فأنت لست بحاجة لتشغيل الشيفرة بطريقة معينة أو أن تتذكر إعدادات نقاط الفصل، وستتمكن من تشغيل البرنامج بطريقة عادية وتفعيل المُنقح من خلال التنفيذ. تعديل مسار عمل البرنامج يتيح لك مُنقح بايثون تغيير مسار التنفيذ (Execution Flow) خلال زمن التنفيذ باستخدام الأمرjump، وهذا يعني أنك تستطيع أن تقفز إلى الأمام خلال البرنامج لمنع بعض الشيفرة البرمجية من التنفيذ أو العودة لتنفيذ جزء من الشيفرة مرة أخرى. سوف نعمل على شرح هذه النقطة باستخدام برنامج صغير يقوم بإنشاء متغير من نوع قائمة (List) من الأحرف النصية موجودة ضمن المتغير النصي sammy = "sammy" : def print_sammy(): sammy_list = [] sammy = "sammy" for letter in sammy: sammy_list.append(letter) print(sammy_list) if __name__ == "__main__": print_sammy() إذا قمنا بتشغيل البرنامج بطريقة عادية باستخدام python letters_list.py فإننا سوف نحصل على النتيجة التالية: Output ['s'] ['s', 'a'] ['s', 'a', 'm'] ['s', 'a', 'm', 'm'] ['s', 'a', 'm', 'm', 'y'] لنستعرض كيفية استخدام مُنقح بايثون في تغيير مسار عمل البرنامج السابق بحيث نقوم بالقفز قُدما خلال الشيفرة البرمجية للبرنامج أثناء التشغيل بعد الدورة الأولى من حلقة التكرار: python -m pdb letter_list.py > /Users/sammy/letter_list.py(1)<module>() -> def print_sammy(): (Pdb) list 1 -> def print_sammy(): 2 sammy_list = [] 3 sammy = "sammy" 4 for letter in sammy: 5 sammy_list.append(letter) 6 print(sammy_list) 7 8 if __name__ == "__main__": 9 print_sammy() 10 11 (Pdb) break 5 Breakpoint 1 at /Users/sammy/letter_list.py:5 (Pdb) continue > /Users/sammy/letter_list.py(5)print_sammy() -> sammy_list.append(letter) (Pdb) pp letter 's' (Pdb) continue ['s'] > /Users/sammy/letter_list.py(5)print_sammy() -> sammy_list.append(letter) (Pdb) jump 6 > /Users/sammy/letter_list.py(6)print_sammy() -> print(sammy_list) (Pdb) pp letter 'a' (Pdb) disable 1 Disabled breakpoint 1 at /Users/sammy/letter_list.py:5 (Pdb) continue ['s'] ['s', 'm'] ['s', 'm', 'm'] ['s', 'm', 'm', 'y'] قمنا خلال جلسة التنقيح السابقة بوضع نقطة فصل عند السطر رقم 5 لمنع الشيفرة البرمجية من الاستمرار، ومن ثم قمنا بطباعة بعض الأحرف والاستمرار من خلال الأمرcontinue لإظهار ماذا يحدث. ثم استخدمنا الأمرjump لتجاهل السطر 6. عند هذه النقطة، المتغيرletter يساوي القيمة a ولكننا تجاهلنا السطر الذي يقوم بإضافة هذه القيمة للقائمة. بعد ذلك قمنا بتعطيل نقطة الفصل وتركنا البرنامج يستمر في التنفيذ. في النهاية، فإن الحرفa لم يُضف للقائمة sammy_list. لنعد تشغيل جلسة التنقيح، ونستخدم المُنقح في العودة للخلف خلال التشغيل بهدف إعادة تنفيذ جملة الإضافة للقائمة sammy_list والتي تم تنفيذها خلال التكرار الأول من حلقة التكرار: > /Users/sammy/letter_list.py(1)<module>() -> def print_sammy(): (Pdb) list 1 -> def print_sammy(): 2 sammy_list = [] 3 sammy = "sammy" 4 for letter in sammy: 5 sammy_list.append(letter) 6 print(sammy_list) 7 8 if __name__ == "__main__": 9 print_sammy() 10 11 (Pdb) break 6 Breakpoint 1 at /Users/sammy/letter_list.py:6 (Pdb) continue > /Users/sammy/letter_list.py(6)print_sammy() -> print(sammy_list) (Pdb) pp letter 's' (Pdb) jump 5 > /Users/sammy/letter_list.py(5)print_sammy() -> sammy_list.append(letter) (Pdb) continue > /Users/sammy/letter_list.py(6)print_sammy() -> print(sammy_list) (Pdb) pp letter 's' (Pdb) disable 1 Disabled breakpoint 1 at /Users/sammy/letter_list.py:6 (Pdb) continue ['s', 's'] ['s', 's', 'a'] ['s', 's', 'a', 'm'] ['s', 's', 'a', 'm', 'm'] ['s', 's', 'a', 'm', 'm', 'y'] خلال جلسة التنقيح السابقة، قمنا بإضافة نقطة فصل عند السطر 6، وقمنا بالعودة للخلف للسطر 5 بعد الاستمرار.طبعنا ما تحتويه القائمة خلال التنفيذ وذلك لكي نظهر أن الحرف s قد أٌضيف مرتين. وبعد ذلك قمنا بتعطيل نقطة الفصل وجعلنا البرنامج يستمر في التنفيذ. النتيجة الظاهرة توضح أن الحرف s أضيف مرتين في بداية القائمة sammy_list. يمنع المنقّح بعض استخدامات الأمرjump ، وخاصة عندما يُعدَّل مسار البرنامج للأمام أو الخلفمن خلال جمل لم تُعرَّف. فمثلا، لا تستطيع القفز إلى دوال قبل أن تعرّف المعطيات الخاصة بها، وكذلك لا تستطيع الدخول في وسط جملة try:except أو الخروج من كتلة الشيفرة البرمجية لـ finally. ملخص ما نستطيع ذكره عن الأمرjump، أنك من خلال استخدامه في مُنقح بايثون تستطيع تغيير مسار التنفيذ خلال التنقيح لمعرفة هل هذا التغيير مفيد ضمن ظروف ومعطيات محددة أم لا، وكذلك يساعدك في فهم أصل أو مكان الخلل والمشاكل التي تظهر خلال تنفيذ البرنامج. جدول أوامر المنقح pdb هنا نلخص لكم أوامر المُنقح pdb مع شرح بسيط عما يقدمه كل أمر لكي يساعدك على التذكر خلال تنقيح البرامج على بايثون: الأمر الاختصار العمل help h يقدم قائمة بالأوامر المتاحة أو شرحا لأمر معين jump j تحديد السطر القادم للتنفيذ list l طباعة السياق (ما حول السطر الحالي) للتعرف أكثر على محيط التنفيذ الحالي next n الاستمرار في التنفيذ حتى السطر القادم الذي تصل فيه الدالة الحالية أو تعود step s تنفيذ السطر الحالي والتوقف عند أول فرصة متاحة pp pp طباعة متغير أو تعبير معين quit أو exit q الخروج من البرنامج return r الاستمرار في التنفيذ حتى تعود الدالة الحالية تستطيع أن تقرأ أكثر عن الأوامر وكيفية العمل مع المنقح من خلال الاطلاع على التوثيق الرسمي في بايثون. خاتمة يعد تنقيح البرمجيات خطوة مهمة في أي مشروع لبناء وتطوير برمجية. يقدم مُنقح بايثون بيئة تفاعلية تستطيع الاستفادة منها في تنقيح أي برنامج بايثون. الأوامر المتاحة خلال المنقح تتيح لك وقف البرنامج الخاص بك، والاطلاع على قيم متغيراته خلال التنفيذ وتعديلها إذا رغبت، وكذلك التحكم في مسارات التنفيذ وغيره من الخصائص التي تساعدك في فهم ما يقوم به برنامجك بشكل كامل ولكي تضع يدك على المشاكل والقضايا التي تظهر خلال التنفيذ. هذه المقالة جزء من سلسة مقالات حول تعلم البرمجة في بايثون 3. ترجمة – بتصرّف – للمقال How To Use the Python Debugger لصاحبته Lisa Tagliaferri. اقرأ أيضًا المقالة التالية: كيفية تنقيح شيفرات بايثون من سطر الأوامر التفاعلي المقالة السابقة: كيفية تطبيق التعددية الشكلية (Polymorphism) على الأصناف المرجع الشامل إلى تعلم لغة بايثون كتاب البرمجة بلغة بايثون
  3. إذا كانت وظيفتك هي إنشاء تصميمات ويب عالية الجودة، عليك أن تدرك أنّ مساهمتك في العملية التسويقية مهمة جدًا، لذلك، فإن قضاء بعض الوقت لصقل معرفتك بتعلم مصطلحات التسويق المشهورة سوف يمنحك فهمًا أكثر لعملك من خلال سياق أكبر في التسويق. كميزة إضافية، من الممكن تعلم بعض المصطلحات التي تستطيع استخدامها في نقاشاتك مع المُشغلين والعملاء وإثارة إعجابهم بمعرفتك وتمكنك في هذا المجال. هذه بعض المصطلحات التي تحتاج للبدء بالتعرف عليها: اختبار أ/ب (A/B Testing) هو نسخة المسوق في المنهج العلمي. عندما تكون هناك مشكلة ما في تصميم موقع، بدلًا من إجراء تعديل شامل على التصميم، او تغيير المحتوى والخطوط أو تغيير الألوان بشكل كامل، يعمد المسوقون لاستخدام اختبار أ/ب كأداة لتجريب نُسخ بديلة للموقع وعادةً ما يتم تغيير عنصر واحد فقط. التحليلات (Analytics) يشير مصطلح التحليلات ببساطة الى بيانات كأرقام. معدل فتح البريد الإلكتروني، وعدد زائري مدونة ما، وعدد النقرات المدفوعة، وعدد المشاهدات وغيره من الأرقام، كل ما سبق يُمثّل مجموعة متنوعة من البيانات التي يُمكن استخلاصها من تحليلات عملية التسويق. B2B يُشير مصطلح B2B الى مفهوم "من قطاع أعمال إلى قطاع أعمال" ونقصد به هنا الطرفان المباشران لعملية التسويق، ويُمثل الطرفان قطاعي أعمال مختلفان بحيث يكون جمهور قطاع أعمال ما هو قطاع أعمال أخر. B2C يشير مصطلح B2C الى مفهوم "من قطاع أعمال إلى المستهلك" وفيه يستهدف قطاع أعمال ما جمهورًا من المستهلكين العاديين (ليسوا قطاع أعمال). معدل الارتداد (Bounce Rate) معدل الارتداد هو نسبة الزائرين الذين يغادرون موقعك بمجرد الدخول لصفحة واحدة. هذه الإحصائية يتم متابعتها لتحديد الجزء الذي يفقد فيه الزائر الاهتمام بالموقع. ستجد هنا دليل يُساعدك في تحسين معدل الارتداد لموقعك. هوية العلامة التجارية (Brand Identity) تتضمن هوية قطاع أعمال ما كل شيء يربطه الناس بالعلامة التجارية الخاصة بهذا القطاع. من الممكن أن تتضمن هوية قطاع الأعمال كل من اسم الشركة، شعار الشركة، ألوان العلامة التجارية، نوع خطوط الطباعة، الصور، محتوى صوتي وهكذا. شخصية المشتري (Buyer Persona) ينشئ قطاع الأعمال هوية جمهوره من خلال بناء ما يًسمى بـ "شخصية المشتري" وتُبنى معالم هذه الشخصية باستخدام المعلومات الجغرافية والسكانية أو تاريخ سلوك المستخدمين وغيره من المعلومات، وتمنح هذه الشخصية الجمهور القدرة على تشكيل محتواه، وتحديد جهود التسويق بالطريقة التي يرغبها. دعوة إلى الإجراء (Call-to-Action) كل صفحة في الموقع لابد أن يكون لها هدف واضح لجمهور الأعمال وكل جزء من التسويق لابد أن يكون مضمونًا. دعوة إلى الإجراء يمثل رسالة تقوم بتوجيه الزائر للقيام بالخطوة التالية لإكمال تحقيق الهدف المُراد منه. المحتوى (Content) المحتوى هو كل شيء يحتويه الموقع من نصوص، وصور، ومقاطع فيديو، ونداء إجراء، ومكونات القائمة الجانبية، والحركات والأيقونات ...إلخ. التحويل (Conversion) التحويل هو غاية التسويق وهدفه النهائي، ويتغير شكل التحويل من موقع لأخر، فالتحويل في مواقع العضويات يتحقق باشتراك الزائر في العضوية. في مواقع التجارة الإلكترونية، التحويل هو شراء سلعة أو منتج. للمدونات، التحويل هو الاشتراك في المدونة ومتابعة الخلاصات فيها. الاشتراك (Engagement) يشير مصطلح الاشتراك الى أي تفاعل بين قطاع أعمال ما والمستخدم النهائي لديه. يستخدم المسوقون هذا المصطلح للإشارة عادةً إلى التفاعل الحاصل في المنصات الاجتماعية والذي يحدث بأشكال متعددة مثل الإعجاب، المشاركة والتعليق. محتوى متجدد (Evergreen Content) يكون المحتوى متجددًا عندما لا يتقيد بوقت ما. وبكلمات أخرى، يبقى هذا المحتوى قيمًا وذو علاقة بغض النظر متى يقوم شخص رؤيته. الارتباك والمقاومة (Friction) تحدث حالة الارتباك ومقاومة التحويل في عملية التسويق عند إزعاج المستخدم وإرباكه أثناء محاولته إتمام إجراء معين. التسويق الضمني (Inbound Marketing) يتطلب التسويق الضمني تكتيكات خفية، وغالبًا يركز على التجربة وشرح الخبرة والمعرفة أكثر من محاولة البيع. الاصطياد (Jacking) الاصطياد (مثل الاختطاف) يحدث عند استخدام فكرة رائجة لصالح قطاع أعمال ولغرض خاص. من أمثلة ذلك هو استخدام newsjacking (تصيد الأخبار الشائعة)، و trendjacking (تصيد المواضيع الشائعة), و memejacking (تصيد النهفات والنكات الشائعة). مؤشر الأداء الأساسي (Key Performance Indicator) نعني بهذا المصطلح (يُختصر بـ KPI) قياس درجة النجاح في تحقيق هدف ما. الكلمة المفتاحية (Keyword) الكلمات المفتاحية هي ما يُركز عليه المسوقون في بناء كل جزء من المحتوى المكتوب. الكلمات المفتاحية هي أحد الطرق التي تُستخدم في تهيئة المحتوى ليناسب محركات البحث. صفحة الهبوط (Landing Page) كل صفحة في موقع ما هي صفحة هبوط. بلغة التسويق، وبشكل خاص، تُصمم صفحات الهبوط لتحقيق هدف خاص بالبيع. العميل المحتمل (Lead) يشير مصطلح Lead في لغة التسويق إلى العميل المحتمل. التسويق المؤتمت (Marketing Automation) التسويق المؤتمت هو عملية تشغيل "مهمة تسويقية" وتنظيمها باستخدام برمجية ما. التهيئة للأجهزة المحمولة (Mobile Optimization) التهيئة للأجهزة المحمولة هو المصطلح العام المستخدم عند تصميم موقع وأخذ الهاتف المحمول في الحسبان. التصميم المتجاوب وتقييم سرعة الصفحة هما مثالان للتهيئة للأجهزة المحمولة. تحسين الصفحة – الداخلي (On-page Optimization) يشير هذا المصطلح إلى أي نوع من التحسينات المتعلقة بعملية البحث التي يتم تطبيقها داخل صفحة ويب. يشمل ذلك استخدام التخطيط المتجاوب وتهيئة النص باستخدام البيانات الوصفية. تحسين الصفحة – الخارجي (Off-page Optimization) يشير هذا المصطلح إلى أي نوع من التحسينات المتعلقة بعملية البحث التي يتم تطبيقها خارج الموقع. الشبكات الاجتماعية وفرص الارتباط هما مثالان على ذلك. التسويق التقليدي (Outbound Marketing) هي العملية التقليدية للتسويق وتكتيكاتها محصورة بغرض البيع المباشر. نقطة الألم (Pain Point) كل حل أو منتج أو خدمة الهدف منه هو حل نقطة ألم للزبون. غالبًا يتم تعريفها عند بناء شخصية المشتري. التطويع (Repurposing) التطويع هو استخدام جزء من محتوى وتجديده كشيء اخر، فمثلًا، يقوم المسوقون بأخذ منشور مدونة ومناقشته خلال جلسة فيديو حية. التهيئة لمحركات البحث (Search Engine Optimization) يشير مصطلح التهيئة لمحركات البحث (السيو SEO) الى أي تكتيك تسويقي يهدف إلى تحسين ترتيب الموقع خلال ظهور نتائج البحث. تحسين الصفحة داخليا وخارجيا هما مثالان للسيو. الإثبات الاجتماعي (Social Proof) يشير الإثبات الاجتماعي إلى اعتماد المستهلك على شهادة الغير من المستخدمين لتحديد نظرته وموقفه تجاه علامة تجارية ما. الشهادات، مراجعات المنتج، التقييمات وصور منتجات الشركة المُصورة من قبل المستخدمين هي أمثلة على الإثبات الاجتماعي. القائد المُفكر (Thought Leader) يُنظر للقائد المُفكر كشخص مؤثر وخبير في مجال مُعين. من منظور تسويقي، يُشير المسوقون للمحتوى التسويقي الداخلي كمحتوى قائد مُفكر. تجربة المستخدم (User Experience) في التسويق، يُستخدم مصطلح تجربة المستخدم (UX) للإشارة غالبًا الى خبرة المستخدم في استخدام شيء ما. يوجد طريقة في تصميم الويب تُسمى تصميم UX والتي تُركز بشكل كبير على بناء كل إنش في الموقع بناءً على إعدادات المستخدمين، سلوكهم وأهدافهم. ترجمة -وبتصرّف- للمقال The Marketing Terms You Need to Know as a Web Designer لصاحبه Brenda Stokes Barron
  4. صُممت صفحة الهبوط هذه كي تتناسب مع الإجراء الذي قاموا به للتو، لذا فإن من الضروري أن تكون دعوة الإجراء (Call to Action) واضحة ومباشرة في صفحات الهبوط المؤثرة. استخدام الإعلانات لتوجيه العملاء لصفحات الهبوط الجذابة هي طريقة رائعة لزيادة الوصول لعلامتك التجارية. بما أن شركة جوجل بدأت بإعطاء أفضلية في التصنيف للمواقع التي تتضمن محتوى فيديو، أصبح استخدام الفيديو طريقة ممتازة لتسريع ولفت الانتباه لعلامتك التجارية. يتميز محتوى الفيديو بالجاذبية لعدة أسباب، لذا فإن الاستفادة من قوة هذا المحتوى في صفحات الهبوط لديك هو أمر حتمي وسيساعدك في الحصول على انطباع عظيم من المرة الأولى من قبل عملائك المحتملين. قوة محتوى الفيديو صفحات الهبوط التي تحتوي على الفيديو هو أحد الاتجاهات القوية في مجال التسويق بالمحتوى. بينما أغلب صفحات الهبوط صُممت بهدف تشجيع العميل على اتخاذ اجراء مُعين مثل تنزيل كتاب الكتروني او الانضمام لقائمة بريدية، فإن محتوى الفيديو يُدخل البهجة والسرور ويسلي العملاء المحتملين. تتميز صفحات الهبوط التي تتضمن محتوى فيديو بقصرها، سهولة استيعابها، وجاذبيتها للمستخدم العصري. ليس كل مستخدم يريد أو لديه الوقت لقراءة محتوى نصي أو تصفح معرض صور، ولكن محتوى الفيديو من الممكن مشاهدته أو الاستماع له بينما يقوم المستخدم بأعمال أخرى، لذلك فمن الأسهل نوعًا ما أن يتم تشجيع العملاء على رؤية محتوى فيديو على أن يقوموا بمشاهدة أشكال أخرى من المحتوى. صفحات الهبوط التي تتضمن محتوى فيديو تستطيع أن ترفع نسبة التحويلات (conversions) إلى 80% وأغلب زوار المواقع يمكثون أطول في الصفحات التي تحتوي على فيديو بنسبة 88% من الصفحات الأخرى. ملاحظة: التحويلات (conversions) هي عملية تحول المستخدم أو الزائر العادي لصفحتك إلى عميل يقوم بشراء خدماتك. محتوى الفيديو فعال خصيصًا لمواقع التجارة الإلكترونية حيث يثق المستخدمون بنسبة 52% أكثر في عمليات شرائهم من المواقع التي تتضمن محتوى فيديو. أضف إلى ذلك أن المستخدمين الذين يشاهدون فيديو على المتاجر الإلكترونية يمكثون في هذه المواقع دقيقتين أكثر، مع احتمالية زائدة للشراء بنسبة 64%. صفحات الهبوط التي تتضمن فيديو مقابل صفحات الهبوط التقليدية يتغير التسويق الرقمي باستمرار ويبقى مجالًا تنافسيًا بشكل كبير. يُغمر المستهلكون بالإعلانات والمحتوى المدعوم والعديد من الأشكال الأخرى للتسويق والتي ببساطة لا تكترث لأي شيء يُعيد تشكيل الإعلان من جديد. يقوم خبراء التسويق الحديث بمهمة خلق انطباعات جديرة بالبقاء في ذاكرة المستهلكين بهدف التميز عن المنافسين الآخرين وبهدف عرض قيمة حقيقة يهتم بها من يشاهدها. تبقى صفحات الهبوط العادية طريقة ممتازة لعرض المحتوى الذي يهتم به المتصفحون، وأنهم في المكان الصحيح الذي يناسب حاجاتهم، وأن هذا المكان هو الذي يتعرفون فيه أكثر عنك وعن علامتك التجارية. بعد الضغط على إعلانك التجاري الموضوع في المكان الصحيح، يتم توجيه المتصفحين الى صفحة الهبوط التي سوف يستفيدون فيها من عرضك مثلًا، أو يحصلون فيه على هدية مجانية او للتعرف عنك أكثر. إن من الضروري أن تكون القيمة والأهمية أمران واضحان للمستخدم وإلا فإنه ببساطة سوف يعتقد أنك ضيعت وقته. يجب أن يكون هناك حافز واضح لجعل المستخدم يضغط على الرابط، ويجب أن تكون النتيجة كما يتوقعه المستخدم، وإذا لم يحدث ذلك، فسوف تتضرر قيمتك لديهم وسيتضرر بالإضافة لذلك معدل التحويل الخاص بك. وبمجرد أن يعتبر أحد المستخدمين أن علامة تجارية معينة أصبحت غير جديرة بالثقة أو ليست من ضمن اهتماماته، فإنه من الصعوبة الكبيرة إعادة الثقة المفقودة. تقوم شركة جوجل بإعطاء أولوية للمواقع التي تحتوي على محتوى فيديو وهذا أحد الفوائد الكبيرة لصفحات الهبوط المرئية. إذا تم تهيئة موقعك لمحركات البحث فإن ترتيب موقعك والوصول إليه سيتحسنان بفضل صفحات الهبوط التي تتضمن فيديو وهذا الوصول الإضافي قيمٌ جدًا لقوة التنافس الحاصل بين المواقع في الحصول على ترتيب أعلى. الهاتف أولًا أدرك العديد من المسوقين مدى القدرة المذهلة لتطوير المحتوى تحت شعار "المحمول أولًا". يستمر معدل مشاهدة المحتوى الخاص بالمحمول في الزيادة ومنطلقًا كالصاروخ كلما زاد عدد مستخدمي الهواتف الذكية وكلما زاد معدلهم في تصفح الانترنت، التسوق ودفع الفواتير. كلما تقدمت تقنية الهاتف الذكي يصبح من السهل شراء أجهزة محمولة ذات عتاد قادر على عرض فيويو عالي الجودة، وتبعًا لذلك، فإن محتوى الفيديو يزداد استهلاكه أكثر فأكثر مع مرور الوقت. أحد الركائز الأخرى للتسويق العصري هو التصميم المتجاوب (Responsive Design). الفضل يعود للوفرة في الخيارات المتاحة للمستهلكين والموجودة في الأجهزة القادرة على الاتصال بالإنترنت، حيث أصبح من المهم أكثر مما مضى أن تُصمم موقعك ومحتواك ليكون مناسبًا للعرض على أغلب الأجهزة المختلفة. فمثلًا من المهم أن تفكر بخيار التنقل بالإبهام (Thumb Navigation) عند تصميم مواقعك بما أن العديد من مستخدمي الهاتف لن يقوموا باستخدام الفأرة للتنقل في المحتوى الخاص بك. إن تهيئة المحتوى ليناسب أجهزة الهواتف الذكية هو أمر ضروري في التسويق الرقمي الحديث، ويدرك محترفو التسويق قيمة الاستثمار في المحتوى المرئي المعروض في مواقع مُهيئة ومُصممة جيدًا. تفتح الهواتف الباب واسعًا لإجراء حملات تسويقية متقدمة ومخصصة، فمثلاً، يستطيع المسوقون تفصيل المحتوى بناءً على الموقع الجغرافي للمستخدم وذلك بهدف تقديم محتوى ذو علاقة أكثر فأكثر. قد يكون هذا الأمر خيارًا غير واقعي لكل جزء في محتوى الفيديو، ولكن يبقى مهمًا تذكر أن المحتوى المُوجه بناءً على المكان الجغرافي له أثاره العميقة على معدل التحويل لديك. نصائح لصفحات الهبوط التي تتضمن فيديو يوجد عدد كبير من الأدوات المتاحة لتطوير محتوى الفيديو بتكاليف بسيطة أو تكاد تنعدم. من الناحية العملية، تستطيع أي مؤسسة أو جهة عمل إنتاج محتوى فيديو عالي الجودة، لذا من المهم الاستفادة من هذه الفرصة بأسرع ما يمكن. قيمة المحتوى المرئي أصبحت معروفة منذ سنوات، وإذا لم تستثمر هذا الأمر لصالح علامتك التجارية، فإن منافسيك بالتأكيد قاموا بذلك لصالحهم. النصائح التالية تُساعدك في بناء صفحات هبوط ذات محتوى فيديو عالي الجودة: ابدأ الآن. إذا لم تدرك بعد أهمية محتوى الفيديو فإن منافسيك أدركوا ذلك قبلك. من المهم الاستثمار في محتوى الفيديو في صفحات الهبوط بأسرع وقت ممكن. الفيديو الخاص بك سيتحسن مع زيادة الفحص والخبرة ومع مرور الوقت، لذا لا ترتبك أو تتراجع إذا لم تكن التجربة الأولى لك مثالية كما تتوقعها. لا تجعل التكلفة تؤثر عليك. إن تكلفة انتاج محتوى الفيديو أرخص مما يدركه أغلب المسوقين. حتى مع امتلاكك خبرة قليلة أو منعدمة في إنتاج الفيديو، لا ينبغي عليك إبهار جمهورك من البداية، يكفي عليك أن تقدم لهم شيئًا ممتعًا وذو قيمة. المحتوى المرئي البسيط مثل الحديث عن قصص نجاح العملاء لديك، عرض نماذج من المنتجات، أخبار الشركة، كل ما سبق هو طريقة عظيمة للبدء في تقديم محتوى فيديو لعملائك. اعرف جمهورك. تُعتبر بيانات العملاء ذات الجودة العالية أحد أهم وأقوى الأدوات في ترسانة المسوق. إذا كان لديك فكرة واضحة جدًا عن العملاء الذين تريد جذبهم إليك، قم ببناء محتوى مرئي يستهدف حاجاتهم ورغباتهم، وقم بالإجابة فيه عن أسئلتهم المتوقعة التي يسألونها عن علامتك التجارية. اعرف كيف تُهيئ محتوى الفيديو. محتوى الفيديو جذاب، ولكنه قد يكون مزعجًا للبعض. فمثلا، خيار التشغيل التلقائي قد يُفجر الصوت الخاص بالفيديو لدى العميل. تأكد أن المستخدم يستطيع وقف وتشغيل الفيديو متى ما أراد ذلك، بالإضافة لقدرته على توسيع المحتوى ليشمل الشاشة كلها وكتم الصوت إذا أراد. من الممكن أيضًا استخدام خاصية التنصيص المغلق (Closed Captioning) خلال المحتوى المرئي بهدف الوصول إلى شريحة أكبر من الجمهور. اجعل محتوى الفيديو ذو علاقة وذو قيمة. إذا كنت تعرف قاعدة العميل لديك، فليس من الصعب أن تبني محتوى فيديو يُستَمتع به. لا تُضيع وقت العميل المهم. لابد من وجود سبب وجيه يجعل العملاء لديك يضغطون على الرابط الإعلاني الخاص بك، وبعد ذلك تأكد من أنهم سيكونون مسرورين بالمحتوى المرئي الذي سيرونه. استمر في المتابعة. فالجولة تتبعها جولة، لذا لا تبني محتوى فيديو منفصل عن بعضه البعض، واربط المحتوى بمحتوى اخر سيأتي في المستقبل. بناء سلسلة محتوى فيديو مترابط من الطرق القوية في بناء وزيادة الاهتمام بعلامتك التجارية وبتوجيه الانضمام لها. المستخدمون الذين يرون الفيديو الخاص بك لأول مرة سيبقون على اتصال لرؤية ما سيأتي، والذين يأتون لاحقا ويرون محتوى جذاب سيقومون بالعودة والنظر في المحتوى السابق لتفحص ما فاتهم. هذه ليست سوى بعض الطرق التي تُمكنك من الاستفادة من قوة محتوى الفيديو في صفحات الهبوط. لقد أصبح من المعروف منذ سنين لدى المسوقين مدى أهمية صفحات الهبوط ومحتوى الفيديو لذا من المهم الاستفادة من الجمع بينهما لصالح علامتك التجارية وللحصول على مستوى تحويل عالي وللبقاء قويًا في سوق يتميز بمنافسة عالية. ترجمة -وبتصرّف-للمقال How You Can Benefit from Video Landing Pages لصاحبه Stephen Moyers
  5. قد تبدو قوائم توزيع البريد الالكتروني والبريد الإلكتروني المشترك أبسط الطرق لمتابعة خدمة العملاء – في بعض الأحيان هم كذلك. إذا كنت تُمثّل شركة صغيرة الحجم -أو بدأت كشركة صغيرة- فقد يكون ذلك طبيعيًا. قد تكون استخدمت نظام Office 360 Microsoft Outlook لمعالجة قضايا العميل كلما ظهرت. ولكن الحلول السهلة والبسيطة لا تكون دائمًا الأفضل. فوضى قوائم توزيع البريد الإلكتروني وكذلك القيود الموجودة في برنامج البريد الإلكتروني المشترك لشركة مايكروسوفت تجعل الموظفين يشعرون بالإحباط وتجعل العملاء يتطلعون لتجربة أفضل قد يجدونها في مكان اخر إذا لم تُنشئ نظامًا جيدًا. عندما تعالج كل محادثات العملاء باستخدام أدوات مثل Gmail أو Outlook فمن السهل أنّ تتذكر لماذا قوائم التوزيع والبريد الالكتروني المشترك لم يتم بناؤهما لخدمة العميل. كلما تطورت الشركة، المنافع التي ستظهر من الانتقال لعملية مبسطة ستفوق بكثير المرحلة الأولى لمنحني التعلم والاستثمار لاستخدام نظام جديد. حلول الدعم من خلال البريد الإلكتروني هذه بعض الأدوات المختلفة قليلًا والمستخدمة على بناءً على البريد الالكتروني ولكنها تشكل تحدٍ لفرق الدعم: صندوق البريد الوارد المشترك صندوق بريد واحد يستخدم اسمًا مستعارًا (مثال: academy@hsoub.com). الرسائل الإلكترونية الواردة تظهر في هذا الصندوق المشترك. يستطيع الموظفون الدخول والرد مما يجعل ارسال الرد وكأنه من الاسم المستعار. قائمة توزيع البريد الإلكتروني هذه الأداة تَستخدم عنوان بريد إلكتروني مُخصص لمجموعة من الناس. إذا قام أحدٌ بإرسال بريد لهذه القائمة فإن البريد يصل لكل المشتركين فيها. يقوم الموظفون بالرد من عناوين بريدهم الخاصة. مجموعة Office 365 مصطلح "مجموعة" هو طريقة في Outlook للإتصال المشترك. انها تعمل كقائمة توزيع بريد إلكتروني ولكنها تحفظ الرسائل وتتضمن بريدًا مشتركًا، وتقويمًا، ومفكرةً ومكتبةً. مجموعة جوجل هذه أداة من جوجل تُمكنك من انشاء بريد إلكتروني مشترك أو قائمة توزيع من خلال بريد Gmail. خمس إشارات تحتاجها للانتقال من قائمة توزيع أو بريد مشترك إلى نظام الدعم الفني تدفق العمل الخاص بدعم العميل مهمُ جدًا لأنه يؤثر غالبًا على تجربة العميل. إذا كان أحدٌ ما غير سعيد بتجربة فإن أصغر خلل سيصل به إلى قرار المغادرة. إليك عدة إشارات واضحة تساعدك في التخلي عن حساب البريد الالكتروني المشترك والانتقال لنظام الدعم الفني: إذا كنت تتابع العملاء من خلال رسائل بريد الكتروني ولم يكن هناك ردًا على الاطلاق بعد عدة أيام. قيام أعضاء فريق بالرد على نفس العميل بشكل مُكرر أو بمعلومات متناقضة. الذي قام بذلك. ليس لديك تقارير عن حجم البريد الإلكتروني الذي تستقبله، أو سرعة رد الفريق، أو من هو الشخص الذي يقوم بالرد، أو ما مدى سعادة العملاء بالردود التي يقرأونها. دون عمل إعادة توجيه لرسالة البريد الإلكتروني لعدة أشخاص. وجود ما سبق يدل على أنك تستخدم قائمة توزيع وصندوق بريد مشترك وهذا يجعل شركتك تظهر بشكل غير محترف ويسلب من فريقك الإنتاجية. بمجرد ظهور أحد الدلائل السابقة، فهذا يعني أنه حان الوقت لبحث خيارات نظام الدعم الفني. ما الذي عليك البحث عنه في نظام الدعم الفني؟ كيف تبدأ عملية استكشاف نظام دعم فني جديد؟ فكر في البداية في أولوياتك، إذ تعلمنا في Help Scout أنه يوجد بعض العناصر الأساسية لا تستغني عنها أي شركة. عند حصولك على تلك المميزات تستطيع أن تُقدم خدمة عملاء أفضل دون الحاجة لحساب بريد إلكتروني مشترك. الشفافية غياب الشفافية مشكلة عامة في Office 360، حيث لا يوجد طريقة لمعرفة إذا كان الغير يعمل على حل نفس القضية في نفس الوقت. إذا كان لديك فريق بإنتاجية عالية فإن هذا قد يعمل ضد مصلحة الشركة حيث ستجد رسائل متعددة تُرسل من نفس العنوان وتحتوي نفس المضمون في وقت واحد. لك أن تتخيل حجم الإحباط الذي سيشعر به العميل عندما يفتح كل هذه الرسائل. خاصية Traffic Cop indicators في Help Scout تُظهر لكل شخص من الذي يعمل على أي قضية من قضايا العملاء وفي الوقت الحقيقي: انه نظام رسومي سهل: مثلث أصفر يُظهر أن مستخدمًا اخر يقوم بمراجعة المحادثة، والمثلث الأحمر يُشير الى أن شخصًا أخرًا يقوم بالرد على المحادثة. بالإضافة لذلك، Help Scout لا يسمح لك بإرسال رسالة لعميل إذا وُجد شخصٌ آخر ردّ خلال الوقت الذي كنت تعمل فيه على ذلك الرد. أنظمة الدعم الفني تُسهّل من التعاون لحل قضايا العملاء الصعبة. بدلًا من إعادة توجيه المشاكل للمشرفين أو باتجاه أعضاء الفريق الداخليين، تستطيع العمل على حل المشكلة مع الغير على منصة Help Scout. يستطيع المدراء تفحّص حالة قضية بشكل مباشر دون الحاجة للرجوع لكل شخص. المسؤولية أثناء تدفق العمل ستخسر كمًا كبيرًا من الإنتاجية عندما يعمل أكثر من موظف على نفس القضية. على الرغم من أن العميل لا يستقبل عدة ردود، ولكن مدة الوقت اللازم لحل مشكلة ما سيحبط العاملين لديك. تستطيع أن تحاول بناء حلول بديلة، ولكن في الحقيقة، القيود الموجودة في البريد المشترك لـ Office 360 تُكبل نظامهم. هناك بالتأكيد طريقة أفضل. مجلدات التعيين في نظام Help Scout تُظهر لك كل شيء تم تكليفه لفريقك. بإمكانك ترتيب القائمة حسب الشخص المُكلَف للتأكد من عدم ضياع أي شيء في حال خروج عضو ليوم أو مغادرته الشركة. تستطيع من هناك إزالة شخص من مهمة وربطها بشخص آخر. هذا الحل السهل يخلق الاستقرار ليس فقط للعاملين لديك، بل أيضًا لعملائك. تقارير لا تقدر بثمن عن عملائك وموظفيك أغلب أنظمة الدعم الفني الأساسية تُقدم تقارير عن العملاء أبعد بكثير من الذي يقدمه Office 360. التفاعل مع العملاء يكشف عن كنز معلومات: أكثر مشاكل تجربة العملاء، وما يحتاجه العملاء، وما هو الشيء الذي يجعل حياتهم أفضل خلال عملك. يُمًكِّنُك Help Scout من متابعة أغلب أنواع المقاييس الخاصة بعملائك وعملك. هذه بعضٌ منها: إجمالي المحادثات عدد العملاء الذين يحتاجون للمساعدة كل يوم أكثر الأيام والأوقات ازدحامًا بطلبات الدعم أشهر المواضيع التي يكتب عنها الناس التغير في الطلبات النموذجية فرص أتمته العمليات تستطيع تحسين كل جزء من عملك من خلال أدوات التقارير في Help Scout ابتداءً من عدد الموظفين الذين يعملون في كل وردية عمل الى حل القضايا المحورية في المنتج التي تؤدي لعدم رضا العميل. يقدم لك Help Scout تقارير عن أداء الأفراد وكفاءة الفريق بقياسات حديثة وواضحة. إذا قام أحدهم بإرسال بريد مرفوض لأحد العملاء ستعرف ذلك من أول يوم. كمدير، هذه التقارير تساعدك في السيطرة للوصول لكفاءة أكبر ونجاحات مثمرة. باختصار، مثل هذه التقارير هي طعامك وشرابك لقيادة فريق مميز. الانتقال من قائمة توزيع بريد إلكتروني أو بريد الكتروني مشترك لنظام دعم فني قد يبدو مُخيفًا، ولكنه يستحق التجربة. بطريقة مبسطة وشفافة لتدفق العمل خلال نظام دعم فني سيتمتع فرق العمل لديك بالقوة وتتلاءم مع تطور الشركة، مع التأكد من أن أفضل عملاءك لن ينزلق نحو مشاكل البريد الإلكتروني المشترك. ترجمة -وبتصرّف-للمقال How to Tell It’s Time to Ditch Your Shared Email Inbox لصاحبه Elizabeth Wellington
  6. تواجه الشركات الناشئة في عالم الأعمال العديد من العوائق في ظل التنافس الشديد في هذا العالم. أحد أبرز هذه العوائق هو تدني ثقة المستهلك، فلا يوجد أحد سيقدم ماله لجهة ما لا تمتلك تقييمات ومراجعات سابقة أو لا تمتلك كيانًا مضمونًا يمكن الرهان عليه. يوجد العديد من الحلول للمشكلة السابقة وأحد أكثر هذه الحلول فعالية هو التسويق باستخدام الشبكات الاجتماعية وتأييد الموظف هو أحد الأشكال الجديدة لهذا الحل. يميل الناس غالبًا للثقة بالتزكيات الغير احتفالية وخاصة من الأقران، لذلك فإن جعل الموظفين يتحدثون عن عملك سيكون مُفيدًا جدًا. ولكن كيف يُمكن تفعيل ذلك؟ وكيف يُمكنك تطبيق تقنية مُثمرة؟ فوضع خطة لجعل الموظف يتحدث عن عملك هو أمر سهل ولكن من الصعب إتقانه، لذلك من الأهمية بمكان جمع ما يمكنك من المعلومات من البداية. ما هو تأييد الموظف؟ عندما يقوم الموظفون بإعادة نشر أو إعادة تغريد منشوراتك وتأييدك في الشبكات الاجتماعية ومناقشة عملك مع الغير بشكل حي على شبكة الإنترنت فهذا هو تأييد الموظف في العالم الحديث. ويشمل ما سبق قيام الموظفين بمشاركة المحتوى المنشور من الغير والذي يخص الجهة المُوظِفة لهم. نستطيع أن نختصر ذلك بقيام العاملين بدعم شركتهم من خلال منصاتهم وحساباتهم الاجتماعية الخاصة بهم بدلًا من الاكتفاء بالقيام بذلك في الصفحات الرسمية والمشهورة فقط. على الرغم بمعرفة الجميع أن الإنترنت غيرت من طريقة ونهج قطاع الأعمال فيما يخص التسويق وجعلت الاعتماد على مساعدة الموظفين أمرًا نادرًا، ولكن هذا الأمر في الحقيقة أصبح مُعيبًا الأن لما يُشكله دعم الموظفين في زيادة ثقة المستهلك وزيادة عدد الزيارات لموقعك. كيف تستخدم تأييد الموظفين؟ بينما العديد من الشركات لديها برامج غير رسمية لتشجيع دعم الشركة من خلال الشبكات الاجتماعية عبر موظفيها، إلا أن هذه الطريقة صعبة في المتابعة كما أنها أقل فاعلية، فأنت تستطيع أن تجعل عينيك تراقب حسابات الموظفين ولكن من الصعب قياس مشاركة الموظف ومتابعة مدى التأثير الناتج عنه، بالإضافة لصعوبة متابعة حسابات العاملين مجتمعة. لحسن الحظ، يوجد منصات "شبكات اجتماعية مصغرة" تستهدف دعم الموظفين مثل LinkedIn Elevate, أو Smarp, أو Sociabble, أو Dynamic Signal. هذه المنصات تُقدم العديد من الخصائص والتحليلات. يسمح لك تتبع الارتباط "Link Tracking" برؤية أكثر المنشورات التي يتم الضغط عليها ورؤيتها، بالإضافة لأكثر محتوى شُهرةً وبذلك تزداد المنافسة لدى الموظفين للحصول على الصدارة وكسب النقاط والحصول على جوائز. هذه المنصات تجعل من السهل نشر المقالات لأن كل شيء يتم إدارته من مكان واحد ومريح، وهذا هو المفتاح إذا أردت أن تأخذ برنامج تأييد الموظفين في مؤسستك على محمل الجد. بهذه الطريقة، وبمجرد نشر المحتوى، فإن الموظفين يستطيعون بسهولة وسرعة مشاركة هذا المحتوى على الشبكات الاجتماعية المختلفة، وهو أمر أسهل من إرسال مذكرات يومية للموظفين لنشر ذلك على تويتر وفيس بوك. هذا النوع من الأدوات يقدم طريقة سهلة للموظفين ومُشغليهم للتواصل، التعاون والبقاء في صورة أخر المستجدات. قد يكون دور البريد الإلكتروني لم ينتهي بعد، ولكن المقدرة على وضع معلومات ذلت علاقة بالمؤسسة ونشرها من خلال تطبيق ما سيكون مريحًا أكثر بدلًا من إرسال بريد إلكتروني ضخم لمجموعة كبيرة من الموظفين. لماذا نحتاج دعم الموظفين؟ إذا أردت، فإنه من الممكن أن تُنشئ بعض حسابات تويتر للمدراء في شركتك، وتقوم بإعداد برنامج وظيفته هي إعادة نشر ما تقوم بإضافته في مدونتك أو صفحتك، وأن يعمل بشكل يومي، ولكن هذا الأمر لن يخرج عن إطار المألوف والمتعارف عليه. إن أغلب مستخدمي الشبكات الاجتماعية لديهم عين حساسة ويستطيعون ملاحظة الحسابات الآلية عن بعد ميل ولن يكون ذلك بالطبع جميلًا في حال استخدمت نفس الطريقة لحساب شركتك. إن المهتمين الذين يزورون حساباتك على المنصات الاجتماعية قد يتركوا متابعة هذه الحسابات بسبب المحتوى المشور بطريقة آلية. لذلك، فإن المحتوى المُثير الذي يتضمن لمسة حقيقة من شخص حقيقي بالإضافة لتفاعل المستخدم لهو أمر يحظى باحترام وتقدير الناس. قد تكون مشغولًا عن البقاء أمام الشاشة لمتابعة المنصات الاجتماعية، ولكن موظفيك قد لا يكونوا كذلك. يقل اهتمام المستهلكين هذه الأيام بالمدراء التنفيذين ويتجه التركيز نحو الشخص العادي، ناهيك عن أن المتابعين العاديين لديهم شبكات خاصة من الأصدقاء والأقران الذين يستطيعون الوصول لمحتواهم، وهذا الوصول للمحتوى هو أحد مفاتيح النجاح. من الواضح لحد ما أن ذلك هو وسيلة تسويق قيمة تستطيع توليد محتوى طبيعي وجذاب. لقد انتبهت الإنترنت لظاهرة Clickbait والحسابات الآلية، لذا فمن المهم الان بذل جهد إضافي لمواجهة ذلك. عندما نتحدث عن التأثير الاجتماعي، فإن الموظفون هم الذين يملكون ثقة الجمهور والعامة. تشجيع تأييد الموظفين بعد أن تعرفت على أهمية دعم الموظفين ولماذا أنت بحاجة له، يأتي السؤال المهم، كيف أستطيع تحفيز الموظفين للقيام بذلك؟ إذا كان نظام الدعم الذي تريده لا يُقدم للموظف حوافز ومكافئات أو تأثير إيجابي على وظيفتهم، فإنهم لن يضيعوا وقتهم في ذلك. عليك تقديم بعض التشجيع لذلك. في البداية، إن إجبار الموظف على الحديث عن شركتك في الشبكات الاجتماعية ليس هو الطريق، حيث تقل المعنويات حتى تنعدم عند إجبار الناس على القيام بشيء لا يهتمون به، وبدلًا من ذلك، حفزهم وزد اهتمامهم بما يقومون به. قم بتطبيق نظام مكافئات أو لائحة صدارة حتى تزيد المنافسة بينهم. تجنب إعطاء فقرات كبيرة من القواعد والقوانين المعقدة، وقم بتجهيز تعليمات مُختصرة وواضحة تسمح للعاملين لديك بأخذ زمام المبادرة وتوليد ونشر المحتوى الذي يستمتعون به ويرونه مناسبًا. سيعرف عملائك متى أن الموظفين لديك يحبون ما يقومون به وستكسب بذلك ثقة كليهما. الشيء المهم هو: لا تُملي كل حركة. القواعد مُهمة، ولكن لا تتطرف فيها. قد يظهر أنه من الخطر أن تمنح شخصًا حرية واسعة للتأثير في صورة شركتك، ولكن المكافئات التي سيحصل عليها الموظف مهمة بالنسبة له. هذه العقيدة تمنح الموظف القدرة على إنشاء محتوى حقيقي ليس كالمحتوى المُنشأ من قبل برنامج ألي أو في مصنع. ربما تسمح أيضًا لهم بإنشاء محتواهم الخاص. الكتاب المبدعين، الفنانين ومحررو الصور والفيديو يُشكلون اصلًا من أصول شركتك إذا استطعت اكتشافهم. أنشئ محتوى ذو صلة عندما لا يملك طاقمك شيئًا لمشاركته، فعن ماذا سيتكلمون إذن؟ إذا لم تكن في خضم الشبكات الاجتماعية بشكل قوي فإنه حان الوقت للبدء بذلك. أدخل توتير، اكتب في فيسبوك وابدأ في كتابة منشوراتك وتغريداتك. بجانب جذب اهتمام إضافي لشركتك، سيكون من الجيد توفير مادة قابلة لإعادة النشر وفتح السبيل للنقاش بين الموظفين ولا تنس إضافة المرح إذا استطعت. فإذا كانت شركتك تُقيم حفلًا قم بالتقاط الصور وانشرها في المحتوى. محتوى كهذا سيقدم نَفَسًا نقيًا لصفحتك ويضع عملائك في وسط مناخ الشركة. باختصار، فإن أيًا ما تنشره في الشبكات الاجتماعية لابد أن يكون ثاقبًا أو جديرًا بالذكر ومَرِحًا. مشاركة مواضيع ذات عناوين عفوية، ذات صلة وتحتوي على صور أو فيديوهات سريعة، كل ذلك هو مناسب. تبني هذه الفكرة العامة سيفيد شُهرتك على المنصات الاجتماعية بالإضافة لبرنامج تأييد الموظفين لديك. طور إستراتيجيتك التسويقية باستخدام تطبيق التأييد الطريقة المؤكدة لتطبيق خطة التسويق هو باستخدام منصة تشبيك. يوجد العديد من التطبيقات التي تساعد في ذلك، ولكن من الأفضل أن تختار تطبيقًا يشمل تأييد الموظفين. تطبيقات مثل هذه تُغطي أغلب الخصائص التي تُقدمها تطبيقات التشبيك للأعمال، بالإضافة أنها تُقدم تحليلات ذات صلة تُساعدك في معرفة ما هو المحتوى الذي تستهدفه وما هي طبيعة العملاء المهتمين في الشركة. دون ذلك، عليك الاعتماد على أتباع وقياس كفاءة ذلك – وهذا غالبًا غير جدير بالثقة. ابدأ بشكل صغير وابحث عن أفضل العاملين لديك الذين يتسمون بالحرص وحب تجربة الأشياء الجديدة. نفذ مسابقات وحدد الأهداف المطلوبة منهم، وإذا نجحوا قم بعرض ذلك على الموظفين الذين يرغبون بالمشاركة حتى تصل لبرنامج مستقر. ومع الوقت، سيكون لديك برنامج ناجح قام بكل من زيادة عدد الزائرين وإعطاء الفرصة للعاملين لديك لتعزيز مهاراتهم ووظائفهم. الأمر يستحق التجربة، فالمخاطر قليلة ولكن الفائدة هائلة. ترجمة -وبتصرّف- للمقال Why Employee Advocacy Must Be Part of Your Social Media Marketing Plan لصاحبه Brenda Stokes Barron
  7. اذا كان حسابك قديم، وحتى لو كنت مُنشئ تطبيقات عليه، ستحتاج الان إلى ان تملأ الطلب وترسله ثم بعد الموافقة عليه تستطيع إنشاء تطبيقات جديدة
  8. وعليكم السلام،،، لم يعد بالامكان حاليًا ان تُنشئ تطبيق بشكل مباشر على حساب مطوري تويتر إلا بعد ان تُقدم طلب Application لهم ومن ثم يراجعونه. بعد موافقتهم تستطيع ان تُنشئ التطبيق وتُطبق المثال الموجود في المقال. تحياتي وبالتوفيق
  9. في جو العمل، يوجد العديد من الطرق التي تُساعدك في تخفيض التكاليف وتوفير الوقت وزيادة الأرباح. قد يبدو مصطلح "نصائح التسويق" جذابًا، ولكن هل هي مفيدة لصالح العلامات التجارية؟ تُشير الدلائل إلى أن النصائح المناسبة في الوقت المناسب تُسرع من الحملات التسويقية دون إنفاق المزيد من المال. هذه ثمانية نصائح لتحسين جهودك التسويقية من دون مشاحنات. حدث محتواك المتجدد يبقى المحتوى المتجدد مُهمًا لسنوات-أو على الأقل خلال المستقبل المنظور. هذا المحتوى هو الذي يجعل قُراءَك يبحثون عنه دائمًا. عناوين مثل "أهم المصطلحات الصناعية" أو "كيف تقوم بـ " هي عناوين لا تفقد عنفوانها مع الزمن. المحتوى المتجدد في موقعك سيُحسن من أدائه في محركات البحث ويبقى أثره لمدة طويلة. بالإضافة إلى ذلك فهو لا يحتاج لمتابعة دائمة حيث لا تحتاج لتحديث المحتوى المتجدد بشكل دوري. نشر المحتوى المتجدد يُميز شركتك كأحد المصادر المهمة في السوق الذي تعمل فيه، ويمنحك عوائد تسويقية بقليل من الجهد بمجرد إنشائه. كنصيحة تسويقية، يجب أن يكون عُمر المحتوى المتجدد طويلًا حتى تستفيد منه. لابد من إعطاء الأولوية لجودة المحتوى، وأضف لذلك وجود روابط تُوجه الزوار لهذا المحتوى بشرط أن تكون هذه الروابط موجودة في مصادر ذات سمعة حسنة ومشهورة وألا تنتهي صلاحية هذه الروابط. تحتاج أيضًا لاستخدام عناوين تُلبي حاجات جمهورك ولها علاقة بما يهتمون به. يجب أن يكون المحتوى المتجدد مقروءًا بشكل واضح، مع وجود بعض العناوين والنقاط التي تُقسم الفقرات الطويلة في المحتوى. المحتوى يجب أن يكون أطول من المواضيع العادية في المدونة وذلك حتى تُقدم محتوى ذُو قيمة للقراء، وكلما مكث القُراء أطول في الموقع كلما حصلت على نقاط أفضل في ترتيب البحث في جوجل. أعد نشر المحتوى القديم مع التحديثات نشر المحتوى الجديد هو أمر مُهم لموقعك ولكنه لا يجب أن يكون النوع الوحيد من المحتوى الذي تُسوقه. ابحث في المحتوى القديم واختار منه الذي له صلة بالجمهور أو الذي يهتمون به. بعد ذلك، أضف بعض التعديلات والتحديثات للمعلومات وأعد نشرها في موقعك وحساباتك الاجتماعية. استخدم كلمات مثل "تحديث" أو "معلومات جديدة" لإبلاغ جمهورك أنك قمت بإضافة شيء ذو صلة بموضوع قديم. تكرار المحتوى طريقة سريعة وسهلة للبقاء متصلًا ومشاركًا دون الحاجة لوقت أو تكاليف. راجع استراتيجية السيو لديك قد يكون التهيئة لمحركات البحث موضوعًا مُكررًا، ولكنه ذو أهمية كبيرة لنجاح جهود التسويق لديك. راجع استراتيجيات التهيئة التسويقية لمحركات البحث وتأكد أنك لا تُضيع المال أو الفرص. فمثلًا، قم بفحص الكلمات المفتاحية غير النموذجية وتأكد هل تستحق الاستثمار أم لا، فقد تجد أن بعض الكلمات المفتاحية الأخرى مهمة أكثر لشركتك. أزل البقية التي ليس لها علاقة واحفظ موازنة التسويق ببساطة ودون عناء. استخدم أدوات مثل Google Keyword Planner او Google Trends للبحث عن المواضيع الساخنة التي يهتم بها جمهورك. يساعدك مخطط جوجل للكلمات المفتاحية في اكتشاف جديد الكلمات المفتاحية التي لها علاقة بمحتواك، وتمكنك من مقارنة اتجاهات الكلمات المفتاحية وأحجام البحث فيها، بالإضافة أنها تساعدك على إنشاء المجموعات وإعداد العروض. راقب آخر الأخبار الخاصة بمجال عملك واستخدم الكلمات المفتاحية المتعلقة بالموقع الجغرافي في إعداد التهيئة المحلية لمحركات البحث Local SEO – إرسال موقع شركتك الجغرافي إلى محركات البحث-. تحقق من منافسيك وتفقد الكلمات المفتاحية التي تعمل لصالحهم. بإمكانك استخدام منصة مدفوعة الأجر مثل Moz.com لإجراء تهيئة الكلمات المفتاحية دون عناء. أعد تسويق محتواك إعادة تسويق المحتوى هو أفضل أصدقائك، حيث يساعدك في متابعة المستخدمين الذين يزورون موقعك ولم يقوموا بإجراء عملية شراء. هؤلاء المستهلكين سوف يرون محتواك في مكان آخر مثل الفيس بوك أو اليوتيوب. يمنحك إعادة التسويق فرصة ثانية لتكون علامة تجارية ذات قيمة للمستهلك. إنه يذكر المستخدمين بإكمال الإجراء الذي بدأوه بزيارة موقعك، ويعمل كطريقة لجعلهم يبقون على اتصال. أعد تسويق محتواك باستخدام الكوكيز، إعلانات البانر وتكتيكات التسويق لجمهور محدد. أدوات مثل Google Display Network و Facebook Remarketing تساعدك في أغلب ما تم ذكره في هذه النصيحة. عُد الى جمهورك المستهدف مع مرور الوقت سيكون من السهل خسارة جمهورك الذي تستهدفه وتحاول جذبه لمحتواك. من الجدير بك أن تتفحص بشكل دوري الجمهور الذي تستهدفه وما يجب عليك فعله بشكل مغاير لتُبقي حملاتك التسويقية مثيرة وممتعة وذات طابع. حلل إعلاناتك واعرف أيًا من حملاتك التسويقية تعود بالنتائج المرجوة منها. قد تكتشف أنك تقوم بأخطاء صغيرة مثل وجود تناقض في العلامة التجارية وهذا سيؤثر على نجاح إعلاناتك. يجب أن تعمل صفحات الهبوط في جميع الأوقات، ويجب أن يرى إعلاناتك مستخدمون ذَوُو علاقة. إذا قمت بالانتقال من فيس بوك الى الانستقرام أو سناب شات مثلًا، عليك أن تكون على رأس التغييرات التي تحدث في ذلك، وأن تقوم بإعادة تفصيل المحتوى وترتيبه ليناسب المنصات الجديدة. راجع دائمًا الفئات العمرية، الجنس والتركيبات السكانية. القيام بذلك سيساعدك في تجنب الإنفاق الغير مجدي على إعلانات تفقد درجتها وتفشل في تحويل جمهورك الى عملاء. راجع مدونتك لا تدع مدونتك تسقط وتحيد عن الطريق بينما تُركز على جهودك وحملاتك التسويقية الأخرى. مدونتك أساسية في نجاح التسويق لعلامتك التجارية. قضاء بعض الساعات أسبوعيًا في تهيئة مدونتك، إنشاء محتوى جديد، والنشر بانتظام، كل ذلك يُسرع في انضمام المستخدمين لك. تذكر النصائح البسيطة التالية: حدث المدونة أولًا بأول. إذا أصبحت المدونة قديمة وليست على علاقة بمحتواك الذي تسوقه، فإن ذلك يؤذي موقعك بشكل جيد. عليك بالنشر بشكل ثابت، فمحرك جوجل يعتني بالمواقع التي تنشر محتوى بشكل دوري، لذا فإن تحديث المدونة أولًا بأول يُسرع من تهيئة الموقع لمحركات البحث ويُحسن من ظهوره في نتائج البحث وبكل تأكيد سيزيد من ظهور علامتك التجارية. اجعل مدونتك ذات طابع. القراء الحاليين يرغبون بالشعور بارتباط حقيقي مع العلامات التجارية. مدونتك هي الخيار الأنسب لتقديم فرصة المشاركة والارتباط بعلامتك التجارية بالإضافة لتقديم محتوى ذو طابع مرغوب. ادرس جمهورك الذي تستهدفه جيدًا واكتب لأشخاص مُعينين. وظف محترف. إذا لم يكن لديك متسع من الوقت والطاقة الضروريان لمتابعة مدونتك، عليك بتوظيف كاتب محتوى محترف. لا تنسى النصائح والممارسات الجيدة التي تساعدك في اختيار الكاتب الجيد، واعتمد الموازنة التي تناسبك. باستخدام المصادر والأدوات الصحيحة، ستكون متابعة المدونة أمرًا سهلًا ومربحًا للغاية. قم بمتابعة المدونة بشكل دوري للتأكد أنها تعمل بالشكل المطلوب. تهيئة المدونة يُحسن من جهود الحملات التسويقية دون الكثير من العمل المطلوب من طرفك. أشعل حملاتك أنشئ ملف مراجع swipe file خاص بعملك ودَون فيه الأفكار والإلهامات المستقاة من منافسيك ومن المواقع التي تحبها. احفظ الصور والتصميمات التي تعتقد أنها مناسبة لعلامتك التجارية والتي من الممكن أن تستفيد منها في المستقبل، ودون أفكار المحتوى الذي ستكتبه. يجب أن يكون ملف المراجع الخاص بك كالكنز الذي يحوي التفكير المبدع والأفكار الجديدة لشركتك. عندما تحتاج بعضًا من الإلهام افتح ملف المراجع الخاص بك واستخدم الأفكار الموجودة فيه لإشعال حملاتك التجارية التي أصبحت مملة أو التي فشلت في جذب الجمهور الذي تبتغيه. ملف المراجع حلٌ بسيط للبقاء في الأمام أثناء لعبة الحملات التسويقية وذلك دون الحاجة لكثير من الوقت والجهد. لا تنسى أصلك قبل كل شيء، إياك ان تبتعد عن المهمة الرئيسية لعلامتك التجارية. في بعض الأحيان، تحتاج الحملات التسويقية المتخبطة أن تتذكر الأهداف الرئيسية لها. ما هي المهمة الرئيسية الخاصة بك – إنقاذ الكوكب مثلًا؟ تبسيط مهام العمل؟ جعل حياة عملائك أسهل؟ تذكر دائمًا مهمتك الرئيسية أثناء عملك وجهودك التسويقية حتى تُقدم للعالم رسالة واحدة ومتماسكة. الرجوع للأصل يُذكر عملائك بالسبب الذي جعلهم ينضمون لك في البداية. قد يُدهشك حجم الإلهام التسويقي الذي ستجده عندما تتذكر السبب الكامن خلف انطلاقك العمل. كن وفيًا لعملك والباقي سيأتي تباعًا. ترجمة -وبتصرّف-للمقال 8 Quick Tips to Boost Your Web Marketing Campaigns لصاحبه Stephen Moyers
  10. المصفوفة في الجافا سكريبت تتكون من قائمة عناصر، وتتيح الجافا سكريبت للمبرمجين العديد من الوظائف التي تعمل على المصفوفات. الوظائف التي تقوم بالتعديل على المصفوفة الأصلية تُعرف بتوابع التعديل (Mutator Methods)، والوظائف التي تُعيد قيمة جديدة أو شكل آخر من المصفوفة تُعرف بتوابع الوصول (Accessor Methods). يوجد نوع ثالث من التوابع يُسمى بتوابع التكرار (Iteration Methods) والتي سنتناولها بالشرح في هذا المقال. تُتيح توابع التكرار العمل على كل عنصر في المصفوفة كلٌ على حدة، وترتبط هذه التوابع بشكل أساسي بحلقات التكرار. للاستفادة أكثر من هذا الدرس، يجب أن يكون لديك معرفة مُسبقة بكيفية إنشاء المصفوفات، فهرستها، التعديل عليها والمرور على عناصرها بواسطة حلقة التكرار. تستطيع مراجعة درس فهم المصفوفات في الجافا سكريبت لأخذ فكرة عما سبق. ما سنتناوله في هذا الدرس يشمل شرح استخدام وظائف التكرار لتنفيذ حلقة التكرار على المصفوفات وإجراء عمليات على كل عنصر في المصفوفة، توضيح كيفية ترشيح نتائج العمل على المصفوفة، تلخيص عناصر المصفوفة في قيمة واحدة والبحث عن قيم وفهارس معينة. فهم الدوال السهمية (Arrow Functions) العديد من الأمثلة في هذا المقال ستستخدم صيغة الدوال السهمية في الجافا سكريبت والتي يتم تمثيلها بواسطة علامة المساواة ثم علامة الأكبر من <=. الدالة في الجافا سكريبت عبارة عن كتلة من الشيفرة البرمجية يتم تنفيذها وإعادة استخدامها أكثر من مرة، وعادةً ما تُكتب وفق الصيغة التالية: var example = function() { // code to execute } example(); النسخة الأخيرة من الجافا السكريبت -حتى وقت كتابة هذا الدرس- تسمح باستخدام الدوال السهمية والتي تُكتب وفق الصيغة التالية: var example = () => { // code to execute } example(); في الدوال السهمية تُكتب الأقواس لاستقبال معاملات الدالة. في حالة كان لدينا مُعامل واحد فقط فنستطيع حينها التخلي عن كتابة الأقواس كما في الصيغة التالية: var example = parameter1 => { // code to execute } سنعتمد في شرح هذا الدرس على الدوال السهمية، وللاطلاع أكثر على هذا الموضوع، تستطيع الذهاب الى هذا المرجع . الوظيفة ()forEach تقوم الوظيفة ()forEach باستدعاء دالة ليتم تنفيذها على كل عنصر في مصفوفة معينة. فمثلًا، نفترض وجود المصفوفة fish بالعناصر التالية: let fish = [ "piranha", "barracuda", "cod", "eel" ]; نستطيع استخدام الوظيفة ()forEach لطباعة كل عنصر في المصفوفة fish على الطرفية: // Print out each item in the array fish.forEach(individualFish => { console.log(individualFish); }) Output piranha barracuda cod eel يوجد طريقة أخرى لعمل ما سبق وذلك باستخدام جملة التكرار for بالإضافة لاستخدام الخاصية length: // Loop through the length of the array for (let i = 0; i < fish.length; i++) { console.log(fish[i]); } استخدام جملة for السابقة في طباعة كل عنصر على حدة يعطينا نفس النتيجة عند استخدام ()forEach، ولكن استخدام الطريقة ()forEach يُعتبر خيارًا مختصرًا ومباشرًا وأفضل لمثل هذه الحالات. الوظيفة ()map تقوم الوظيفة ()map ببناء مصفوفة ناتجة عن استدعاء دالة على عناصر مصفوفة أخرى. نستطيع طباعة عناصر مصفوفة عنصر-عنصر كمثال توضيحي على كيفية استخدام وظيفة ()map ولكن على العكس من الوظيفة ()forEach، لابد من حفظ ناتج الوظيفة في متغير جديد. let fish = [ "piranha", "barracuda", "cod", "eel" ]; // Print out each item in the array let printFish = fish.map(individualFish => { console.log(individualFish); }); printFish; Output piranha barracuda cod eel مثال أخر على استخدام الوظيفة ()map، حيث نستطيع أيضًا أن نُغير قيمة كل عنصر في مصفوفة وحفظ العناصر الجديدة الناتجة عن هذا التغيير في مصفوفة أخرى. فمثلًا، يمكننا إضافة الحرف s الى نهاية كل عنصر في المصفوفة fish لجعل الأسماء أسماء جمع. // Pluralize all items in the fish array let pluralFish = fish.map(individualFish => { return `${individualFish}s`; }); pluralFish; Output [ 'piranhas', 'barracudas', 'cods', 'eels' ] المصفوفة الأصلية fish لم تتغير، ولكن المصفوفة الجديدة pluralFish أصبحت الان تحتوي على النسخة المُعدلة من المصفوفة الأصلية. الوظيفة ()filter تقوم الوظيفة ()filter بإنشاء مصفوفة جديدة تحتوي على عناصر من المصفوفة الأصلية تتوافق مع شرط معين. الهدف الرئيسي من هذه الوظيفة هو إجراء عملية الترشيح، فمثلًا، نستطيع أن نحصل من الوظيفة ()filter على مصفوفة جديدة تحتوي على العناصر التي تبدأ بحرف مُعين، وذلك بالاستفادة من خاصية فهرسة النصوص التي تُمكننا من الحصول على الحرف الأول لكل عنصر. let seaCreatures = [ "shark", "whale", "squid", "starfish", "narwhal" ]; // Filter all creatures that start with "s" into a new list let filteredList = seaCreatures.filter(creature => { return creature[0] === "s"; }); filteredList; Output [ 'shark', 'squid', 'starfish' ] في المثال السابق اختبرنا جميع العناصر التي تبدأ بالحرف s وحفظنا النتيجة في مصفوفة جيدة باسم filteredList. الوظيفة ()reduce تقوم الوظيفة ()reduce باختصار مصفوفة في قيمة واحدة، وعادةً يُرى هذا الاستخدام مع المصفوفات التي تحتوي على أرقام، مثل الحصول على مجموع عناصر مصفوفة: let numbers = [ 42, 23, 16, 15, 4, 8 ]; // Get the sum of all numerical values let sum = numbers.reduce((a, b) => { return a + b; }); sum; Output 108 تُستخدم الوظيفة ()reduce أيضًا مع النصوص وأنواع البيانات الأخرى، وتكون القيمة المُرجعة من الوظيفة إما رقم أو نص أو أي نوع بيانات أخر. الوظيفة ()find تُعيد الوظيفة ()find أول عنصر من مصفوفة يتوافق مع شرط مُعين. لتوضيح ذلك، سوف نُنشئ مصفوفة تحتوي على أسماء مخلوقات بحرية، وسنستخدم الوظيفة ()find في إيجاد المخلوقات البحرية ذات النوع الرخوي مثل الأخطبوط (من الرخويات). let seaCreatures = [ "whale", "octopus", "shark", "cuttlefish", "flounder" ]; // Check if a given value is a cephalopod const isCephalopod = cephalopod => { return [ "cuttlefish", "octopus" ].includes(cephalopod); } seaCreatures.find(isCephalopod); Output Octopus بما أن “octopus” هو العنصر الأول في المصفوفة seaCreatures الذي ينطبق عليه الشرط، فإنه هو القيمة الأولى التي تم إرجاعها. نستفيد من الوظيفة ()find في عملنا مع المصفوفات التي تحتوي على قيمة عديدة. الوظيفة ()findIndex تُعيد الوظيفة ()findIndex فهرس أول عنصر من مصفوفة يتوافق مع شرط مُعين. سنستخدم نفس المثال السابق في وظيفة ()find لإيجاد فهرس أول عنصر من المصفوفة من النوع الرخوي. let seaCreatures = [ "whale", "octopus", "shark", "cuttlefish", "flounder" ]; باستخدام المصفوفة isCephalopod مع الوظيفة ()findIndex سنحصل على رقم الفهرس للعنصر بدلا من قيمته. // Check if a given value is a cephalopod const isCephalopod = cephalopod => { return [ "cuttlefish", "octopus" ].includes(cephalopod); } seaCreatures.findIndex(isCephalopod); Output 1 العنصر “octopus” هو العنصر الأول من المصفوفة الذي ينطبق عليه الشرط وموقعه في الفهرس رقم 1 وهي القيمة التي حصلنا عليها. في حالة لم ينطبق الشرط على أية عنصر في المصفوفة، فإن القيمة المرجعة هي -1. const isThereAnEel = eel => { return [ "eel" ].includes(eel); } seaCreatures.findIndex Output -1 خاتمة في هذا الدرس قمنا بمراجعة أغلب وظائف توابع التكرار في الجافا سكريبت. وظائف التكرار تعمل على كل عنصر في المصفوفة كلٌ على حدة وغالبًا ما يتم تطبيق دالة جديدة معها. تم شرح كيفية المرور على المصفوفة وعناصرها من خلال حلقة تكرار، تغيير قيمة العنصر في المصفوفة، ترشيح المصفوفة، اختصار المصفوفة في قيمة واحدة والبحث في المصفوفة باستخدام قيم العناصر او فهارسها. لأخذ فكرة عن المصفوفات تستطيع الاطلاع على درس فهم المصفوفات في الجافا سكريبت . ترجمة -وبتصرّف- للمقال How To Use Array Methods in JavaScript: Iteration Methods لصاحبته Tania Rascia حقوق الصورة البارزة محفوظة لـ Freepik
  11. المصفوفة في جافا سكريبت هي نوع من أنواع البيانات المتاحة فيها وتتكون من قائمة من العناصر. تحتوي الجافا سكريبت على العديد من الوظائف المُرفقة والتي تعمل على المصفوفات. الوظائف التي تقوم بالتعديل على المصفوفة الأصلية تُعرف بتوابع التعديل (Mutator Methods)، والوظائف التي تُعيد قيمة جديدة أو شكلًا آخر من المصفوفة تُعرف بتوابع الوصول (Accessor Methods). في هذا المقال سنتحدث عن توابع الوصول. للاستفادة أكثر من هذا الدرس، يجب أن يكون لديك معرفة مسبقة بكيفية إنشاء المصفوفات، فهرستها، التعديل عليها والمرور على عناصرها بواسطة حلقة التكرار. تستطيع مراجعة درس فهم المصفوفات في الجافا سكريبت لأخذ فكرة عما سبق. هذا الدرس يوضح كيفية دمج المصفوفات ببعضها، تحويل المصفوفات الى نصوص، نسخ أجزاء من مصفوفة وحفظها كمصفوفة جديدة بالإضافة لتحديد فهارس المصفوفة. الوظيفة ()concat تقوم الوظيفة ()concat بدمج مصفوفتين أو أكثر ببعضها البعض لينتج لدينا مصفوفة جديدة. في المثال التالي نقوم بإنشاء مصفوفتين تحتويان على أنواع الأسماك الصدفية ومن ثم نقوم بدمجهما في مصفوفة واحدة. // Create arrays of monovalves and bivalves let monovalves = [ "abalone", "conch" ]; let bivalves = [ "oyster", "mussel", "clam" ]; // Concatenate them together into shellfish variable let shellfish = monovalves.concat(bivalves); بمجرد استدعائنا للمصفوفة الجديدة، سنرى أنها تحتوي على العناصر الموجودة في كلا المصفوفتين السابقتين. shellfish; Output [ 'abalone', 'conch', 'oyster', 'mussel', 'clam' ] نستطيع تمرير أكثر من مُعطى للوظيفة ()concate لتسمح لنا بكفاءة وبخطوة واحدة أن ندمج مجموعة مصفوفات ببعضها البعض. الوظيفة ()join تقوم الوظيفة ()join بتحويل جميع عناصر مصفوفة معينة إلى قيمة نصية. في المثال التالي، تقوم الوظيفة بعملية تحويل عناصر المصفوفة fish الى قيمة نصية. لاحظ أنه بدون أن نُمرر أي معطى للوظيفة ()join سيتم فصل عناصر المصفوفة عن بعضها بواسطة فاصلة عادية وذلك في القيمة النصية الناتجة. let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Join the elements of an array into a string let fishString = fish.join(); fishString; Output 'piranha,barracuda,koi,eel' اذا أردنا أن يتم فصل العناصر عن بعضها البعض بواسطة مسافة أو أي فاصل اخر، فعلينا أن نضيف الفاصل الذي نرغب به كمُعطى للوظيفة ()join. // Join the elements of an array into a string let fishString = fish.join(', '); fishString; Output 'piranha, barracuda, koi, eel' في المثال السابق، مررنا الفاصل ‘, ’ الذي يحتوي على فاصلة عادية ومسافة وذلك لفصل عناصر المصفوفة ولكي نحصل على نص مقروء بطريقة أفضل. في حالة قمنا بتمرير فاصل فارغ للوظيفة ()join، فإن الفاصلة التلقائية سيتم ازالتها بالكامل. الوظيفة ()slice نستخدم الوظيفة ()slice لنسخ أجزاء من مصفوفة إلى مصفوفة أخرى جديدة. let fish = [ "piranha", "barracuda", "koi", "eel" ]; لنفترض أننا نربد نسخ أخر عنصرين في المصفوفة fish الى مصفوفة جديدة، فإننا سنبدأ بالنسخ من الفهرس 2 الذي يمثل موقع العنصر “koi” وسينتهي النسخ عند رقم الفهرس الذي يلي فهرس أخر عنصر نريد نسخه. بما أن فهرس أخر عنصر “eel” هو 3، فإننا سنمرر للمعطى الثاني القيمة 4. // Slice a new array from 2 to 5 let fishWithShortNames = fish.slice(2, 4); fishWithShortNames; Output [ 'koi', 'eel' ] في هذه الحالة الخاصة، وبسبب أن العنصر “eel” هو أخر عنصر في المصفوفة، فإن المُعطى الأخير في الوظيفة ()slice غير ضروري، حيث أن النسخ سيبدأ من فهرس البداية وينتهي لنهاية المصفوفة عند عدم تمرير المعطى الثاني. // Slice a new array from 2 to the end of the array let fishWithShortNames = fish.slice(2); fishWithShortNames; Output [ 'koi', 'eel' ] انتبه ألا يختلط عليك الأمر مع وظيفة توابع التعديل المسماة ()splice والتي تقوم بإضافة أو حذف العناصر من المصفوفة الأصلية. الوظيفة ()indexOf تُعيد هذه الوظيفة رقم الفهرس لأول وجود لعنصر معين في مصفوفة، وتظهر فائدة هذه الوظيفة بشكل واضح في المصفوفات التي تحتوي قيم عديدة ومتكررة. في المثال التالي، يتكرر وجود العنصر”barracuda” مرتين في المصفوفة fish. let fish = [ "piranha", "barracuda", "koi", "barracuda" ]; باستخدام الوظيفة ()indexOf نستطيع الحصول على موقع العنصر الأول من القيمة “barracuda”. // Find the first instance of an element fish.indexOf("barracuda"); Output 1 إذا قمنا بتمرير قيمة غير موجودة في المصفوفة فإن نتيجة الوظيفة ستكون القيمة الخاصة -1. fish.indexOf("shark"); Output -1 الوظيفة ()lastIndexOf تُعيد هذه الوظيفة رقم الفهرس للوجود الأخير لعنصر معين في مصفوفة. نستطيع اختبار هذه الوظيفة على نفس المثال السابق الذي يحتوي على تكرار القيمة “barracuda” مرتين. let fish = [ "piranha", "barracuda", "koi", "barracuda" ]; // Find the last instance of an element fish.lastIndexOf("barracuda"); Output 3 الوظيفة ()lastIndexOf تبدأ بالبحث عن العنصر ابتداءً من نهاية المصفوفة وبذلك فهي فعليًا تعيد فهرس أول عنصر تجده أثناء عملية البحث. خاتمة من خلال هذا الدرس قمنا بمراجعة وظائف توابع الوصول المرفقة مع مصفوفات الجافا سكريبت. توابع الوصول تقوم بإنشاء نسخة جديدة من المصفوفة بعكس توابع التعديل التي تقوم بتغيير المصفوفة الأصلية. تعلمنا كيفية دمج مصفوفتين أو أكثر، تحويل عناصر المصفوفة الى مجموعة قيم نصية مُجزأة بفاصلة عادية بالإضافة الى كيفية نسخ أجزاء من المصفوفة الى مصفوفة جديدة. وفي النهاية تعلمنا كيفية الحصول على فهرس أول وجود لعنصر أو أخر وجود له في مصفوفة معينة. لمراجعة أساسيات المصفوفات، راجع درس فهم المصفوفات في الجافا سكريبت. ترجمة -وبتصرّف- للمقال How To Use Array Methods in JavaScript Mutator Methods لصاحبته Tania Rascia
  12. مقدمة تُعتبر خدمات تخزين البيانات المرنة والقابلة للتوسع حسب الحاجة، متطلب أساسي لأغلب التطبيقات والخدمات التي يتم تطويرها بالأدوات والتقنيات الحديثة. بغض النظر عن تخزين كميات قليلة أو كثيرة من الصور، الفيديوهات والنصوص الضخمة فإن مُطوري التطبيقات يحتاجون حلًا لتخزين واسترجاع المحتوى الخاص بالمستخدم، سجلات عمله، نسخه الاحتياطية وغيره من الأمور الأخرى. في ظل الأنظمة المنشورة المعقدة، وفي ظل الحاويات المختلفة والبيئات سريعة التغير والزوال، فإن زمن حفظ الملفات ببساطة في وحدة تخزين على خادوم واحد قد انتهى، حيث قام مزودو الخدمات السحابية بتطوير خدمات لتلبية حاجات التخزين في الأنظمة والتطبيقات الحديثة، وغالبًا تندرج خدمات التخزين السحابية تحت نوعين هما التخزين الكائني (Object Storage) والتخزين الكتلي (Block Storage). سنتناول هنا مميزات وسلبيات كل نوع. ما هو التخزين الكتلي؟ تعتبر خدمات التخزين الكتلي بسيطة ومألوفة نوعًا ما، حيث تُقدم هذه الخدمات خدمة التخزين العادية –كما في القرص الصلب– ولكن من خلال الشبكة. يقدم مزودو الخدمات السحابية الأدوات اللازمة التي تُتيح الحصول على جهاز تخزين كتلي بأي حجم وربطه بالآلة الافتراضية الخاصة بك، ومن هنا تستطيع التعامل مع الجهاز كقرص عادي، حيث تستطيع تهيئته، حفظ الملفات عليه، ربط أكثر من قرص بنظام RAID أو حتى إعداد قاعدة بيانات عليه للكتابة مباشرةً على الجهاز الكتلي. بالإضافة لما سبق، فإن أجهزة التخزين المرتبطة بشبكة غالبًا ما تتميز عن الأقراص الصلبة العادية بما يلي: تستطيع أخذ نسخة حية بسهولة للجهاز للأغراض الاحتياطية. من الممكن إعادة تغيير حجم جهاز التخزين الكتلي وتلبية الاحتياجات المتراكمة. تستطيع فك وربط الجهاز بين الآلات الوهمية بسهولة. ما ذكرناه من مميزات هي خصائص مرنة من الممكن أن تكون مفيدة غالبًا لأي تطبيق. فيما يلي نسرد بعضًا من مميزات وعيوب هذه التقنية. مميزات التخزين الكتلي: التخزين الكتلي شائع ومألوف، حيث أن المستخدمين والبرمجيات يفهمونه ويستطيعون التعامل مع ملفاته وأنظمته بشكل واسع. الأجهزة الكتلية مدعومة جيدًا. كل لغات البرمجة تستطيع قراءة وكتابة الملفات منها. صلاحيات وأذونات ملفات النظام في الأجهزة الكتلية مألوفة ومفهومة بشكل جيد. أجهزة التخزين الكتلي لديها وقت استجابة منخفض في عمليات الإدخال والإخراج، مما يجعلها مناسبة لقواعد البيانات. عيوب التخزين الكتلي: التخزين مرتبط بخادم واحد في نفس الوقت. تحتوي كتلة التخزين وملفات النظام على بيانات وصفية (metadata) قليلة عن المعلومات التي تُخزنها مثل تاريخ الإنشاء، المستخدم الذي تعود له البيانات وحجم هذه البيانات. أي معلومات إضافية عما تُخزنه وحدة التخزين الكتلي يجب أن يتم التعامل معها على مستوى التطبيق أو قاعدة البيانات مما يؤدي إلى زيادة الأعباء على المطور لمتابعة هذه المعلومات. يجب عليك أن تدفع مقابل حجم التخزين الذي حجزته حتى لو لم تقم بالاستفادة منه أو استخدامه. تستطيع أن تصل لخدمة التخزين الكتلي عبر خادومٍ واحد يعمل فقط. التخزين الكتلي يحتاج إلى اعدادات تنصيب وعمل أكثر (اختيار ملفات النظام، الأذونات، الإصدارات، النسخ الاحتياطية...وغيرها) مقارنة بالتخزين الكائني. بسبب سرعة عمليات الإدخال والإخراج في التخزين الكتلي ، فإنه يُعتبر خيارًا أفضل لتخزين البيانات في قواعد البيانات العادية. بالإضافة لذلك، فإن العديد من الأنظمة القديمة تتطلب وجود ملفات نظام عادية للتخزين مما يجعل التخزين الكتلي هو الحل في هذه الحالة. إذا لم يتوفر لدى مزود الخدمات السحابية خدمة التخزين الكتلي، تستطيع أن تقوم بتشغيل الخدمة الخاصة بك بنفسك باستخدام OpenStack Cinder، Ceph، أو خدمة iSCSI المُضمنة مع العديد من أجهزة NAS. ما هو التخزين الكائني؟ في عالم الحوسبة السحابية الحديث، يُعرف التخزين الكائني بأنه تخزين واسترجاع البيانات غير المُرتبة وفق بنية معينة (Unstructured) عبر استخدام الواجهة البرمجية ل HTTP. فبدلًا من تقسيم الملفات إلى كُتل متعددة وحفظها باستخدام نظام الملفات على وحدة التخزين، يتم التعامل مع الملفات ككائنات وتُحفظ على الشبكة. قد تكون هذه الكائنات عبارة عن صورة، سجلات، ملفات HTML أو أية كائنات ثنائية كبيرة بذاتها. تكون هذه الكائنات غير مرتبة وفق بنية معينة لأنها لا تحتاج لاتباع مُخطط أو تنسيق محدد. أصبح التخزين الكائني معروفًا بسبب قدرته الكبيرة على تبسيط تجربة المطور في بناء وتطوير خدمات التخزين، حيث تم تطوير مكتبات تدعم بناء الواجهات البرمجية (التي تحتوي طلبات (HTTP في أغلب لغات البرمجة. حفظ ملف ثنائي كبير أصبح أمرًا سهلًا باستخدام طلب HTTP PUT، وكذلك استرجاع الملف وبياناته الوصفية يتم عبر طلب GET عادي. علاوة على ذلك، فأغلب خدمات التخزين الكائني تستطيع مشاركة هذه الملفات مع المستخدمين الآخرين دون الحاجة لإعدادات خاصة على الخادم المُستضيف. بالإضافة لما سبق، لن تَدفع مقابل خدمة التخزين الكائني إلا مقابل المساحة التي تَستخدمها (بعض الخدمات تُدفع مقابل كل طلب HTTP أو حسب استهلاك النقل عبر النطاق) وهذا الأمر يُعد نعمةً لبعض المطورين الذين يحصلون على خدمة استضافة وتخزين عالمية مقابل تكلفة تتلاءم مع حجم الاستخدام. التخزين الكائني ليس الحل الجيد لكل الحالات. لنلقي نظرة على مميزات وعيوب هذه النوع. مميزات التخزين الكائني: واجهة برمجية بسيطة عبر HTTP تدعم أغلب المستخدمين بغض النظر عن نظام التشغيل المستخدم أو لغة البرمجة. تكلفة التخزين تُحدد مقابل ما يتم استخدامه من مساحة وليس ما يتم حجزه. لن تحتاج لحجز خادوم كامل للحصول على خدمة التخزين الكائني لملفاتك الساكنة. بعض مزودي خدمة التخزين الكائني تُقدم خاصية الدمج CDN المُضمنة، والتي تتيح تخبئة ملفاتك حتى يكون تنزيلها أسرع للمستخدمين. خاصية الأَصْدَرَة (Versioning) التي تتيح لك استرجاع النسخ القديمة من ملفاتك واستعادتها بعد التعديل عليها بشكل خاطئ. تتكيف خدمات التخزين الكائني مع احتياجات الاستخدام بدءًا من الاستخدام البسيط وحتى حالات الاستخدام المكثف دون أن يحتاج المطور لزيادة المصادر أو إعادة الهيكلة لمعالجة الحمل المطلوب. باستخدام خدمات التخزين الكائني لن تحتاج لمتابعة وإدارة وحدات التخزين أو أنظمة RAID لأنها من مسئولية مزود الخدمة. تستطيع حفظ بيانات وصفية بجانب البيانات الأصلية وذلك يُبسط لك هيكلة التطبيق الذي تعمل عليه. عيوب التخزين الكائني: لا تستطيع أن تستضيف قاعدة بيانات عادية على خدمة التخزين الكائني بسبب وقت الاستجابة العالي واللازم لقاعدة البيانات. باستخدام التخزين الكائني لا تستطيع التعديل على جزء من الكائن الذي تحفظه، حيث عليك قراءة أو كتابة الكائن كله في العملية الواحدة وهذا له آثار مترتبة على الأداء. فمثلًا، باستخدام نظام الملفات تستطيع بسهولة أن تُضيف سطر في نهاية ملف سجلات، ولكن في نظام التخزين الكائني يجب عليك قراءة الملف كاملا ثم التعديل عليه ثم إعادة كتابته وحفظه مرة أخرى، وهذا الأمر يجعل من التخزين الكائني خيارًا غير مثالي في حفظ البيانات التي تتغير بشكل مستمر. لا تستطع نُظم التشغيل تعيين كائن كمحرك أقراص بشكل سهل. يوجد بعض العملاء والمحولات التي تساعد في تنفيذ هذا الأمر، ولكن بشكل عام، استخدام الكائن وتصفحه ليس متاحًا بسهولة كما هو متاح لدى التنقل خلال المجلدات في نظام الملفات. بسبب هذه الخصائص، التخزين الكائني مفيد في استضافة الملفات الساكنة، حفظ محتوى المستخدم المتمثل مثلًا في الصور ولقطات الفيديو، حفظ ملفات النسخ الاحتياطي والسجلات. يوجد بعض حلول التخزين الكائني التي تتيح لك حفظ ملفاتك وبياناتك دون القلق على كيفية إدارة الأقراص أو خيارات التوسع. تستطيع مثلا أن تُجرب Minio، وهو خادوم مشهور مُطَوَّرْ باستخدام لغة Go ويقدم خدمة التخزين الكائني، أو تستطيع تجربة Ceph أو OpenStack Swift. خاتمة اختيار طريقة التخزين قد يكون قرارًا معقدًا للمطورين. ناقشنا مزايا وعيوب كلًا من التخزين الكتلي والتخزين الكائني. على الأرجح أن أي تطبيق معقد وذو كفاءة سيحتاج لاستخدام كلا النوعين في التخزين لتلبية كافة الاحتياجات اللازمة للعمل. ترجمة -وبتصرّف- للمقال Object Storage vs. Block Storage Services لصاحبه Brian Boucheron
  13. تتكون المصفوفة في الجافا سكريبت من قائمة عناصر، وتحتوي الجافا سكريبت على العديد من الوظائف المرفقة والتي تعمل على المصفوفات. الوظائف التي تقوم بالتعديل عل المصفوفة الأصلية تُعرف بتوابع التعديل (Mutator Methods)، والوظائف التي تعيد قيمة جديدة أو شكل آخر تُعرف بتوابع الوصول (Accessor Methods). للاستفادة أكثر من هذا المقال، يجب أن يكون لديك معرفة مسبقة بكيفية إنشاء المصفوفات، فهرستها، التعديل عليها والمرور على عناصرها بواسطة حلقة التكرار. تستطيع مراجعة درس فهم المصفوفات في الجافا سكريبت لأخذ فكرة عما سبق. المصفوفات تتشابه مع النصوص من حيث أن كلاهما يتكون من مجموعة من العناصر التي يمكن الوصول لها عبر رقم الفهرس. على الرغم من ذلك، من الأهمية أن نتذكر أن النصوص ثابتة وغير قابلة للتعديل (Immutable). ولكن على الجانب الاّخر، فإن المصفوفات غير ثابتة (Mutable)، ونستطيع التعديل عليها بشكل مباشر. في هذا المقال سوف نشرح عمليات إضافة وإزالة العناصر من المصفوفة، عكس المصفوفة، استبدال المصفوفة والتعديل على عناصرها. الوظيفة ()isArray قبل البدء بشرح توابع التعديل، سنتعرض للوظيفة ()isArray والتي تقوم بفحص هل الكائن عبارة عن مصفوفة أم لا. في حالة كان الكائن الذي نقوم بفحصه من نوع مصفوفة، فإن الوظيفة ستعيد القيمة المنطقية true، وفي حالة لم يكن مصفوفة، فإن الوظيفة ستعيد القيمة المنطقية false. let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Test if fish variable is an array Array.isArray(fish); Output True الوظيفة ()isArray مفيدة بسبب أن العملية typeof التي تُستخدم عادة في فحص هذه الحالات ستعيد لنا القيمة object عند استخدامها مع المصفوفة، ومن المهم في بعض الأحيان معرفة هل الكائن مصفوفة أم لا. لاحظ أن الوظيفة ()isArray تُكتب بطريقة مختلفة عن أغلب وظائف المصفوفات، حيث يتم تمرير الكائن الذي يمثل المصفوفة كمُعطى للوظيفة. بعد أن تعرفنا على الوظيفة التي تساعدنا في فحص هل الكائن الذي نتعامل معه مصفوفة أم لا، سنبدأ بشرح وظائف توابع التعديل. الوظيفة ()pop أول وظيفة سنتناولها في الشرح هي وظيفة ()pop، التي تُزيل العنصر الأخير من نهاية مصفوفة. لنفترض أنه لدينا مصفوفة باسم fish تحتوي على أنواع بعض الأسماك: let fish = [ "piranha", "barracuda", "koi", "eel" ]; عند استدعاء الوظيفة ()pop سيتم إزالة اخر عنصر في المصفوفة، والذي سيكون العنصر الذي يساوي القيمة النصية “eel” : // Use pop method to remove an item from the end of an array fish.pop(); نقوم بطباعة محتوى المصفوفة لنتأكد من أنها أصبحت لا تحتوي القيمة المحذوفة: fish; Output [ 'piranha', 'barracuda', 'koi' ] بذلك نكون قد أزلنا العنصر “eel” من المصفوفة بنجاح. الوظيفة ()pop لا تأخذ أي معاملات أخرى. الوظيفة ()shift الوظيفة ()shift هي وظيفة أخرى من توابع التعديل وتقوم بإزالة العنصر الأول من المصفوفة. لنفترض وجود المصفوفة fish بالعناصر التالية: let fish = [ "piranha", "barracuda", "koi", "eel" ]; نستخدم الوظيفة ()shift لإزالة العنصر الأول “piranha” والموجود في الفهرس رقم 0، وكذلك سيتم إزاحة كافة عناصر المصفوفة بمقدار فهرس واحد للأسفل. // Use shift method to remove an item from the beginning of an array fish.shift(); fish; Output [ 'barracuda', 'koi', 'eel' ] في المثال السابق، تم إزالة العنصر الأول وإجراء عملية الإزاحة لكافة العناصر الباقية، لهذا السبب، وبشكل عام، فإنه يُفضل أن يتم استخدام الوظيفة ()pop قدر المستطاع لإزالة العناصر من المصفوفة لعدم وجود عملية إزاحة العناصر عند استخدامها. الوظيفة ()push الوظيفة ()push تعمل على إضافة عنصر جديد أو عدة عناصر جديدة في نهاية المصفوفة. let fish = [ "piranha", "barracuda", "koi", "eel" ]; لإضافة عنصر جديد، نمرر العنصر للوظيفة كمُعامل: // Use push method to add an item to the end of an array fish.push("swordfish"); fish; Output [ 'piranha', 'barracuda', 'koi', 'eel', 'swordfish' ] من الممكن أيضًا أن نضيف أكثر من عنصر دفعة واحدة لنهاية المصفوفة بالشكل التالي: fish.push("swordfish", "dragonfish") الوظيفة unshift() لإضافة عنصر جديد أو عدة عناصر في بداية المصفوفة، نستخدم الوظيفة ()unshift. let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Use unshift method to add an item to the beginning of an array fish.unshift("shark"); fish; Output [ 'shark', 'piranha', 'barracuda', 'koi', 'eel' ] في المثال السابق، العنصر shark”” تم اضافته في الفهرس رقم 0، مع إزاحة كافة العناصر للإمام. نستطيع إضافة عدة عناصر دفعة واحدة بنفس الطريقة التي استخدمناها مع الوظيفة ()shift وذلك بتمرير العناصر بحيث تكون مفصولة عن بعضها بفاصلة عادية. الوظيفتان ()pop و ()push تؤثران على نهاية المصفوفة، والوظيفتان ()shift و ()unshift تؤثران على بداية المصفوفة. يوجد طريقة سهلة لتذكر هذه المعلومة وهي معرفة أن الوظيفتان ()shift و ()unshift تقومان بعمل إزاحة للعناصر في المصفوفة. الوظيفة ()splice تقوم الوظيفة ()splice بإضافة أو إزالة عنصر من أي موقع في المصفوفة. الوظيفة تقوم إما بالإضافة أو الحذف كلٌ على حدة، أو الإضافة والحذف بشكل متزامن. تأخذ الوظيفة ()splice ثلاث معاملات، الأول هو الفهرس الذي سنبدأ من عنده العملية، الثاني هو عدد العناصر التي نريد حذفها، الثالث هو العنصر الذي نريد اضافته (اختياري). splice(index number, number of items to remove, items to add) الأمثلة التالية توضح كيفية استخدام الوظيفة ()splice في إضافة وحذف العناصر في المصفوفة. الإضافة باستخدام ()splice إذا قمنا بإعداد المعامل الثاني في الوظيفة ()splice ليأخذ القيمة 0، فإنه لن يتم حذف أي عنصر. بهذه الطريقة، نستطيع أن نضيف عنصر لمصفوفة في أي موقع فيها، وهذه الطريقة تُعتبر أفضل وأقوى من استخدام الوظيفتين ()push و ()unshift واللتان تقومان بالإضافة في نهاية المصفوفة أو بدايتها فقط. let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Splice a new item number into index position 1 fish.splice(1, 0, "manta ray"); fish; Output [ 'piranha', 'manta ray', 'barracuda', 'koi', 'eel' ] النص الجديد “manta ray” تم إضافته للمصفوفة في الفهرس رقم 1. الإزالة باستخدام ()splice إذا تجاهلنا المُعامل الثالث (الاختياري) في الوظيفة ()splice، نستطيع ببساطة إزالة أي عنصر في المصفوفة ومن أي موقع فيها: let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Remove two items, starting at index position 1 fish.splice(1, 2); fish; Output [ 'piranha', 'eel' ] في المثال السابق، قمنا بحذف عنصرين من المصفوفة ابتداء من الفهرس 1. إذا لم نقم بإدخال المعامل الثاني الذي يُمثل عدد العناصر التي نريد حذفها، سيتم حذف جميع عناصر المصفوفة ابتداءً من الفهرس 1 وحتى نهاية المصفوفة. الإضافة والإزالة باستخدام ()splice باستخدام كافة المعاملات للوظيفة ()splice، نستطيع إجراء كلتا عمليتي الإضافة والحذف في نفس الوقت. لتوضيح هذا، لنقم بحذف نفس العناصر السابقة في المثال قبل السابق واضافة العنصر الجديد في الفهرس 1: let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Remove two items and add one fish.splice(1, 2, "manta ray"); fish; Output [ 'piranha', 'manta ray', 'eel' ] الوظيفة ()splice تُعتبر وظيفة قوية في إجراء التعديلات على أي مصفوفة. انتبه أن لا يكون لديك لبس بين الوظيفة ()splice والوظيفة ()slice التي تُعتبر وظيفة من توابع الوصول وتقوم بإنشاء نسخة من جزء من مصفوفة. الوظيفة ()reverse تقوم هذه الوظيفة بعكس ترتيب العناصر في المصفوفة. let fish = [ "piranha", "barracuda", "koi", "eel" ]; باستخدام الوظيفة ()reverse، فإن العنصر الأخير سيكون الأول، والعنصر الأول سيكون اّخر العناصر، ولا تأخذ هذه الوظيفة أي معاملات. // Reverse the fish array fish.reverse(); fish; Output [ 'eel', 'koi', 'barracuda', 'piranha' ] الوظيفة ()fill تقوم الوظيفة ()fill باستبدال جميع عناصر المصفوفة بقيمة ثابتة. let fish = [ "piranha", "barracuda", "koi", "eel" ]; لنفترض وجود المصفوفة fish ولتحتوي على 4 عناصر، باستخدام الوظيفة ()fill سنستبدل جميع العناصر الأربعة بقيمة واحدة: // Replace all values in the array with "shark" fish.fill("shark"); fish; Output [ 'shark', 'shark', 'shark', 'shark' ] نستطيع أن نمرر للوظيفة ()fill معاملين إضافيين وكلاهما اختياري، ويمثلان فهرس البداية الذي نبدأ من عنده عملية الاستبدال وفهرس النهاية الذي ننهي عملية الاستبدال قبله. fish.fill("shark", 1) // > [ 'piranha', 'shark', 'shark', 'shark' ] fish.fill("shark", 1, 3); // > [ 'piranha', 'shark', 'shark', 'eel' ] الوظيفة ()sort الوظيفة ()sort تقوم بترتيب عناصر المصفوفة بناءً على الحرف الأول في العنصر. في حالة وجود أكثر من عنصر بنفس الحرف الأول، يتم الترتيب بناءً على الحرف الثاني وهكذا. بشكل تلقائي تقوم الوظيفة بالترتيب الأبجدي لمصفوفة نصية والتي يكون جميع عناصرها إما uppercase أو lowercase. let fish = [ "piranha", "barracuda", "koi", "eel" ]; // Sort items in array fish.sort(); fish; Output [ 'barracuda', 'eel', 'koi', 'piranha' ] بما أن الوظيفة ()sort تعتمد على الترميز النصي للحرف الأول، فإنها ستُرتب العناصر التي تكون حالتها uppercase قبل العناصر التي حالتها lowercase. انظر للمثال التالي: let fish = [ "piranha", "barracuda", "Koi", "eel" ]; fish.sort(); fish; Output [ 'Koi', 'barracuda', 'eel', 'piranha' ] الأرقام تأتي قبل الأحرف بغض النظر عن حالتها في ترتيب المصفوفة. انظر للمثال التالي: let fish = [ "piranha", "barracuda", "Koi", "1 eel" ]; fish.sort(); Output [ '1 eel', 'Koi', 'barracuda', 'piranha' ] لن تقوم الوظيفة بترتيب مصفوفة أعداد حسب قيمة الأعداد فيها (الأصغر ثم الأكبر)، ولكنها ستقوم بفحص الرقم الأول في كل عدد ويتم الترتيب بناءً عليه. let numbers = [ 42, 23, 16, 15, 4, 8 ]; numbers.sort(); Output [ 15, 16, 23, 4, 42, 8 ] لترتيب الأعداد في مصفوفة أعداد بطريقة سليمة وحسب قيمة الأعداد (من الأصغر إلى الأكبر)، نستطيع إنشاء وظيفة “مقارنة” ونمررها كمعامل للوظيفة ()sort: // Function to sort numbers by size const sortNumerically = (a, b) => { return a - b; } numbers.sort(sortNumerically); Output [ 4, 8, 15, 16, 23, 42 ] خاتمة في هذا الدرس، قمنا باستعراض أغلب وظائف توابع التعديل في لغة الجافا سكريبت. الوظائف من هذا النوع تقوم بالتعديل على المصفوفة الأصلية التي تستخدمها، على العكس من وظائف توابع الوصول، وتعلمنا خلال هذا الدرس كيفية إضافة وإزالة العناصر من المصفوفة في بدايتها أو نهايتها، بالإضافة لكيفية ترتيب المصفوفة، عكسها واستبدال عناصرها. لمراجعة أساسيات المصفوفات، راجع درس فهم المصفوفات في الجافا سكريبت. ترجمة -وبتصرّف- للمقال How To Use Array Methods in JavaScript Mutator Methods لصاحبه Tania Rascia حقوق الصورة البارزة محفوظة لـ Freepik
  14. مقدمة تُعتبر المصفوفة في الجافا سكريبت كائن عمومي (global) الغرض منه هو تخزين البيانات، وتحتوي المصفوفة إما على مجموعة من العناصر بنوع بيانات واحد أو أكثر، وقد تكون فارغة. نستخدم الفهارس العددية التي تبدأ من القيمة 0 للوصول إلى عناصر المصفوفة. المصفوفات مفيدة جدًا بما أنها تُخزن عدة قيم في متغير واحد، وهذا الأمر يقلل وينظم الشيفرة البرمجية التي نكتبها ويجعلها أكثر ملائمة للقراءة والصيانة. تستطيع المصفوفة أن تحتوي على أي نوع بيانات، ابتداءً من الأرقام ومرورا بالنصوص والكائنات وغيرها من أنواع البيانات. لتوضيح كيف من الممكن أن تكون المصفوفات مهمة، لنفترض أننا نريد أن نحفظ أسماء المحيطات في متغيرات عدة، بحيث يكون لكل محيط المتغير الخاص به: oceans.js // Assign the five oceans to five variables const ocean1 = "Pacific"; const ocean2 = "Atlantic"; const ocean3 = "Indian"; const ocean4 = "Arctic"; const ocean5 = "Antarctic"; هذه الطريقة مُضجرة جدا، وتُصبح أكثر صعوبة بشكل متسارع في المتابعة والصيانة. باستخدام المصفوفات، نستطيع تبسيط الأمر. oceans.js // Assign the five oceans let oceans = [ "Pacific", "Atlantic", "Indian", "Arctic", "Antarctic", ]; بدلًا من استخدام خمسة متغيرات منفصلة، نستطيع الان أن يكون لدينا متغير واحد يحتوي على جميع العناصر الخمسة. لإنشاء المصفوفة، نستخدم الأقواس المربعة [ ] كما هو واضح في الشيفرة البرمجية السابقة، وللوصول إلى عنصر معين في المصفوفة، نستخدم الفهرس مع المصفوفة بالطريقة التالية: // Print out the first item of the oceans array oceans[0]; Output Pacific في هذا الدرس سنتعلم كيفية بناء المصفوفة، وكيفية الوصول إلى عناصرها، والاضافة إليها وتعديلها والحذف منها، كما سنتعلم كيفية المرور خلال عناصرها باستخدام حلقة التكرار. إنشاء مصفوفة يوجد طريقتان لإنشاء المصفوفة في جافا سكريبت: التعريف اللفظي باستخدام الأقواس المعكوفة. التعريف بواسطة الباني (constructor) باستخدام كلمة new. لنوضح كيفية إنشاء مصفوفة تحتوي على أنواع سمك القرش، وذلك باستخدام التعريف اللفظي بواسطة الأقواس المربعة: sharks.js // Initialize array of shark species with array literal let sharks = [ "Hammerhead", "Great White", "Tiger", ]; الان نُعرف نفس المصفوفة باستخدام الباني وذلك بواسطة الجملة new Array() : sharks.js // Initialize array of shark species with array constructor let sharks = new Array( "Hammerhead", "Great White", "Tiger", ); كلا الطريقتين سوف يُنشئ لنا المصفوفة، ولكن طريقة التعريف اللفظي هي المشهورة والأكثر تفضيلا بما أن التعريف باستخدام الباني قد يؤدي إلى نتائج غير مستقرة وغير متوقعة وعليك الانتباه في حال صادفتك تلك الطريقة في التعريف أو في حال استخدامك لها. نستطيع طباعة محتويات المصفوفة بكتابة المتغير الخاص بها مباشرة: // Print out the entire sharks array sharks; Output [ 'Hammerhead', 'Great White', 'Tiger' ] تُستخدم المصفوفات عادة في تجميع العناصر أو القوائم من نفس نوع البيانات، ولكن من الناحية التقنية، فإن المصفوفات تستطيع أن تحتوي على عناصر من أنواع مختلفة بالإضافة إلى إمكانية أن تحتوي على مصفوفات أخرى: // Initialize array of mixed datatypes let mixedData = [ "String", null, 7, [ "another", "array", ], ]; بعد أن تعلمنا كيفية إنشاء المصفوفة، نستطيع الان التعامل معا بأكثر من طريقة، ولكننا في البداية نحتاج الى فهم كيفية فهرسة المصفوفات (Arrays Indexing). ملاحظة: قد تجد اخر عنصر في المصفوفة ينتهي بفاصلة وأحيانا قد لا تجد هذه الفاصلة. تُعرف هذه الفاصلة بالفاصلة التابعة (Trailing comma)، ومن الشائع ان تكون غير موجودة، ولكن بشكل عام أصبح من الأفضل أن يتم استخدامها في الشيفرة البرمجية بسبب أنها تجعل الاختلافات بين الإصدارات (في عملية إدارة الإصدارات Versions Control) أكثر وضوحا وتسهل من إضافة وإزالة عناصر المصفوفة دون أخطاء. لاحظ أن الفاصلة التابعة غير مسموح بها في ملفات JSON. فهرسة المصفوفات إذا تعاملت مسبقاً مع النصوص والفهرسة في الجافا سكريبت، ستكون مُلمًا بمفهوم فهرسة المصفوفات، حيث أن النص يُعتبر شبيهًا بالمصفوفة. لا تحتوي المصفوفات على عناصر مزدوجة على شكل اسم/قيمة، وبدلا من ذلك، فإن المصفوفات تُفهرس بقيم عددية تبدأ من القيمة 0. المثال التالي ينشئ مصفوفة باسم seaCreatures: seacreatures.js let seaCreatures = [ "octopus", "squid", "shark", "seahorse", "starfish", ]; الجدول التالي يُفصل كيف يتم فهرسة كل عنصر في المصفوفة بقيمة عددية ابتداءً من 0: octopus squid shark seahorse starfish 0 1 2 3 4 العنصر الأول في المصفوفة هو octopus ومُفهرس في الموقع 0 من المصفوفة، والعنصر الأخير هو starfish ومُفهرس في الموقع 4. تبدأ الفهرسة من 0، وهذا يتضارب مع طبيعتنا الفطرية ببدء العد من القيمة 1، لذلك نحتاج لأخذ الاحتياط وأن نتذكر هذه النقطة دائما حتى تصبح طبيعية. نستطيع أن نحصل على عدد العناصر في المصفوفة باستخدام الخاصية length: seaCreatures.length; Output 5 على الرغم من أن الفهارس الخاصة بالمصفوفة seaCreatuers تبدأ من 0 إلى 4، فإن الخاصية length سوف تُرجع العدد الفعلي للعناصر الموجودة في المصفوفة. إذا أردنا معرفة رقم الفهرس لعنصر معين في المصفوفة، وليكن مثلا seahorse، نستطيع أن نستخدم لذلك الوظيفة indexOf() : seaCreatures.indexOf("seahorse"); Output 3 إذا لم تحتوي المصفوفة على العنصر الذي نريده، فلن نحصل على رقم فهرس لعنصر غير موجود، وفي هذه الحالة، فإن الوظيفة سترجع لنا القيمة -1 كما في المثال التالي: seaCreatures.indexOf("cuttlefish"); Output -1 بواسطة أرقام الفهارس المرتبطة بعناصر المصفوفة، فإنه لدينا القدرة على الوصول لكل عنصر بشكل منفرد بهدف العمل على هذا العنصر والتعامل معه. الوصول لعناصر المصفوفة يتم الوصول لعنصر في مصفوفة جافا سكريبت بواسطة الإشارة لرقم الفهرس للعنصر بين قوسين معكوفين: seaCreatures[1]; Output squid نعلم أن الرقم 0 سيعيد لنا دائما العنصر الأول في المصفوفة. كذلك نستطيع إيجاد العنصر الأخير في المصفوفة بواسطة إجراء عملية طرح قيمة 1 من قيمة الخاصية length للمصفوفة، والإشارة لناتج هذه العملية كرقم فهرس للعنصر الأخير كما هو موضح في المثال التالي: const lastIndex = seaCreatures.length - 1; seaCreatures[lastIndex]; Output starfish محاولة الوصول لعنصر غير موجود سيعيد لنا undefined: seaCreatures[10]; Output undefined للوصول لعنصر مصفوفة متداخلة (مصفوفة داخل مصفوفة)، فعلينا إضافة فهرس اخر يعود للمصفوفة الداخلية: let nestedArray = [ [ "salmon", "halibut", ], [ "coral", "reef", ] ]; nestedArray[1][0]; Output coral في المثال السابق، قمنا بالوصول للعنصر coral بالإشارة لرقم الفهرس الذي يحتوي المصفوفة الداخلية وهو 1، ثم أشرنا للفهرس الذي يحتوي على العنصر في المصفوفة الداخلية وهو 0. إضافة عنصر لمصفوفة في المتغير seaCreatuers يوجد لدينا 5 عناصر بأرقام فهراس تبدأ من 0 الى 4. إذا أردنا أن نُضيف عنصر جديد لهذه المصفوفة، فيمكننا أن نقوم بذلك بإعطاء قيمة للفهرس التالي الذي يلي اخر فهرس: seaCreatures[5] = "whale"; seaCreatures; Output [ 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale' ] إذا قمنا بإضافة عنصر وتجاهلنا قيمة الفهرس التالي ووضعنا بدلا منه فهرس بقيمة 7 مثلا، فإن ذلك يؤدي لإضافة عنصر غير مُعرف (undefined) للمصفوفة كما في المثال التالي: seaCreatures[7] = "pufferfish"; seaCreatures; Output [ 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale', , 'pufferfish' ] هذه المشكلة نستطيع تجنبها باستخدام الوظيفة push() والتي تقوم بإضافة العنصر الجديد في نهاية المصفوفة: // Append lobster to the end of the seaCreatures array seaCreatures.push("lobster"); seaCreatures; Output [ 'octopus', 'squid', 'shark', 'seahorse', 'starfish', , 'whale', 'pufferfish', 'lobster' ] على العكس تماما من الوظيفة push()، فإن الوظيفة unshift() تقوم بإضافة العنصر في بداية المصفوفة: // Append dragonfish to the beginning of the seaCreatures array seaCreatures.unshift("dragonfish"); seaCreatures; Output [ 'dragonfish', 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale', , 'pufferfish', 'lobster' ] باستخدام الوظيفتين السابقتين، ستكون لديك المقدرة على إضافة عناصر جديدة للمصفوفة إما في بدايتها، أو نهايتها. إزالة عنصر من مصفوفة لإزالة عنصر معين من مصفوفة، نستخدم الوظيفة splice(). في المصفوفة seaCreatuers قمنا بإضافة عنصر غير مُعرف وليس له قيمة، ولإزالته نقوم بالتالي: seaCreatures.splice(7, 1); seaCreatures; Output [ 'dragonfish', 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale', 'pufferfish', 'lobster' ] في الوظيفة splice()، المُعامل الأول يشير لرقم الفهرس الذي سنبدأ بالإزالة من عنده (في هذه الحالة 7)، والمُعامل الثاني يشير لعدد العناصر التي نرغب بإزالتها (في حالتنا سيكون 1 حيث أننا نرغب بإزالة عنصر واحد). الوظيفة splice() ستؤثر على المتغير الأصلي. لذلك، إذا أردنا أن نحافظ على المصفوفة الأصلية دون تغيير، نستخدم الوظيفة slice() ونعطي القيمة الناتجة عنها لمتغير جديد. let newArray = slice(7, 1); الوظيفة pop() ستزيل العنصر الأخير من المصفوفة: // Remove the last item from the seaCreatures array seaCreatures.pop(); seaCreatures; Output [ 'dragonfish', 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale', 'pufferfish' ] العنصر lobster أُزيل من المصفوفة لأنه العنصر الأخير، ولإزالة العنصر الأول في المصفوفة، نستخدم الوظيفة shift(): // Remove the first item from the seaCreatures array seaCreatures.shift(); seaCreatures; Output [ 'octopus', 'squid', 'shark', 'seahorse', 'starfish', 'whale', 'pufferfish' ] باستخدام الوظيفتين pop() و shift() نستطيع إزالة العناصر من بداية المصفوفة أو نهايتها. يُفضل استخدام الوظيفة pop() قدر الإمكان، حيث أن باقي العناصر في المصفوفة تبقى في مواقعها دون تغيير. تعديل العناصر في المصفوفة نستطيع تغيير أي قيمة عنصر في المصفوفة وذلك بإعطاء القيمة الجديدة للعنصر باستخدام عملية المساواة، كما نفعل تماما عند التعامل مع المتغيرات العادية: // Assign manatee to the first item in the seaCreatures array seaCreatures[0] = "manatee"; seaCreatures; Output [ 'manatee', 'squid', 'shark', 'seahorse', 'starfish', 'whale', 'pufferfish' ] طريقة أخرى لتغيير قيمة العنصر باستخدام الوظيفة splice() وذلك بإضافة مُعامل جديد. فمثلا، إذا أردنا تغيير قيمة العنصر seahorse والذي يقع في الفهرس 3، نستطيع إزالته وإضافة قيمة جديدة بدلا منه: // Replace seahorse with sea lion using splice method seaCreatures.splice(3, 1, "sea lion"); seaCreatures(); Output [ 'manatee', 'squid', 'shark', 'sea lion', 'starfish', 'whale', 'pufferfish' ] في المثال السابق، قمنا بإزالة العنصر seahorse من المصفوفة، ووضعنا بدلا منه القيمة sea lion في نفس الفهرس 3. حلقة التكرار خلال المصفوفة نستطيع المرور على عناصر المصفوفة من خلال حلقة تكرار for وذلك بالاستفادة من خاصية length. في المثال التالي، نُنشئ مصفوفة باسم shellfish ونطبع رقم كل فهرس فيها بالإضافة إلى قيمة العنصر المرتبط بالفهرس: // Create an array of shellfish species let shellfish = [ "oyster", "shrimp", "clam", "mussel", ]; // Loop through the length of the array for (let i = 0; i < shellfish.length; i++) { console.log(i, shellfish[i]); } Output 0 'oyster' 1 'shrimp' 2 'clam' 3 'mussel' نستطيع أيضا استخدام حلقة التكرار for…of وهي خاصية جديدة في الجافا سكريبت: // Create an array of aquatic mammals let mammals = [ "dolphin", "whale", "manatee", ]; // Loop through each mammal for (let mammal of mammals) { console.log(mammal); } Output dolphin whale manatee حلقة التكرار for…of لا تقوم باستخدام رقم الفهرس للعناصر في المصفوفة، ولكنها بشكل عام طريقة أبسط وأكثر اختصارا للمرور على المصفوفة من خلال حلقة التكرار. استخدام حلقات التكرار مفيد بشكل كبير في طباعة قيم عناصر المصفوفة وهو يشبه عرض العناصر من قاعدة بيانات خلال موقع الكتروني. خاتمة تُعتبر المصفوفات جزء أساسي ومهم في برمجة الجافا سكريبت. في هذا الدرس تعلمنا كيفية إنشاء المصفوفة، وكيفية فهرستها، وتعلمنا إجراء بعض العمليات المهمة على المصفوفات مثل إزالة العناصر والتعديل عليها. وكذلك تعلمنا طريقتين للمرور على عناصر المصفوفة من خلال حلقات التكرار والتي تهدف لإجراء عمليات على عناصر المصفوفة مثل طباعة محتوياتها وطباعة أرقام الفهارس. ترجمة -وبتصرّف- للمقال Understanding Arrays in JavaScript لصاحبه Tania Rascia حقوق الصورة البارزة محفوظة لـ Freepik
×
×
  • أضف...