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

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

  1. سارة فايز

    سارة فايز

    الأعضاء


    • نقاط

      3

    • المساهمات

      5


  2. عبد اللطيف ايمش

    • نقاط

      2

    • المساهمات

      1395


  3. وصال الأحدب

    وصال الأحدب

    الأعضاء


    • نقاط

      1

    • المساهمات

      3


  4. حسام برهان

    حسام برهان

    الأعضاء


    • نقاط

      1

    • المساهمات

      215


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

المحتوى الأعلى تقييمًا في 04/17/17 في كل الموقع

  1. هذا هو الدرس الأول من درسين يشرحان لك كيف تطوِّر مواقع الويب ذات الاتجاه من اليمين إلى اليسار (RTL)، وهذا يعني جعل موقع الويب متوافقًا مع اللغات التي تُكتَب من اليمين إلى اليسار مثل العربية والفارسية والأردو. ماذا يعني اتجاه الكتابة من اليمين إلى اليسار؟ لتوضيح الأمور، هنالك فرقٌ بين اللغة (التي هي الشكل المحكي) والمخطوطة (script، أي طريقة الكتابة). أي تقنيًا، الاتجاه من اليمين إلى اليسار يكون للمخطوطات التي تُكتَب بها اللغات، وذلك مقارنةً مع الاتجاه من اليسار إلى اليمين في لغاتٍ مثل الإنكليزية أو الفرنسية. مصطلح «اليمين-إلى-اليسار» (Right-to-Left) أو RTL اختصارًا، يُشير إلى أكثر من مجرد المخطوطة المستعملة للكتابة؛ حيث يُشير إلى جميع الأمور المتعلقة بتطوير مواقع وتطبيقات الويب لكي تظهر بشكل سليم عند استخدام اللغة العربية أو غيرها من اللغات التي تُكتَب من اليمين إلى اليسار. قبل المتابعة، لنوضِّح بعض الالتباسات حول RTL. أولًا، RTL لا تعني ترجمة النص إلى العربية: فالأمر أكثر من مجرد ترجمة واجهة موقعك إلى العربية، وإنما جعل كل جزء من الواجهة الرسومية ملائمًا لاتجاه RTL؛ وأنصحك أن تفعل ذلك بشكلٍ صحيح، فعدم إكمالك لدعم اتجاه RTL سيفقدك زوارك ومصداقيتك. ثانيًا، اتجاه RTL لا يعني «قلب كل شيء»: لستُ متأكدًا إن أُصلِحتَ هذه العلة أم لا، لكن ضبط «المحلية» (locale) إلى العربية في واجهة Gnome سيؤدي إلى إظهار الوقت بالشكل «PM 33:12» بدلًا من «‏12:33‎ PM‏‏». هذا ليس صحيحًا، نحن لا نذكر الوقت بالمقلوب بالعربية. أي أنَّ هنالك استثناءات وأشياء يجب الانتباه إليها مثل الأرقام، وسنشرح ذلك لاحقًا. لماذا عليك أن تهتم بدعم موقعك لاتجاه RTL؟ ربما تطور مواقع عالمية بلغاتٍ مثل الإنكليزية أو الفرنسية، وأنت متخوفٌ من RTL وتحسبها صعبةً ومرعبةً وستُضيف كمًا كبيرًا من العمل على مشروعك. حسنًا، الأمر ليس كما تظن، فبعد أن تستوعب المبادئ الأساسية، فلن تحتاج إلا لبذل جهدٍ قليلٍ. من البدهي أن تهتم –كمطور ويب عربي– بدعم الموقع التي تطوره للغة العربية (أو لبقية اللغات التي تُكتَب من اليمين إلى اليسار)؛ فلا حاجة لتذكيرك أنَّ هنالك أكثر من 410 مليون شخص حول العالم يتحدث لغةً تُكتَب من اليمين إلى اليسار (وهذا عددٌ ضخمٌ جدًا. لاحظ أنَّ الرقم التقديري السابق مبنيٌ على قائمة اللغات في ويكيبيديا). أصبحت أغلبية الشركات تُضيف دعمًا للغات المكتوب من اليمين إلى اليسار في برمجياتها (مثل ويندوز، و iOS، وأندرويد) وكذلك الأمر للعديد من المواقع العالمية؛ لذا سيتوقع زوار موقعك مِمَن يتحدثون العربية (وغيرها من اللغات المكتوبة من اليمين إلى اليسار) أن يحقق موقعك هذه التوقعات بما يخص دعم RTL. فبدون هذا الدعم قد لا يتحول زوار موقعك إلى زوارٍ دائمين. دورة تطوير واجهات المستخدم ابدأ عملك الحر بتطوير واجهات المواقع والمتاجر الإلكترونية فور انتهائك من الدورة اشترك الآن نصائح عامة لدعم اتجاه RTL هذه بعض القواعد العامة التي أحببت أن أذكرك بها والتي عليك أن تبقيها ببالك عند تطوير تطبيقات ومواقع ويب تدعم RTL: ابدأ من اليمين: تُفتح الكتب من الطرف الأيمن في البلدان التي تتحدث بلغاتٍ مكتوبةٍ من اليمين إلى اليسار، ولهذا يجب أن تُقلَب أغلبية عناصر الواجهة المتعلقة بمقروئية النص. الأزرار العتادية لها نفس الترتيب في البلدان المتحدثة بالعربية: أماكن أزرار التحكم بالأجهزة الصوتية هو نفسه في البلدان التي تتحدث لغاتٍ تكُتَب من اليمين إلى اليسار. لذا لن تتغير أماكن أزرار «التشغيل» و«التمرير» و«الإيقاف المؤقت» و«الإيقاف». ولهذا فلا يُنصَح أن يُقلَب اتجاه أيٌ من تلك الأزرار. مثالٌ آخر هو أزرار الهواتف، فقبل ظهور الهواتف الذكية كانت هنالك الهواتف الأرضية التي ما تزال شائعةً جدًا في البلدان العربية. ولهذا السبب يكون من المستحسن ألّا نعكس مفاتيح الأرقام. لا تظن أنَّ مستخدمي RTL هم أشخاصٌ يستعملون أياديهم اليسرى. فأغلبية مَن يتحدث بالعربية يكتبها بيده اليمنى، كما هو الحال في بقية أنحاء العالم. لذا لا تقلب أيّ شيءٍ ليس متعلقًا بكيفية قراءة المستخدم لمحتوى الصفحة. مثالٌ على هذا هو شريط التمرير «أ-ي A-Z» (الموجود على يمين الصورة السابقة) في تطبيق «جهات الاتصال» في أغلبية الهواتف الذكية. هذا الشريط موضوعٌ على الجهة اليمنى لأنه من الأسهل استخدامه باليد اليمنى، لذا لا حاجة إلى قلب اتجاهه وجعله في الجزء الأيسر في نمط RTL. كيفية جعل المحتوى RTL أول خطوة نحو جعل اتجاه صفحة الويب من اليمين إلى اليسار هي إضافة dir="rtl"‎ إلى وسم <html>: <html dir="rtl"> الخاصية dir هي اختصارٌ لكلمة «direction»، وضبط قيمتها إلى rtl تجعل نقطة البداية الأفقية لعناصر صفحة الويب من اليمين بدلًا من اليسار. لكي تضع نمط CSS لعنصرٍ معيّن إذا كانت الصفحة RTL فقط: أنشِئ نسخةً من أيّة أنماط CSS اعتيادية التي ستُطبَّق على العنصر الهدف. أضف المُحدِّد html[dir="rtl"] قبل سلسلة المُحدِدات (selector chain). كلما وجدت خاصيةً أو قيمة تُمثِّل التموضع الأفقي للعنصر، فاستعمل القاعدة المُعاكسة لها. على سبيل المثال، إذا وجدتَ float: left فبدِّلها إلى float: right. كمثالٍ عمليٍ على كلامنا السابق، إذا كان أحد أنماط CSS كالآتي: .someClass { text-align: left; padding: 0 10px 0 0; text-decoration: underline; } فسنأخذ نسخةً منه ونحدِّثها كالآتي: html[dir="rtl"] .someClass { text-align: right; padding: 0 0 0 10px; } لاحظ أننا حذفنا القاعدة text-decoration: underline;‎، فلسنا بحاجة إلى إعادة تعريف هذه القيمة لنسخة RTL لأنها لا تؤثر على اتجاه أي عنصر. وبالتالي ستُطبَّق القاعدة الأصلية. هذا مثالٌ أكثر تفصيلًا. يمكنك أن تجربه مباشرةً على متصفحك. شيفرة HTML: <html dir="ltr"> <body> <input type="button" id="directionSwitch" value="Switch LTR/RTL"/> <hr/> <div class="boxOne"></div> <div class="boxTwo"></div> </body> </html> شيفرة CSS: .boxOne { width: 170px; height: 170px; background-color: #0072C6; margin: 0 0 0 20px; } .boxTwo { width: 120px; height: 120px; background-color: #C3191E; margin: 0 0 0 70px; } html[dir="rtl"] .boxOne { margin: 0 20px 0 0; } html[dir="rtl"] .boxTwo { margin: 0 70px 0 0; } شيفرة JavaScript: document.getElementById('directionSwitch').addEventListener('click', function() { var docDirection = document.documentElement.dir; var isRTL = (docDirection === 'rtl'); document.documentElement.dir = isRTL ? 'ltr' : 'rtl'; }); لن تكون الحالات العملية بهذه البساطة؛ فهنالك تطبيقاتٌ فيها عددٌ كبيرٌ جدًا من قواعد CSS ومن المحددات، ولديك عدِّة استراتيجيات يمكنك اتباعها. وهذه إحداها: انسخ القواعد واحذف ما ليس لازمًا: أولًا، انسخ محتوى صفحة الأنماط إلى ملفٍ آخر، وأضف html[dir="rtl"] إلى جميع القواعد، ثم احذف أيّة خاصيات لا تتعلق بالاتجاه الأفقي للعناصر. وسينتهي بك المطاف بملفٍ صغيرٍ هدفه هو التعامل مع اتجاه RTL فقط. اقلب الاتجاهات: عدِّل كل الخاصية التي تُشير إلى اليسار (left) في الملف الجديد إلى معاكسها: أي padding-left ستصبح padding-right، و float: right ستصبح float: left …إلخ. لاحظ أنَّه إذا كان عندك خاصية padding-left في الملف الأصلي ثم عدَّلتها إلى padding-right فستبقى الخاصية الأصلية padding-left مطبقةً. لذا عليك إضافة الخاصية padding-left: unset بالإضافة إلى خاصية padding-right، وإلا فسيُطبِّق المتصفح كلا القاعدتين: خاصية padding-left من ملف CSS الأصلي وخاصية padding-right من الملف المعدَّل لاتجاه RTL. والأمر مشابهٌ لبقية الخاصيات مثل margin-left|right و border-left|right … أعد لصق المحتويات في الملف الأصلي: بعد أن تنتهي من إكمال الخطوتين السابقتين، فالصق القواعد الجديدة في الملف الملف الأصلي بعد القواعد الأصلية. أفضِّل شخصيًا أن أضيف تعليقًا صغيرًا مثل /* **** RTL Content **** */ لكي أستطيع التفريق بسهولة بين الأنماط الأصلية والأنماط المُعدَّلة لاتجاه RTL. طريقة أفضل: فصل أنماط RTL و LTR عن بعضهما قد تواجه في بعض الأحيان حالاتٍ غريبة التي يحدث فيها تضاربٌ بين الأنماط. وهذا يتضمن وراثة قيم بعض الخاصيات من خاصياتٍ أخرى، مما يعني أنَّك في بعض الأحيان لا تعرف تمامًا ما هي القاعدة التي عليك تجاوزها. وربما أضفتَ margin-right إلى قواعد RTL لكنك لستَ متأكدًا ما هي القيمة التي عليك ضبطها إلى خاصية margin-left الأصلية. أرى أنَّه من المستحسن أن تتبع منهجية أخرى، والتي هي أفضل في الحالات العملية لكنها أطول بعض الشّيء. سنفصل الخاصيات التابعة لكل اتجاه (RTL و LTR) عن بعضها بعضًا تمامًا. هذا مثالٌ عنها: لنقل أنَّنا لدينا قاعدة تتضمن ‎.wrapper .boxContainer .fancyBox كالآتية: .wrapper .boxContainer .fancyBox { text-align: left; padding-left: 10px; text-decoration: underline; color: #4A8CF7; } بدلًا من إضافة خاصيات أخرى لاتجاه RTL فيها padding-left و padding-right، فيمكنك أن تكتب: .wrapper .boxContainer .fancyBox { text-decoration: underline; color: #4A8CF7; } html[dir="ltr"] .wrapper .boxContainer .fancyBox { text-align: left; padding-left: 10px; } html[dir="rtl"] .wrapper .boxContainer .fancyBox { text-align: right; padding-right: 10px; } هذا الحل يتضمن ثلاثة أجزاء: القاعدة (أو المُحدِّد) الأصلية وفيها خاصياتٌ ليست متعلقة بالاتجاه، لأنها مشتركة بين الاتجاهين RTL و LTR. محدد يُعالج الاتجاه من اليسار إلى اليمين –html[dir="ltr"]– لا يوجد فيه سوى خاصيات لها علاقة بالاتجاه والتي تتوافق قيمها مع التخطيط (layout) الذي لديك لاتجاه LTR. مُحدِّد يعالج الاتجاه من اليمين إلى اليسار –html[dir="rtl"]– بنفس خاصيات حالة LTR، لكن قيمها مضبوطة لكي تتوافق مع التخطيط الذي لديك لاتجاه RTL. لاحظ كيف أنَّ القاعدة الثانية تملك خاصية padding-left فقط، بينما القاعدة الثالثة تملك خاصية padding-right فقط. وهذا لأنَّ كل واحد منها خاصة بالاتجاه المُحدَّد في خاصية dir. هذه الطريقة جيدة وجميلة ويسهل التعامل معها، ولا تحتاج فيها إلى حذف قيم بعض الخاصيات (لاحظ أنَّ الكلمة المحجوزة unset غير مدعومة في جميع المتصفحات. لأكبر قدر من التوافقية، عليك أن تُعيد تعريف القيمة التي ترغب بها لأي خاصية تريد حذف قيمتها). كيفية ضبط اتجاه الصفحة باستخدام JavaScript؟ هذا سهلٌ جدًا، ويتطلب سطرًا وحيدًا فقط: document.documentElement.dir يمكنك طباعة هذه القيمة إلى console كما يلي: var direction = document.documentElement.dir; console.log(direction); أو تستطيع تجربة المثال الحي. استعمل السطر الآتي لضبط اتجاه الصفحة: document.documentElement.dir = "rtl" هذا مثالٌ متكاملٌ حول الحصول على قيمة اتجاه الصفحة وضبطها: شيفرة HTML: <html dir="ltr"> <body> <input type="button" value="Set document direction to RTL" id="setDirection"/> <div id="directionStatus"></div> </body> </html> شيفرة JavaScript: function getDirection() { var direction = document.documentElement.dir; document.getElementById('directionStatus').textContent = 'This document\'s direction is: ' + direction; } var dirButton = document.getElementById('setDirection'); dirButton.addEventListener('click', function(evt) { var isRTL = (document.documentElement.dir === 'rtl'); document.documentElement.dir = isRTL ? 'ltr' : 'rtl'; dirButton.value = isRTL ? 'Set document direction to RTL' : 'Set document direction to LTR'; getDirection(); }); حلول مؤتمتة تحدثنا بما فيه الكفاية عن الطرق اليدوية لقلب الاتجاه إلى RTL. لننظر الآن إلى بعض الحلول المؤتمتة. css-flip طوَّرت تويتر حلًا لأتمتة كامل العملية وجعل قلب الاتجاه إلى RTL أسهل للمشاريع الكبيرة. هذا المشروع مفتوح المصدر ويمكنك أن تجده على Github. إضافة NPM هذه تغطي جميع الحالات التي قد تواجهها عندما تعمل على قلب الاتجاه إلى RTL، بما في ذلك الحالات الغريبة. بعض ميزاتها: no-flip: لإخبار مُحرِّك القلب أنَّك لا تريد أن تُقلَب هذه الخاصية وذلك بإضافة /* @noflip*/ في بداية الخاصية. على سبيل المثال، إذا كتبتَ ‎/* @noflip*/ float: left فستبقى الخاصية float: left عند تشغيل css-flip. replace: عندما تكون لديك صور خلفية تختلف بين RTL و LTR، فيمكنك أن تُحدِّد صورةً بديلةً بتضمين ‎/*@replace: url(my/image/path) */‎ قبل الخاصية الأصلية. فلنقل أنَّ لديك الخاصية background-image: url(arrow-left.png) وإذا حدثت السطر إلى ‎/*@replace: url(arrow-rightish.png) */ background-image: url(arrow-left.png);‎ فستصبح الخاصية النهائية في اتجاه RTL كالآتية: background-image: url(arrow-rightish.png);‎. يمكنك استعمال css-flip عبر سطر الأوامر بتنفيذ css-flip path/to/file.css > path/to/file.rtl.css أو عبر تضمين css-flip في صفحتك. للمزيد من المعلومات راجع مستودع github. يجدر بالذكر أنَّ css-flip يُستعمَل في برمجيات تويتر. rtlcss أداةٌ أخرى لأتمتة العملية برمجها «محمد يونس» تدعى rtlcss التي تتوفر على github وتوفر ميزاتٍ رائعة. يمكنك باستخدام هذه الأداة أن: تعيد تسمية القواعد (مثلًا، إعادة تسمية ‎#boxLeft إلى ‎#boxRightSide). تتجاهل بعض القواعد من عملية القلب. تتجاهل خاصياتٍ معينة. تضيف قيمًا جديدة. تضيف قيم خاصيات جديدة بين قيم الخاصيات الأخرى. يمكنك استخدام هذه الأداة عبر سطر الأوامر؛ ويمكنك إنشاء ملف أنماط RTL بتنفيذ الأمر الآتي في نفس المجلد الذي يتوفر فيه ملف CSS الأصلي: rtlcss input.css output.rtl.css أو يمكنك أن تضمنه في صفحتك. للمزيد من المعلومات راجع صفحة المشروع على github. هذا المشروع مشهور جدًا ويستعمل من عدِّة مشاريع بما فيها ووردبريس. خاتمة ما يزال هنالك الكثير لنغطيه، لكن هذه المقالة أمدتك بالمعلومات اللازمة لبدء مشوارك مع RTL. سنشرح في المقالة القادمة مواضيع متقدمة عن RTL. إذا كانت لديك أيّة أسئلة حول RTL، فاطرحها في التعليقات. ترجمة -وبتصرّف- للمقال Building RTL-Aware Web Apps & Websites: Part 1 لصاحبه أحمد نفزاوي
    1 نقطة
  2. كيف تتعلم البرمجة هو سؤال من أشهر الأسئلة على الإنترنت التي تدور في فلك البرمجة وعلوم الحاسوب وشهرته تأتي من كون البرمجة programming من أهم المجالات وأكثرها طلبًا في وقتنا الحالي، ولا أحد ينكر أنها جزءٌ أصيلٌ مرتبط بالتقنية التي تشكل حاضرنا ومستقبلنا، فكل شيء أصبح مرتبط بالحواسيب ويحتاج الحاسوب إلى أن نخاطبه بلغته للتواصل معه وتوجيهه وتلقينه الأوامر. وبذكر الحاسوب، فقد أصبحنا محاصرين بكم كبير من الحواسيب حولنا بدءًا من هواتفنا الذكية التي هي حواسيب مصغَّرة مرورنا بآلة الغسيل وجلي الصحون وحتى الطائرات، ولنذكر أن عالمنا الآن يتجه إلى أتمتة المعلومات وحوسبة العمليات على جميع الأصعدة بطريقة سريعة وبعيدًا عن الروتين، كما يتجه إلى الاعتماد على التطبيقات الحاسوبية اعتمادًا كبيرًا وكل ذلك لا يتحقق إلا بوجود عدد كبير من المبرمجين لبرمجتها. تعد البرمجة من المهارات الرائعة صراحة إذ تمكنك من بناء تطبيقات مفيدة تحل الكثير من المشكلات الحياتية كما قد تخترع أنظمة وتقنيات مفيدة للبشرية مثل أنظمة الاتصالات وأيضًا الأنظمة البنكية وأنظمة البيع والشراء وغيرها التي سهلت حياة البشر وزادت من إنتاجيتهم وقدراتهم، فعملك كبمرمج يكسبك دومًا خبرات متجددة تزداد مع زيادة سنوات عملك كمبرمج، ولا ننسَ أن أشهر أثرياء عالمنا اليوم هم مبرمجون في الأصل. أضف إلى أن البرمجة توسع من خبرتك باطراد دائم، وتفتح لك أبوابًا لمهن مطلوبة في يومنا الحالي وبشدة أكثر من أي مهنة أخرى، لتؤمن لك دخلًا جيدًا بل وحتى حرية ومرونة في العمل أينما كنت حتى من منزلك فلا يتطلب في بعض الحالات وجود المبرمج في موقع العمل. بناءً على ما سبق، من الطبيعي أن ترى أعداد المتوافدين على باب تعلم البرمجة كبيرًا يزداد يومًا بعد يوم، وتحتاج قبل دخوله وبدء تعلم البرمجة إلى امتلاك بوصلة تهديك طيلة الطريق فبدونها ستضيع في هذا العالم الكبير الواسع وقد تنسحب منه وتعود أدراجك لعدم سلوكك الطريق الصحيح، لذا ستحصل في نهاية هذا المقال على بوصلة كيف تتعلم البرمجة تعينك على دخول هذا الطريق من أسهل طرقه وأسرعها إلى امتلاك الخبرة ودخول سوق العمل، فهل أنت جاهز؟ لننطلق! فهرس المحتويات ماذا تعني البرمجة؟ لماذا تتعلم البرمجة؟ طرق لتعلم البرمجة تعلم البرمجة عبر الجامعة تعلم البرمجة عن بعد عبر الإنترنت كيف تتعلم البرمجة مفاهيم تعلم البرمجة: التأسيس الصحيح أدوات تعلم البرمجة: اختيار الوجهة والتخصص نصائح لتعلم البرمجة أسئلة شائعة حول كيف تتعلم البرمجة هل تعلم البرمجة صعب؟ هل يؤثر نمط شخصيتي على تعلم البرمجة؟ هل احتاج إلى إتقان اللغة الإنجليزية لتعلم البرمجة؟ هل هناك مصادر عربية لتعلم البرمجة؟ هل احتاج إلى خبرة في الرياضيات لتعلم البرمجة؟ كيف تتعلم البرمجة من الصفر؟ أنا لست منظمًا فكيف ألتزم في تعلم البرمجة بنفسي؟ هل يمكنني تعلم البرمجة عبر الجوال؟ ماذا تعني البرمجة؟ البرمجة -كما ذكرنا باختصار في المقدمة- هي الطريقة الوحيدة للتخاطب مع الحواسيب والأجهزة الإلكترونية الذكية لإخبارهم بكيفية تنفيذ الأوامر والمهام التي يجب عليهم تنفيذها، فعلى الرغم من ظننا بأن الحواسيب والأجهزة ذكية كما يقال، إلا أن تلك المقولة خطأ لأن تلك الأجهزة لا تفكر ولا تتمتع بذرة من الذكاء وإنما تتسم بالسرعة والدقة الكبيرة في تنفيذ ما يُقال لها فقط. إذًا، البرمجة هي الطريقة وأسلوب سرد الخطوات المراد تنفيذها للحاسوب بناء على خوارزمية معينة أما الأداة المستخدمة في توضيح تلك الطريقة والخطوات فهي لغة البرمجة وبما أنها أداة فالأدوات كثيرة لتناسب مختلف الاحتياجات لهذا تجد الكثير من لغات البرمجة أما المفهوم والأسلوب فهو شبه ثابت لا يتغير وهنا قد تتطرق في طريق تعلم البرمجة إلى مفهوم لخوارزميات التي يمكن تنفيذها بأكثر من لغة برمجة. لماذا تتعلم البرمجة؟ هناك طلب كبير على مطوري البرامج اليوم، إذ سيزداد الطلب عليهم بنسبة 22 بالمائة بين عامي 2022 و 2030 وفقًا لمكتب إحصاءات العمل الأمريكي وذلك موازنةً بأربعة بالمائة بالنسبة للوظائف الأخرى، إذ تُعَدّ البرمجة مجال العصر والأكثر طلبًا في الوقت الحالي بين المهن الأخرى كما ذكرنا، فامتلاكك لهذه المهارة بمثابة امتلاكك لنقطة من نقاط قوة هذا العصر وتفتح لك أبوبًا واسعة في سوق العمل وضمن قطاعات مختلفة بسبب التقدم الرهيب في التقنية. كما تتعدد الأسباب حول الهدف من تعلم البرمجة، ولكن أكثرها انتشارًا هو ما يلي: تُعَدّ البرمجة مهنة عالمية عابرة للدول والقارات، إذ يمكن تطبيقها وتوظيفها في أيّ بلد كان مهما كانت ثقافته أو لغته. تعلم البرمجة مهم كون العالم يتجه إلى أتمتة المعلومات كما ذكرنا، وبالتالي تسريع المهام الروتينية وتوفير المزيد من الوقت والجهد البشري. يتعلق تعلم البرمجة بصورة أساسية بتعلم المنطق والرياضيات، لذا فهي توجّه ممتع لمن يهتم بمثل هذه المجالات. تحقيق مكاسب مادية، إذ يتقاضى المبرمجون رواتب عالية من خلال وظائف في شركات كبرى أو من خلال مشاريع ذاتية يصممها المبرمج بذاته ويبيعها لجهة معينة. تمكّنك من العمل الحر عبر منصات عمل حر مثل مستقل دون التقيد بجهة معينة كما يمكنك العمل من أيّ مكان كان من منزلك مثلًا، وبالتالي ستوفر عليك العديد من الالتزامات مثل قوانين بيئة العمل، وبعض النفقات مثل المواصلات. ممارسة البرمجة على أساس هواية إلى جانب عمل رئيسي آخر، فكثير من الأحيان قد تصادف أشخاصًا مهتمين بتعلم البرمجة وهم أساسًا أطباء على سبيل المثال وذلك لكونها شيء مكتسب بالتعلم والقراءة والممارسة وليست موهبةً أو شيئًا موروثًا. تعلم خوارزميات من خلال البرمجة يعزز عدد من المهارات لديك مثل مهارات التواصل وحل المشكلات وحتى مهارة الصبر. تفيد البرمجة في توسيع المعرفة وتعلّم تصميم حلول لأيّ مشكلة تواجهك، إذ تُعَدّ البرمجة طريقة تفكير منظمة وطريقة لتبسيط المشكلة وتفكيكها إلى أجزاء صغيرة يمكن التعامل معها بصورة أسهل. تعزيز الإبداع والاختراع لدى المبرمج، إذ سيصبح توّاقًا لتقديم أفضل ما لديه ومنافسة ذويه والسعي نحو تقديم مشاريع جديدة غير متوفرة سابقًا. طرق لتعلم البرمجة هنالك عدة طرق لتعلم البرمجة ودخول مجال علوم الحاسوب ولكن سأصنفها ضمن مسارين عريضين، الأول عبر التعليم الجامعي والثاني عبر التعليم الحر، وسأشرح كل منهما بالتفصيل مع توضيح مزايا وتحديات كل منهما. وإن كنت مهتمًا بتعلم البرمجة والتخصص بها ولم تختر مسارك بعد، فأنصحك أن تركز على هذا القسم بعناية لتحديد مسارك التعليمي. تعلم البرمجة عبر الجامعة يمكن تعلم البرمجة عبر مسار الجامعة بدخول إحدى التخصصات المرتبطة بها مثل تخصص علوم الحاسوب computer science أو تخصص هندسة البرمجيات software engineering أو هندسة الحاسوب computer engineering وستدرس بانتظام وعبر سنوات بين 4 إلى 5 سنوات هذا التخصص لتتخرج بدرجة بكالوريوس ويمكنك أن تكمل بعدها إلى مرحلة الماجستير والدكتوراه، وهذا الخيار مناسب تمامًا لك إن كنت تفكر في تسلق هذا السلم والذي تكون نهايته المهنية غالبًا العمل في مهنة التدريس في المؤسسات التعليمية. هذا الطريق أشهر الطرق لتعلم البرمجة ويتسم بأنه الأطول ولا يمكن البدء به إلا عند الدخول بالمرحلة الجامعية، ومن خلال هذه الطريق سيتلقى الشخص شهادة جامعية رسمية ومعترف عليها في سوق العمل بغض النظر عن الخبرة العملية التي يكتسبها خلال مسيرته الدراسية والتي تكون قليلة نوعًا ما وغير كافية. ضع في بالك أمر مهم في هذا المسار وهو أنك ستتعلم الكثير من المواد -وأحيانًا بتعمق- كما ذكرنا مثل الرياضيات المتقدمة وقواعد البيانات وأنظمة التشغيل والأنظمة المتقدمة والدارات الكهربائية والمنطقية والشبكات الحاسوبية وغيرها من المواد النظرية التي أما قد لا تهمك ولا ترغب في التخصص فيها والعمل فيها وإما أنها لا تفيد بشكل مباشر في الحياة العملية التطبيقية لاحقًا (تضيف مثلًا بعض الجامعات مواد إثرائية مثل تاريخ وجغرافية وأدب) مما يعني نسيانها لاحقًا وإضاعة للوقت والجهد. العائق الوحيد للدخول في هذا الطريق هو المُعدَّل الدراسي المطلوب بالنسبة للجامعات الحكومية والذي يكون مرتفعًا، وذلك لأن المقاعد الدراسية محدودة؛ أما بالنسبة للجامعات الخاصة، فستحتاج إلى مبلغ مالي قد تجده كبيرًا لتستطيع التسجيل في الجامعة وتتمة سنواتها الدراسية، فضلًا عن التفرغ الكامل للجامعة وتأمين النفقات اليومية البسيطة ما بين مواصلات ومعيشة ووربما تحتاج إلى كتب وقرطاسية وغيرها من نفقات إضافية طارئة، ولا ننسى أنه إذا كنت من محافظة تختلف عن المحافظة التي تقع فيها الجامعة، فإنك ستحتاج إلى مصروف إضافي يخص المواصلات بالإضافة إلى مصروف مخصص للسكن إذا لم ترغب في المكوث في السكن الجامعي أو إذا اخترت التسجيل في جامعة خاصة غير موجودة في مدينتك. والأهم مما سبق كله أن مجال علوم الحاسوب عمومًا والبرمجة خصوصًا مجال سريع التغير والتطور، فقد تتعلم تقنيات قديمة في بداية دراستك الجامعية لن تُستخدم في سوق العمل عند تخرجك بعد عدة سنوات أو أنها على الأقل تغيرت تغيرًا كبيرًا عما تعلمته وكم أسمع مشكلات تواجه طلاب الجامعات اليوم من هذا القبيل، لهذا السبب تجد أن أغلب الشركات لا تقبل بالشهادة الجامعية بمفردها بل تجري للمتخرج الجامعي اختبارًا تقنيًا أو تطلب منه مشروعًا يطلع عليه فريق برمجي متخصص ليتأكد من مواكبة معلوماته لأحدث التقنيات الحالية آنذاك. ومن الجدير بالذكر أنّ تعلم البرمجة عن طريق الجامعة يجبرك على الدراسة لسنين طويلة قد تصل إلى خمس سنوات وربما أكثر إذا لم تجتاز مواد محددة خلال السنة الدراسية، كما أنّ هذا الطريق لوحده لا يكفي للدخول إلى سوق العمل على الرغم من امتلاكك شهادة جامعية قوية وامتلاكك خلفية ثقافية علمية غير متاحة في الوسائل الأخرى، إذ ينبغي عليك اكتساب الخبرة اللازمة لتدعم سيرتك الذاتية، ولكن على الرغم من ذلك فبعض الشركات تهتم بالشهادة الجامعية في الدرجة الأولى وبعدها تنظر في الخبرة التي تملكها على أساس درجة ثانوية، إذ قد تمتلك برنامجًا تدريبًا خاصًا بالخريجين الجدد. والخلاصة، قد لا يكون هذا الخيار متاحًا لك -بسبب مجموعك في المرحلة الثانوية من التعليم- وباهظًا أيضًا وقد لا تملك وقتًا له وغيرها من التحديات وهنا ننصحك بخيار آخر لتعلم البرمجة وهو التعلم الحر عبر الإنترنت. تعلم البرمجة عن بعد عبر الإنترنت هنالك طريق آخر لتعلم البرمجة يعد الأسرع من بين عدة طرق لتعلم البرمجة غير التعليم التقليدي في الجامعات وهو التعلم الموجه عن بعد عبر الإنترنت نظرًا لانتشار الإنترنت في كل الأرجاء وازدياد سرعته، فأصبح بالإمكان اليوم مشاهدة فيديوهات والتواصل مرئيًا بدقة عالية دون الاكتراث لتكلفة الإنترنت أو سرعته. ونظرًا لأن مجال البرمجة لا يتطلب أي أمور وأدوات فيزيائية فأصبح تعلمه عبر الإنترنت شائعًا جدًا وسهلًا وعزز من ذلك تطوره السريع كما أشرنا وحاجة سوق العمل الكبير للمبرمجين مما جعل الشركات الموظفة تتنازل عن شرط وجود شهادة جامعية وأصبحت تطلب بدلًا من ذلك الخبرة والمشاريع العملية مع اجتياز اختبار أو مقابلة تقنية تجريها الشركة للمتقدمين المرشحين. تنقسم عملية تعلم البرمجة عبر الإنترنت إلى عدة مسارات فرعية تكون عمومًا إما منظمة ومهيكلة أو متفرقة. الدورات التعليمية تُعَدّ الدورات التعليمية من أشهر الطرق التي يلجأ إليها مَن يرغب في تعلم البرمجة سواءً كانت على أرض الواقع أو عبر الانترنت، إذ تأخذ بيده بدءًا من الصفر وتساعده كثيرًا في تعلم أيّ شيء جديد بصورة عامة وفي تعلم البرمجة بصورة خاصة وذلك عن طريق تسلسل مدروس ينتج عنه في ختام الدورة تعلم الأساسيات والتمكن بعض الشيء في النقاط التي تقدمها الدورة ليتابع بعدها المتلقي رحلة تعلمه عن طريق مصادر أخرى أو التسجيل في دورة تعليمة جديدة بمستوى أعلى. غالبًا ما تقترن الدورات التعليمية بجانب تطبيقي عملي يبني المتعلم عبرها مشاريع عملية تحاكي المشاريع المطلوبة في سوق العمل كما تفيده في بناء معرض أعمال عملية يغنيه عن عرض الشهادات النظرية. وقد يحتاج الطالب الأكاديمي الذي يدرس في الجامعة -كما ذكرنا في المسار الأول السابق- إلى دورات برمجية تعليمية مخصصة لترميم ما ينقصه أو اكتساب خبرة أوسع والتخصص فيه وبناء مشاريع عملية. لن تعيقك الدورات التعليمية من ناحية العدد المحدود للحضور والتكلفة الباهظة، إذ توجد العديد من الدورات البرمجية منخفضة التكلفة ومقبولة بالنسبة للطلاب مقابل الفائدة التي سيتلقونها، كما أنك لن تحتاج إلى إهدار 4 أو 5 سنوات من حياتك -على الأقل- كما في المرحلة الجامعية. تحدي مسار تعلم البرمجة عبر دورات تعليمية هو التسويف والتقصير، إذ يحتاج إلى تنظيم وعزيمة وإصرار وحمل النفس على التعلم وطلب العلم ووضع مخطط صارم وخطة واضحة من بداية الطريق، وهذا عكس المسار الأكاديمي الذي يكون فيه دور الجامعة تلقين المعلومة والتخطيط نيابة عنك مثل تحديد أوقات الامتحانات. ومن الجدير بالذكر أنه تهدف أكاديمية حسوب إلى توفير دورات تعليمية باللغة العربية تساعدك في تعلم البرمجة، كما يمكنك طرح أيّ سؤال على المدرِّبين أثناء التعلم إذا صادفت أيّ صعوبة، بالإضافة إلى أنه يمكنك مشاهدة أيّ دورة اشتركت فيها متى ما شئت، وفي حال أردت الانسحاب فبإمكانك التواصل مع فريق الأكاديمية لاسترداد ثمنها. دورة علوم الحاسوب دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب اشترك الآن الورشات والمخيمات البرمجية Bootcamps تعد المخيمات البرمجية فكرة أخرى منبثقة عن الدورات التعليمية فهي عبارة عن دورة تعليمية مكثفة ومضغوطة بفترة زمنية قد تقصر أو تطور بحسب البرنامج والتخصص وعادةً ما تمتد المخيمات البرمجية المتخصصة في مجال تطوير الويب أو تطوير تطبيقات الجوال من ستة أشهر إلى سنة. وتركز المخيمات البرمجية على تعلم البرمجة وتطبيقها مباشرةً على مشاريع عملية كبيرة تختمها بمشروع تخرج شامل، فيتخرج الطالب منها بحقيبة مشاريع مشرفة يعرضها في مقابلات العمل. القنوات والفيديوهات التعليمية هذه القنوات منتشرة انتشارًا كبيرًا على اليوتيوب مثل قناة أكاديمية حسوب، كما يوجد العديد من المبرمجين المحترفين الذين لديهم قناة على اليوتيوب تحتوي على سلسلة من المحاضرات التعليمية النظرية والعملية أو حتى مواضيع متفرقة، وفي هذا الطريق لن تحتاج إلى التقيد بمكان معيّن لحضور دورة تعليمية ما ولن تضطر إلى دفع تكاليفها، إذ تكون أغلبها مجانية، ولن تضطر إلى دفع أي تكلفة إضافية مثل المواصلات والسكن، كما أنك غير مقيّد بوقت محدد بما أنها عبر الانترنت ومسجَّلة مسبقًا. القيد الوحيد في هذا المسار أنه من المسارات الموجهة وغير المنظمة أو المهيكلة إذ ستتقيد بما هو موجود وقد تجد المعلومة وقد لا تجدها وغالبًا ستكون ضمن المستويات الأساسية دون المتقدمة ولن تجد من يجيب على أسئلتك أيضًا. الكتب والمقالات يفضل العديد من الأشخاص اللجوء إلى كتب برمجية للوصول إلى فهم أكثر دقة، والعديد من هذه الكتب توفرها أكاديمية حسوب مترجمة ومدققة جيدًا، كما يلجأ العديد من الراغبين في تعلم البرمجة إلى المقالات البرمجية لأخذ لمحة عامة حول تعلم البرمجة أو لتعلم البرمجة بصورة خاصة. تمتلك كل طريقة من الطرق السابقة ميزات ومساوئ وضحنا لتتمكن من تحديد الطريق الأنسب لك والذي يخدم أهدافك، ولكن ستكون أنت الرابح مهما كان طريقك في تعلم البرمجة، لذلك لا بد من تعلم البرمجة بصورة احترافية مهما كانت الوسيلة لتحقيق رغبتك في الدخول إلى سوق العمل بقوة وتحقيق دخل ممتاز. وفي نهاية هذا القسم، أنصحك بمشاهدة الفيديو التالي الذي يناقش فكرة الشهادات مقابل الخبرة في سوق العمل: المسابقات والتدريبات البرمجية تعزز المسابقات البرمجية والتدريبات البرمجية من عملية تعلم البرمجة تعزيزًا كبيرًا وتكسب المبرمج خبرة كبيرة واسعة تميزه عن بقية المبرمجين وترفع من قدره ومنصبه خصوصًا أن سمة البرمجة عمومًا هي حل المشكلات والبعد عن النمطية والروتين، فستصادف خلال رحلة البرمجة مشكلات منها القديم ومنها الجديد وغالبًا ستجد لكل مشكلة عدة حلول. أضف إلى ذلك أن أغلب أسئلة المقابلات البرمجية تكون على شكل مشكلة تتطلب إيجاد حل لها وكتاب شيفرته وغالبًا تكون تلك المشكلة شائعة وبسيطة وبمقابلة مباشرة يعني أن الفريق التقني يكون حاضرًا أثناء حلك للمشكلة، وينصب جل تركيزهم على كيفية إيجادك الحل وأسلوب كتابتك للشيفرة، فأحيانًا تجد حلًا لمشكلة يخلق مشاكل أخرى لم تخطر على بالك أو تفكر بها والأصوب أن يكون حلك شاملًا لا يؤدي إلى مشاكل أخرى ولا يسبب تأثيرات جانبية، ولا يمكن الوصول إلى تلك الدرجة من الخبرة والإتقان دون إطلاع على حلول مشاكل سابقة والتمرن على حل مشاكل جديدة ومناقشة الحلول للوصول إلى الحل الأفضل. هنالك الكثير من منصات التدريب تختلف باختلاف المواضيع ولغة البرمجة التي تريد التدرب عليها يمكنك البحث والسؤال وتجرب عدة منصات لتختار ما يناسب وشاع منها هذه الأيام منصة HackerRank ومنصة Codewars، ولكن لا أرى اللجوء إلى هذا الخيار إلى بعد تعلم المفاهيم الأساسية وعلى الأقل أساسيات لغة برمجة وعمومًا هنالك دومًا مستويات لكل تدريب يمكنك اختيار ما يناسب مستواك آنذاك. كيف تتعلم البرمجة؟ البرمجة عالم كبير مترامي الأطراف متباين التضاريس فيه السهل وفيه الصعب وإن كان الصعب يغلب على بدايته إذ يتسم طريق بداية تعلم البرمجة بالصعوبة وشدة الانحدار فهنالك الكثير من الأساسيات والمفاهيم التي عليك تعلمها وفهمها مثل مفهوم التعابير expressions والمتغيرات variables وأنواع البيانات data types والعمليات وحلقات التكرار والتعابير الشرطية والدوال والأصناف …إلخ. ثم تعلم تطبيق تلك المفاهيم بلغة البرمجة التي تريد استخدامها والتقنيات والمكتبات المرتبطة بها وقد تصل إلى بعض الطرق المسدودة -من جملة المشاكل الكثيرة التي تواجهك- التي تتطلب أن تشق طريقًا جديدًا لحلها. لا تخشَ مما سبق فكلما كان الطريق صعبًا ذقت حلاوة الوصول! مفاهيم تعلم البرمجة: التأسيس الصحيح ابدأ أولًا بتعلم المفاهيم البرمجية الأساسية، فعندما تتقن تلك المفاهيم تصبح قادرًا على تطبيقها على الأدوات مهما اختلفت وكثرت، وهنا وجب الفصل بين المفاهيم والأدوات، لأن الأدوات كما ذكرنا كثيرة وإن بدأت بها فقد تضيع وقد تواجه صعوبة في استخدام أداة لكثرة المفاهيم البرمجية المعقدة المبنية عليها وبدلًا من ذلك يجب البدء بصب أساس متين وإتقان المفاهيم البرمجة التأسيسية التي ستمكنك من استخدام أي أداة أو تقنية برمجية موجودة أو حتى مستحدثة جديدة قد تظهر مستقبلًا. أهم المفاهيم التأسيسية البرمجية التي يمكنك البدء بها هي: التفكير المنطقي الخوارزميات وحل المشكلات التعابير المنطقية أو البوليانية العمليات الرياضية الأساسية الأصناف classes والكائنات objects الدوال functions والتوابع methods بنى التحكم مثل التكرار Loop والشروط conditions التعاود Recursion المكتبات والحزم وأطر العمل أنواع البيانات أنواع لغات البرمجة البرمجة كائنية التوجه والبرمجة الوظيفية ننصحك بإتقان تلك المفاهيم وصقلها قبل البدء في تعلم أي لغة برمجة والتعمق فيها لأنك إن فعلت، فستلجأ إلى الرجوع إلى كل مفهوم والتعرف عليه مما يصعب عملية التعلم ويطيل الطريق عليك، وبعد التعرف عليها، يمكنك الانتقال إلى تعلم لغة البرمجة التي تمثل إحدى أدوات تعلم البرمجة والتخصص في المجال الذي تريده. أدوات تعلم البرمجة: اختيار الوجهة والتخصص لا أقصد بذكري أدوات تعلم البرمجة محررات النصوص وما سيلزمك أثناء البرمجة وكتابة الشيفرة، بل أقصد بها الأدوات والوسائل التي تتعلم البرمجة بها وتطبقها وأقصد تحديدًا لغات البرمجة والتقنيات المرتبطة بها التي تتعلم البرمجة بها. هنالك الكثير من لغات البرمجة والتقنيات البرمجية وهي ليست ثابتة بل تزداد وتتوسع يومًا بعد يوم، فلا تلبث إلا أن تسمع عن نزول لغة برمجة جديدة أو تقنية أو إطار عمل Framework جديد فإن تعلمت المفاهيم وأسست نفسك بها، فستطبقها مع أي لغة برمجة أو تقنية برمجية، فلغات البرمجة تنتمي إلى عائلات وتُشتق اللغات الجديدة من لغات سابقة وتُبنى تقنيات جديدة على أخرى سابقة أو مشابهة لها فلا وقت لاختراع العجلة من جديد، وفي هذا الصدد أنصحك بالاطلاع على مقال دليلك الشامل إلى لغات البرمجة. وقد تتساءل، كيف تتعلم البرمجة دون الاهتمام بتعلم لغة برمجة والانشغال بها؟ سؤالك صحيح، فستحتاج أثناء تعلم المفاهيم إلى أداة أي لغة برمجة تطبق عليها ما تعلمته ولكن في الوقت نفسه لا تريد الانشغال بتعلم لغة البرمجة تلك وتفاصيلها وشيفراتها وهنا لحل المشكلة جاءت لغات البرمجة المرئية مثل سكراتش Scratch وما شابهها. سكراتش هي لغة برمجة مرئية مؤلفة من كتل جاهزة يمكنك عبر سحبها وتركيبها بناء برنامج كامل، وهي مناسبة جدًا للبدء بتعلم البرمجة من الصفر وتأسيس المفاهيم البرمجية التي ذكرناها أهمها الخوارزميات والتفكير المنطقي، وبناءً على ذلك، تجد أن دورة علوم الحاسوب من أكاديمية حسوب تؤسس تلك المفاهيم أولًا بلغة سكراتش. بعد أن تتعلم المفاهيم، تبدأ بتطبيقها على لغة برمجة حقيقية ويمكنك بعدها التخصص بلغة البرمجة التي تريد تعلمها ودخول مجالها، وهنا يمكن أن أنصحك بدلًا من ذلك البدء بأساسيات لغة برمجة سهلة مثل لغة جافاسكربت JavaScript أو لغة بايثون والسبب سهولة كتابة الشيفرات فيهما وتنفيذها دون الحاجة إلى أي تعقيد في ضبط البيئة البرمجية لهما، ثم بعد ذلك يمكنك الانتقال إلى لغة البرمجة التي تُستخدم في المجال الذي تريد التخصص فيه مثل مجال تطوير مواقع الويب أو تطوير تطبيقات الجوال أو برمجة أنظمة التشغيل والأنظمة المدمجة. قد تسألني عن الأدوات والبرامج المطلوبة لكتابة الشيفرات وهنا أقول لك، لا تشغل نفسك بها فستتعرف عليها متى ما احتجتها فكل لغة برمجة أو تقنية لها محرر وأدوات تدعمها أكثر من غيرها. نصائح لتعلم البرمجة توجد بعض النصائح لتعلم البرمجة التي ستحتاجها أثناء رحلتك نسردها فيما يلي. حدد هدفك من تعلم البرمجة عليك تحديد هدفك حتى يسهل عليك تحديد التخصص الذي تريد الدخول إليه وبالتالي اللغة المستعملة في ذلك التخصص الأمر، فاللغات التي تُستخدم في مجال برمجة تطبيقات الويب مثلًا تختلف عن لغات برمجة تطبيقات الهاتف المحمول والتطبيقات المكتبة، كما سيسهل عليك تحديد طبيعة الجهاز الذي سيكون موجه إليه هذا التطبيق. تعلم لغة واحدة على الرغم من تشابه لغات البرمجة من حيث المفهوم، إلا أنّ لكل لغة برمجية بنية لغوية syntax تختلف عن غيرها، لذا من الأفضل عدم إجهاد نفسك في تعلم أكثر من لغة على التوازي حتى لا تتشتت وخاصةً إذا كنت في بداية طريقك في تعلم البرمجة. وعمومًا، يمكنك تعلم المفاهيم البرمجية بدايةً بلغة سكراتش ثم الانتقال إلى اللغة التي تريد التخصص فيها فالمفاهيم متشابهة كما ذكرنا ولكن صياغة اللغة وطريقة كتابة شيفراتها وترتيبها هي التي تختلف ولن يكون الاختلاف كبيرًا عادةً. ابدأ ببرامج بسيطة البرمجة مثلها مثل أيّ مجال آخر، أي حتى تتقنها عليك البدء من مكونات صغيرة وذلك بتصميم برامج بسيطة ثم تعديلها وتطويرها على عدة مراحل للوصول إلى تطبيق متكامل، فعلى سبيل المثال تطبيق الآلة الحاسبة يبدأ بعملية واحدة وبعدها يُطوّر ليشمل كافة العمليات وبعد ذلك يمكن تطويره ليتعامل مع المعادلات الرياضية المعقدة وهكذا. تحلى بالصبر جميعنا يريد أن يكتسب الخبرة بين ليلة وضحاها، لكن الأساس مهم جدًا وهذا يحتاج لأيام وأيام، لذا خذ الطريق من بدايته وأساسياته ولا تستعجل فتندم وتفقد الشغف وربما تتعب من مواصلة التعلم وتقرر الابتعاد نهائيًا، ولا تيأس عندما تواجهك أخطاء، فكلها ستدعم مسيرتك البرمجية في المستقبل وتكسبك الخبرة، ففي النهاية إنما العلم بالتعلّم وإنما الحلم بالتحلّم. صاحب مبرمجًا بما أنك قررت دخول عالم البرمجة، فحاول مصاحبة المبرمجين بدخول مجتمعات البرمجة على وسائل التواصل الاجتماعي وإبداء اهتمامك بأي محتوى برمجي على الإنترنت والتفاعل مع أصحاب المحتوى والتواصل معهم والاستفسار أو السؤال عما يلزمك أن احتجت، فبذلك يصبح لديك شبكة من الأصدقاء تستفيد منهم وتفيدهم بتبادل الخبرات. اعتمد على نفسك في حل الأخطاء البرمجية لا شك أنه كل منا سيواجه أخطاء في مسيرته التعليمية، ولكن من الأفضل عدم الاعتماد على الغير في حلها إلا بعد البحث والتقصي عن سبب المشكلة وإيجاد حلها بأفضل طريقة ممكنة، وفي حال عدم التوصل إلى حل بعد البحث المتواصل، فلا مانع من الرجوع إلى مبرمج محترف يبيّن لك سبب المشكلة وطريقة حلها، فاللجوء فورًا إلى مبرمج محترف لن يفيدك وربما قد تكون عبئًا عليه في حال تواصلت معه على أبسط الأخطاء وباستمرار دون بذل أيّ جهد منك في البحث. لا تتوقف عن الممارسة والتدريب كل علم لا يُمارس فمصيره الزوال والنسيان وكذلك البرمجة، إذ عليك التدرب أكثر فأكثر إلى حين إتقان هذه اللغة وعدم التوقف عن ممارستها بين الحين والآخر لتجنب خسارتها. أسئلة شائعة حول كيف تتعلم البرمجة هل تعلم البرمجة صعب؟ قد يقول قائل أن البرمجة صعبة وتعلمها أصعب، ولكن هل هذا صحيح؟ أقول أنه لا شيء سهل وأي مهنة فيها مستوى متفاوت من السهولة والصعوبة، والبرمجة من المهن التي تتطلب بذل جهد ذهني وفكري كبير ولا تتطلب بذل جهد بدني بينما تجد بعض المهن تتطلب بذل جهد بدني أكثر من الجهد الذهني وهكذا، وقد لا يناسب البعض بذل هذا الجهد الذهني الكبير والجلوس لفترات طويلة أمام الشاشة بتركيز كبير وهنا يجد تلك الصعوبة التي يشير إليها. إن أردت إجابة تفصيلية على هذا السؤال، فشاهد فيديو هل البرمجة صعبة. هل يؤثر نمط شخصيتي على تعلم البرمجة؟ التعامل مع البرمجة والحاسوب يتطلب بعض الانعزال عن الناس والأنشطة الاجتماعية والتعامل مع آلة أمامك بمخاطبتها عبر شيفرة طويلة تمضي أيامًا وأسابيعًا في كتابتها على انفراد وهذا قد لا يناسب بعض الأشخاص الاجتماعيين الذين يفضلون التعامل مع الناس والاحتكاك بهم، وهنا تظهر فكرة أن غالبية المبرمجين انطوائيين وأرى أنها صحيحة بنسبة ما، ويمكنك الاطلاع على مناقشة شخصيتك كمبرمج ومناقشة هل فعلاً تخصص البرمجة يؤثر بالسلب على الحياة الاجتماعية؟ في حسوب IO. هل احتاج إلى إتقان اللغة الإنجليزية لتعلم البرمجة؟ صحيح أن شيفرات لغات البرمج كلها مكتوبة باللغة الإنجليزية ولكن الحقيقة أنك لا تحتاج إلى إتقانها لتكون مبرمجًا محترفًا، إذ أن كل لغة برمجة مكونة من كلمات مفتاحية keywords محصورة العدد يمكنك حفظها وحفظ استخداماتها وقد قابلت عدة مبرمجين من بلدان آسيا وأوربا غير ناطقين باللغة الإنجليزية ولا يعرفونها بل أتحدث معهم بالإنجليزية فلا يستطيعون الرد علي وفي الوقت نفسه أتفاجأ من أنهم بنوا الكثير من المواقع وتطبيقات الجوال، حتى أن أحدهم بنى مكتبة CSS بلغته ويستطيع أي متحدث بتلك اللغة استخدامها. هل هناك مصادر عربية لتعلم البرمجة؟ قد يقول قائل، مراجع تعلم البرمجة قليلة في اللغة العربية أو ليست بجودة عالية، وأنا أقول أن المحتوى العربي غني جدًا بمصادر تعلم البرمجة بالعربية وهنا أحيلك إلى مقال الدليل الشامل لتعلم البرمجة باستخدام المصادر العربية لتتأكد من نفسك. كما يوجد دورات برمجة عربية تأخذ بيدك من الصفر وحتى الاحتراف مثل دورات أكاديمية حسوب، فالمميز في دوراتها أن الشرح بلغة عربية فصيحة وأنها توفر بيئة عربية متكاملة بدءًا من توفير التوثيقات البرمجية العربية التي تجدها في موسوعة حسوب وحتى المقالات البرمجية والكتب البرمجية في كافة المواضيع واللغات البرمجية وأخيرًا بمنصة أسئلة وأجوبة برمجية لطلب أي مساعدة أو الإجابة عن سؤال كما تجد دعمًا أيضًا في مجتمع البرمجة العربي في منصة حسوب IO. هل أحتاج إلى خبرة في الرياضيات لتعلم البرمجة؟ لا تحتاج إلى خبرة متقدمة في الرياضيات بل كل ما تحتاج إليه في البداية هو معرفة بالعمليات الرياضية الأساسية من جمع وطرح وضرب وقسمة ورفع للأس، وهنالك الكثير من القصص عن أطفال ويافعين بأعمار صغيرة تعلموا البرمجة وبدؤوا بكتابة برامج وألعاب. كيف تتعلم البرمجة من الصفر؟ إن لم تكن تريد الالتحاق بمسار جامعي، فهنا أنصحك باتباع دورات تعليمية أو ورشات أو مخيمات برمجية منظمة ومهيكلة ولا تتطلب أي خبرة برمجة مسبقة بحيث تبدأ معك من الأساسيات وتنطلق حتى المواضيع المتقدمة يقترن ذلك ببناء مشاريع عملية. وإن سألتني عن ترشيحات في المحتوى العربي، فأرشح دورات أكاديمية حسوب فكلها لا تتطلب خبرة برمجة مسبقة وتشرح المواضيع من الصفر، كما أنك عندما تشترك بدورة ما، فإن المسارات الأساسية من كل الدورات تصبح متاحة لك وهي ميزة ممتازة تساعدك على صب أساس قوي في كل المجالات البرمجية، وأضف إلى تلك الميزة، هنالك فريق من المبرمجين جاهز للرد على استفساراتك ومساعدتك بأي شيء، فهي خيار جيد تستحق النظر. أنا لست منظمًا فكيف ألتزم في تعلم البرمجة بنفسي؟ تعلم البرمجة -خصوصًا عبر دورات- يحتاج إلى حمل النفس على ما تكره وهو التنظيم، والتنظيم يحتاج إلى روتين، لذا ألزم نفسك بروتين قاسٍ وعاقبها إن تخلَّفت وقصرت مثل عدم الخروج إلى مكان محبب لك في عطلة نهاية الأسبوع، وفي الوقت نفسه كافئها إن أنجزت وثابرت، وفي هذا الصدد أنصحك بمقال دليلك لتنظيم حياتك ففيه فوائد كبيرة تساعدك على التنظيم لا تفوتها. وتذكر دومًا أن لذة الوصول تنسيك تعب الطريق وهذا يجب أن يدفعك دومًا إلى بذل الجهد ورفع الهمّة، وصحيح أن طريق تعلم البرمجة قد يكون طويلًا لكن بدايته متعبة فقط أما بعد ذلك فيصبح سهلًا، وتذكر أن المبرمج الخبير المتمرس يملك الكثير من المزايا بدءًا من الراتب المرتفع بقدر خبرته وحتى قدرته على تأسيس شركات برمجية أو إدارتها. هل يمكنني تعلم البرمجة عبر الجوال؟ حقيقةً، لا! يتطلب تعلم البرمجة حاسوبًا لتعلم البرمجة وكتابة الشيفرات البرمجية، فمن الصعب كتابة شيفرات برمجية على الهاتف الجوال هذا لم نتحدث عن إمكانية تنفيذ الشيفرات عليه وتجريبها وتنقيحها وتصحيح الأخطاء فيها. أما إن سألتني عن مواصفات الحاسوب، فيمكن استعمال أي حاسوب بدايةً وبعدها ستجد نفسك إما مرتاحًا بمواصفاته آنذاك أو تحتاج إلى مواصفات أخرى محددة، وقد تحتاج من البداية إلى وجود بطاقة شاشة منفصلة إن أردت التخصص في مجالات برمجة تتطلب معالجة رسوميات عالية مثل تطوير الألعاب أو محاكاة تطبيقات جوال أثناء تطويرها، وقد تحتاج إلى حاسوب ماك إن أردت تطوير أي شيء يتعلق بأنظمة ماك مثل تطوير تطبيقات iOS وهو حالة خاصة ومحددة فقط بمنتجات ماك. خاتمة أرجو أن أكون قد وفقت في الإجابة على سؤال "كيف تتعلم البرمجة؟" إجابة وافية شاملة في هذا المقال وأرجو أيضًا أن يكون هذا المقال بوصلة ترشدك للسير في الطريق الصحيح نحو تعلم البرمجة. وتذكر أنه بالنسبة لبعض المبرمجين، رحلة البرمجة لا تنتهي، فهنالك دومًا أشياء جديدة يمكن تعلمها وتطبيقها! وفي نهاية المقال، أحيلك لقراءة المقالات التالية المرجعية بعده التي تدور في فلك تعلم البرمجة ولكن قبل ذلك، قم وخذ قسطًا من الراحة! ملاحظة: كُتب هذا المقال سابقًا عام 2015 وقد جرى تعديله وتحديث محتواه لاحقًا. اقرأ أيضًا المدخل الشامل لتعلم علوم الحاسوب تعلم بايثون تعلم PHP فوائد تعلم البرمجة دليلك الشامل إلى أنواع البيانات تعلم لغة HTML أسهل لغات البرمجة البرمجة باستخدام سكراتش Scratch
    1 نقطة
  3. أعتبرُ أنَّ شريط العنوان في المتصفح هو أشهرُ عنصرٍ من عناصر الواجهات الرسومية في العالم، إذ أصبحت تُعرَض روابط URL على اللوحات الإعلانية، وعلى جوانب الطرقات، وحتى في الكتابات على الجدران؛ مجتمعًا مع زر الرجوع إلى الخلف –أحد أهم الأزرار في المتصفح– ستحصل على مقدرةٍ على التنقل إلى الأمام وإلى الخلف في شبكة المعلومات الكبيرة التي نسميها الويب. الواجهة البرمجية للتعامل مع التأريخ في HTML5 هي طريقةٌ معياريةٌ لتعديل تأريخ (history) المتصفح باستخدام السكربتات. جزءٌ من هذه الواجهة البرمجية (التنقل في التأريخ) موجودٌ في الإصدارات السابقة من HTML؛ أما الأجزاء الجديدة في HTML5 تضمَّنت طرائق لإضافة مدخلات إلى تأريخ المتصفح، ولتغيير رابط URL الظاهر في شريط المتصفح (دون الحاجة إلى تحديث الصفحة)، وإضافة حدث سيُفعَّل عندما تُحذَف تلك المدخلات من المكدس (stack، وهذه هي آلية التعامل الداخلية مع التأريخ) بوساطة المستخدم عند ضغطه لزر الرجوع في المتصفح. وهذا يعني أنَّ رابط URL في شريط العنوان في المتصفح سيستمر بأداء عمله كمُعرِّف فريد للمورد الحالي (current resource)، حتى في التطبيقات التي تعتمد اعتمادًا كبيرًا على السكربتات التي لن تُجري تحديثًا كاملًا للصفحة. السبب وراء تعديل التأريخ لماذا تريد تعديل تأريخ المتصفح يدويًا؟ بكل بساطة، يمكن لرابطٍ بسيطٍ أن ينقلك إلى URL جديد؛ وهذه هي الطريقة التي عَمِلَ بها الويب لأكثر من 25 سنة، وسيستمر بذلك. هذه الواجهة البرمجية لن تحاول تقويض الويب، وإنما العكس. ففي السنوات الأخيرة، وجَدَ مطورو الويب طرائق جديدة ومثيرة لتخريب الويب دون أي مساعدة من المعايير الناشئة. صُمِّمَت واجهة التأريخ البرمجية في HTML5 للتأكّد من أنَّ روابط URL ستستمر بأداء وظيفتها وأن تبقى مفيدةً حتى في تطبيقات الويب التي تعتمد تمامًا على السكربتات. بالعودة إلى المفاهيم الأساسية، ما وظيفة رابط URL؟ إنَّه يُعرِّف موردًا فريدًا (unique resource). يمكنك إضافة رابط مباشر إليه، أو وضع علامة مرجعية إليه، ويمكن لمحركات البحث فهرسته، ويمكنك نسخه ولصقه في رسالةٍ عبر البريد الإلكتروني لشخصٍ ما، الذي يستطيع أن يضغط عليه ويرى نفس المورد الذي رأيته أنت. هذه الميزات الرائعة تُريك أهمية روابط URL. حسنًا، نحن نريد أن تكون للموارد المختلفة روابط URL فريدة. لكن المتصفحات تُعاني من قصورٍ أساسي: إذا غيّرتَ رابط URL، حتى باستخدام السكربتات، فستطلب من خادوم الويب البعيد تحديثًا لكامل الصفحة. وهذا يأخذ وقتًا ومواردَ، وسيبدو لك كم أنَّ ذلك مُبدِّدٌ للموارد إذا كانت الصفحة التي ستنتقل إليها شبيهةً جدًا بالصفحة الحالية. ستُنزَّل كل أجزاء الصفحة الجديدة، حتى الأجزاء المُماثِلة للصفحة الحالية. لا يوجد هنالك طريقةٌ لتغيير رابط URL وتنزيل نصف الصفحة فقط. أتت الواجهة البرمجية للتعامل مع التأريخ في HTML5 لحل هذه الإشكالية. فبدلًا من تحديث كامل الصفحة، يمكنك أن تستخدم سكربتًا لتنزيل «نصف صفحة». هذه الخدعة صعبة قليلًا وتحتاج إلى قليلٍ من العمل… لنقل أنَّ لديك صفحتان، الصفحة A و الصفحة B. الصفحتان متماثلتان بنسبة 90%؛ وهنالك 10% فقط من المحتوى يختلف بين الصفحتين. زار المستخدمُ الصفحةَ A، ثم حاول الانتقال إلى الصفحة B، لكن بدلًا من تحديث الصفحة تحديثًا كاملًا، حاولتَ اعتراض هذه العملية وإجراء الخطوات الآتية يدويًا: تحميل 10% من الصفحة B المختلفة عن A (ربما باستخدام XMLHttpRequest)، وهذا سيتطلب بعض التعديلات من جهة الخادوم لتطبيق الويب الخاص بك. إذ ستحتاج إلى كتابة شيفرة لكي تُعيد 10% فقط من الصفحة B المختلفة عن A، وربما تفعل ذلك عبر رابط URL مخفي أو عبر تمرير وسيط في الطلبية الذي لا يستطيع المستخدم النهائي رؤيته في الحالات العادية. تبديل المحتوى الذي تغيّر (عبر استخدام innterHTML أو دوال DOM الأخرى)، قد تحتاج أيضًا إلى إعادة ضبط أيّة دوال لمعالجة الأحداث المرتبطة بالعناصر الموجودة في المُحتوى المُبدَّل. تحديث شريط العنوان في المتصفح لكي يحتوي على رابط URL للصفحة B، وذلك عبر دالة خاصة من الواجهة البرمجية للتعامل مع التأريخ في HTML5 التي سأريك إياها بعد قليل. في نهاية هذه الخدعة (إذا طبّقتها تطبيقًا صحيحًا)، سينتهي الأمر بحصول المتصفح على شجرة DOM مماثلة لتلك التي سيحصل عليها لو انتقل إلى الصفحة B مباشرةً. وسيُصبِح العنوان في شريط المتصفح مساويًا لرابط URL للصفحة B، كما لو أنَّك انتقلت إلى الصفحة B مباشرةً. لكنك في الحقيقة لم تنتقل إلى الصفحة B ولم تُجرِ تحديثًا كاملًا للصفحة. وهذه هي الخدعة التي كنت أتحدث عنها. لأنَّ الصفحة النهاية مماثلةٌ تمامًا للصفحة B ولها نفس رابط URL للصفحة B، لكن المستخدم لم يلاحظ الفرق (ولم يكن ممنونًا لك على جهودك لتحسين تجربته مع التطبيق). طريقة تعديل التأريخ يوجد في واجهة التأريخ البرمجية عددٌ من الدوال في كائن window.history، بالإضافة إلى حدثٍ وحيد في الكائن window. يمكنك استخدامها لاكتشاف الدعم لواجهة التأريخ البرمجية، وهنالك دعمٌ لا بأس به من أغلبية المتصفحات الحديثة لهذه الواجهة البرمجية. IE Firefox Safari Chrome Opera iPhone Android 10+ 4.0+ 5.0+ 8.0+ 11.5+ 4.2.1+ *4.3+ * من المفترض أنَّ هنالك دعمٌ لواجهة التأريخ البرمجية في الإصدارات السابقة من متصفح أندرويد، لكن لوجود عدد كبير من العلل البرمجية في تطبيق هذا الدعم في إصدار 4.0.4، فسنعتبر أنَّ الدعم «الحقيقي» لواجهة التأريخ البرمجية قد بدأ منذ الإصدار 4.3. «Dive Into Dogs» هو مثالٌ بسيطٌ وعمليٌ لكيفية الاستفادة من الواجهة البرمجية للتأريخ في HTML5. حيث يُبرِز مشكلةً شائعةً: مقالةٌ طويلةٌ يرتبط بها معرضُ صورٍ. سيؤدي الضغط على رابط «Next» أو «Previous» في معرض الصور إلى تحديث الصورة آنيًا وتحديث رابط URL في شريط العنوان في المتصفح دون الحاجة إلى تحديث كامل الصفحة. أما في المتصفحات التي لا تدعم واجهة التأريخ البرمجية –أو في المتصفحات الداعمة لها، لكن المستخدم عطَّل السكربتات– سيعمل الرابطان «Next» و «Previous» كرابطين اعتياديين، ويأخذانك إلى الصفحة التالية بعد تحديث كامل الصفحة. وهذا يثير النقطة المهمة الآتية: لنتعمّق في مثال «Dive Into Dogs» ونرى كيف يعمل. هذه هي الشيفرة التي تُستعمل لعرض صورة وحيدة: <aside id="gallery"> <p class="photonav"> <a id="photonext" href="casey.html">Next ></a> <a id="photoprev" href="adagio.html">< Previous</a> </p> <figure id="photo"> <img id="photoimg" src="gallery/1972-fer-500.jpg" alt="Fer" width="500" height="375"> <figcaption>Fer, 1972</figcaption> </figure> </aside> لا يوجد شيءٌ غير اعتياديٍ فيما سبق. الصورة نفسها هي عنصر <img> موجودٌ ضمن عنصر <figure>، جميع الروابط هي عناصر <a>، وكل شيء محتوىً في عنصر <aside>، من المهم أن نلاحظ أنَّ هذه الروابط العادية تعمل عملًا صحيحًا. جميع الشيفرات التي تتحكم بالتأريخ موجودةٌ بعد سكربت لاكتشاف الدعم، فإن لم يكن متصفح المستخدم داعمًا للواجهة البرمجية للتأريخ، فلا حاجة إلى تنفيذ الشيفرات المتعلقة بها، وكذلك الأمر للمستخدمين الذي عطَّلوا تنفيذ السكربتات بالمجمل. الدالة الرئيسية تحصل على كل رابط من تلك الروابط وتمرِّره إلى الدالة addClicker()‎، التي عملها هو إعداد دالة خاصة للتعامل مع الحدثclick. function setupHistoryClicks() { addClicker(document.getElementById("photonext")); addClicker(document.getElementById("photoprev")); } هذه هي دالة addClicker()‎ التي تأخذ عنصر <a> وتُضيف إليه دالة للتعامل مع الحدث click، التي يحدث فيها أمرٌ مثيرٌ للاهتمام. function addClicker(link) { link.addEventListener("click", function(e) { swapPhoto(link.href); history.pushState(null, null, link.href); e.preventDefault(); }, false); } الدالة swapPhoto()‎ تقوم بأول خطوتين من الخطوات الثلاث التي تحدثنا عنها. أول قسم من الدالة swapPhoto()‎ يأخذ جزءًا من URL لرابط التنقل –أي casey.html و adegio.html وهكذا…– ويبني رابط URL جديد يُشير إلى صفحةٍ مخفيةٍ التي لا تحتوي إلا على الشيفرة اللازمة لعرض الصورة التالية. function swapPhoto(href) { var req = new XMLHttpRequest(); req.open("GET", "http://diveintohtml5.org/examples/history/gallery/" + href.split("/").pop(), false); req.send(null); هذا مثالٌ عن الشيفرات التي تُنتِجها تلك الصفحات (يمكنك التأكد من ذلك في متصفحك بزيادة الرابط السابق مباشرةً). <p class="photonav"> <a id="photonext" href="brandy.html">Next ></a> <a id="photoprev" href="fer.html">< Previous</a> </p> <figure id="photo"> <img id="photoimg" src="gallery/1984-casey-500.jpg" alt="Casey" width="500" height="375"> <figcaption>Casey, 1984</figcaption> </figure> هل تبدو الشيفرة السابقة مألوفةً لديك؟ هذا طبيعي، لأنها نفس الشيفرة التي استخدمناها في صفحتنا الرئيسية لعرض أول صورة. القسم الثاني من دالة swapPhoto()‎ يجري الخطوة الثانية من الخطوات الثلاث التي تحدثنا عنها: وضع الشيفرة الجديدة التي نُزِّلَت في الصفحة الحالية، تذكَّر أنَّ هنالك عنصر <aside> محيطٌ بالصورة والشرح التوضيحي لها، لذلك تكون عملية إضافة شيفرة الصورة الجديدة بسيطةً عبر ضبط خاصية innterHTML لعنصر <aside> إلى خاصية responseText من كائن XMLHttpRequest. if (req.status == 200) { document.getElementById("gallery").innerHTML = req.responseText; setupHistoryClicks(); return true; } return false; } لاحظ أيضًا استدعاء الدالة setupHistoryClicks()‎، وهذا ضروريٌ لإعادة ضبط دوال التعامل مع الحدث click في روابط التنقل الجديدة، لأن ضبط المحتوى باستخدام innerHTML سيمسح كل آثار الروابط القديمة مع دوال التعامل مع أحداثها. لنعد الآن إلى الدالة addClicker()‎، فبعد النجاح بتغيير الصورة، هنالك خطوةٌ إضافيةٌ علينا عملها من الخطوات الثلاث: ضبط رابط URL في شريط عنوان المتصفح دون تحديث الصفحة. history.pushState(null, null, link.href); تأخذ الدالة history.pushState()‎ ثلاثة وسائط: state: يمكن أن يكون أي بنية من بُنى بيانات JSON، وستُمرَّر إلى الدالة التي تتعامل مع الحدث popstate، الذي ستتعلم المزيد من المعلومات عنه بعد قليل. لا نحتاج إلى تتبع أي حالة في هذا المثال، لذا سأترك القيمة مساويةً إلى null. title: يمكن أن يكون أي سلسلة نصية. لكن هذا الوسيط غير مدعوم من أغلبية المتصفحات الرئيسية، فإذا أردت ضبط عنوان الصفحة، فعليك تخزينه في الوسيط state ثم ضبطه يدويًا في الدالة التي تتعامل مع الحدث popstate. url: يمكن أن يكون أي رابط URL، وهو الرابط الذي سيظهر في شريط العنوان في متصفحك. استدعاء الدالة history.pushState سيؤدي إلى تغيير رابط URL الظاهر في شريط العنوان في المتصفح على الفور، لكن أليست هذه نهاية القصة؟ ليس تمامًا، بقي علينا أن نتحدث عمّا سيحصل إذا ضغط المستخدم على الزر المهم «الرجوع». الحالة العادية عندما يزور المستخدم صفحة جديدة (بتحميلها كلها) هي إضافة المتصفح لرابط URL الجديد في «مكدس» التأريخ (history stack) ثم يُنزِّل ويعرض الصفحة الجديدة. وعندما يضغط المستخدم على زر الرجوع إلى الخلف، فسيزيل المتصفح الصفحة الحالية من مكدس التأريخ ويعرض الصفحة التي تسبقها، لكن ماذا سيحدث عندما عبثتَ بهذه الآلية لكي تتفادى تحديثًا لكامل الصفحة؟ حسنًا، لقد زيّفتَ «التقدم إلى الأمام» إلى رابط URL جديد، وحان الوقت الآن لتزييف «الرجوع إلى الخلف» إلى رابط URL السابق. والمفتاح نحو تزييف «الرجوع إلى الخلف» هو الحدث popstate. window.addEventListener("popstate", function(e) { swapPhoto(location.pathname); } بعد أن استخدمتَ الدالة history.pushState()‎ لإضافة رابط URL مزيّف في مكدس التأريخ الخاص بالمتصفح، سيُطلِق المتصفح الحدث popstate في الكائن window عندما يضغط المستخدم على زر الرجوع. وهذه هي فرصتك لإكمال عملك في إيهام المستخدم أنَّه انتقل فعلًا إلى تلك الصفحة. في هذا المثال، عملية إعادة الصفحة السابقة بسيطةٌ جدًا، فكل ما عليك فعله هو إعادة الصورة الأصلية، وذلك باستدعاء الدالة swapPhoto()‎ مع تمرير رابط URL الحالي لها. لأنَّه عند استدعاء الدالة التي تُعالِج الحدث popstate، يكون رابط URL الظاهر في المتصفح قد تغيّر إلى رابط URL السابق. وهذا يعني أيضًا أنَّ قيمة الخاصية العامة location قد حُدِّثَت لرابط URL السابق. لكي أساعدك في تخيل الوضع، دعني أتلو عليك العملية «السحرية» من بدايتها إلى نهايتها: يُحمِّل المستخدم الصفحة http://diveintohtml5.org/examples/history/fer.html ويشاهد القصة وصورةً للكلب Fer. يضغط المستخدم على الرابط المُعَنوَن «Next»، الذي هو عنصر <a> تكون قيمة خاصية herf فيه هي http://diveintohtml5.org/examples/history/casey.html. بدلًا من الانتقال إلى http://diveintohtml5.org/examples/history/casey.html مباشرةً وتحديث الصفحة تحديثًا كاملًا، فستعترض دالة خاصة للحدث click عملية الضغط على عنصر <a> وتُنفِّذ شيفرةً خاصةً بها. تستدعي تلك الدالة التي تُعالِج الحدث click الدالةَ swapPhoto()‎، التي تُنشِئ كائن XMLHttpRequest لكي ينُزِّل جزء HTML الموجود في http://diveintohtml5.org/examples/history/gallery/casey.html بشكل تزامني. الدالة swapPhoto()‎ تضبط الخاصية innerHTML للعنصر الذي يحوي الصورة (عنصر <aside>)، وبهذا ستُبدَّل صورة Casey بصورة Fer. في النهاية، ستستدعي الدالةُ التي تتعامل مع الحدث click الدالةَ history.pushState()‎ لتغيير رابط URL يدويًا في شريط عنوان المتصفح إلى http://diveintohtml5.org/examples/history/casey.html. يضغط المستخدم على زر الرجوع في المتصفح. يلاحظ المتصفح أنَّ رابط URL قد تغيّر يدويًا وأُضيف إلى مكدس التأريخ (عبر الدالة history.pushState()‎) وبدلًا من الانتقال إلى رابط URL السابق وإعادة تحديث الصفحة، فسيُحدِّث المتصفح الرابط الموجود في شريط العنوان إلى رابط URL للصفحة السابقة (http://diveintohtml5.org/examples/history/fer.html) ثم يُطلِق الحدث popstate. الدالة التي تُعالِج الحدث popstate ستستدعي الدالة swapPhoto()‎ مرةً أخرى، لكن هذه المرة مع تمرير الرابط القديم إليها الذي أصبح موجودًا الآن في شريط عنوان المتصفح. ثم باستخدام XMLHttpRequest مرةً أخرى، ستُنزِّل الدالة swapPhoto()‎ جزءًا من صفحة HTML الموجودة في http://diveintohtml5.org/examples/history/gallery/fer.html ثم ستضبط الخاصية innerHTML للعنصر الذي يحوي الصورة (عنصر <aside>)، وبهذا ستُبدَّل صورةFer بصورة Casey. اكتملت خدعتنا، جميع الأدلة الظاهرة (محتوى الصفحة، وعنوان URL في المتصفح) تُشير إلى أنَّ المستخدم قد انتقل إلى الأمام صفحةً وإلى الخلف صفحةً. لكن لم يحصل تحديثٌ كاملٌ للصفحة. مصادر إضافية Session history and navigation في معيار HTML5 Manipulating the browser history على Mozilla Developer Center استعراض بسيطة لواجهة التأريخ البرمجية Using HTML5 today التي تشرح كيف يستعمل موقع فيسبوك الواجهة البرمجية للتأريخ The Tree Slider التي تشرح استعمال موقع GitHub للواجهة البرمجية للتأريخ History.js هي مكتبةٌ للتعامل مع التأريخ في المتصفحات الحديثة والقديمة ترجمة -وبتصرّف- لفصل History من كتاب Dive Into HTML5 لمؤلفه Mark Pilgrim. اقرأ أيضًا المقال التالي: تحديد الموقع الجغرافي (GeoLocation) في HTML5 المقال السابق: إضافة مقاطع الفيديو عبر العنصر <video> في HTML5 النسخة العربية الكاملة من كتاب نحو فهم أعمق لتقنيات HTML5
    1 نقطة
  4. السلام عليكم يا رفاق .. أنا كاتبة محتوى ولكن أعلم أنه مازال ينقصنى الكثير لأكون ناجحة فى مجالى، فقط أرعب بمعرفة المهارات اللازمة والواجب توافرها فى كاتب المحتوى الناجح فى شكل نقاط ؟
    1 نقطة
  5. لدي سؤال أستاذ زاهر، عند ماذا تعني كلمة rasterize؟ ولماذا عندما أحفظ العمل على صيغة GIF الصورة لا تصبح متحركة؟.. شكرا جزيلا أستاذ زاهر. وهذا ثاني تطبيق لي للدرس.
    1 نقطة
  6. شرح فوق الممتاز يا أستاذ زاهر، شكرا جزيلا لحضرتك.
    1 نقطة
  7. يوجد لدى كثيرين خلط بين مصطلحات متقاربة هي التعميّة Encryption، الترميز Encoding، التجزئة Hashing والتشويش Obfuscation. سيتناول هذا المقال ماهية كلّ واحد من هذه المصطلحات. الترميز يهدف الترميز إلى تحويل بياناتٍ ليصبح بإمكان أنظمة مختلفة التعامل معها بطريقة صحيحة وآمنة. على سبيل المثال: إرسال ملفات تنفيذية في بريد إلكتروني أو عرض محارف Characters خاصّة على صفحة ويب. ليس الغرض هنا إبقاءَ المعلومة سريّة بل التأكد من أن التعامل معها سيكون على النحو الأمثل. يحوّل الترميز البيانات من صيغة إلى أخرى بآلية متاحة للعموم ويمكن بالتالي عكسُ التحويل بسهولة. لا تحتاج البيانات بعد ترميزها لمفتاح سري حتى يمكن التعامل معها، إذ أن المطلوب الوحيد ليمكنَ فك الترميز هو الخوارزمية Algorithm المستخدمة فيه. أمثلة: ASCII ،Unicode، ترميز روابط URL و Base64. التعمية تُستخدَم التعميّة لتحويل صيغة البيانات بغرض إبقائها مجهولة للآخرين؛ مثلا عند إرسال رسالة إلى شخص لا تريد أن يتمكن غيره من قراءتها أو لإيصال كلمة مرور بسريّة على الإنترنت. تهدف التعمية، بدلا من التركيز على قابلية استخدام المعلومة، إلى التأكد من أنه لا يمكن لغير المصرّح لهم الاستفادة من البيانات. تحوّل التعميّة البيانات إلى صيغة أخرى لا يمكن سوى لأشخاص محدّدين فهمُها. يُستخدَم لتنفيذ التعمية مفتاح تعمية إضافة إلى خوارزمية والنص المراد تحويله. يتطلب نزعُ التعمية الحصولَ على النص المعمَّى، خوارزمية التعميّة والمفتاح السري (نفس مفتاح التعمية أو مفتاح سري آخر). أمثلة: AES ،Blowfish و RSA. التجزئة تعمل التجزئة على التأكد من سلامة البيانات Integrity، بمعنى إن حدث تعديل عليها فستستطيع معرفة ذلك. تأخذ عمليّة التجزئة مُدخَلا عشوائيا وتُنتِج سلسلة محارف ثابتة الطول لديها الخصائص التالية: نحصُل دائما على نفس النتيجة بتنفيذ العمليّة على نفس المُدخَل. لا يجوز أن تُنتج العملية نفس المُخرَج لمُدخلات متعدّدة. يجب ألا يكون بالإمكان استنتاج المُدخَل من المُخرَج. يؤدي أي تعديل على مُدخَل مّا إلى تغييرات كبيرة في نتيجة تطبيق العملية عليه. تُستخدَم التجزئة مع الاستيثاق Authentication للحصول على دليل قوي أن رسالة مّا لم يُعدَّل عليها. تتم العملية بأخذ مُدخَل معيَّن، تعميّته بمفتاح محدَّد، تجزئته بنفس المفتاح، ثم تعميّة المفتاح بالمفتاح العمومي Public key الخاص بالمرسَل إليه ثم توقيع التجزئة بالمفتاح السريّ الخاص بالمرسِل. يفتح المرسَل إليه الرسالة ثم يفكّ تعمية المفتاح المستخدَم لتعميّة الرسالة باستخدام مفتاحه السّري مما يمكّنه من الحصول على النص الأصلي للرسالة. يمكنها بعدها تجزئة الرسالة ومقارنة نتيجة التجزئة بالتجزئة الموقَّعة من المرسِل فإن حصل تطابق فهذا يعني أن الرسالة لم يُعدَّل عليها وأنها أرسلت من الشخص المُنتظَر. أمثلة: SHA-3 و MD5 (أصبح قديما) التشويش يهدف التشويش إلى جعل المعلومة أصعب فهما، لتصعُب مهاجمتها أو نسخها. من الاستخدامات الشائعة له تشويش الشفرة المصدرية لجعل تكرار منتَج معيَّن أصعب عند تطبيق الهندسة العكسية Reverse engineering عليه. من المهم ملاحظة أن التشويش ليس تحكما قويا مثل التعميّة بل مجرّد عرقلة. يمكن غالبا عكسُه، مثل ما يحدُث مع الترميز، بنفس الطريقة التي يتمّ بها. يقتصر التشويش في حالات أخرى على عمليات يدوية تأخذ الكثير من الوقت لإجرائها. يجب الانتباه أيضا إلى أنه يوجد حدّ للتشويش حسب المحتوى. عند تشويش شفرة برمجية مثلا فالحدّ هو أن نتيجة التشويش يجب أن تبقى في حدود ما يمكن للحاسوب التعامل معه وإلا فإن البرنامج سيتوقّف عن العمل. أمثلة: مشوِّش JavaScript و ProGuard. ملحوظة: ربما تتساءل متى يُستحسن استخدام التشويش بدلا من التعمية؛ والجواب هو أن التشويش يُستخدَم لجعل البيانات أصعب فهما على مستغِلّ محدَّد (شخص مّا) مع إبقائها في متناول مستغِلّ آخر (حاسوب). بالنسبة للتعميّة فيصعُب في جميع الأحوال الاستفادة من البيانات دون الحصول على المفتاح السّري. خلاصة يهدف الترميز إلى الإبقاء على قابلية استخدام البيانات، ويمكن عكسُه بنفس خوارزمية الترميز؛ أي أنه لا يحتاج لمفاتيح سرية. تُستخدَم التعمية للحفاظ على خصوصية البيانات وتتطلّب إزالةُ التعمية استخدامَ مفتاح سري. تُستخدَم التجزئة لغرض التحقق من سلامة البيانات باكتشاف وجود تعديلات تدلّ عليها مُخرجات التجزئة. يُستخدم التشويش لمنع الأشخاص من فهم معنى بيانات خصوصا شفرات برمجية للحد من إمكانية تطبيق الهندسة العكسية على برنامج أو سرقة وظائفه. ترجمة -وبتصرّف- لمقال Encoding vs. Encryption vs. Hashing vs. Obfuscation لصاحبه Daniel Miessler.
    1 نقطة
  8. تناولنا في الجزء الأوّل كيفيّة إعداد خادوم وتجهيزه بتغيير اسمه وضبط عنوان IP فريد له. سنتابع العمل الآن في هذا الدرس ونحوّل هذا الخادوم إلى متحكّم بالمجال Domain Controller. سنعمل أولًا على إنشاء المجال hsoub-sp.com وهو مجال افتراضي وغير حقيقي. يشير الحرفان sp في اسم المجال إلى SharePoint. كما سنُكسِب هذا المتحكّم ميّزة DNS Server تسمح للمستخدمين بالوصول إلى خادوم ويب الخاص بمزرعة شير بيونت عن طريق عنوان مقروء وليس مجرّد عنوان IP عادي. الترقية إلى خادوم متحكّم بالمجال شغّل برنامج مدير الخادوم Server Manager من صفحة البداية، حيث تجده في القسم الأيسر منها. أو يمكنك أن تلاحظ وجوده بسهولة بجوار زر إبدا مباشرةً: بعد أن تظهر نافذة برنامج مدير الخادوم، انقر على القائمة Manage في الأعلى واختر Add Roles and Features لإضافة مزايا جديدة إلى ويندوز. ستظهر النافذة التالية: تعطينا هذه النافذة بعض المعلومات حول طريقة الاستخدام. انقر زر Next لتنتقل إلى نافذة أخرى تسمح لنا باختيار نمط التنصيب Select installation type. سنترك الإعدادات الافتراضيّة كما هي، انقر Next لتظهر النافذة التي تحدّد الخادوم الذي نريد التنصيب عليه: يمكننا في الواقع اختيار خادوم آخر لإضافة المزايا المطلوبة إليه. في حالتنا هذه لا يوجد سوى خادومنا الحالي لذلك فانقر Next. ستظهر نافذة تحتوي على جميع الأدوار Roles المتاحة التي من الممكن يأخذها هذا الخادوم: اختر من هذه الأدوار ما يلي: Active Directory Domain Services DNS Server من الممكن أن تظهر نافذة عند اختيار أيّ من هذين الدورين السابقين، تخبرك بوجود مزايا متعلّقة بهما والتي من الضروري تنصيبها أيضًا. سنوافق بالتأكيد على هذا الأمر لذلك فانقر زر Add Features في حال ظهرت مثل هذه النافذة. انقر بعد ذلك زر Next لتظهر نافذة المزايا Features. لا نريد إجراء أي تغيير هنا لذلك فانقر Next. ستظهر بعد ذلك نافذة Active Directory Domain Services توضّح أنّنا بصدد تنصيب الدليل النشط Active Directory حيث يعطينا معلومات عن هذا الموضوع. انقر زر Next لتظهر نافذة أخرى وهي DNS Server توضّح أنّنا سنثبّت ميزة خادوم DNS أي أنّ خادومنا سيلعب دور متحكّم بالمجال وأيضًا خادوم DNS. يفيد خادوم DNS في السماح للمستخدمين بكتابة عناوين إنترنت مقروءة بدلًا من كتابة عناوين IP مجرّدة. انقر Next لتظهر النافذة الأخيرة التي تسبق عمليّة التنصيب: اختر صندوق الاختيار Restart the destination server automatically if required واختر Yes في حال ظهرت رسالة تأكيد. يسمح هذا الاختيار بإعادة تشغيل الخادوم بشكل تلقائيّ إذا تطلّب الأمر ذلك. انقر زر Install لتبدأ عمليّة التنصيب، ستتطلّب عمليّة التنصيب بعض الوقت. بعد أن تنتهي هذه العمليّة، أنصح بإعادة تشغيل الخادوم حتى ولو لم يطلب ويندوز ذلك. بعد إعادة تشغيل الخادوم وتسجيل الدخول إلى ويندوز، شغّل برنامج مدير الخادوم Server Manager من جديد. هذه المرّة ستلاحظ وجود إشارة تعجّب ضمن مثلث أصفر صغير، انقر فوقها لتظهر قائمة صغيرة كما في الشكل التالي: انقر فوق Promote this server to a domain controller لترقية هذا الخادوم وتحويله إلى متحكّم بالمجال. ستظهر بعد ذلك سلسلة من النوافذ المتتالية التي تعرض علينا خيارات متعلّقة بالمجال الذي نريد إنشائه. النافذة الأولى هي نافذة اختيار كيفيّة إنشاء المجال، والتي تتضمّن ثلاثة خيارات: الخيار الأوّل هو إضافة هذا الخادوم إلى مجال domain موجود مسبقًا. أمّا الخيار الثاني فهو إضافة مجال جديد إلى مجموعة خواديم موجودة مسبقًا. أمّا الخيار الأخير، فهو إنشاء مجال جديد لمجموعة من الخواديم (Add a new forest). اختر الخيار الأخير، ثمّ اكتب الاسم hsoub-sp.com لاسم المجال Root domain name كما يظهر في الشكل التالي تمامًا. ثمّ انقر بعد ذلك الزر Next. بعد ذلك ستظهر النافذة التالية، التي تسمح لنا بوضع كلمة مرور خاصّة بطور الاستعادة restore mode. اكتب كلمة المرور التي ترغبها ثم انقر Next. ملاحظة أفضّل أن تكون كلمات المرور التي ستستخدمها من أجل هذه السلسلة متطابقة، وذلك من أجل عدم نسيان أيّ منها. ولكن عندما تجهّز هذه المزرعة من أجل شركة فعليّة يتوجّب عليك بكل تأكيد استخدام كلمات مرور قويّة ومختلفة. إعداد خدمة DNS ستظهر بعد ذلك النافذة الخاصة بخيارات DNS والتي يظهر في أعلاها شريط تنبيه أصفر صغير، ولا بأس في ذلك لأنّنا نعمل على شبكة داخلية. لا نريد إجراء أي تغيير هنا لذلك انقر زر Next فحسب، لتحصل على نافذة الخيارات الإضافيّة والتي تضم اسم NetBIOS الخاص بهذا المجال لأغراض التوافقيّة: انقر زر Next لتظهر النافذة الخاصّة بتحديد المسارات، لا نريد أيضًا إجراء أي تغييرات هنا، لذلك انقر الزر Next دون إجراء أيّ تعديل. ستحصل على النافذة التالية التي تلخّص المهام التي سيعمل على تنفيذها برنامج الإعداد. انقر على الزر Next لتظهر النافذة الأخيرة التي تفحص متطلّبات التنصيب والتي ستعطيك تقريرًا في نهاية عملها حول إمكانيّة بدء عمليّة التنصيب. ستحصل على نافذة شبيهة بما يلي: يمكنك سحب شريط التمرير كما يظهر من الشكل أعلاه لتتأكّد أنّ الاختبارات قد نجحت تمامًا. لاحظ العلامة الخضراء الصغيرة التي تظهر بجوارها العبارة: All prerequisite checks passed successfully. Click 'Install' to begin installation. التحذيرات ذات اللون الأصفر ليست مهمّة حاليًا فهي تتعلّق بميّزة DNS وبموضوع التشفير والتوافقيّة مع الإصدارات القديمة ولن تؤثّر على عملنا مطلقًا. نحن مستعدّون الآن لبدء عمليّة التنصيب النهائيّة. انقر زر التنصيب Install. ستبدأ عمليّة التنصيب وتأخذ بعض الوقت، وعندما تنتهي سيتم إعادة تشغيل الخادوم بشكل تلقائيّ. بعد إعادة التشغيل والوصول إلى نافذة تسجيل الدخول ستلاحظ وجود بعض التغييرات. انظر إلى الشكل التالي: لاحظ كيف أصبح اسم مدير النظام Administrator مسبوقًا باسم المجال HSOUB-SP الذي أنشأناه قبل قليل، وهذه بالطبع إشارة جيّدة إلى نجاح العمليّة. أدخل كلمة المرور ثم سجّل الدخول. هذه المرّة ستسجّل الدخول إلى المجال HSOUB-SP. أنصحك عند هذه النقطة التحقّق من وجود تحديثات لويندوز، وتثبيتها أولًا قبل المتابعة. أصبح بذلك المجال hsoub-sp.com جاهزًا لإضافة باقي خواديم مزرعة شير بوينت إليه. إنشاء حساب مدير المجال hsoub-sp.com سنعمل الآن على إنشاء حساب مدير المجال ضمن الدليل النشط Active Directory. انقر زر ابدأ لتحصل على نافذة البداية. اكتب مباشرةً Active Directory Users and Computers لتحصل على النتيجة المطلوبة في قائمة نتائج البحث. انقر النتيجة التي ستحصل عليها لتظهر النافذة التالية: من الجهة اليسرى للنافذة، انشر محتويات اسم المجال hsoub-sp.com واختر المستخدمين Users، سيؤدّي ذلك إلى تحديث القسم الأيمن من هذه النافذة بجميع المستخدمين الموجودين افتراضيًّا ضمن المجال hsoub-sp.com. انقر بزر الفأرة الأيمن على المستخدم Administrator الموجود في أعلى القائمة، ثم اختر نسخ Copy لتظهر النافذة المسؤولة عن عمليّة النسخ كما في الشكل التالي: أدخل الاسم SPAdmin لكلّ من Full name و User logon name كما في الشكل السابق، ثم انقر Next لتصل إلى نافذة تطلب منك إدخال كلمة المرور وتأكيد لها لهذا المستخدم الجديد. أدخل كلمة مرور مناسبة، واحرص على أن تكون صناديق الاختيار كما في الشكل التالي: انقر زر Next لتحصل على نافذة تلخّص عمليّة النسخ، انقر زر Finish منها لتتم هذه العمليّة. تفيد عمليّة النسخ هذه في الحصول على جميع الصلاحيّات التي يتمتّع بها مدير المجال Administrator وإسنادها للمستخدم الجديد SPAdmin. الخلاصة تعلّمنا في هذا الدرس كيفيّة إنشاء متحكّم بالمجال Domain Controller بالإضافة إلى إنشاء مجال خاص بشركة وهمية hsoub-sp.com، كما أضفنا له ميّزة خادوم DNS. سنضمّ أيّ خادوم جديد نجهّزه إلى المجال السابق. لذلك يُعتبر هذا الدرس أساسيًّا لأنّ باقي دروس هذه السلسلة والتي تتحدّث عن ضم باقي أنواع الخودايم إلى مزرعة شير بوينت تعتمد عليه.
    1 نقطة
  9. في هذه الأيام تتسابق جميع الشركات إلى غزو الوِب بأطنان من الإعلانات ومحاولات جذب إنتباه العملاء، لذا إن لم تكتب محتوىً تسويقيًا مُمتازًا فلن تحصل على ما تريد. فيما يلي أربع قواعد أساسية ينبغي أن يتبعها كل كاتب إعلانات عند إنشاء محتوى جديد: - ركّز على ما تريد، سواء كنت تهدف إلى بيع منتج ما، أو تحصيل ترقية، أو دعوة لإشتراك، فلا تدع القرّاء يصرفون المزيد من الوقت لمعرفة غرضك من الرسالة. أنصحك بأن تقف أمام كل كلمة في المحتوى الذي كتبته وإسأل نفسك إن كانت ضروريّة أم لا وتذكّر أن البلاغة دومًا في الإيجاز. - اكتب على شكل نقاط، هذا أسلوب أظنك تلاحظ كثرة متبعيه هذه الأيام، إذ إن مُعظم المحتوى اليومي على الوِب يدور حول "خمسة طرق يمكن لك.."، و "ثمانية أشياء يجب أن تعرفها".. لستَ مُجبرًا على كتابة عناوين بهذا الأسلوب، لكنك ستستفيد حتمًا من كتابة محتواك على شكل نقاط مُختصرة. - احرص على لغة سليمة ودودة، وقد يبدو هذا بدهيًا لك للوهلة الأولى، لكننا لا نزال نطالع محتوىً ترويجي يضمّ أخطاء نحويّة، هذه كارثة لا يجب أن ترتكبها. أضف إلى ذلك أن تبتعد عن الأسلوب الرسمي في كتابة الخطابات، استخدم لغة ودودة قريبة من قلب العملاء. - اكتب عنوانًا واضحًا وجذابًا، لا تعتقد أن العميل سيفتح رسالتك فور أن يرى إشعارًا جديدًا، الإحصائيات تقول العكس، لذا ينبغي أن تُعطي للعنوان أهمية متساوية تمامًا مع ما تُعطيه للمحتوى، فبدون عنوانٍ جيّد لن تحصل على قراء لمحتواك. المصدر.
    1 نقطة
×
×
  • أضف...