لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 02/07/16 في كل الموقع
-
ما هي PHP؟ PHP هي اختصارٌ للعبارة PHP: Hypertext Preprocessor؛ وهي معروفةٌ كلغة سكربتات (scripting language) مُفسَّرة (interpreter) من جهة الخادوم تُستعمَل لتطوير الويب؛ وهذا يعني أنَّ PHP تُستعمَل على الخادوم لتوليد صفحات الويب الديناميكية. ما يُقصَد بصفحات الويب الديناميكية هي تلك الصفحات التي تُنشَأ أو تُعدَّل من الخادوم قبل إرسالها إلى العميل. إن لم تكن تعرف ما هو الخادوم وما هو العميل، فافتح لسانًا جديدًا في متصفح الويب الخاص بك واكتب فيه academy.hsoub.com، وبهذا يُصبِح متصفحك "عميلًا" (client) والمكان الذي تأتي منه صفحة الويب المطلوبة هو "الخادوم" (خادوم الويب أو web server). يمكن تضمين سكربتات PHP في مستندات HTML، وهي لغةٌ سهلة التعلم، وتشبه بنيتها كثيرًا البنية القاعدية للغات C و Java و Perl. التثبيت يمكنك بسهولة تثبيت WAMP (على نظام ويندوز) أو LAMP (على لينُكس) أو حزمة البرمجيات XAMPP (التي تعمل على ويندوز، ولينُكس، وماك) وذلك تبعًا لنظام تشغيل حاسوبك، راجع مقال كيفية تنصيب ووردبريس محليا باستخدام MAMP لمزيدٍ من المعلومات عن MAMP. تجربة الأمثلة يمكنك تجربة سكربتات PHP عبر تثبيت خادم أباتشي مع دعم PHP يدويًا أو عبر تثبيت حزم جاهزة كالتي ذكرناها آنفًا، لكن توفِّر PHP لك طريقتين لتنفيذ الملفات: عبر سطر الأوامر، وعبر الخادوم المدمج مع PHP؛ وسنشرح كلا الطريقتين في هذا الدرس. استخدام الخادوم المدمج وفَّرت PHP من الإصدار 5.4.0 خادومًا مدمجًا معها يُسهِّل تجربة السكربتات دون عبء تثبيت خادوم ويب كامل مثل أباتشي وضبطه؛ لكن الغرض منه هو تجربة البرامج فقط وليس مصممًا للاستعمال كخادوم إنتاجي على الشبكة. ستُخدَّم الملفات الموجودة في مجلد العمل الحالي عبر ذاك الخادوم المدمج، الذي يُشغَّل كالآتي: cd ~/public_html php -S localhost:8000 PHP 5.5.9-1ubuntu4.5 Development Server started at Fri Jan 8 13:58:31 2016 Listening on http://localhost:8000 Document root is /home/user/public_html Press Ctrl-C to quit. الأمر php -S localhost:8000 سيشغِّل الخادوم في مجلد العمل الحالي (~/public_html) وسيكون متاحًا للوصول من الجهاز المحلي فقط، وسيعمل على المنفذ 8000؛ إن أردت أن يعمل على البطاقات الشبكية، فضع 0.0.0.0 بدلًا من localhost؛ اضغط على Ctrl+C لإيقاف الخادوم. أنشِئ الملف test.php وضع فيه المحتويات الآتية لتجربه: <?php // هذه تجربة لتنفيذ سكربتات PHP من الخادوم المدمج echo "test"; ?> افتح الآن المتصفح وأدخِل http://localhost:8000/test.php في شريط العنوان، وستحصل على نتيجة مشابهة لما يلي: يجدر بالذكر أنَّه بإمكانك تخديم صفحات HTML الثابتة عبر هذا الخادوم، وليس بالضرورة أن تكون الصفحة بلاحقة PHP. ملاحظة: اختر رقمًا أكبر من 1024 كرقم للمنفذ الذي سيستعمله الخادوم، كي لا تحتاج إلى امتيازات إدارية لتشغيله. استعمال سطر الأوامر من البدهي أن تستطيع تنفيذ شيفرات PHP (كغيرها من لغات السكربتات) من سطر الأوامر؛ كل ما عليك فعله هو استدعاء السكربت من الأمر PHP كالآتي: php ~/public_html/test.php أو يمكن تضمين ما يسمى shebang في الأنظمة الشبيهة بيونكس (كنظامَي لينُكس وماك) في بداية السكربت ليبدو كما يلي: #!/usr/bin/php <?php // هذه تجربة لتنفيذ سكربتات PHP من سطر الأوامر echo "test"; ?> وعندها تستطيع تنفيذ السكربت مباشرةً دون استدعاء مفسر PHP كما يلي: ~/public_html/test.php ملاحظة: لا تنسَ إعطاء الملف امتيازات التنفيذ قبل محاولة تنفيذه: chmod +x ~/public_html/test.php يمكن أيضًا تنفيذ الشيفرات تفاعليًا، عبر تنفيذ الأمر php -a ثم كتابة الأوامر تفاعليًا كما يظهر في الصورة الآتية (لاحظ أنه بإمكانك استعمال زر tab لإكمال أسماء الدوال والأصناف وغيرها): البنية القاعدية للغة لنأخذ مثالًا بسيطًا لنشرح فيه القواعد الأساسية للكتابة. <?php /* author: Abd Allatif Eymsh website: academy.hsoub.com version: 1.0 date: 22 12 2015 */ // هذا تعليقٌ ذو سطرٍ وحيد // يتم تجاهل التعليقات من المفسِّر $variable = 'variable'; // نستعمل عبارة echo لطباعة الجمل echo "string"; echo $variable; ?> انسخ ما سبق والصقه في ملفٍ باسم index.php في مجلد htdocs (في نظام ويندوز) أو www (في لينُكس) أو أي مكان تريده إن كنت تستعمل الخادوم المدمج، ثم افتح ذاك الملف في متصفح الويب (بعد أن تُشغِّل الخادوم) وستحصل على النتيجة "stringvariable"، لنُقسِّم الآن الملف ولنشرح بنيته. تُكتَب شيفرات PHP في ملفٍ بامتداد .php تُكتَب شيفرات PHP بين وسمَيّ البداية <?php والنهاية ?> وكما في لغتَيّ C أو Perl، تتطلب PHP أن تنتهي التعليمات البرمجية بفاصلة منقوطة ";" يُشير الرمز $ إلى متغير (variable)، سنتحدث عن المتغيرات في هذا الدرس لاحقًا تكافئ علامات الاقتباس المفردة والمزدوجة بعضها (لكنها ليس لها نفس المعنى تمامًا، سنشرح الاختلاف البسيط لاحقًا) يُستعمَل الأمر echo لطباعة البيانات التعليقات التعليقات جزءٌ من البرنامج لا ينفِّذها مُفسِّر اللغة؛ وهي ملاحظاتٌ لكي يتذكر القارئ أو يفهم أمرًا برمجيًا ما لاحقًا. وهنالك نوعان من التعليقات: التعليقات ذات السطر الوحيد: وهذه التعليقات قصيرةٌ تمتد لسطرٍ وحيدٍ فقط، وتبدأ عادةً بالرمز "//"، ولا بأس أن يكون قبلها تعليماتٌ برمجية، لكن التعليق سينتهي مع نهاية السطر؛ ويستحق أن نذكر أننا نستطيع أن نبدأ التعليقات ذات السطر الوحيد برمز المربع (#) بدلًا من شرطتين مائلتين. التعليقات متعددة الأسطر: وهي تعليقاتٌ طويلة، قد تمتد لأكثر من سطر؛ وتوضع بين علامة البداية /* وعلامة النهاية */، ومن استعمالات هذا النوع من التعليقات أيضًا هي تعطيل جزء من الشيفرة ﻷغراض التجربة. يمكنك أن ترى نوعَيّ التعليقات السابقين في المثال أعلاه. المتغيرات تسمح لك المتغيرات بتخزين ومعالجة البيانات في السكربتات، ويمكنك اعتبارها شبيهةً بالمتغيرات التي تستعملها في الرياضيات؛ إذ أنَّ المتغير -ببساطة- هو حاويةٌ تحوي قيمةً معيّنة؛ أُطلِقَت تسمية "المتغيرات" عليها لأنها القيمة المُسنَدة إليها قد تتغير أثناء تنفيذ السكربت، وقابلية التغير تلك تجعل من المتغيرات أداةً مفيدةً جدًا. وكما ذكرنا سابقًا، يبدأ اسم المتغير بالإشارة $. هذه بعض الأمثلة عن أسماءٍ صحيحةٍ للمتغيرات: $simple $_start_with_underscore $_includes_numbers_23 $_includes_UPPERCASE_2 $_23_it_is_valid ملاحظة: لا يمكنك بدء اسم المتغير برقمٍ كالاسم الآتي $2_invalid_variable_name، ولا يمكن أيضًا أن تستعمل الشرطة "-" في اسمه. أنواع البيانات أنواع البيانات (data types) هي أنواع المتغيرات في PHP؛ وأنواعُ البياناتِ البسيطة في PHP هي: الأعداد الصحيحة (integers) الأعداد ذات الفاصلة (floats) السلاسل النصيّة (strings) القيم المنطقية البوليانية (صح [true] أو خطأ [false])؛ وهنالك أنواع بياناتٍ أخرى مثل الكائنات (objects) والمصفوفات (arrays) سنتحدث عنها لاحقًا في هذه السلسلة. ملاحظة: إن كانت لديك معلوماتٌ سابقة عن إحدى لغات البرمجة التي تُحدِّد نوع البيانات المُخزَّنة في المتغيرات (أي strongly typed)، فاعلم أنَّ PHP هي لغةٌ لا تتطلب منك تحديد النوع (أي أنها loosely typed)؛ فلا تحتاج إلى أن تخبر اللغة ما نوع البيانات التي ستُخزَّن في المتغير. الثوابت الثابت هو مُعرِّف (أي اسم) يحمل قيمةً معيّنة، وكما يوحي اسمه، لن تتغير قيمته أثناء تنفيذ السكربت بعد أن تُعرَّف لأول مرة، واسمه حساسٌ لحالة الأحرف، وتُستعمَل الأحرف الكبيرة فيه عادةً؛ وله نفس قواعد تسمية المتغيرات (لا يجوز أن يبدأ برقم، أو يحتوي على شرطة…)، لكن لا يوضع الرمز $ قبله. <?php /* author: Abd Allatif Eymsh website: academy.hsoub.com version: 1.0 date: 22 12 2015 */ // هذا تعليقٌ ذو سطرٍ وحيد $variable = 'variablename'; echo "string"; echo $variable; define( "MY_CONSTANT", "19" ); define('PI', 3.14); echo PI; echo MY_CONSTANT; ?> تكون PI و MY_CONSTANT ثوابت في المثال السابق. ملاحظة: يمكن استعمال الكلمة المحجوزة const لتعريف الثوابت بدلًا من الدالة define() في إصدار PHP 5.3 وما بعده كما يلي: <?php // تعمل في إصدار PHP 5.3 const CONSTANT = 'Hello World'; echo CONSTANT; ?> لكن لا يمكن تعريف الثوابت باستخدام const داخل الدوال أو الحلقات، لأنها تُعرَّف في وقت التصريف (compile-time). المعاملات يأخذ المعامل قيمةً أو أكثر (أو "تعبيرًا" [expressions] كما نقول في الاصطلاحات البرمجية) ويُنتِج قيمةً أخرى. يمكن أن تُجمَّع المعاملات بناءً على عدد القيم التي تأخذها، فمثلًا المعاملات الأحادية (unary operators) تأخذ قيمةً واحدةً فقط (مثل معامل الزيادة الذي شرحناها أدناه)، والمعاملات الثنائية تأخذ قيمتين مثل المعاملات الحسابية البسيطة (الجمع والطرح والضرب…) وتُصنَّف أغلبية المعاملات في PHP ضمن هذا القسم؛ وهنالك معامل ثلاثي وحيد يأخذ ثلاث قيم سنشرحه في درسٍ لاحق. هنالك عددٌ كبيرٌ من المعاملات في لغة PHP، أهمها: المعاملات الحسابية الإسناد معاملات الأعداد الثنائية (Bitwise) معاملات المقارنة الزيادة أو الإنقاص معامل السلاسل النصية المعاملات الحسابية هي تلك المعاملات التي تستعملها في الحسابات الرياضية، مثل الجمع (+)، والطرح (-)، والضرب (*)، والقسمة (/)، وباقي القسمة (%)؛ مثال: $a = 4 + 5; // + هو معامل حسابي لاحظ الفرق بين المعاملين / و %، إذ أنَّ / هو معامل القسمة بينما % هو باقي القسمة؛ أي 8 /5 = 1.6 ، بينما 8 % 5 = 3 (إذ أنَّ 8 = 5 *1 +3، فإن باقي القسمة هو 3). أما معامل الإسناد، فيسند القيم إلى المتغيرات، وهو إشارة = كما في المثال الآتي: $a = 4;. تجري المعاملات الثنائية العمليات الحسابية على البتات الموجودة في الأعداد الصحيحة، وهي & (and)، و | (or)، و >> (الإزاحة نحو اليسار)، و << (الإزاحة نحو اليمين)، و ^ (XOR)، و ~ (NOR)؛ مثال على ذلك هو 14 & 3 = 2، لأنَّ 00001110 & 00000011 = 00000010. أما معاملات المقارنة، فهي -كما يدل اسمها- تقارن بين قيمتين؛ يُظهِر الجدول الآتي معاملات المقارنة الشائعة: المثال اسم المعامل النتيجة $a == $b المساواة TRUE إن كان المتغير $a مساويًا بالقيمة إلى المتغير $b $a === $b مطابقة TRUE إن كان المتغير $a مساويًا المتغير $b بالقيمة والنوع $a != $b $a <> $b عدم مساواة TRUE إن لم يكن المتغير $a مساويًا للمتغير $b $a !== $b عدم مطابقة TRUE إن لم يكن المتغير $a مساويًا للمتغير $b بالقيمة أو بالنوع $a < $b أصغر من TRUE إن كان المتغير $a أصغر تمامًا من المتغير $b $a > $b أكبر من TRUE إن كان المتغير $a أكبر تمامًا من المتغير $b $a <= $b أصغر من أو يساوي TRUE إن كان المتغير $a أصغر أو يساوي المتغير $b $a >= $b أكبر من أو يساوي TRUE إن كان المتغير $a أكبر أو يساوي المتغير $b تستعمل معاملات الزيادة أو الإنقاص لزيادة أو إنقاص قيمة المتغير بقيمة 1. المثال شرحه ++$x; إضافة القيمة 1 إلى المتغير $x ثم إعادة القيمة النهائية $x++; إعادة قيمة المتغير $x ثم إضافة 1 –-$x; إنقاص القيمة 1 من المتغير $x ثم إعادة القيمة النهائية $x–-; إعادة قيمة المتغير $x ثم إنقاص 1 <?php echo "Postincrement"; $a = 5; echo "Should be 5: " . $a++; echo "Should be 6: " . $a; echo "Preincrement"; $a = 5; echo "Should be 6: " . ++$a; echo "Should be 6: " . $a; echo "Postdecrement"; $a = 5; echo "Should be 5: " . $a--; echo "Should be 4: " . $a; echo "Predecrement"; $a = 5; echo "Should be 4: " . --$a; echo "Should be 4: " . $a; ?> معامل السلاسل النصية (.) يستعمل لجمع سلسلتين نصيتين أو متغيرين مع بعضهما بعضًا؛ انظر إلى الشيفرة الآتي: <?php $a = 4; $q = 5; $c = $a.$q; // المتغيران $a و $b أصبحا مدمجين مع بعضهما echo $c; $n = 'myname'; echo "string ".$n.' $n inserted'; // دمج ثلاث سلاسل نصيّة ?> حاول أن تتدَّرب على تعريف وطباعة قيمة المتغيرات الخاصة بك، وأن تستعمل مختلف المعاملات السابقة عليها. المصادر مقال Introduction to PHP لصاحبه Harish Kumar. صفحة Operators من دليل PHP، وغيرها.2 نقاط
-
لا شك أنك كنت ذات يوم في الحمام، ثم خرجت مسرعا متقافزا وصارخا، كما فعل أرخميدس من قبل: أوريكا.. أوريكا. مبروك، لقد وجدت الفكرة العبقرية التي ستتفوق على جوجل، فيسبوك وأبل. الآن جلست إلى مكتبك المهترئ لتبدأ التخطيط لشركتك الناشئة، وسريعا غرقت في الأحلام وبدأت في بناء قصور رملية ضخمة... ثم منتشيا بأحلامك عدت للواقع وسؤال كئيب يؤرق تفكيرك: مشروع ضخم مثل هذا يحتاج إلى سيرفرات صخمة ولغة برمجة قادرة على معالجة كل تعقيدات المشروع. فما هي هذه اللغة المناسبة؟ مهلا مهلا يا فتى. مشروع ضخم سيتفوق على جوجل وفيسبوك؟ حسنا، هذا ليس أمرا مستحيلا، لكنه ليس عمل يوم وليلة. الأمر سيتطلب عمل سنوات قبل أن تصل إلى ذلك. فلماذا تزعج نفسك اليوم بالتفكير في مشاكل المستقبل؟ من الرائع أن تكون لديك رؤية مستقبلية طويلة المدى حول مشروعك وما الذي يمكنك أن تقدم من خلاله. لكن من العبث أن تزعج نفسك بالتفكير في مشاكل لن تواجهها قبل سنوات، أو ربما لن تواجهها أبدا. حُل مشاكل اليوم هذا اليوم، ودع مشاكل الغد للغد. لكن السؤال يبقى قائما: ما هي لغة البرمجة التي ستعتمدها؟ ببساطة، اعتمد لغة البرمجة التي تتقنها. ابدأ البرمجة بها وقدم مشروعك اليوم. ثم حين يكبر المشروع غدا وتجد أن لغة البرمجة تلك لم تعد مناسبة، ستكون احتياجاتك واضحة آنذاك بشكل كاف يسمح لك باختيار لغة البرمجة المناسبة التي ستواصل العمل بها. يساعدك هذا الفيديو على معرفة المعايير التي من خلالها ستتمكن من اختيار لغة البرمجة التي تتناسب مع تطلعاتك وأهدافك المستقبلية. هل تعلم بأن شبكة فيسبوك برمجت في البداية كاملة بـ PHP؟ نعم ذلك صحيح. ثم لاحقا بعد أن كبر المشروع كثيرا ولم تعد PHP مناسبة لتقديم مستوى الأداء المطلوب، بدأ فريق الشركة في تحويل أجزاء من الشبكة، تباعا، للغات برمجية أخرى مثل جافا وC. لكن ماذا لو كنت تتقن أكثر من لغة برمجة، كيف ستختار اللغة المناسبة لتنفيذ مشروعك؟ بعيدا عن مسألة أداء كل لغة -المتشابه عموما بين أغلبها- فإن أبرز معيار لاختيار اللغة المناسبة هو حجم الطلب العالمي على تلك اللغة. لا شك أنك لن تبقى المبرمج الوحيد لمشروعك، فيوما ما ستنمو شركتك وستحتاج لتوظيف مبرمجين آخرين. لو اخترت لغة برمجية نادرة فإنه سيصعب عليك كثيرا إيجاد المبرمجين لفريقك، وحتى لو وجدت أحدهم بشق الأنفس سيطلب راتبا أكبر مما تتوقع. لذلك عليك أن تختار اللغة التي يتقنها الكثير من المبرمجين، بحيث يمكنك بسهولة إيجاد الكفاءات التي تريد، وبرواتب معقولة. إذن، كيف ستعرف اللغة الأكثر شعبية؟ الجواب في فهرس تيوبي (Tiobe index) للغات البرمجة الأكثر شعبية. وهو فهرس شهري يرتب شعبية اللغات اعتمادا على عدد مرات البحث عن اللغة في محركات البحث ككلمة مفتاحية، ويشمل ذلك عمليات البحث في جوجل، مدونات جوجل، بينج، ياهو، ويكيبيديا و يوتيوب. وهو مخصص فقط للغات البرمجة الكاملة، ولا يتضمن اللغات البرمجية الوصفية مثل SQL وHTML. فيما يلي تقرير شهر نوفمبر الحالي، وهو يظهر استمرار لغة جافا في المركز الأول، وإن كانت نسبة نمو لغة C توحي بأنها قريبا ستصل للمركز الأول. في حين تأتي لغة PHP في مركز متقدم مقارنة بلغات أخرى تستخدم في تطوير مواقع الإنترنت الديناميكية، مثل بايثون وروبي.1 نقطة
-
أوراق الأنماط المتتالية (Cascading Style Sheets أو CSS اختصارًا) هي لغة تُستخدم لوصف كيفيّة عرض المستندات للمستخدمين. تُكتب هذه المستندات في لغة رُماز مثل HTML. المستند هو مجموعة من المعلومات التي تهيكل باستخدام لغة رُماز (markup language). يُقصّد بعرض المستند للمستخدم تحويله إلى صيغة مُفيدة للجمهور، فالمتصفحات مثل Firefox وChrome وInternet Explorer مًصمّمة بحيث تعرض المستندات للمستخدمين مرئيًّا، مثلًا: على شاشة حاسوب أو جهاز إسقاط (projector) أو طابعة. سنتعرض خلال هذه السلسلة إلى المواضيع التالية: مدخل إلى أوراق الأنماط المتتالية (CSS) (هذا الدرس). آلية عمل تعليمات CSS داخل المتصفحات. المحددات (Selectors) في CSS. كيفية كتابة تعليمات CSS يسهل قراءتها. تنسيق نصوص صفحات الويب باستخدام CSS. التعامل مع الألوان في CSS. إضافة محتوى إلى صفحة ويب باستخدام CSS. تنسيق القوائم (Lists) في CSS. تعرف على الصناديق (Boxes) في CSS. رصف العناصر (Layout) في CSS. الجداول (Tables) في CSS. التعامل مع أجهزة العرض المختلفة والمطبوعات في CSS. أمثلة صفحة الويب هذه الّتي تقرأها هي مُستند. تُهيكل المعلومات التي تشاهدها في صفحة ويب باستخدام لغة HTML (اختصارًا لـHyperText Markup Language). مرُبعات الحوار في التطبيقات هي أيضًا مُستندات، وقد تكون مُهيكلة باستخدام لغة رماز مثل XUL (اختصارًا لـXML User Interface Language)، والتي قد تجدها في بعض برامج Mozilla. في هذه السلسلة، ستُقرأ معلومات مُدرجة تحت عنوان تفاصيل أكثر كالفقرة التالية، تحوي هذه الفقرات على معلومات وروابط لمصادر إضافية عن مفهوم أو موضوع تغطّيه هذه الأقسام. اقرأ هذه المعلومات حالما تُشاهدها وتابع الروابط، أو تجاوزها وعُد لقراءتها لاحقًا. تفاصيل أكثر كلمة المستند لا تعني ما تعنيه كلمة "ملفّ"، إلّا أنّه يمكن حفظ المستندات ضمن ملفّات. المستند الذي تقرأه الآن لم يُحفَظ في ملفّ، بل يُجلب من قاعدة بيانات على الخادم والذي بدوره يولّد المستند بجمع أجزائه من عدّة ملفّات. مهما يكن الأمر، فإنّك في هذه السّلسلة ستتعامل مع مستندات محفوظة في ملفّات. بإمكانك إيجاد معلومات أكثر عن المستندات ولغات الرُماز في مواقع أخرى من شبكة مطوّري Mozilla: اللغة الوظيفة HTML لصفحات الويب XML للصفحات المُهيكلة بشكل عامّ SVG للرسوم XUL لواجهات برامج Mozilla سنطّلع على أمثلة من هذه اللغات في الجزء الثّاني من السلسلة. تفاصيل أكثر يُدعى البرنامج الذي يعرض المستندات على المستخدم في المصطلحات الرسميّة لـCSS بوكيل المستخدم (user agent أو UA). المتصفّح ليس إلّا واحدًا من وكلاء المستخدم، فلا تقتصر CSS على المتصفّحات أو العرض المرئيّ، ولكنّنا في الجزء الأوّل من السّلسلة لن نتعامل إلّا مع CSS في المتصفّح. للاطّلاع على التعاريف الرسمية للمصطلحات في CSS، انظر Definitions في وصف CSS من قبل جمعيّة W3C المسؤولة عن تعيين المعايير القياسيّة للويب. لنبدأ العمل: إنشاء مستند أنشئ مجلّدًا جديدًا في جهازك لحفظ وتنظيم تمارين هذه السّلسلة. افتح محرّر النصوص وأنشئ ملفًّا نصيًّا جديدًا، سنقوم بكتابة المستند في هذا الملف خلال التمارين القليلة التالية. انسخ والصق HTML أدناه. احفظ الملف باسم doc1.html. <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Sample document</title> </head> <body> <p> <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets </p> </body> </html> افتح علامة تبويب أو نافذة جديدة في متصفّحك، ثم افتح الملف الذي أنشأته. من المُفترض أن ترى النّص وحروفه الأولى بخطّ عريض، كهذه الصّورة: قد يختلف ما تراه في متصفحك قليلًا عن الصّورة من حيث الخط أو الألوان أو المسافات بين الحروف، وهذا غير مهمّ الآن. المستند الآن لا يستخدم CSS، وهذا ما سنفعله في الخطوة التالية. لماذا نستخدم CSS؟ استخدم CSS لتعريف تنسيق مستنداتك، بما في ذلك التصميم والتخطيط والاختلافات في العرض بين الأجهزة المختلفة وقياسات الشاشات المختلفة. بإمكانك إضافة CSS في رأس (<head>) مستند (نُسمّي ذلك ورقة أنماط مُضمّنة) أو إرفاق ملف منفصل يحوي تعريف التنسيقات (ورقة أنماط خارجيّة)، ثمّ ربطها مع المستند برابط يُضاف إلى رأسه. لللأسلوب الأخير عدّة محاسن، ففصل التنسيقات عن الرُماز: يقلّل من التكرار يُسهل الصّيانة يسمح بإجراء تغيير على نطاق الموقع كاملًا من مكان واحد مثال يمكنك مثلًا حفظ معلومات التنسيقات في ملفات مشتركة بين كلّ الصّفحات، فعندما يُربَط مستند بورقة أنماط تُحدّد لون العناوين الثانويّة (h2)، بإمكانك استخدام هذا التنسيق في كل صفحات الموقع بالإشارة إلى هذه الورقة. عندما يعرض مستخدم صفحة ويب، يقوم المتصفح بجلب معلومات التنسيق في الوقت نفسه. عندما يطبع مستخدم صفحة ويب، بإمكانك توفير معلومات تنسيق مختلفة تُسهّل من قراءة الصّفحة المطبوعة. كيف تعمل HTML وCSS معًا؟ بشكل عامّ، استخدم HTML لوصف محتوى الموقع، وليس تنسيقه. بإمكانك استخدام CSS لتحديد تنسيق المستند، وليس محتواه. أحيانًا نضطر لإجراء بعض الاستثناءات لهذه القاعدة، كما سنرى لاحقًا. تفاصيل أكثر توفّر لُغة رُماز مثل HTML بعض الوسائل لوصف تنسيق المستند بشكل منفصل عن CSS، فيمكنك مثلًا في HTML استخدام الوسم <b> لجعل النّص عريضًا، ويمكنك تحديد لون خلفيّة المستند في وسم متن المستند <body>. عندما تستخدم CSS، يُفضّل عادةً تجنّب استخدام هذه الميزات في لغة الرُماز بحيث يبقى وصف تنسيق المستند في موضع واحد فقط. لنعمل: إنشاء ورقة أنماط أنشئ ملفًّا نصيًّا آخر بجوار الملف السابق doc1.html. احفظ الملف باسم style1.css. سيحوي هذا الملف وصف التنسيقات. في ملفّ CSS، انسخ والصق السّطر التالي ثمّ احفظ الملف: strong {color: red;} ربط المستند بورقة الأنماط لربط المستند بورقة الأنماط، عدّل ملفّ HTML، أضف السّطر التالي في موقعه: <link rel="stylesheet" href="style1.css"> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Sample document</title> <link rel="stylesheet" href="style1.css"> </head> <body> <p> <strong>C</strong>ascading <strong>S</strong>tyle <strong>S</strong>heets </p> </body> </html> احفظ الملف وحدّث الصّفحة في متصفّحك. تجعل ورقة الأنماط الحروف الأولى بلون أحمر، كهذا: ما التالي؟ لدينا الآن مستند بسيط مرتبط بورقة أنماط خارجيّة، وسنتعلّم كيف يجمعهما المتصفح معًا لعرض الصّفحة في الجزء التالي: كيف تعمل CSS؟ ترجمة (بتصرّف) للجزأين الأوّلين What is CSS و Why use CSS من سلسلة Getting started with CSS على شبكة مطوّري Mozilla.1 نقطة
-
سنتعرّف في هذا الدّرس على العبارات الشرطيّة وكيفيّة استخدامها لتنفيذ أوامر أو تجاهلها استنادًا إلى شرط معيّن. افتح ملفّ روبي جديد وسمّه logic.rb أو أيّ اسم آخر مع التأكّد من كتابة rb. في آخر اسم الملفّ واكتب الشيفرات البرمجيّة التّالية والتي تمثّل نسخة مجرّدة من لعبة إلقاء النّرد: number = rand(1..6) puts "You rolled #{number}" ماذا فعلنا هنا؟ أنشأنا متغيّرًا وحفظنا به قيمة عشوائيّة بين 1 و 6، ثمّ استعملنا هذا المتغيّر لطباعة القيمة العشوائيّة على الشّاشة باستخدام أمر puts مخبرين المستخدم أنّ ناتج إلقائه للنرد هو ذلك الرقم العشوائي النّاتج عن استخدام دالّة rand (التي سبق وأن اطّلعنا عليها في الدّرس السّابق). سنتعرّف الآن على بعض العبارات الشرطيّة التي يمكننا استخدامها لإخراج بعض المعلومات عن الرقم استنادًا إلى ما إذا كان الشّرط متحقّقًا أم لا. اكتب السطر التّالي أسفل الشيفرات البرمجيّة السّابقة: puts "You rolled the highest number possible" if number == 6 تلاحظ في العبارة الشرطيّة السّابقة أنّ الشرط هو أن يكون المتغيّر number يساوي 6. إذا تحقّق هذا الشرط سنقوم بإخراج رسالة "You rolled the highest number possible". الأمر المهم لدينا هنا هو عبارة if التي تأتي قبل الشّرط الذي يجب أن يكون صحيحًا من أجل طباعة السّلسلة، في حالتنا هذه كما ذكرنا فالشّرط هو أن يكون المتغيّر مساويًا لـ 6. لاحظ كيف استخدمنا علامتي == لاختبار المساواة بين الطرفين. يختلف هذا عمّا فعلنا في بداية الشيفرات حيث استخدمنا علامة مساواة واحدة لتعيين قيمة للمتغيّر. إذًا فنستخدم علامة يساوي واحدة لتعيين القيم وعلامتين من أجل اختبار إذا كان طرفين متساويين أم لا. يمكننا أيضًا استخدام بنية مشابهة لذلك لمعرفة إذا كان الشّرط غير متحقّق كالتّالي: puts "You didn't roll the lowest number possible" if number != 1 كما تلاحظ فالجملة مشابهة إلى حدٍّ كبير، نريد طباعة هذه السلسلة إذا كان المتغيّر number لا يساوي (!=) 1. سيتم طباعة تلك السلسلة فقط عن تحقّق هذا الشرط. في الحالتين السّابقتين لدينا الجملة الشّرطيّة موجودة بالنهاية والشيفرة البرمجيّة التي نريدها أن تنفّذ موجودة في البداية. يمكننا كتابة ذلك بترتيب مختلف بأن نضع الجملة الشّرطيّة في البداية كالتّالي: if number < 5 then puts "You rolled a number less than 5" end كما تلاحظ، نحن نخبر روبي إذا كان قيمة المتغيّر أقل من 5 يجب تنفيذ الأمر الموجود بعد الكلمة المفتاحيّة then. وبالنّهاية نضع end والتي نحتاج إليها لإخبار روبي بأنّ عبارة if قد انتهت. كتابة أكثر من شرط يمكننا أيضًا كتابة أكثر من شرط في أكثر من سطر. مثال على ذلك: if number.even? puts "You rolled and even number" else puts "You rolled an odd number" end السّطر الأوّل يتحقّق إذا كان المتغيّر number عددًا زوجيًّا باستخدام دالّة even، إذا كانت الإجابة true سيتمّ تنفيذ أمر puts الخاصّ بهذا الشرط. إذا كانت قيمة المتغيّر عددًا غير زوجي، فمن البديهي أنه سيكون فرديًّا. إذًا فإنّ else تعدّ بمثابة ما نريد تنفيذه إذا لم يتحقّق الشرط. لاحظ أنّه يجب وضع end مرّة واحدة في النهاية تمامًا وليس بعد if مرّة وبعد else مرّة. elsif يمكننا كتابة عدد أكبر من الجمل الشرطيّة أيضًا باستخدام elsif. if number == 1 then puts "You rolled one" elsif number == 2 then puts "You rolled two" elsif number == 3 then puts "You rolled three" else puts "You rolled a number bigger than three" end لدينا في هذا المثال ثلاثة جمل شرطيّة مختلفة متبوعة بجملة else والتي ستُنفّذ إذا لم يتحقّق أيّ شرط من الشّروط الثلاثة السّابقة لها. لنبدأ مع أول سطر، جملة if عاديّة تتحقّق إذا كانت قيمة المتغيّر number تساوي 1، إذا كان الجواب نعم فستنفّذ روبي الأمر الموجود بعد then وتستبعد باقي الجمل الشرطيّة. أمّا إذا لم تتحقّق الجملة الشرطيّة الأولى فتنتقل روبي إلى السطر التّالي والذي يحتوي على جملة شرطيّة أخرى والتي تختبرها روبي فقط إذا لم تتحقّق الجملة الشرطيّة السّابقة، لذلك فهي تسمّى elsif. تعمل تمامًا elsif عمل if، الفرق فقط هو أنّها لا تنفّذ في حالة تحقّق الجملة الشرطيّة السّابقة لها. السطر الثالث مشابه للسطر الثّاني. وبالنهاية لدينا else والتي لا تحتوي على شرط محدّد وإنّما تنفّذ في حال عدم تحقّق أي جملة شرطيّة من الثلاث. ثم end. عبارة Case يمكننا استخدام عدد لا نهائي من جمل if, elsif, else ولكن مع زيادى عدد الشروط المطلوبة قد يصبح الأمر متعبًا ومستهلكًا للوقت. لذلك فهناك عبارة أخرى يمكننا استخدامها وهي case. حاول تخمين ما تفعله case بالاطّلاع على الشيفرات التالية: case number when 4 then puts "You rolled four" when 5 then puts "You rolled five" when 6 then puts "You rolled six" else puts "You rolled a number less than four" end كما تلاحظ، فهي تعمل بشكل مشابه جدًّا للمثال السّابق. الفرق أنّنا نستخدم case بدلاً من if. لاحظ أنّنا نضع بالبداية المتغيّر number حيث أنّ كل الجمل الشّرطيّة الموجودة بـ case تشير إلى هذا المتغيّر. على سبيل المثال بالنّظر إلى السطر الثاني، فهو يشير أنّه عندما (when) تكون قيمة المتغيّر number تساوي 4 إذًا (then) ننفّذ أمر puts. وهكذا حتى الوصول إلى else ثم end في نهاية عبارة case واللذان يستخدمان تمامًا مثل استخدامهما في عبارة if. سلسلة عبارات if يمكننا أيضًا وضع جمل if كمتسلسلات كما ترى أدناه: if number == 2 or number == 3 or number == 5 puts "You rolled a prime number" end استخدمنا جملة if عاديّة ونخبر روبي بأنّه إذا كانت قيمة المتغيّر number تساوي 2، أو (or) تساوي 3، أو (or) تساوي 4 فكما قد تكون توقّعت سيتمّ تنفيذ الأمر الخاصّ بتلك العبارة. إذًا فنحن في الواقع نختبر ثلاث شروط مختلفة وإذا تحقّق شرط واحد منها فإنّ ناتج هذه العبارة الشّرطيّة سيصبح true. هناك طريقة أخرى لكتابة تلك الشيفرات. puts "You rolled a square number" if number == 1 || number == 4 يسمّى || برمز الأنبوب المزدوج (Double Pipe Symbol) والذي يمثّل كلمة or. لاحظ أيضًا كيف قمنا بعكس الجملة الشرطيّة وذلك بوضع الشرط في النهاية كما فعلنا سابقًا. هناك أيضًا عبارة and والتي تتحقّق إذا تحقّقت جميع الشروط الموجودة والتي مربوط بينها باستخدام and. if number.odd? and number >= 4 puts "You rolled five" end في الشيفرات البرمجيّة أعلاه نتحقّق إذا كانت قيمة المتغيّر هي عدد فردي و (and) أكبر من أو تساوي 4. هذا الرّمز >= يعني أنّ الطرف الأيسر من الجملة أكبر من أو يساوي الطرف الأيمن. بالرجوع مجدّدًا إلى الشيفرة البرمجيّة السّابقة فإنّه عند تحقّق الشرطين معًا (وليس أحدهما فقط) فسيتمّ تنفيذ الأمر puts الذي يلي العبارة الشرطيّة. مثل or، هناك أيضًا طريقة أخرى لكتابة and. if number.even? && number <= 3 puts "You rolled two" end الشيفرة أعلاه مشابهة تمامًا للسّابقة، نتحقّق إذا كانت قيمة المتغيّر عددًا زوجيًّا و (&&) أقل من أو تساوي 3. إذا تحقّق الشّرطيّن المربوط بينها باستخدام && فسيتمّ تنفيذ أمر puts الخاصّ بالعبارة الشرطيّة. رمز && يسمّى Double Ampersand Symbol. ختام تعرّفنا في هذا الدّرس على العبارات الشرطيّة في ruby وكيفيّة استخدامها. إذا كتبت الشيفرة البرمجيّة المستخدمة في هذا الدّرس في ملفّ روبي فعلاً فجرّب تنفيذها في سطر أوامر روبي التفاعليّ كما تعلّمنا في الدّروس السّابقة وقارن النتائج بالشيفرات الموجودة لمعرف وظيفة كل جزء منها.1 نقطة
-
إن بيوتنا غالبا تكاد لا تخلو من رفوف وخزانات تمتلئ بالأغراض المختلفة والتي قد تتشابه في بعض أجزائها، لذا سنستمتع برسم خزانة نصفها العلوي عبارة عن رفوف تحتوي على أغراض مختلفة والتي ستبدو في النهاية كما في الصورة: وبما أن درسنا يحتوي على الكثير من التفاصيل فسنقوم بتجزئته إلى جزأين. خطوات رسم الخلفية ارسم مستطيلا عبارة عن جدار الغرفة واجعله بالعرض والارتفاع المناسب، ثم ارسم أسفله مستطيلا آخر بنفس العرض إلا أنه أقل ارتفاعا ليمثل أرضية الغرفة. ارسم فوق الجدار مجموعة من المستطيلات الأخرى بلون أقتم من المستطيل الأصلي. ملاحظة: لتكرار المستطيلات استخدم الزر الأيمن للشكل المراد تكراره ثم اختر Duplicate. قم بتسوية المساحة بين المستطيلات بتحديدها مع الضغط على Shift أثناء التحديد لتتمكن من تحديدها جميعا، ثم اجعل اصطفافها متساويا عموديا من لوحة المحاذاة والاصطفاف Align and distribute. ارسم وسط الجدار مستطيلا مستدير الزوايا بالعرض والطول الذي ترغب أن تكون عليها الخزانة، واختر لها اللون المناسب وأزل عنها الحدود من لوحة التعبئة والحدود Fill and stroke. ارسم في النصف السفلي من الخزانة بابين بأداة المستطيل مع إبقاء حدودهما، ولون الحدود بلون أقتم من لون الخزانة. أضف في النصف العلوي للخزانة مستطيلا ثالثا ولونه بلون أقتم من الخزانة، وأضف للبابين على جانبيهما مستطيلا صغيرا بلون قاتم. ولإعطائه لونًا أقتم من الخزانة، قم بتلوينه بنفس لون الخزانة ثم من لوحة التعبئة Fill and stroke مع التأكد من اختيار نمط الألوان HSL اختر الشريط الذي عند الحرف L وحركه لجهة اليسار. أضف المقبض لبابي الخزانة برسم شكل بيضاوي بأداة الدائرة، ثم أضف رفّين بأداة المستطيل وسط المستطيل القاتم ولونهما بنفس لون الخزانة. قم بتسوية المسافة بين المستطيلين بتحديد خيار اصطفافهما أفقيا من لوحة المحاذاة والاصطفاف. قم بإقفال الطبقة الحالية من لوحة Layers وذلك باختيار layer من الشريط العلوي الرئيسي ثم اختر layers من القائمة المنسدلة لتظهر لنا لوحة الطبقات، ثم من اللوحة اضغط على رمز القفل، حتى لا تقوم بتحريك أحد أجزائها خطأ أثناء رسم بقية التفاصيل. من علامة الزائد في لوحة الطبقات اختر العلامة + لإضافة طبقة جديدة ثم من النافذة المنبثقة اختر إضافة Add لإضافة الطبقة الجديدة التي سنرسم فيها بقية التفاصيل. خطوات رسم الكتب والدفاتر سنبدأ بالرّفّ العلوي ونصف فيه مجموعة من الكتب بأداة المستطيل سندور آخرها من جهة اليمين ليبدو مائلا، وبنفس الأداة يمكننا إضافة بعض التفاصيل والخطوط للكتب. ارسم في الطرف الأيمن من الرّفّ الثاني مجموعة من الدفاتر عن طريق أداة المستطيل، وليظهر شكل الأوراق في بعضها، قم بتكرار الشكل وتلوينه باللون الأبيض، ثم اختر الشكل المكرر وعن طريق أسهم التحجيم قم بسحب السهم العلوي المتوسط للأسفل مع الضغط على Shift أثناء ذلك وذلك لتصغير الشكل من الجهتين بشكل متساوي. أضف دفترا أعرض فوق الدفاتر السابقة في الأعلى وكرر الخطوات التي عملتها مع الدفتر الماضي لتظهر الأوراق، وارسم مستطيلات رفيعة وسط المساحة البيضاء، ومن لوحة المحاذاة والاصطفاف رتب اصطفافها عاموديا. ملاحظة: إذا أردت تحديد مجموعة متماثلة من الأشكال لها سمة مشتركة في (اللون، الحدود، أوكلاهما،..) دون الاضطرار لتحديدها شكلًا شكلًا، اختر الشكل المطلوب تحديد نظائره وعن طريق الزر الأيمن اختر التحديد المماثل Select same. ستظهر لك مجموعة من الخيارات، اختر أحدها، وهنا اخترنا Fill color ليحدد لنا جميع المستطيلات المعبئة باللون الرمادي. ارسم على الدفتر العريض مجموعة من الحلقات، عن طريق أداة المستطيل مع جعل المستطيل بزوايا كاملة الاستدارة، ورتب المسافة بينها عن طريق تبويب المحاذاة والاصطفاف. حدد أجزاء الدفتر وقم بتجميعها Group عن طريق Ctrl+G ثم كرّره وغير لونه وضع نسخة منه في الرّفّ العلوي مع تدويره بمحاذات الكتاب المائل. خطوات رسم علبة الأقلام بما أننا رسمنا الدفاتر والكتب، فلا شك أننا بحاجة للأقلام، والأقلام بحاجة لعلبة لحفظها، لذا بأداة المستطيل سنرسم مستطيلا مستدير الزوايا، وسنحرره عن طريق أداة التحرير Node tool ثم من الشريط العلوي نختار Object to path لتحويل الشكل لمسار حيث ستظهر لنا أربع عقد nodes حول الشكل. نختار الأربع عقد السفلية للشكل ثم من لوحة المفاتيح نضغط Ctrl+> لنحرك العقد الأربع للداخل. ارسم ثلاث مستطيلات وسط علبة الأقلام وحددها معا. من الشريط العلوي الرئيسية اختر المسار Path ومن القائمة المنسدلة اختر توحيد Union وذلك حتى تصبح هذه المستطيلات شكلا واحدا. كرّر شكل العلبة مجددا ثم اختر الشكل المُكرّر مع المستطيلات التي أصبحت جزء واحدا، ومن نفس قائمة Path اختر Intersection ليظهر عرض المستطيلات ملائما مع حواف العلبة دون زوائد. سنرسم القلم الملون الذي يستخدم مع الكتب لتحديد سطورها بالألوان، وذلك عن طريق رسم مستطيلين بزوايا مستديرة، وبأداة الرسم Bezier سنرسم خطا أفقيا ليفصل الغطاء عن قلمه، ولجعل الخط في اتجاه مستقيم دون ميلان اضغط على Ctrl أثناء رسم الخط، ثم أعد الخط خطوة واحدة للخلف عن طريق تحديده ثم اختيار Page down من الشريط العلوي. سنرسم قلم الحبر بنفس الطريقة السابقة إلا أنا سنرسم حامل الغطاء على أحد جانبي القلم. قلم الرصاص سيحتاج لتفاصيل أكثر لذا لرسمه اتبع الخطوات التالية: ارسم الممحاة عن طريق أداة المستطيل مع جعله كامل الاستدارة ثم ارسم فوقه مستطيلين بزوايا حادة، أحدهما يمثل المعدن الذي يحيط بالممحاة واجعله أعرض منها بقليل والآخر يمثل ارتفاع القلم واجعله طويلا بطول القلم. كرر المستطيل الأصفر الذي هو عبارة عن ارتفاع القلم ولونه باللون الأسود ثم بتحديده، واختيار أحد السهمين الجانبيين المتوسطين قم بتصغيره مع الضغط على زر Shift أثناء ذلك ليصغر من الجهتين اليمنى واليسرى. ارسم مستطيلا في طرف القلم ليمثل رأس القلم، وتأكد من أن زواياه حادة وأن عرضه كعرض القلم تماما. ملاحظة: لجعل عرض رأس القلم كعرض القلم، يمكنك تحديد المستطيل الأصفر ثم من الشريط العلوي عند الحرف w الذي يمثل عرض المستطيل رقميا، انسخ الرقم ثم ألصقه في عرض المستطيل الجديد بعد تحديده، أو يمكننا نسخ المستطيل الأصفر وتقليل عرضه وتغيير لونه بدلا من رسم مستطيل جديد. نحرر المربع الجديد عن طريق Node tool ثم من الشريط العلوي نختار Object to path ثم نحدد بنفس الأداة الضلع العلوي للمستطيل، ومن الشريط العلوي نختار Insert new node لإضافة عقدة جديدة. اختر العقدتين العلويتين الجانبيتين دون الوسطى التي أنشأناها توًا، ثم من لوحة التحكم حركهما للأسفل عن طريق الأسهم، أو اسحبهما بمؤشر الفأرة مع الضغط على Ctrl للمحافظة على اتجاههما. حدد الضلع السفلي وأضف ثلاث عقد جديدة وذلك بالضغط مرتين على علامة زائد من الشريط العلوي. قم بتحديد العقدتين الداخليتين دون الوسطى – أي حدد العقدة الثانية والرابعة من جهة اليمين - واسحبهما بالفأرة للأسفل مع الضغط على Ctrl أثناء السحب للمحافظة على ثبات مكانها عاموديا، أو حركهما عن طريق سهم لوحة المفاتيح السفلي. لرسم السمرة في طرف القلم، كرّر رأس القلم ولونه باللون الأسود، ثم ارسم مستطيلا وأنزله حيث الموضع الذي ترغب أن يكون عليه ارتفاع السمرة. حدد الشكلين ومن قائمة Path اختر Difference. وبذلك يكتمل القلم: قم بصف الأقلام الثلاثة في علبة الأقلام مع ملاحظة أنه بإمكانك جعل علبة الأقلام شفافة لتظهر التفاصيل التي قمت برسمها إن رغبت بذلك عن طريق لوحة التعبئة وذلك بتغيير قيمة شفافية العلبة Opacity. خطوات رسم الصناديق والسجلات ارسم صندوقا بنفسجيًا في الرف الثاني بأداة المستطيل مع تدوير غطائه بجانبه. انتقل للرّفّ الأخير وارسم فيه صندوقا آخر مع غطاء أعرض منه بقليل، واجعل الغطاء قاتما عن طريق لوحة التعبئة والحدود، ثم كرر الغطاء ولونه بنفس لون الصندوق وارفعه قليلا للأعلى. نأتي الآن لرسم السجلات عن طريق اتباع الخطوات التالية: ارسم مستطيلا بزوايا مستديرة، وفي وسطه ارسم ورقة بيضاء حادة الزوايا. ارسم في الورقة عن طريق Bezier خطا مستقيما، مع الضغط على Ctrl أثناء رسمه، ثم قم بتكراره على طول الورقة. ارسم في الطرف العلوي من السجل دائرة، وحتى تصبح بأبعاد متساوية اضغط Ctrl أثناء رسمها، ثم لونها بلون أقتم، وكررها ولون الدائرة المكررة بلون فاتح. كرر الدائرة الفاتحة ولونها بلون مغاير وحركها لليمين وللأسفل قليلا بالنسبة للدائرة الرمادية. حددها هي والدائرة الرمادية ثم من قائمة Path اختر Intersection. قم بتجميع أجزاء السجل، ثم كرره بالعدد الذي ترغب. هذا ما وضعنا من أغراض حتى الآن:1 نقطة
-
تحتاج إلى إعادة تشغيل الخادم عندما تريد أن يتم إعادة تحميل ريلز مرة أخرى من البداية، فمثلا عند إضافة أو حذف gem فستحتاج في هذه الحالة إلى إعادة تشغيل الخادم. أو إذا قمت بتغيير إصدار لغة روبي أو قمت بتغييرات في gemfile أو بإحدى الأصناف الداخلية لريلز لأنه قد تحدث أخطاء عند استمرارك بالعمل. أعتقد أن هذه هي أهم حالات التي تحتاج فيها إلى إعادة تشغيل الخادم.1 نقطة
-
كيف أستطيع وضع رأس صفحة مختلف في كتابي عند كل قسم جديد في برنامج Word؟1 نقطة
-
حكاية تتكرّر دائما. عادة ما نُشاهد تلك الفرق المكوّنة من شابّين أحدهما يمتلك ذلك النشاط والعزم الكبيرين واﻵخر خبير في الشؤون التقنية، يسعيان معًا إلى تأسيس شركة ناشئة، ليناضلا بعدها لتحقيق حلمهما في الوصول إلى مصافّ الشركات العملاقة مثل Google و Facebook. يتقلّد الشاب النشيط منصب المدير التنفيذي CEO بينما يتقلّد الشاب الخبير بالشؤون التقنية منصب المدير التنفيذي التقني CTO، لا مشكلة في ذلك لحدّ اﻵن أليس كذلك؟ حسنًا، ﻻ يبدو ذلك صحيحًا، إذ يعلم الكثير من الذين أصبحوا مدراء تنفيذيين في شركة ناشئة لأول مرة أنه سيأتي يوم في المستقبل سيضطرون فيه إلى اتخاذ قرار حاسم، فإما أن يكون غنيًا أو يكون ملكًا في شركته، وقد يؤدي ذلك إلى التنحّي عن هذا المنصب والاستعانة بشخص آخر لديه خبرة أكبر في هذا المجال. يتعلم المدير التنفيذي ذلك عندما يسأله المستثمرون إن كان يودّ البقاء في هذا المنصب إلى اﻷبد. ولكن ماذا بشأن المدير التنفيذي التقني؟ قد تكون اﻷمور مختلفة قليلًا ولكن هناك بعض أوجه الشبه، ولنكتشف ذلك معًا. ما هي وظيفة المدير التنفيذي التقني في الشركات الناشئة الاعتياديةلمّا كان هذا الشخص هو الأكثر خبرة في المجال التكنولوجي في هذا الفريق المكوّن من شخصين، فإنه يعدّ مسؤولًا عن جميع اﻷمور ذات الطبيعة التقنية، وهذا يعني بالتأكيد البرمجة ، ويعني كذلك اختيار البنية التحتية المضيّفة والتي سيعمل عليها البرنامج، والحزمة الضمنية للبرنامج Underlying stack، والمعمارية التقنية، وأدوات إدارة الشيفرة المصدرية، الخ، ولا غرابة في ذلك. ماذا عن إنشاء الموقع اﻹلكتروني الخاص بالشركة، وإدارة الراوتر اللاسلكي في المكتب، وتقديم المساعدة للمدير التنفيذي عندما يصاب حاسبه المحمول بالفيروسات، وإدارة خادوم البريد اﻹلكتروني الخاص بالشركة؟ نعم، يقوم المدير التقني بكلّ ذلك، إضافة إلى كنس أرضية البيت الذي يعمل فيه، وإحضار الرسائل من صندوق البريد المحلي. نعم، يؤدي المؤسسون الكثير من اﻷعمال، وهذا طبيعي جدًّا. النمو والنجاح هما سبب المعضلةتبرز المعضلة عندما تبدأ الشركة بالنمو لتجلب المزيد من الخبراء في المجال التقني، وستوكل الكثير من المهام التي كان يؤديها المدير التنفيذي التقني في اﻷيام اﻷولى إلى أشخاص آخرين، وفي نهاية المطاف سيدرك المدير التنفيذي وفريق اﻹدارة ضرورة وجود شخص يعمل على مراقبة عمليات التطوير يومًا بيوم (سواء من من ناحية العتاد أو البرمجيات) وآخر يكون هو المسؤول عن وضع اﻷفكار التقنية إضافة إلى كونه المتحدث الرسمي للشركة في الشؤون التقنية، وفي هذه الحالة ستحتاج الشركة إلى وجود منصبين اﻷول هو نائب الرئيس للهندسة VP of Engineering (أو أي عنوان مشابه) والمدير التنفيذي التقني. ولكن ما هو المنصب اﻷفضل بالنسبة للمدير التنفيذي التقني المؤسّس للشركة استنادًا إلى المهارات والطموحات المستقبلية؟ إن كانت اﻹجابة هي المراقبة اليومية لعمليات التطوير فلا يمكن حينها اﻹبقاء على لقب "المدير"، وقد يكون هناك احتمال ﻹنقاص الرتبة عندما تصبح المهمّتان أساسيتين في تحقيق نجاح الشركة وضمان استمرارية نموها. يمكن "رفع" اللقب إلى النائب الأول للرئيس Senior VP ولكن إن كانت الشركة مكوّنة من 30 موظّفًا فقط فإن وجود عدد من النواب الأوائل يبدو أمرًا سخيفًا، ولكن بالمقابل فإن أيّ لقب لا يحتوي على كلمة "مدير" (Chief) سيبدو كإنقاص لمرتبة الشخص الذي كان يحمل هذا اللقب سابقًا. استباق المعضلةعادة ما أنصح مؤسسي الشركات الناشئة بمناقشة هذا اﻷمر في وقت مبكّر جدًا. إذ يجب أن يعي من يرغب في تقلّد منصب المدير التنفيذي التقني منذ البداية أنّه سيأتي يوم في المستقبل حيث تتوزّع المهام التي يتحمل مسؤوليتها على عدد من اﻷشخاص، ما يعني أنه قد يفقد هذا اللقب في يوم من اﻷيام. ولكن يجب أن يعي هذا الشخص أيضًا أن التغيير لا يعني تخفيضًا للمرتبة، بل هو مناسبة للاحتفال باﻹنجاز الذي حقّقته الشركة في تجاوزها لمرحلة إثبات البقاء إلى مرحلة النموّ إلى درجة تظهر فيها الحاجة إلى تقسيم اﻷدوار. وإن كان الشخص الذي يدير هذا الحوار هو المدير التنفيذي المؤسس، فإنّ بإمكانه الاستعانة بما ذكرته في المقدّمة عن إمكانية استبدال المدير التنفيذي بشخص آخر ذي خبرة أكبر. يتفادى بعض مؤسسي الشركات الناشئة استخدام جميع اﻷلقاب السابقة (المدير التنفيذي والمدير التنفيذي التقني) لمدة عام أو أكثر على بداية المشروع، وتحتوي بطاقات العمل الخاصة بهم على عبارة (المؤسس الشريك Co-Founder) فقط، أو عبارة "الشّؤون التّجارية" (Everything Business) و "الشّؤون التّقنية” (Everything Technical) المبالغة في استخدام لقب "المدير"تُثار حفيظتي عندما أسمع بشركة ناشئة مكوّنة من 5 أشخاص يأخذ كل واحد منهم لقب (المدير). أنا لا أرى أن هناك حاجة لاستخدام هذه اﻷلقاب حتى من قِبَل 5 مؤسسين لهم خبرة كبيرة في هذا المجال. لذا يمكنك أن تتخيّل ردّة فعلي عندما أرى شركة ناشئة مكوّنة من 5 موظّفين يمتلكون خبرة تراكمية لا تتجاوز 10 سنوات وهم يحملون ألقاب مثل مدير التسويق، ومدير العائدات المالية، ومدير الشؤون المالية، ومدير المنتجات، وما إلى ذلك. ترجمة –وبتصرّف– للمقال The Dilemma of the Startup CTO Title لصاحبه Gordon Daugherty. حقوق الصورة البارزة: Designed by Freepik.1 نقطة
-
سنتعلّم في هذا الدّرس كيفيّة الحصول على شهادة SSL من سلطة شهادات تجاريّة (Commercial Certificate Authority (CA وكيفيّة تثبيتها، تسمح شهادات SSL لخواديم الويب بتشفير حركة مرور بياناتها traffic وتُوفِّر آليّة للتحقّق من هويّات الخواديم من أجل الزوّار، إنّ الميزة الأساسيّة لشراء شهادة SSL من سلطة شهادات تجاريّة (CA) موثوقة عن الشهادات المُوقَّعة ذاتيًّا self-signed أنّه لن يتم عرض تحذير مُخيف للزوّار حول عدم القدرة على التحقّق من هويّة موقعنا. يغطّي هذا الدرس كيفيّة الحصول على شهادة SSL من سلطات الشهادات الموثوقة التالية: GoDaddyRapidSSL via Namecheapبإمكانك أيضًا استخدام أي سلطة شهادات CA من اختيارك. سنشرح بعد أن حصلنا على شهادة SSL كيفيّة تثبيتها على خواديم ويب Nginx و Apache HTTP. سنشاهد في هذا الدّرس كيفيّة الحصول على شهادة SSL مُفردة النطاق أو wildcard من GoDaddy وRapidSSL، ولكنّ الحصول على الأنواع الأخرى من الشهادات مماثل تمامًا. توليد CSR ومفتاح خاص Private Keyبعد أن تقوم بتجهيز المتطلبات الأساسيّة وتختار نوع الشهادة التي نريد الحصول عليها، تحتاج لتوليد طلب توقيع الشهادة (certificate signing request (CSR ومفتاح خاص private key. إن كنت تخطّط لاستخدام Apache HTTP أو Nginx كخادوم ويب لديك فاستخدم openssl لتوليد CSR ومفتاحك الخاص على خادومك الويب، سنبقي في هذا الدّرس كافّة الملفات المرتبطة بهذا في الدليل الرئيسي home directory ولكن لا تتردد في تخزينها في أي موقع آمن على خادومك: cd ~نقوم بتنفيذ هذا الأمر لتوليد مفتاح خاص يُدعى example.com.key و CSR يُدعى example.com.csr (ضع اسم نطاقك بدلًا من example.com): openssl req -newkey rsa:2048 -nodes -keyout example.com.key -out example.com.csrعند هذه النقطة سيتم حثنا على إدخال عدّة أسطر من المعلومات تُضمَّن في طلب شهادتنا، إنّ الجزء الأهم منها هو حقل الاسم الشائع Common Name والذي يجب أن يُطابق الاسم الذي نرغب باستخدام الشهادة معه، على سبيل المثال example.com ،www.example.com، أو (بالنسبة لطلب شهادة wildcard) *.example.com، إن كنت تُخطّط للحصول على شهادة OV أو EV فتأكّد من أن تتوافق كافّة الحقول الأخرى بدقة مع بيانات منظمتك أو عملك. على سبيل المثال: Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:New York Locality Name (eg, city) []:New York Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Company Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:example.com Email Address []:sammy@example.comسيقوم هذا بتوليد ملفات key. و csr.، حيث يكون الملف key. هو مفتاحنا الخاص ويجب أن نبقيه في مكان آمن، والملف csr. هو الذي يجب أن نرسله إلى سلطة الشهادات لطلب شهادة SSL. نحتاج إلى نسخ ولصق CSR الخاصّة بنا عند تقديم طلب الشهادة إلى سلطة الشهادات، نستخدم هذا الأمر لطباعة محتويات ملف CSR لدينا (ضع اسم ملفّك بدلًا من التالي): cat example.com.csrنحن الآن مستعدون لشراء شهادة من سلطة الشهادات، سنعرض هنا مثالين، GoDaddy و RapidSSL عبر Namecheap، ولكن لك الحرية بالحصول على الشهادة من أي بائع آخر. مثال سلطة الشهادات الأول: RapidSSL via Namecheapتوفّر Namecheap طريقة لشراء شهادات SSL من مجموعة متنوعة من سلطات الشهادات، سنشرح عمليّة الحصول على شهادة نطاق مُفرَد من RapidSSL، ولكن إن أردت نوعًا مختلفًا من الشهادات فبإمكانك فعل ذلك. ملاحظة: إن طلبنا شهادة نطاق مُفرَد من RapidSSL من أجل النطاق الفرعي www لنطاقنا (على سبيل المثال www.example.com) فسيقومون بإصدار الشهادة لنا مع SAN لنطاقنا الأساسي، فإن كان طلب شهادتنا على سبيل المثال من أجل www.example.com فستعمل الشهادة الصادرة من أجل www.example.com و example.com. اختيار وشراء الشهادةنذهب إلى صفحة Namecheap لشهادات SSL . نستطيع هنا البدء في اختيار مستوى التحقّق، نوع الشهادة ("Domains Secured") أو ("CA Brand"). سنضغط في مثالنا على زر مقارنة المنتجات Compare Products في مربّع التحقّق من النطاق "Domain Validation"، بعدها نستطيع إيجاد "RapidSSL" والضغط على زر إضافة إلى السلّة Add to Cart. عند هذه النقطة يجب علينا التسجيل في Namecheap أو تسجيل الدخول إليه، وإنهاء عمليّة الدفع. طلب الشهادةنذهب بعد أن دفعنا من أجل الشهادة التي اخترناها إلى الرابط Manage SSL Certificates الموجود تحت القسم "Hi Username". سنشاهد هنا قائمة بكامل شهادات SSL التي اشتريناها عبر Namecheap، نضغط على رابط التفعيل الآن Activate Now من أجل الشهادة التي نريد استخدامها. نختار الآن برمجيّة خادوم الويب لدينا والتي تُحدِّد تنسيق الشهادة التي سيسلمها Namecheap لنا، الخيارات التي نختارها بشكل شائع هي "Apache + MOD SSL"، "nginx"، أو "Tomcat". نلصق CSR الخاصة بنا في المربّع ونضغط بعدها زر التالي Next. يجب أن نكون الآن في خطوة اختيار المُصادِق "Select Approver" من العمليّة، والتي سترسل بريد إلكتروني لطلب التحقّق إلى عنوان في تسجيل WHOIS لنطاقنا أو إلى عنوان من نوع مدير administrator للنطاق الذي نريد أن نحصل على شهادة له، نختار العنوان الذي نريد أن نرسل إليه البريد الإلكتروني للتحقّق. نقوم بتزويد معلومات التواصل الإداريّة "Administrative Contact Information" ونضغط على زر تقديم الطلب Submit order. التحقق من النطاقسيتم عند هذه النقطة إرسال بريد إلكتروني إلى عنوان المُصادِق "approver"، نفتح البريد الإلكتروني ونصادق على طلب الشهادة. تنزيل الشهاداتبعد المُصادَقة على الشهادة سيتم إرسالها عبر البريد الإلكتروني إلى القسم التقني Technical Contact، ستكون الشهادة الصادرة لنطاقنا وشهادة سلطة الشهادات الوسيطة CA's intermediate certificate في أسفل رسالة البريد الإلكتروني. ننسخها ونحفظها إلى خادومنا في نفس المكان الذي وضعنا فيه CSR ومفتاحنا الخاص. نقوم بتسمية الشهادة باسم النطاق مُضافًا إليه اللاحقة crt.، مثل example.com.crt، وتسمية الشهادة الوسيطة intermediate.crt. تكون الشهادة الآن جاهزة للتثبيت على خادوم الويب لدينا. مثال سلطة الشهادات الثاني: GoDaddyإنّ GoDaddy هي سلطة شهادات شائعة تملك كافّة أنواع الشهادات الأساسية، سنشرح عمليّة الحصول على شهادة نطاق مُفرَد، ولكن إن أردت نوعًا مختلفًا من الشهادات فبإمكانك فعل ذلك. اختيار وشراء الشهادةنذهب إلى صفحة GoDaddy لشهادات SSL. ننزل للأسفل ونضغط على زر البدء Get Started. نختار نوع شهادة SSL الذي نريده من القائمة المنسدلة: نطاق مُفرَد single domainنطاقات متعدّدة (multidomain (UCCwildcard نختار بعدها نوع الخطّة plan: نطاق domainمُنظَّمة organizationتحقّق مُوسَّع extended validationثم نختار المدى term (مُدّة الصلاحية). نضغط بعدها على زر إضافة إلى السلّة Add to Cart. نُراجع طلبنا الحالي ثم نضغط على المتابعة إلى الدفع Proceed to Checkout. ومن ثمّ نكمل التسجيل وعمليّة الدفع. طلب الشهادةبعد إكمال طلبنا نضغط على زر SSL Certificates* (أو نضغط على My Account > Manage SSL Certificates الموجودة في الزاوية العلوية اليمنى). نقوم بإيجاد شهادة SSL التي اشتريناها للتو ونضغط على زر الإعداد Set Up، إن لم تستخدم GoDaddy من قبل من أجل شهادات SSL فسيتم حثك على إعداد مُنتَج "SSL Certificates" وربط طلب شهادتك الأخيرة مع المُنتَج (نضغط على زر Set Up الأخضر وننتظر عدّة دقائق قبل تحديث متصفّحنا). بعد أن تتم إضافة مُنتَج "SSL Certificates" إلى حسابنا في GoDaddy ينبغي أن نرى شهادتنا الجديدة "New Certificate" وزر التنفيذ "Launch"، نضغط على الزر Launch الموجود بجانب شهادتنا الجديدة. نقوم بتقديم CSR الخاص بنا عن طريق لصقه في المربع، تُستخدَم خوارزميّة SHA-2 افتراضيًّا. نضع علامة في خانة التأشير I agree ونضغط على زر طلب الشهادة Request Certificate. التحقق من النطاقيجب الآن أن نُثبِت أنّنا نمتلك تحكّمًا بنطاقنا ونزوّد GoDaddy ببعض المستندات، تقوم GoDaddy بإرسال رسالة بريد إلكتروني للتحقّق من ملكيّة النطاق إلى العنوان الموجود في تسجيل WHOIS لنطاقنا، نتبع الخطوات الموجودة في رسائل البريد الإلكتروني التي تصلنا ونُصرِّح بإصدار الشهادة. تنزيل الشهادةبعد أن نُثبِت لـ GoDaddy أنّنا نمتلك النطاق، نتحقّق من بريدنا الإلكتروني (الذي قمنا من خلاله بالتسجيل في GoDaddy) بحثًا عن رسالة تقول أنّه تم إصدار شهادة SSL الخاصة بنا، نفتحها ونتبع رابط تنزيل الشهادة (أو نضغط على زر Launch بجانب شهادة SSL التي نريدها في لوحة تحكّم GoDaddy). نضغط الآن على زر التنزيل Download. نختار برمجيّة الخادوم التي نستخدمها من القائمة المنسدلة لنوع الخادوم Server type، إن كنّا نستخدم Apache HTTP أو Nginx نختار "Apache" ثم نضغط على زر تنزيل الملف المضغوط Download Zip File. نستخرج الملف المضغوط، الذي ينبغي أن يحتوي على ملفين crt.، أحدهما شهادة SSL الخاصّة بنا (التي ينبغي أن تملك اسمًا عشوائيًّأ) وحزمة bundle شهادة GoDaddy الوسيطة (gd_bundle-g2-1.crt)، نقوم بنسخهما إلى خادوم الويب لدينا، ونعيد تسمية الشهادة إلى اسم نطاقنا مع إضافة اللاحقة crt.، على سبيل المثال example.com.crt، ونعيد تسمية حزمة الشهادة الوسيطة إلى intermediate.crt. تكون الشهادة الآن جاهزة للتثبيت على خادوم الويب لدينا. تثبيت الشهادة على خادوم الويب لديناينبغي بعد الحصول على شهادتنا من سلطة الشهادات التي نختارها أن نقوم بتثبيتها على خادوم الويب لدينا، يتضمّن هذا إضافة بعض الأسطر المتعلّقة بـ SSL لملفّات إعدادات خادومنا. سنغطي في هذا القسم الإعدادات الأساسيّة لخادوم Nginx و Apache HTTP على Ubuntu. سنفترض الأمور التالية: يتوضّع المفتاح الخاص وشهادة SSL والشهادات الوسيطة لسلطة الشهادات-إن كان ذلك قابلًا للتطبيق- في الدليل الرئيسي على المسار home/sammy/يُدعى المفتاح الخاص باسم example.com.keyتُدعى شهادة SSL باسم example.com.crtتُوجد الشهادة أو الشهادات الوسيطة لسلطة الشهادات في ملف يُدعى intermediate.crtإن كنت تملك جدار ناري مُمكَّنًا لديك فتأكّد من أنّه يسمح بالمنفذ 443 (منفذ HTTPS)ملاحظة: يجب في البيئة الحقيقيّة تخزين هذه الملفّات في مكان يستطيع فقط المستخدم الذي يُشغِّل عملية خادوم الويب الرئيسيّة (عادة root) الوصول إليه، ينبغي الاحتفاظ بالمفتاح الخاص في مكان آمن. خادوم Nginxإن كنت ترغب باستخدام شهادتك مع خادوم Nginx على Ubuntu فاتبع هذا القسم. ينبغي في Nginx إن كانت سلطة الشهادات قد أعطتنا شهادة وسيطة أن نقوم بإنشاء ملف شهادة مُفرَد محمي بالسلاسل chained يحتوي على شهادتنا والشهادات الوسيطة لسلطة الشهادات. نذهب إلى الدليل الذي يحوي مفتاحنا الخاص، الشهادة، وشهادة سلطة البيانات الوسيطة (أي الملف intermediate.crt)، سنفترض أنّها في الدليل الرئيسي على سبيل المثال: cd ~بافتراض أنّ ملف الشهادة يُدعى example.com.crt نستخدم هذا الأمر لإنشاء ملف مُدمَج يُدعى example.com.chained.crt (نضع اسم نطاقنا بدلًا من example.com): cat example.com.crt intermediate.crt > example.com.chained.crtنذهب الآن إلى دليل إعدادات كتلة block خادوم Nginx، وبافتراض أنّه موجود في المسار etc/nginx/sites-enable/ نستخدم هذا الأمر للانتقال إليه: cd /etc/nginx/sites-enabledبافتراض أنّنا نريد إضافة SSL إلى ملف كتلة الخادوم الافتراضي default نفتح الملف من أجل تحريره: sudo vi defaultنبحث عن الأمر التوجيهي listen ونقوم بتعديله بحيث يبدو كما يلي: listen 443 ssl;نبحث بعدها عن الأمر التوجيهي server_name ونتأكد من أنّ قيمته مُطابِقة لاسم شهادتنا، نُضيف أيضًا الأوامر التوجيهيّة ssl_certificate و ssl_certificate_key لتحديد المسارات لشهادتنا وتحديد ملفّات المفاتيح الخاصّة (نضع الأسماء الموجودة لدينا بدلًا من example.com): server_name example.com; ssl_certificate /home/sammy/example.com.chained.crt; ssl_certificate_key /home/sammy/example.com.key;ولنسمح فقط بالشيفرات ciphers وميفاقات SSL protocols الأكثر أمانًا نُضيف الأسطر التالية إلى الملف: ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_ciphers AES256+EECDH:AES256+EDH:!aNULL;إن أردنا إعادة توجيه المرور عبر HTTP إلى HTTPS نستطيع إضافة هذه الكتلة الإضافيّة للخادوم في أعلى الملف (نضع معلوماتنا بدلًا من example.com): server { listen 80; server_name example.com; rewrite ^/(.*) https://example.com/$1 permanent; }نقوم بعدها بالحفظ والخروج. نعيد تشغيل خادوم Nginx الآن لتحميل الإعدادات الجديدة وتمكين TLS/SSL عبر HTTPS: sudo service nginx restartنختبر ذلك بالوصول إلى موقعنا عبر HTTPS، على سبيل المثال https://example.com. خادوم Apacheإن كنت ترغب باستخدام شهادتك مع خادوم Apache على Ubuntu فاتبع هذا القسم. نقوم بعمل نسخة احتياطيّة لملف إعداداتنا عن طريق نسخه، وبافتراض أنّ خادومنا يعمل على ملف إعدادات المُضيف الوهمي virtual الافتراضي، etc/apache2/sites-available/000-default.conf/، نستخدم هذه الأوامر لعمل النسخة: cd /etc/apache2/sites-available cp 000-default.conf 000-default.conf.origنفتح بعدها الملف لتحريره: sudo vi 000-default.confنبحث عن المُدخَل <VirtualHost *:80> ونقوم بتعديله بحيث يستمع خادوم الويب لدينا على المنفذ 443: <VirtualHost *:443>نقوم بعدها بإضافة الأمر التوجيهي ServerName إن لم يكن موجودًا مُسبقًا (نضع اسم نطاقنا هنا): ServerName example.comنضيف بعد ذلك الأسطر التالية لتحديد شهادتنا ومسارات المفاتيح (نضع مسارنا الفعلي هنا): SSLEngine on SSLCertificateFile /home/sammy/example.com.crt SSLCertificateKeyFile /home/sammy/example.com.keyإن كُنّا نستخدم Apache 2.4.8 أو أكثر نُحدِّد حزمة الشهادة الوسيطة لسلطة الشهادات بإضافة هذا السطر (نضع المسار الفعلي لدينا): SSLCACertificateFile /home/sammy/intermediate.crtإن كُنّا نستخدم إصدار أقدم من Apache نُحدِّد حزمة الشهادة الوسيطة لسلطة الشهادات بإضافة هذا السطر (نضع المسار الفعلي لدينا): SSLCertificateChainFile /home/sammy/intermediate.crtعند هذه النقطة أصبح خادومنا مُعدًّا ليستمع إلى HTTPS فقط (المنفذ 443)، لذا لن يتم تخديم طلبات HTTP (المنفذ 80)، لإعادة توجيه طلبات HTTP إلى HTTPS نضيف ما يلي إلى أعلى الملف (نكتب اسم نطاقنا بدلًا من example.com): <VirtualHost *:80> ServerName example.com Redirect permanent / https://example.com/ </VirtualHost>نقوم بالحفظ والخروج. نقوم بتمكين وحدة Apache SSL بتنفيذ هذا الأمر: sudo a2enmod sslنعيد تشغيل خادوم Apache الآن لتحميل الإعدادات الجديدة وتمكين TLS/SSL عبر HTTPS: sudo service apache2 restartنختبر ذلك بالوصول إلى موقعنا عبر HTTPS، على سبيل المثال https://example.com، نريد أيضًا اختبار الاتصال عبر HTTP، مثل http://example.com لنضمن أنّ إعادة التوجيه تعمل بشكل صحيح. الخاتمةنمتلك الآن فكرة جيّدة عن كيفيّة إضافة شهادة SSL موثوقة لتأمين خادوم الويب لدينا، احرص على أن تتسوّق من سلطة شهادات تجعلك مسرورًا معها. ترجمة -وبتصرّف- لـ How To Install an SSL Certificate from a Commercial Certificate Authority لصاحبه Mitchell Anicas.1 نقطة
-
كما هو موضح في العنوان فإنّك في هذا الدرس سوف تتعلم كيفية إنشاء تأثير وكأنّك تتصفح كتابًا ما. وسوف نستخدم في هذا الدرس إضافة تدعى BookBlock، والفكرة من هذا الدرس هو أنّك سوف تقوم بإنشاء تأثير يُمكّن الزوار من تصفح موقع ما وكأنهم يتصفحون أحد الكتب. الفكرة هي أنّك سوف تتصفح صفحات الموقع باستخدام سهمين سوف يكونان موجودين في أعلى الصفحة أو أزرار لوحة المفاتيح أو حتى بالسحب باستخدام الفأرة وأيضًا سيكون هناك قائمة جانبية سوف تظهر عندما تقوم بالضغط على أيقونة ما. وسوف تحتوي القائمة الجانبية على روابط لصفحات الموقع وعندما تقوم بالضغط على أحد هذه الروابط فإنّها سوف تنقلك إلى الصفحة المطلوبة. سوف نستخدم أيضًا إضافة اسمها jScrollPane وذلك للحصول على شريط تمرير (scrollbar) يظهر عندما يكون المحتوى أطول من ارتفاع المتصفح. وهذه قائمة بإضافات jQuery التي سوف نستخدمها: BookBlockCustom jQuery++jScrollPanejQuery Mouse Wheel PluginCustom Mdernizerيمكنك معاينة المثال الموضح في هذا الدرس من هنا. كما يمكنك تحميل الملفات المصدرية. بنية ملف HTMLفي البداية يجب أن يكون لدينا حاوٍ رئيسي لاحتواء جميع العناصر، وداخل هذا الحاوي سوف يكون هناك عنصر <div> للقائمة الجانبية وسوف نعطيه فئة (class) بالاسم "menu-panel" وسوف يكون هناك عنصر <div> آخر يحتوي على المحتوى الرئيسي للموقع وسوف نعطيه فئة بالاسم "bb-custom-wrapper". وفي داخل كل قسم سوف يكون هناك حاوٍ للمحتوى وعنصر <div> سوف نحتاجه من أجل شريط التمرير الذي ذكرناه سابقًا. <div id="container" class="container"> <div class="menu-panel"> <h3>Table of Contents</h3> <ul id="menu-toc" class="menu-toc"> <li class="menu-toc-current"><a href="#item1">Self-destruction</a></li> <li><a href="#item2">Why we die</a></li> <li><a href="#item3">The honeymoon</a></li> <li><a href="#item4">A drawing joke</a></li> <li><a href="#item5">Commencing practice</a></li> </ul> </div> <div class="bb-custom-wrapper"> <div id="bb-bookblock" class="bb-bookblock"> <div class="bb-item" id="item1"> <div class="content"> <div class="scroller"> <h2>Self-destruction</h2> <p>...</p> </div> </div><!-- /content --> </div><!-- /bb-item --> <div class="bb-item" id="item2"><!-- ... --></div> <div class="bb-item" id="item3"><!-- ... --></div> <div class="bb-item" id="item4"><!-- ... --></div> <div class="bb-item" id="item5"><!-- ... --></div> </div><!-- /bb-bookblock --> <nav> <a id="bb-nav-prev" href="#">←</a> <a id="bb-nav-next" href="#">→</a> </nav> <span id="tblcontents" class="menu-button">Table of Contents</span> </div><!-- /bb-custom-wrapper --> </div><!-- /container -->سوف نقوم بربط عناصر القائمة الجانبية بصفحات الموقع (التي تحمل الفئة "bb-item)، وسوف نُضيف أيضًا سهمين في أعلى الصفحة من أجل التنقل بين الصفحات وزر يقوم بفتح وإغلاق القائمة الجانبية. لنقم الآن بإضافة تنسيقات CSS. تنسيقات CSSلن نتحدث هنا عن التنسيقات التي تأتي مع إضافة BookBlock لأنك سوف تجدها داخل ملف bookblock.css، وإنّما سوف نُركّز على التنسيقات الأخرى المهمة. لنبدأ التنسيقات بإضافة سطر يقوم بجلب الخط المسمى "Lato" من خدمة Google web fonts: @import url(http://fonts.googleapis.com/css?family=Lato:300,400,700);سوف نقوم بإعطاء الوسم <html> الخاصية height: 100% وذلك لأننا سوف نحتاج أن نجعل بعض العناصر تتمدد على ارتفاع المتصفح كاملًا: html { height: 100%; }سوف نستخدم أيضًا الخاصية box-sizing: border-box وذلك حتى نستخدم قيم مئوية لكل من العرض والإرتفاع أثناء استخدام padding دون القلق حول أبعاد العناصر والقيام بعمليات حسابية نحن بغنىً عنها: *, *:after, *:before { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: 0; margin: 0; }لنقم الآن بتعريف الخط الذي سوف نستخدمه في الموقع (العنصر body) ونُعطيه ارتفاع بقيمة 100% (تذكّر أننا نريد ارتفاع بهذه القيمة لأنه سوف يكون هناك عناصر تتموضع بشكل مطلق (absolute positioning) وسوف تحتاج أن تتمدد على ارتفاع المتصفح كاملًا): body { font-family: 'Lato', Calibri, Arial, sans-serif; font-weight: 400; font-size: 100%; color: #333; height: 100%; }سوف نستعمل أيضًا إضافة Modernizr وسوف نُضيف الفئة "no-js" إلى وسم <html>، فإذا كانت الجافاسكربت مفعّلة فإنّ Modernizr سوف يستبدل تلك الفئة بالفئة "js". وهذا سوف يساعدنا على إعطاء خصائص CSS معينة لبعض العناصر التي لا نريدها إذا كانت الجافاسكربت معطّلة. لاحظ أيضًا أننا نحتاج أن يكون عرض الصفحة وارتفاعها بقيمة 100% فقط إذا كانت الجافاسكربت مفعّلة وعندها فقط نريد من العنصر body أن يكون له خاصية overflow: hidden: .js body { overflow: hidden; }وهذه بعض التنسيقات الخاصة بالروابط: a { color: #555; text-decoration: none; } a:hover { color: #000; }نريد من الحاوي الرئيسي أن يكون بعرض وارتفاع المتصفح كاملًا، وسوف نقوم بموضعة القائمة الجانبية خارج هذا الحاوي باستعمال الخاصية left وإعطائها قيمة سالبة تكون بنفس قيمة العرض الخاص بالقائمة الجانبية. والفكرة هي أنّه عند النقر على أيقونة القائمة الجانبية فإنّ الحاوي سوف يتحرك إلى اليمين مما يؤدي إلى ظهور القائمة الجانبية. دعونا إذًا نقوم بإعطاء الحاوي الرئيسي عرضًا وارتفاعًا بقيمة 100% وأن نُضيف الخاصية transition إلى الحاوي container: .container, .bb-custom-wrapper, .bb-bookblock { width: 100%; height: 100%; } .container { position: relative; left: 0px; transition: left 0.3s ease-in-out; }عند النقر على أيقونة القائمة الجانبية فإن فئة (class) أخرى سوف يتم إضافتها إلى الحاوي container والتي سوف تحتوي على الخاصية left: 240px (نفس العرض الخاص بالقائمة الجانبية) وبالتالي فإنّ الصفحة كاملة سوف تتحرك إلى اليمين بمقدار 240px وبالتالي ظهور القائمة الجانبية: .slideRight { left: 240px; }ولكن بدون الجافاسكربت لن نكون قادرين على القيام بما سبق لذلك سوف نقوم بإضافة الخاصية padding-left: 240px: .no-js .container { padding-left: 240px; }ونريد أن تكون القائمة الجانبية ثابتة في الجانب الأيسر بشكل افتراضي: .menu-panel { background: #f1103a; width: 240px; height: 100%; position: fixed; z-index: 1000; top: 0; left: 0; text-shadow: 0 1px 1px rgba(0,0,0,0.1); }وإذا كانت الجافاسكربت مفعلة فسوف نقوم بموضعة القائمة الجانبية بشكل مطلق وإلى اليسار بقيمة -240px: .js .menu-panel { position: absolute; left: -240px; }وهذه هي التنسيقات الخاصة بعناصر القائمة الجانبية: .menu-panel h3 { font-size: 1.8em; padding: 20px; font-weight: 300; color: #fff; box-shadow: inset 0 -1px 0 rgba(0,0,0,0.05); } .menu-toc { list-style: none; } .menu-toc li a { display: block; color: #fff; font-size: 1.1em; line-height: 3.5; padding: 0 20px; cursor: pointer; background: #f1103a; border-bottom: 1px solid #dd1338; } .menu-toc li a:hover, .menu-toc li.menu-toc-current a{ background: #dd1338; }وأمّا بالنسبة للقائمة الرئيسية التي سوف تحتوي على السهمين فإننا سوف نقوم بموضعتها بشكل مطلق وفوق جميع العناصر الأخرى: .bb-custom-wrapper nav { top: 20px; left: 60px; position: absolute; z-index: 1000; }كما أنّ روابط السهمين وزر القائمة الجانبية سوف يتموضعان بشكل مطلق (position: absolute) وسوف نعطيها الخاصية border-radius: 50% لنجعلها تظهر كالدائرة: .bb-custom-wrapper nav span, .menu-button { position: absolute; width: 32px; height: 32px; top: 0; left: 0; background: #f1103a; border-radius: 50%; color: #fff; line-height: 30px; text-align: center; speak: none; font-weight: bold; cursor: pointer; } .bb-custom-wrapper nav span:last-child { left: 40px; } .bb-custom-wrapper nav span:hover, .menu-button:hover { background: #000; }سوف يكون الزر الذي يفتح ويغلق القائمة الجانبية موجودًا في أعلى يسار الصفحة وسوف نقوم بإخفاء النص الموجود بداخله (نريد أن تظهر الأيقونة فقط): .menu-button { z-index: 1000; left: 20px; top: 20px; text-indent: -9000px; }لنقم الآن بإنشاء أيقونة بسيطة بدون استعمال أي صور وذلك باستعمال العنصر الزائف :after واستعمال الخاصية box-shadow والتي سوف تعمل على إنشاء الخطين العلوي والسفلي للأيقونة: .menu-button:after { position: absolute; content: ''; width: 50%; height: 2px; background: #fff; top: 50%; margin-top: -1px; left: 25%; box-shadow: 0 -4px #fff, 0 4px #fff; }وفي حالة كان الجافاسكربت معطلًا فإننا نريد أن نخفي هذه العناصر: .no-js .bb-custom-wrapper nav span, .no-js .menu-button { display: none; }لننتقل الآن إلى تنسيق الأجزاء الداخلية لكل قسم من أقسام الصفحة (bb-item). نريد أن يتم موضعة المحتوى (content) بشكل مطلق ونريد ان نستعمل الخاصية overflow: hidden، وهذا مهم لأننا نريد تطبيق شريط التمرير هنا ونريد أن نفعل ذلك فقط عند قلب/تغيير الصفحة. فإذا لم نستخدم الخاصية overflow: hidden فإنّك سوف ترى المحتوى يتداخل ببعضه. وأعيد وأكرر مرة أخرى بأنّ هذا سوف يحدث فقط إذا كان الجافاسكربت مفعلًا ولذلك سوف نستخدم الفئة "js": .js .content { position: absolute; top: 60px; left: 0; bottom: 50px; width: 100%; overflow: hidden; }العنصر <div class="scroller"> هو الذي سوف ينمو مع المحتوى لذلك سوف نعطيه الخاصية padding: .scroller { padding: 10px 5% 10px 5%; }لاحظ أننا استعملنا قيم مئوية للجوانب وذلك حتى نجعل الصفحة تتجاوب مع حجم الشاشة. دعونا نتخلص من الحواف الحادة عندما نقوم بالتمرير (scroll) وذلك باستخدام العناصر الزائفة إلى أعلى وأسفل عنصر المحتوى مع استخدام تدرج بين اللون الأبيض والشّفّاف: .js .content:before, .js .content:after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 20px; z-index: 100; pointer-events: none; background: linear-gradient( to bottom, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100% ); } .js .content:after { top: auto; bottom: 0; background: linear-gradient( to top, rgba(255,255,255,1) 0%, rgba(255,255,255,0) 100% ); }هذا سوف يجعل النص يظهر بشكل باهت. لنقم الآن بتنسيق عناصر النصوص: .content h2 { font-weight: 300; font-size: 4em; padding: 0 0 10px; color: #333; margin: 0 1% 40px; text-align: left; box-shadow: 0 10px 0 rgba(0,0,0,0.02); text-shadow: 0 0 2px #fff; } .no-js .content h2 { padding: 40px 1% 20px; } .content p { font-size: 1.2em; line-height: 1.6; font-weight: 300; padding: 5px 8%; text-align: justify; }كل ما تبقى علينا الآن من تنسيقات CSS هو استخدام الـmedia queries. فإذا كانت الجافاسكربت معطلة فإننا لا نريد أن تظهر القائمة الجانبية إذا كان العرض أقل من 800px. كان هذا فقط مثالًا بسيطًا على كيفية التحكم بالعناصر تحت ظروف وشروط معينة. الـmedia query الأخيرة سوف تعمل على تكبير الخط قليلًا من أجل الأجهزة صغيرة الحجم كالهواتف. @media screen and (max-width: 800px){ .no-js .menu-panel { display: none; } .no-js .container { padding: 0; } } @media screen and (max-width: 400px){ .menu-panel, .content { font-size: 75%; } }كان هذا كل ما يتعلق بتنسيقات CSS ويتبقى علينا استخدام بعض الجافاسكربت. بعض الجافاسكربتسوف نبدأ اولًا بتخزين (caching) بعض العناصر حتى لا نضطر إلى استدعائها في كل مرة وسوف نقوم أيضًا بتهئية/مناداة إضافة BookBlock. نُريد أيضًا أن نقوم بضبط بعض الأمور بعد كل قلب/تغيير للصفحة وهذه الأمور هي رقم الصفحة الحالية والسلوك الخاص بإضافة jScrollPane. وهذا محدد في الاستدعاء الخلفي (callback) المسمى onEndFlip والممرر إلى إضافة BookBlock. var $container = $( '#container' ), // the element we will apply the BookBlock plugin to $bookBlock = $( '#bb-bookblock' ), // the BookBlock items (bb-item) $items = $bookBlock.children(), // index of the current item current = 0, // initialize the BookBlock bb = $( '#bb-bookblock' ).bookblock( { speed : 800, perspective : 2000, shadowSides : 0.8, shadowFlip : 0.4, // after each flip... onEndFlip : function(old, page, isLimit) { // update the current value current = page; // update the selected item of the table of contents (TOC) updateTOC(); // show and/or hide the navigation arrows updateNavigation( isLimit ); // initialize the jScrollPane on the content div for the new item setJSP( 'init' ); // destroy jScrollPane on the content div for the old item setJSP( 'destroy', old ); } } ), // the navigation arrows $navNext = $( '#bb-nav-next' ), $navPrev = $( '#bb-nav-prev' ).hide(), // the table of content items $menuItems = $container.find( 'ul.menu-toc > li' ), // button to open the TOC $tblcontents = $( '#tblcontents' ), transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' }, // transition event name transEndEventName = transEndEventNames[Modernizr.prefixed('transition')], // check if transitions are supported supportTransitions = Modernizr.csstransitions;لنقم أولًا بربط الأحداث ببعض العناصر التي تم تهيئتها سابقًا، كما أننا نريد أن نقوم بتهيئة jScrollPane لأول عنصر (العنصر الحالي). function init() { // initialize jScrollPane on the content div of the first item setJSP( 'init' ); initEvents(); }بما أننا سوف نقوم بتهيئة وإعادة تهيئة وتدمير jScrollPane فلنقم بتعريف دالة لذلك: function setJSP( action, idx ) { var idx = idx === undefined ? current : idx, $content = $items.eq( idx ).children( 'div.content' ), apiJSP = $content.data( 'jsp' ); if( action === 'init' && apiJSP === undefined ) { $content.jScrollPane({verticalGutter : 0, hideFocus : true }); } else if( action === 'reinit' && apiJSP !== undefined ) { apiJSP.reinitialise(); } else if( action === 'destroy' && apiJSP !== undefined ) { apiJSP.destroy(); } }سوف نحتاج إلى ربط العديد من الأحداث كالتالي: سوف يتم استدعاء الدالتين ()next و()prev الخاصتين بإضافة BookBlock وذلك عند النقر على أزرار التنقل أو السحب باستخدام الفأرة.سوف يظهر جدول المحتويات أو يختفي عند النقر على زر القائمة (tblcontents$).سوف يتم استدعاء الدالة ()jump الخاصة بإضافة BookBlock وذلك عند النقر على أي عنصر من عناصر جدول المحتويات.سوف يتم تهيئة jScrollPane عند القيام بتغيير حجم النافذة (window resize).function initEvents() { // add navigation events $navNext.on( 'click', function() { bb.next(); return false; } ); $navPrev.on( 'click', function() { bb.prev(); return false; } ); // add swipe events $items.on( { 'swipeleft' : function( event ) { if( $container.data( 'opened' ) ) { return false; } bb.next(); return false; }, 'swiperight' : function( event ) { if( $container.data( 'opened' ) ) { return false; } bb.prev(); return false; } } ); // show TOC $tblcontents.on( 'click', toggleTOC ); // click a menu item $menuItems.on( 'click', function() { var $el = $( this ), idx = $el.index(), jump = function() { bb.jump( idx + 1 ); }; current !== idx ? closeTOC( jump ) : closeTOC(); return false; } ); // reinit jScrollPane on window resize $( window ).on( 'debouncedresize', function() { // reinitialise jScrollPane on the content div setJSP( 'reinit' ); } ); } ظهور أزرار التنقل من عدمه سوف يعتمد على الصفحة الحالية، فإذا كُنّا في الصفحة الأولى فإننا سوف نرى فقط زر "التالي" وإذا كُنّا في الصفحة الأخيرة فإننا سوف نرى فقط زر "السابق": function updateNavigation( isLastPage ) { if( current === 0 ) { $navNext.show(); $navPrev.hide(); } else if( isLastPage ) { $navNext.hide(); $navPrev.show(); } else { $navNext.show(); $navPrev.show(); } }عندما نفتح جدول المحتويات (القائمة الجانبية) فإننا نريد أن تختفي عناصر التنقل وأن تظهر مرة أخرى عندما نقوم بإغلاق القائمة الجانبية. سوف نقوم بتحريك القائمة الجانبية باستخدام خاصية transition، وإذا لم تكن هذه الخاصية مدعومة من المتصفح فإننا سوف نستخدم fallback بسيط: function toggleTOC() { var opened = $container.data( 'opened' ); opened ? closeTOC() : openTOC(); } function openTOC() { $navNext.hide(); $navPrev.hide(); $container.addClass( 'slideRight' ).data( 'opened', true ); } function closeTOC( callback ) { $navNext.show(); $navPrev.show(); $container.removeClass( 'slideRight' ).data( 'opened', false ); if( callback ) { if( supportTransitions ) { $container.on( transEndEventName, function() { $( this ).off( transEndEventName ); callback.call(); } ); } else { callback.call(); } } } خاتمةهذا كان كل شيء يخص هذا الدرس أتمنى أن يكون قد أعجبك وأن تكون قد وجدته مفيدًا. ترجمة -وبتصرّف- للدرس Fullscreen Pageflip Layout لصاحبته Mary Lou.1 نقطة
-
ينصح خبراء التسويق بالتركيز على المنافع والفوائد في الحملات التسويقية وليس على المميزات. فالمستخدم، سواء العادي أو حتى المحترف، لا يفهم دائما التفاصيل التقنية وهو غير مهتم بها بقدر ما هو مهتم بالفوائد التي سيجنيها من ذلك المنتج أو تلك الخدمة. مثلا الباحث عن جهاز كمبيوتر محمول لا يهمه أن تقول له بأن البطارية من نوع ليثيوم، ما يهمه هو أن تقول بأن البطارية توفر له -مثلا- سبع ساعات من التشغيل المتواصل. فالمستخدم، ما لم يكن متخصصا جدا، لا يبحث عن التفاصيل التقنية للمميزات قدر ما يبحث عن الفوائد التي ستشبع احتياجاته من المنتج. نفس الفكرة يمكن تطبيقها في مجال تطوير المواقع. أغلب أصحاب المشاريع يضيعون الكثير من الوقت في البحث عن التقنيات الجديدة المناسبة ثم يبدؤون بالبرمجة ويتركون تصميم واجهات المستخدم إلى النهاية، وغالبا ما يتم إنجاز التصميم بدقة أقل وخلال وقت أقصر بسبب الوقت الطويل الذي ضاع في البرمجة. السؤال هنا: ما الذي يهم المستخدم حقا؟ المستخدم لا يهمه ما لغة البرمجة الخارقة التي استخدمتها ولا الخوارزميات العبقرية التي ألفتها ولا جمالية الكود البرمجي. ما يهم المستخدم هو أن يعمل الموقع بشكل سليم وأن يكون سهل التصفح. بالنسبة للمستخدم الواجهة أهم، لذلك هي ما يجب أن تركز عليه أكثر. لا بأس أن يكون الكود البرمجي بشعا ومليئا بالثغرات في البداية، تلك أمور قابلة للإصلاح بسهولة دون أن تزعج المستخدم، عكس الأخطاء الفادحة في التصميم التي تعرقل من تجربة المستخدم. ما أقصده بالتصميم هنا ليس مخططات الصفحات، بل التصميم الفعلي والكامل لواجهات المستخدم بـ HTML مع تضمين الواجهات النصوص الحقيقية للمحتوى الذي سيتوفر لاحقا في الموقع. حين تبدأ بالتصميم فأنت تحصل على رؤية واقعية عن منتجك/موقعك قبل البدء في برمجته. الفكرة تصبح واضحة ويمكنك آنذاك بسهولة تحديد الأولويات والأجزاء الأهم في الموقع التي تحتاج أن تبدأ بها. يمكنك أن تعرض الواجهات على المستخدمين المتوقعين وتحصل على آرائهم في منتجك قبل أن تكتب سطرا برمجيا واحدا. التعديل على التصميم سهل. يمكنك تلقي الاقتراحات والملاحظات وإجراء كل التعديلات بسرعة. ثم حين تبدأ في البرمجة ستكون الأمور واضحة جلية أمامك.1 نقطة