<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x645;&#x642;&#x627;&#x644;&#x627;&#x62A; &#x639;&#x627;&#x645;&#x629; &#x62D;&#x648;&#x644; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/page/11/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x645;&#x642;&#x627;&#x644;&#x627;&#x62A; &#x639;&#x627;&#x645;&#x629; &#x62D;&#x648;&#x644; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</description><language>ar</language><item><title>&#x627;&#x644;&#x62D;&#x644;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x62A;&#x643;&#x631;&#x627;&#x631;&#x64A;&#x629; &#x641;&#x64A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1306/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/6129d7b0c617f_---.png.54ed7ff99c1827a99e349efdcb15c6fa.png" /></p>
<p>
	رأينا في التدريب الأخير من <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D9%85%D8%B2%D9%8A%D8%AF-%D9%85%D9%86-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D9%88%D8%A3%D9%85%D9%88%D8%B1-%D8%A3%D8%AE%D8%B1%D9%89-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1289/" rel="">المقال السابق</a> كيف طبعنا جزءًا من جدول ضرب العدد 12، لكن ذلك تطلب منا كثيرًا من الكتابة، وسيستغرق توسيعه وقتًا طويلًا، ولحسن الحظ توجد طريقة أسهل سترينا بداية المزايا القوية التي توفرها لنا لغات البرمجة في تنفيذ المهام وإنجازها.
</p>

<h2>
	حلقات for
</h2>

<p>
	تتيح لغة البرمجة تكرار تنفيذ أمر أو عدة أوامر لعدد محدَّد من المرات، في ما يسمى حلقة تكرار، حيث يمكن استعمال متغير تزيد قيمته مع كل دورة للحلقة، وستبدو هذه العملية في بايثون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9394_15" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> n </span><span class="kwd">in</span><span class="pln"> range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 12 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pln">
</span><span class="lit">2</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">24</span><span class="pln">
</span><span class="lit">3</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">36</span><span class="pln">
</span><span class="lit">4</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">48</span><span class="pln">
</span><span class="lit">5</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">60</span><span class="pln">
</span><span class="lit">6</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">72</span><span class="pln">
</span><span class="lit">7</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">84</span><span class="pln">
</span><span class="lit">8</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">96</span><span class="pln">
</span><span class="lit">9</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">108</span><span class="pln">
</span><span class="lit">10</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">120</span><span class="pln">
</span><span class="lit">11</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">132</span><span class="pln">
</span><span class="lit">12</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">144</span></pre>

<p>
	لندرس الشيفرة السابقة ونستخرج بعض الملاحظات منها:
</p>

<ul>
	<li>
		انتهى سطر <code>for</code> بنقطتين رأسيتين (:)، وهذا أمر مهم، إذ يخبر بايثون أن ما سيكتَب بعد هاتين النقطتين هو ما سيُكرَّر.
	</li>
	<li>
		كتبنا مجال الأعداد الذي نريده في دالة <code>range()‎</code> بالشكل <code>range(1,13)‎</code>، رغم أننا نريد تكرار عملية الضرب إلى العدد 12 فقط، لأن دالة <code>range()‎</code> تولد الأعداد من العدد الأول فيها إلى العدد الذي يسبق العدد الثاني، 13 في مثالنا، وهذا له أسبابه قطعًا وستعتاده مع الوقت، لكن تجدر الإشارة إلى أن هذه الدالة تستطيع توليد مجموعات معقدة من الأعداد، لكننا اخترنا هذا المثال البسيط لأنه يحقق الغرض.
	</li>
	<li>
		العامل <code>for</code> في بايثون هو عامل <code>foreach</code> في الواقع، إذ يطبق تسلسل الشيفرة التالي على كل عنصر في التجميعة، والتي هي في حالتنا قائمة الأعداد التي تولدها الدالة <code>range()‎</code>، ونستطيع استخدام قائمة أعداد صراحةً عوضًا عن الدالة <code>range()‎</code>، بالشكل التالي:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9394_17" style=""><span class="pln">  </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> n </span><span class="kwd">in</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">6</span><span class="pun">,</span><span class="lit">7</span><span class="pun">,</span><span class="lit">8</span><span class="pun">,</span><span class="lit">9</span><span class="pun">,</span><span class="lit">10</span><span class="pun">,</span><span class="lit">11</span><span class="pun">,</span><span class="lit">12</span><span class="pun">]:</span><span class="pln">
  </span><span class="pun">...</span><span class="pln">     </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 12 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">,</span><span class="pln"> n</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<ul>
	<li>
		أُزيح سطر <code>print</code> موازنةً بسطر حلقة <code>for</code> الذي فوقه، وهذا مهم جدًا لأن هذه الإزاحة تخبر بايثون أن عليها تكرار القسم الخاص بـ <code>print</code>، ومن الممكن إزاحة أكثر من سطر، وستكرر بايثون هذه الأسطر المزاحة جميعًا لكل عنصر في التجميعة، ولا يهم مقدار الإزاحة المستخدمة طالما هي نفسها في كل الأسطر المزاحة، وستخبرنا بايثون إذا وجدت اختلافًا في الإزاحة.
	</li>
	<li>
		نحتاج إلى ضغط زر الإدخال Enter مرتين في المفسر التفاعلي لتشغيل البرنامج، لأن مفسر بايثون يضيف سطرًا جديدًا إلى شيفرة الحلقة التكرارية عندما نضغط مرةً واحدةً؛ أما مع الضغطة الثانية فستفترض بايثون أننا أنهينا إدخال الشيفرة، فتشغّل البرنامج.
	</li>
</ul>

<p>
	وبما أننا قد رأينا الآن هيكل حلقة for، لننظر في كيفية عملها خطوةً خطوةً على النحو الآتي:
</p>

<ul>
	<li>
		أولًا: تستخدم بايثون دالة <code>range()‎</code> لتوليد قائمة أعداد من 1 إلى 12، وفقًا لآلية خاصة تسمى بالمولد generator، وتشبه القائمة التي تزيد من عناصرها عنصرًا واحدًا في كل مرة حسب الطلب، مما يوفر الذاكرة عندما تكون القائمة كبيرةً، وهو نفس سبب توليد القائمة صراحةً باستخدام <code>list()‎</code> عندما طبعنا <code>range()‎</code> أعلاه، وهذا شبيه بما فعلناه في مثال مفاتيح القاموس <code>keys()‎</code> في <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A7%D9%84%D8%AA%D8%AC%D9%85%D9%8A%D8%B9%D8%A7%D8%AA-collections-r1288/" rel="">المقال الخامس</a> من هذه السلسلة والمتعلق بالمواد الخام للبرمجة.
	</li>
	<li>
		ثانيًا: تجعل بايثون قيمة <code>n</code> مساويةً للقيمة الأولى في القائمة، وهي 1 في هذه الحالة، ثم تنفذ الشيفرة المزاحة باستخدام القيمة <code>n = 1</code>:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9394_20" style=""><span class="pln">   </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 12 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	ثم تعود إلى سطر <code>for</code> وتضبط <code>n</code> على القيمة التالية في القائمة، وهي 2 في هذه الحالة، ثم تنفذ الشيفرة المزاحة مع القيمة <code>n = 2</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9394_23" style=""><span class="pln">   </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 12 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	وتستمر في تكرار هذا التسلسل حتى تمر <code>n</code> على جميع القيم في القائمة، ثم تنتقل إلى الأمر التالي غير المزاح، في حالتنا لا توجد أي أوامر، لذا سيتوقف البرنامج.
</p>

<h3>
	الحلقة التكرارية في VBScript
</h3>

<p>
	تُعَد <code>For...Next</code> أبسط حلقة تكرارية في VBScript، وتُستخدم بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_25" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">For</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="typ">To</span><span class="pln"> </span><span class="lit">12</span><span class="pln">
    </span><span class="typ">MsgBox</span><span class="pln"> N </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" x 12 = "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> N</span><span class="pun">*</span><span class="lit">12</span><span class="pln">
</span><span class="typ">Next</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	يُعَد أسلوب VBScript أوضح وأسهل في فهم ما تفعله الشيفرة، إذ تتغير قيمة <code>N</code> من 1 إلى 12، وتنفَّذ الشيفرة التي توجد قبل الكلمة المفتاحية <code>Next</code>، وفي حالتنا تطبع الشيفرة النتيجة في صندوق حواري؛ أما إزاحة السطر هنا فاختيارية وليست شرطًا، لكنها تجعل الشيفرة أسهل في القراءة، وقد يحتوي متن الحلقة التكرارية على أكثر من سطر ينفَّذ على عناصر القائمة، كما في حالة بايثون التي رأيناها قبل قليل، ورغم أن VBScript تبدو أوضح للوهلة الأولى؛ إلا أن بايثون أكثر مرونةً كما سنرى بعد قليل.
</p>

<h3>
	الحلقة التكرارية في جافاسكربت
</h3>

<p>
	تستخدم جافاسكربت البُنية <code>for</code> الشائعة في كثير من لغات البرمجة الشبيهة بلغة C، وستبدو الحلقة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_27" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> n </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln"> n</span><span class="pun">++){</span><span class="pln">
    document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">n </span><span class="pun">+</span><span class="pln"> </span><span class="str">" x 12 = "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> n</span><span class="pun">*</span><span class="lit">12</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"&lt;BR&gt;"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="typ">Script</span><span class="pun">&gt;</span></pre>

<p>
	تبدو هذه الشيفرة معقدةً للوهلة الأولى، وهي تتكون من ثلاثة أجزاء بين القوسين <code>()</code> هي:
</p>

<ul>
	<li>
		جزء البداية: <code>n = 1</code> الذي يُنفَّذ مرةً واحدةً قبل أي شيء آخر.
	</li>
	<li>
		جزء الاختبار: <code>n &lt;= 12</code> الذي يُنفَّذ قبل كل تكرار.
	</li>
	<li>
		جزء الزيادة: <code>n++‎</code> وهو اختصار "زِد n بمقدار 1"، وينفَّذ بعد كل تكرار.
	</li>
</ul>

<p>
	لاحظ أن جافاسكربت تضع الشيفرة المكرَّرة، أي متن الحلقة التكرارية، بين قوسين معقوصين <code>{}</code>، وهذا كافٍ لتكون الحلقة صالحةً للتنفيذ، إلا أنه يفضَّل إزاحة الشيفرة التي داخل الأقواس المعقوصة لتحسين قابلية قراءة الشيفرة.
</p>

<p>
	لن ينفَّذ متن الحلقة loop body إلا إذا تحقق جزء الاختبار، أي كان true. وقد تحتوي هذه الأجزاء على شيفرات عشوائية، إلا أن الجزء الثاني الخاص بالاختبار يجب أن يعطي قيمةً بوليانيةً.
</p>

<h3>
	مزيد من المعلومات حول حلقة for في بايثون
</h3>

<p>
	تتكرّر حلقة <code>for</code> في بايثون على تسلسل، تذكر أن التسلسل الذي شرحناه في المقالات السابقة يشمل أشياء، مثل السلاسل النصية والقوائم والصفوف tuples، كما تستطيع بايثون أن تكرِّر عدة أنواع أخرى لكننا سنؤجل ذلك إلى وقت لاحق، وبناءً على ذلك نستطيع كتابة حلقات <code>for</code> تتعامل مع أي نوع من التسلسلات، ولنجرب مثلًا طباعة حروف كلمة حرفًا حرفًا باستخدام حلقة <code>for</code> مع سلسلة نصية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> c in </span><span class="str">'word'</span><span class="pun">:</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> c </span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
w
o
r
d</span></pre>

<p>
	لاحظ أننا طبعنا كل حرف على سطر منفصل، وأنه يمكننا إضافة متن الحلقة، عندما يكون سطرًا واحدًا، إلى نفس سطر الحلقة بوضعه بعد نقطتين رأسيتين <code>:</code>، إذ تخبران بايثون بوجود كتلة برمجية تليهما.
</p>

<p>
	ويمكن التكرار على صف tuple:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> word in </span><span class="pun">(</span><span class="str">'one'</span><span class="pun">,</span><span class="str">'word'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'after'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'another'</span><span class="pun">):</span><span class="pln"> print </span><span class="pun">(</span><span class="pln">word</span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	جعلنا في هذا المثال كل كلمة في سطر منفصل على خلاف المثال السابق، ويمكن وضعها جميعًا في سطر واحد باستخدام ميزة خاصة بدالة <code>print()‎</code>، إذ نستطيع إضافة وسيط argument بعد العنصر المراد طباعته كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_34" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> word in </span><span class="pun">(</span><span class="str">'one'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'word'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'after'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'another'</span><span class="pun">):</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> word</span><span class="pun">,</span><span class="pln"> end</span><span class="pun">=</span><span class="str">''</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	لاحظ كيف ستظهر الكلمات الآن في سطر واحد، لأن الوسيط <code>end=''‎</code> يخبر بايثون أن تستخدم سلسلةً نصيةً فارغةً <code>''</code> لنهاية السطر عوضًا عن محرف السطر الجديد الذي تستخدمه افتراضيًا، لنجرب حلقة <code>for</code> مرةً أخرى مع القوائم:
</p>

<pre class="ipsCode">&gt;&gt;&gt; for item in ['one', 2, 'three']: print( item )
...
</pre>

<p>
	ستظهر هنا مشكلة عند استخدام الحلقات التكرارية التي على نمط <code>foreach</code>، وهي أن الحلقة تعطينا نسخةً مما كان في التجميعة، دون أن نستطيع تعديل محتوياتها مباشرةً، فإذا احتجنا إلى تعديلها؛ فعلينا استخدام برنامج غريب الشكل نستخدم فيه فهرس التجميعة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_36" style=""><span class="pln">myList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">]</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> index in range</span><span class="pun">(</span><span class="pln">len</span><span class="pun">(</span><span class="pln">myList</span><span class="pun">)):</span><span class="pln">
    print</span><span class="pun">(</span><span class="pln"> myList</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
    myList</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
print</span><span class="pun">(</span><span class="pln"> myList </span><span class="pun">)</span></pre>

<p>
	سيزيد هذا البرنامج كل فهرس في <code>myList</code>، ولو أننا لم نستخدم طريقة الفهرس تلك، لكنا زدنا العناصر المنسوخة فقط دون تغيير القائمة الأصلية، وقد صار لدينا متن متعدد الأسطر في حلقتنا التكرارية.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<h3 data-gramm="false">
		دالة التعداد enumerate function
	</h3>

	<p>
		إن المثال الذي أوردناه أعلاه شائع جدًا لدرجة أن بايثون توفر دالةً سهلة الاستخدام لتجنب هذه المشكلة، أو تخفيفها على الأقل، وهي دالة <code>enumerate</code> التي تعيد عنصرين في كل مرة نستخدمها على تجميعة ما، هذان العنصران هما قيمة التجميعة ورقم فهرسها، مما يسمح لنا بالوصول إلى القيمة كما فعلنا في حلقة <code>for</code> الأصلية، وتعديلها بواسطة الفهرس كما فعلنا في المثال أعلاه، وتبدو دالة <code>enumerate</code> كما يلي:
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_38" style=""><span class="pln">     myList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">]</span><span class="pln">
     </span><span class="kwd">for</span><span class="pln"> index</span><span class="pun">,</span><span class="pln"> value in enumerate</span><span class="pun">(</span><span class="pln">myList</span><span class="pun">):</span><span class="pln">
         print</span><span class="pun">(</span><span class="pln"> value </span><span class="pun">)</span><span class="pln">
         myList</span><span class="pun">[</span><span class="pln">index</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
     print</span><span class="pun">(</span><span class="pln"> myList </span><span class="pun">)</span><span class="pln">    </span></pre>

<p>
	لاحظ أننا لم نستخدم محث بايثون التفاعلي <code>‎&gt;&gt;&gt;‎</code> في هذا المثال، لذا عليك كتابته في ملف كما شرحنا في مقال <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D9%85%D8%B2%D9%8A%D8%AF-%D9%85%D9%86-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D9%88%D8%A3%D9%85%D9%88%D8%B1-%D8%A3%D8%AE%D8%B1%D9%89-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1289/" rel="">المزيد من التسلسلات البرمجية وأمور أخرى</a>؛ أما إذا حاولنا كتابته في محث بايثون، فسنحتاج إلى أسطر فارغة إضافية لنخبر بايثون بانتهاء كتلة برمجية، وذلك بعد السطر <code>myList[index] += 1</code> مثلًا، وهذه الطريقة مفيدة لتعلّم بداية الكتل البرمجية ونهايتها، بكتابة الشيفرة وتخمين أماكن الحاجة إلى السطر الإضافي، إذ يجب أن يكون عند الموضع الذي تتغير فيه الإزاحة.
</p>

<p>
	لا بد من ملاحظة أمر آخر في حلقات <code>foreach</code>، وهو أننا لا نستطيع حذف العناصر من التجميعة التي نمر عليها، لأن ذلك يربك الحلقة نفسها، فهو يشبه قطع فرع من شجرة أثناء جلوسك عليه، والحل هو استخدام نوع مختلف من الحلقات التكرارية، كما سنرى في جزئية لاحقة من هذه السلسلة.
</p>

<p>
	ربما تجب الإشارة إلى أن كلًا من جافاسكربت وVBScript لديهما بنىً للتكرار على العناصر الموجودة في تجميعة ما، ولن نتحدث عنها بتفصيل هنا، لكن إذا أردت أن تبحث في الأمر بنفسك فانظر صفحات المساعدة لبنية <code>for each...in...‎</code> في لغة VBScript، وبنية <code>for...in...‎</code> في جافاسكربت.
</p>

<h2>
	حلقات While التكرارية
</h2>

<p>
	تتطلب حلقات <code>for</code> أن يعلم المبرمج عدد مرات التكرار التي يريد تنفيذها قبل بدء الحلقة نفسها، أو أن يستطيع حسابها على الأقل، لكن ماذا لو أردنا تنفيذ مهمة ما حتى وقوع حدث معين لا نعرف موعده؟ فقد نرغب في قراءة بيانات من المستخدم ومعالجتها مثلًا إلى أن يخبرنا المستخدم نفسه بالتوقف عن ذلك، كما لن نعرف عدد عناصر البيانات التي سنعالجها إلى أن يكتفي المستخدم ويخبرنا بذلك أيضًا. يُعَد تنفيذ مثل هذه المهام باستخدام حلقة <code>for</code> ممكنًا نظريًا لكنه معقد، لهذا لدينا نوع آخر من الحلقات التي تحل مثل هذه المشاكل، وهي حلقة <code>while</code>، وستبدو في بايثون بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_9394_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">while</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 12 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    j </span><span class="pun">=</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	لنحلل هذه الشيفرة:
</p>

<ol>
	<li>
		نهيئ أولًا <code>j</code> لتأخذ القيمة <code>1</code>، وهذه الخطوة مهمة للغاية، أي تهيئة متغير التحكم في حلقة <code>while</code>، لأن نسيان تهيئته يتسبب في أخطاء كثيرة.
	</li>
	<li>
		ننفذ تعليمة <code>while</code> نفسها، التي تختبر تعبيرًا بوليانيًا هو <code>j&lt;=12</code> في حالتنا.
	</li>
	<li>
		ننفذ الكتلة المزاحة التي تتبعها إذا كانت النتيجة <code>True</code>، وهو محقق في حالتنا بما أن قيمة <code>j</code> أقل من <code>12</code>، لذا سننتقل إلى الكتلة.
	</li>
	<li>
		ننفذ تعليمة الطباعة لإخراج أول سطر من جدولنا.
	</li>
	<li>
		يزيد السطر التالي في الكتلة متغير التحكم <code>j</code>، وهو السطر الأخير في حالتنا، ليشير إلى نهاية كتلة <code>while</code>.
	</li>
	<li>
		نعود إلى تعليمة <code>while</code> ونكرر الخطوات من 4 إلى 6 بقيمة <code>j</code> الجديدة.
	</li>
	<li>
		نكرر هذا التسلسل إلى أن تصل قيمة <code>j</code> إلى <code>13</code>.
	</li>
	<li>
		هنا يعيد اختبار <code>while</code> القيمة <code>False</code>، فنتخطى الكتلة المزاحة إلى السطر الجديد الذي يوازي تعليمة <code>while</code> في إزاحتها.
	</li>
	<li>
		يتوقف البرنامج في مثالنا لأنه لا توجد أسطر أخرى.
	</li>
</ol>

<p>
	تعليمة while واضحة وبسيطة كما رأينا، لكننا نريد الإشارة إلى النقطتين الرأسيتين <code>(:)</code> اللتين في نهاية سطر تعليمة while -وتعليمة for أيضًا-، إذ تخبر هاتان النقطتان بايثون أن ما يليهما كتلة برمجية أو مجموعة مترابطة من التعليمات، وكل لغة لها طريقتها في إخبار المفسر بجمع عدة أسطر معًا كما سنرى، ففي حالة بايثون مثلًا، سنستخدم النقطتين الرأسيتين وإزاحة الأسطر.
</p>

<h3>
	حلقة While في VBScript
</h3>

<p>
	فيما يلي حلقة while في لغة VBScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_44" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
DIM J
J </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="typ">Do</span><span class="pln"> </span><span class="typ">While</span><span class="pln"> J </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">12</span><span class="pln">
    </span><span class="typ">MsgBox</span><span class="pln"> J </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" x 12 = "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> J</span><span class="pun">*</span><span class="lit">12</span><span class="pln">
    J </span><span class="pun">=</span><span class="pln"> J </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="typ">Loop</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	يعطينا هذا المثال نفس النتيجة التي حصلنا عليها من مثال بايثون السابق، مع ملاحظة انتهاء كتلة الحلقة التكرارية بالكلمة المفتاحية <code>Loop</code>
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		هذه البنية التي تستخدمها VBSCript، أي <code>Do...Loop</code> هي بنية متعددة الاستخدامات، ومنها نستطيع تشكيل عدة بنىً مختلفة تعطينا تأثيرًا مختلفًا في كل مرة، ونختار ما يناسبنا وفق حالة التطبيق الذي نعمل عليه، وهذه البنى هي:
	</p>

	<ul>
		<li>
			Do…Loop: وهي البنية الأبسط التي تكرر إلى ما لا نهاية، لكن يمكن الخروج منها بطريقة سنراهافي جزئية لاحقة من هذه السلسة.
		</li>
		<li>
			Do While <test>…Loop: وهي البنية التي استخدمناها في المثال أعلاه.</test>
		</li>
		<li>
			Do Until <test>…Loop: عكس منطق البنية السابقة.</test>
		</li>
		<li>
			Do…Loop While <test>‎: تشبه حلقة while لكنها تنفَّذ مرةً واحدةً على الأقل، لأنها تختبر الشرط في نهاية متن الحلقة.</test>
		</li>
		<li>
			Do…Loop Until <test>‎: تشبه البنية السابقة لكن مع عكس منطق الاختبار.</test>
		</li>
	</ul>
</blockquote>

<h3>
	حلقة While في جافاسكربت
</h3>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_46" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
j </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">){</span><span class="pln">
   document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">j </span><span class="pun">+</span><span class="pln"> </span><span class="str">" x 12 = "</span><span class="pun">+</span><span class="pln"> j</span><span class="pun">*</span><span class="lit">12</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">"&lt;BR&gt;"</span><span class="pun">);</span><span class="pln">
   j</span><span class="pun">++;</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	تتشابه هذه البنية مع ما سبق، لكن مع بعض الأقواس المعقوصة بدلًا من كلمة <code>Loop</code> التي في VBScript، لاحظ أن <code>++J</code> تعني زيادة قيمة <code>j</code> بمقدار 1، كما ذكرنا في مقال سابق، وأن جافاسكربت وVBScript لا تشترطان إزاحة الأسطر، على عكس لغة بايثون، لكننا أزحنا الأسطر لتسهيل قراءة الشيفرة فقط.
</p>

<p>
	لنراجع الآن حلقة <code>for</code> في جافاسكربت:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_48" style=""><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">&lt;=</span><span class="lit">12</span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++){....}</span></pre>

<p>
	نلاحظ أنها تشبه حلقة <code>while</code> تمامًا، لكنها مكتوبة في سطر واحد بحيث يمكن رؤية المهيئ initializer وشرط الاختبار ومعدِّل الحلقة معًا، وبهذا يتبين أن حلقة <code>for</code> في جافاسكربت ما هي إلا حلقة <code>while</code> ولكن بصورة مضغوطة، وسنستنتج أن بعض اللغات قد تستغني عن حلقة <code>for</code> نهائيًا، وهو ما يحدث حقًا.
</p>

<h2>
	حلقات تكرارية مرنة
</h2>

<p>
	إذا عدنا إلى مثال جدول ضرب العدد 12 الذي ذكرناه في بداية هذا المقال، فسنجد أن الحلقة التي أنشأناها ستطبع جدول هذا العدد بكفاءة، لكن هل يمكننا تعديل الحلقة لجعلها تطبع جدول العدد 7 مثلًا؟ ينبغي أن تبدو الحلقة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_50" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> j in range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x 7 = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln">j</span><span class="pun">*</span><span class="lit">7</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	وهذا يعني أن علينا تغيير 12 إلى 7 مرتين، وإذا أردنا قيمةً أخرى غيرهما فسنغير في موضعين من جديد، ولكن ألا توجد طريقة أفضل لإدخال مضاعف الضرب ذاك؟، يمكن ذلك باستخدام متغير آخر للقيم التي في سلسلة الطباعة، ثم ضبط ذلك المتغير قبل تشغيل الحلقة التكرارية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_52" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> multiplier </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> j in range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x %d = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln"> multiplier</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">*</span><span class="pln">multiplier</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	وهذا جدول العدد 12 السابق، وإذا أردنا تغييره إلى العدد 7 مثلًا، فلا نغير إلا قيمة <code>multiplier</code>، جرب كتابة هذا البرنامج في ملف سكربت بايثون وتشغيله من محث سطر الأوامر، ثم عدِّل قيمة المضاعف <code>multiplier</code> إلى أعداد أخرى، لاحظ أننا جمعنا هنا بين التسلسل والحلقات التكرارية، فقد كتبنا أمرًا وحيدًا في البداية هو <code>multiplier = 12</code>، متبوعًا بحلقة <code>for</code>.
</p>

<h2>
	تكرار الحلقة نفسها
</h2>

<p>
	لنطور مثالنا السابق قليلًا، ولنفترض أننا نريد طباعة جميع جداول الضرب للأعداد من 2 حتى 12، سيكون كل ما نحتاجه هو ضبط متغير المضاعف ليكون جزءًا من الحلقة التكرارية، ونفعل بذلك بالشكل التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_54" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> multiplier in range</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    </span><span class="kwd">for</span><span class="pln"> j in range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">       print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x %d = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln">multiplier</span><span class="pun">,</span><span class="pln">j</span><span class="pun">*</span><span class="pln">multiplier</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	لاحظ أن الجزء المزاح داخل حلقة <code>for</code> الأولى هو نفس الحلقة التي بدأنا بها، وستنفَّذ الحلقة كما يلي:
</p>

<ol>
	<li>
		نضبط multiplier أولًا على القيمة الأولى <code>2</code> ثم ننتقل إلى الحلقة الثانية الداخلية.
	</li>
	<li>
		نعيد ضبط multiplier على القيمة التالية <code>3</code> ثم ننتقل إلى الحلقة الداخلية مرةً أخرى.
	</li>
	<li>
		نكرر هذا حتى نمر على جميع الأعداد.
	</li>
</ol>

<p>
	يُعرف هذا الأسلوب باسم الحلقات المتشعبة nesting loops، لكن من مساوئه أن جميع الجداول ستكون مدمجةً معًا، ونستطيع إصلاح هذه المشكلة بطباعة سطر فاصل في نهاية الحلقة الأولى، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_56" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> multiplier in range</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    </span><span class="kwd">for</span><span class="pln"> j in range</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">13</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">       print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"%d x %d = %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln">multiplier</span><span class="pun">,</span><span class="pln">j</span><span class="pun">*</span><span class="pln">multiplier</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">...</span><span class="pln">    print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"------------------- "</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	لاحظ أن تعليمة الطباعة الثانية لها نفس إزاحة تعليمة <code>for</code> الثانية، وهي ثاني تعليمة في تسلسل التكرار، فتسلسل الإزاحة مهم جدًا في بايثون كما ذكرنا.
</p>

<p>
	دعنا نرى الآن كيفية تنفيذ هذا التدريب في جافاسكربت، لرؤية الفرق بينهما فقط:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_9394_58" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">multiplier</span><span class="pun">=</span><span class="lit">2</span><span class="pun">;</span><span class="pln"> multiplier </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">13</span><span class="pun">;</span><span class="pln"> multiplier</span><span class="pun">++){</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">j</span><span class="pun">=</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> j </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">12</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> j</span><span class="pun">++){</span><span class="pln">
        document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">j</span><span class="pun">,</span><span class="pln"> </span><span class="str">" x "</span><span class="pun">,</span><span class="pln"> multiplier</span><span class="pun">,</span><span class="pln"> </span><span class="str">" = "</span><span class="pun">,</span><span class="pln"> j</span><span class="pun">*</span><span class="pln">multiplier</span><span class="pun">,</span><span class="pln"> </span><span class="str">"&lt;BR&gt;"</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
    document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"---------------&lt;BR&gt;"</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	حاول أن تجعل السطر الفاصل يشير إلى الجدول التابع له، يمكنك استخدام متغير المضاعف وسلسلة التنسيق التي في بايثون لفعل ذلك.
</p>

<h2>
	حلقات أخرى
</h2>

<p>
	توفر بعض اللغات الأخرى بنىً مختلفةً للتكرار، كما رأينا في مثال VBScript أعلاه، غير أنها لا تخلو من صورة ما لحلقتي <code>for</code> و<code>while</code>، ولا تحوي بعض اللغات، مثل Modula 2 وOberon، إلا حلقة while فقط، بما أننا نستطيع تمثيل سلوك for منها كما رأينا قبل قليل.
</p>

<p>
	ومن الحلقات التكرارية الموجودة في اللغات الأخرى:
</p>

<ul>
	<li>
		do-while: هذه الحلقة هي نفسها حلقة while لكن مع وجود الاختبار في نهايتها، بحيث تُنفَّذ الحلقة مرةً واحدةً على الأقل.
	</li>
	<li>
		repeat-until: شبيهة بالسابقة أيضًا لكن مع عكس المنطق.
	</li>
	<li>
		GOTO وJUMP وLOOP: هذه الحلقات التكرارية موجودة في اللغات القديمة، وهي تعين علامةً في الشيفرة ثم تقفز إليها مباشرةً.
	</li>
</ul>

<h2>
	خاتمة
</h2>

<p>
	لقد رأينا أن حلقات <code>for</code> تكرر مجموعةً من الأوامر لعدد محدد وثابت من المرات، وأن <code>while</code> تكرر تلك الأوامر إلى أن يتحقق شرط محدد في الحلقة، ولا تنفذ متن الحلقة أصلًا إذا كان شرط إنهاء الحلقة غير متحقق من البداية، أي أعطى اختباره النتيجة <code>false</code>، وعلمنا أنه توجد أنواع أخرى من الحلقات التكرارية؛ لكن اللغة التي تحتوي عليها، ستحتوي على حلقتي for وwhile أو إحداهما على الأقل، وأن حلقات for في بايثون ما هي إلا حلقات foreach حقيقةً، إذ تعمل على قائمة من العناصر، كما تعلمنا الحلقات التكرارية المتشعبة، بإدخال حلقة فرعية داخل أخرى أكبر منها.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutloops.htm" rel="external nofollow">للفصل السابع: Looping - Or the art of repeating oneself من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D9%84%D9%88%D8%A8-%D9%83%D8%AA%D8%A7%D8%A8%D8%A9-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A9-%D9%88%D8%AA%D8%AD%D9%82%D9%8A%D9%82-%D8%B3%D9%87%D9%88%D9%84%D8%A9-%D9%82%D8%B1%D8%A7%D8%A1%D8%AA%D9%87%D8%A7-r1307/" rel="">أسلوب كتابة الشيفرات البرمجية وتحقيق سهولة قراءتها</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B9%D8%B6-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%85%D9%87%D9%85%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1289/" rel="">بعض التسلسلات النصية المهمة لتعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%AA%D8%B9%D9%84%D9%85%D9%87%D8%A7%D8%9F-r1279/" rel="">ما هي البرمجة ومتطلبات تعلمها؟</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-loops-%D9%81%D9%8A-cpp-r893/" rel="">الحلقات التكرارية Loops في Cpp</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%A8%D9%86%D9%89-%D8%A7%D9%84%D8%AA%D8%AD%D9%83%D9%85-%D9%88%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-php-r1048/" rel="">بنى التحكم والحلقات التكرارية في PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/c-sharp/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-%D9%84%D8%BA%D8%A9-%D8%B3%D9%8A-%D8%B4%D8%A7%D8%B1%D8%A8-c-r320/" rel="">الحلقات التكرارية في لغة سي شارب #C</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D8%AD%D9%84%D9%82%D8%A7%D8%AA-for-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D8%A8%D8%A8%D8%B3%D8%A7%D8%B7%D8%A9-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r624/" rel="">حلقات for التكرارية ببساطة في جافاسكريبت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1306</guid><pubDate>Thu, 26 Aug 2021 15:00:00 +0000</pubDate></item><item><title>&#x628;&#x639;&#x636; &#x627;&#x644;&#x62A;&#x633;&#x644;&#x633;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x646;&#x635;&#x64A;&#x629; &#x627;&#x644;&#x645;&#x647;&#x645;&#x629; &#x644;&#x62A;&#x639;&#x644;&#x645; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D8%A8%D8%B9%D8%B6-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%85%D9%87%D9%85%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1289/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/610e47b7ef96d_-----.png.308b51c5adf6daf15d228cf1532055fd.png" /></p>
<p>
	إذا قرأت المقالات السابقة من هذه السلسلة فأنت على دراية بأننا تعلمنا فيها كيف نكتب أوامر بسيطةً وحيدة المدخلات في بايثون، وعرفنا أهمية البيانات وما نفعله بها، ثم كتبنا تسلسلات أطول قليلًا (5-10 أسطر). وها نحن نقترب من كتابة برامج مفيدة، لكن لا زالت لدينا عقبة هنا، وهي خسارة البيانات والبرامج كلما خرجنا من بايثون على الحاسوب، وإذا كنت تستخدم جافاسكربت أو VBScript فسترى أنك قد خزنت تلك الأمثلة في ملفات تستطيع تشغيلها وقتما أردت، ونريد أن نفعل ذلك مع بايثون أيضًا، وقد ذكرنا من قبل أن هذا ممكن باستخدام أي محرر نصي مثل notepad أو pico ، وذلك بحفظ ملف بامتداد <code>‎.py</code> ثم تشغيل الملف من محث أوامر نظام التشغيل مع كتابة اسم السكربت مسبوقًا بكلمة <code>python</code>، يستخدم المثال التالي تسلسلًا من أوامر بايثون، فيه كل النقاط التي شرحناها من قبل:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_9" style=""><span class="com">#  File: firstprogram.py</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"hello world"</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"Here are the ten numbers from 0 to 9\n0 1 2 3 4 5 6 7 8 9"</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"I'm done!"</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="com"># نهاية الملف</span></pre>

<p>
	لاحظ أن السطرين الأول والأخير ليسا ضروريين، وهما تعليقان سنشرحها في هذا المقال، وقد أضفناهما لنوضح ما يحدث في الملف.
</p>

<p>
	يمكن استخدام notepad أو أي محرر نصي لإنشاء الملف طالما سنحفظه بصيغة نصية مجردة، ولا نستخدم معالج نصوص متقدمًا مثل MS Word، لأنه يحفظ الملفات بصيغة ثنائية خاصة لا تستطيع بايثون فهمها، ولا نستخدم صيغة html التي تحوي كثيرًا من النصوص المنسقة التي لا تعني شيئًا لبايثون كذلك.
</p>

<p>
	لتشغيل هذا البرنامج افتح سطر أوامر نظام التشغيل الآن، يمكنك مراجعة مقال <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D8%B1%D8%AD%D9%84%D8%A9-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1280/" rel="">البداية في تعلم البرمجة</a> لمعرفة سطر أوامر النظام، وانتقل إلى المجلد الذي حفظت فيه ملف بايثون لديك، ثم نفّذه بكتابة python قبله كما ذكرنا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_7" style=""><span class="pln">D</span><span class="pun">:</span><span class="pln">\PROJECTS\Python</span><span class="pun">&gt;</span><span class="pln"> python firstprogram</span><span class="pun">.</span><span class="pln">py
hello world
</span><span class="typ">Here</span><span class="pln"> are the ten numbers </span><span class="kwd">from</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> to </span><span class="lit">9</span><span class="pln">
</span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="lit">8</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> 
I</span><span class="str">'m done!

D:\PROJECTS\Python&gt;</span></pre>

<p>
	في السطر الأول محث أوامر ويندوز إضافةً إلى الأمر الذي كتبناه، ثم خرج البرنامج معروضًا قبل أن يظهر محث ويندوز مرةً أخرى، لكن توجد طريقة أسهل، فقد يكون لدينا أكثر من إصدار لبايثون على نفس الحاسوب إذا كان النظام نفسه يستخدم الإصدار الثاني منها لبعض المهام مثلًا، وإذا كتبنا <code>python</code> في تلك الحالة فقد نحصل على أخطاء لم نتوقعها، ولتجنب مثل تلك الحالة نلحق رقم إصدار بايثون الذي نريد استخدامه إلى الاسم، فإذا كنا نريد الإصدار الثالث نكتب:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_16" style=""><span class="pln">    D</span><span class="pun">:</span><span class="pln">\PROJECTS\Python</span><span class="pun">&gt;</span><span class="pln"> python3 firstprogram</span><span class="pun">.</span><span class="pln">py</span></pre>

<p>
	لاحظ أنها صارت الآن <code>python3</code> بدلًا من <code>python</code> فقط، وبذلك سنتجنب كثيرًا من الأخطاء على أغلب نظم التشغيل.
</p>

<h2>
	مزايا استخدام البيئة المتكاملة
</h2>

<p>
	يثبَّت مع بايثون تلقائيًا عند تثبيتها على الحاسوب تطبيق مفيد، وهو برنامج مكتوب بلغة بايثون أيضًا، ويسمى IDLE اختصارًا لبيئة التطوير المتكاملة Integrated Development Environment، وهو يعني أن فيه أدوات عديدةً مدمجةً فيه لمساعدة المبرمجين، ولن نتعمق فيه هنا، لكن نريد تسليط الضوء على مزيتين فيه، أولاهما أنه يوفر نسخةً محسنةً من محث بايثون <code>‎&gt;&gt;&gt;‎</code> فيها تظليل للكلمات، حيث تُعرَض خصائص اللغة بألوان مختلفة لإبرازها، إضافةً إلى محرر نصي خاص ببايثون، يسمح لك بتشغيل ملفات برنامجك مباشرةً من داخل IDLE، وننصحك بتجربة IDLE إذا لم تكن قد فعلت، وإذا أردت شرحًا للبرنامج فانظر <a href="https://www.hashcollision.org/hkn/python/idle_intro/" rel="external nofollow">دليل داني يو Danny Yoo</a> عنه.
</p>

<p>
	أما في حالة استخدام ويندوز فثمة خيار آخر هو PythonWin الذي يمكن تحميله ضمن حزمة <a href="https://github.com/mhammond/pywin32/releases/latest" rel="external nofollow">PyWin32</a>، والذي يسمح لنا بالوصول إلى جميع دوال البرمجة الدنيا لـمكتبة MFC الخاصة بويندوز، وهو بديل جيدًا جدًا لبيئة IDLE، لكنه لا يعمل إلا على ويندوز، وستحصل عليه تلقائيًا إذا حمّلت بايثون من ActiveState، فنسختهم فيها جميع مزايا PyWin32 بما فيها Pythonwin افتراضيًا.
</p>

<p>
	لكن من الناحية الأخرى فإن IDLE يأتي افتراضيًا في حزمة بايثون القياسية، وهو يعمل على أغلب أنظمة التشغيل، لذا يُستخدم أكثر، ولا تهم الأداة التي تستخدمها بأي حال طالما ليست notepad من ويندوز إذ الخيارات المتقدمة أفضل من مجرد محرر نصي بسيط.
</p>

<p>
	أخيرًا، إذا كنت تفضل الأسلوب البسيط في كتابة البرامج فستجد محررات عدةً تدعم البرمجة ببايثون، حيث يوفر محرر <a href="https://www.vim.org/download.php" rel="external nofollow">ViM</a> مثلًا تظليلًا للكلمات المفتاحية، ويوفر <a href="https://www.gnu.org/software/emacs/download.html" rel="external nofollow">emacs</a> وضع تعديل كامل خاص ببايثون، كما يوفر محرر <a href="https://www.scintilla.org/SciTEDownload.html" rel="external nofollow">Scite</a> الخفيف تظليل الكلمات المفتاحية لبايثون إضافةً إلى مزايا أخرى. وإذا اخترت طريق المحررات النصية فستجد نفسك مع الوقت تعمل أمام ثلاث نوافذ في نفس الوقت، هي نافذة المحرر التي تكتب فيها شيفرتك المصدرية وتحفظها، وجلسة بايثون التي تجرب فيها ما تكتب من خلال محث بايثون قبل إضافتها إلى برنامجك في المحرر، وسطر أوامر نظام التشغيل الذي تستخدمه لتشغيل البرنامج من أجل اختباره.
</p>

<p>
	أما أغلب المبتدئين فيفضلون أسلوب بيئات التطوير المتكاملة التي تأتي كلها في نافذة واحدة مثل IDLE، والأمر كله اختياري فيه سعة ولهذا اختر ما يناسبك، وإذا كنت تستخدم جافاسكربت أو VBScript؛ فنقترح استخدام أحد المحررات النصية المذكورة أعلاه، ومتصفح ويب حديث لجافاسكربت مثل كروم أو فاير فوكس؛ أما بالنسبة للغة VBScript فهذا يعني إنترنت إكسبلورر حصرًا، وليس متصفح Edge حتى، ويكون المتصفح مفتوحًا على الملف الذي تعمل عليه، فإذا أردت تجربة تغيير أو تعديل ما، فاضغط زر إعادة تحميل الصفحة.
</p>

<h2>
	التعليقات السريعة
</h2>

<p>
	إحدى أهم الأدوات البرمجية التي لا يشعر المبتدئون بأهميتها هي التعليقات، وهي أسطر داخل البرنامج تصف ما يحدث فيه، وليس لها أي تأثير على أداء البرنامج أو سير عملياته، فهي أسطر وصفية لما يحدث فقط، إلا أن دورها في غاية الأهمية، إذ تخبر المبرمج ما يفعله البرنامج في كل كتلة برمجية أو كل سطر، ولماذا يتصرف على هذا النحو، وتظهر أهمية التعليقات هنا إذا كان البرنامج الذي يقرؤه المبرمج قد كتبه شخص غيره، أو قد كتبه هو بنفسه لكن منذ مدة طويلة فنسي سبب اختياره لخاصية أو دالة بعينها.
</p>

<p>
	وسيشعر المبرمج بأهمية التعليقات حسنة الوصف مع الوقت، وقد أضفنا تعليقات إلى بعض الشيفرات التي استخدمناها في شرح هذه السلسلة إلى الآن، فهي تلك الأسطر المسبوقة بعلامة <code>#</code> في بايثون، أو بعلامة <code>'</code> في VBScript، وسنبدأ تدريجيًا من الآن بكتابة شرح الشيفرة في التعليقات، إلى أن يقل ما نكتبه من الشرح خارج الشيفرة ثم يختفي.
</p>

<p>
	لكل لغة طريقة في ترميز التعليقات، ففي VBScript مثلًا تكون <code>REM</code> مثل اختصار إلى كلمة Remark أو ملاحظة، لكن يشيع استخدام العلامة <code>'</code> لتؤدي نفس الوظيفة بحيث يتجاهل البرنامج أي شيء مكتوب بعدها.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_18" style=""><span class="pln">REM </span><span class="pun">لن</span><span class="pln"> </span><span class="pun">يُعرض</span><span class="pln"> </span><span class="pun">هذا</span><span class="pln"> </span><span class="pun">السطر</span><span class="pln">
</span><span class="str">' ولا هذا
msgBox "أما هذا السطر فسيُعرض"</span></pre>

<p>
	لاحظ أن استخدام علامة اقتباس مفردةً <code>'</code> مثل محدد للتعليقات في VBScript هو سبب منع بدء السلسلة النصية بها، لئلا تظن اللغة أنها تعليق، أما بايثون فتستخدم رمز <code>#</code> مثل حدد للتعليقات فيها، وتتجاهل أي شيء يتبعه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_20" style=""><span class="pln">v </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pln">     </span><span class="com"># القيمة 12 v أعط </span><span class="pln">
x </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">*</span><span class="pln">v    </span><span class="com"># v تساوي مربع x</span></pre>

<p>
	غير أن هذا الأسلوب في التعليقات سيء للغاية، إذ لا يجب أن تصف التعليقات ما تفعله الشيفرة فحسب، فنحن نستطيع رؤية ذلك بأنفسنا، لكنها يجب أن تصف سبب اختيار المبرمج لهذه الدالة أو تلك القيمة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_22" style=""><span class="pln">v </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3600</span><span class="pln">    </span><span class="com"># 3600 عدد الثواني في الساعة الواحدة</span><span class="pln">
s </span><span class="pun">=</span><span class="pln"> t</span><span class="pun">*</span><span class="lit">3600</span><span class="pln">  </span><span class="com"># تحتوي الوقت المار بالساعة t</span><span class="pln">
            </span><span class="com"># لذا نحولها إلى ثوانٍ.</span></pre>

<p>
	هذه النسخة من التعليقات أكثر فائدةً إذ تشرح سبب ضرب t في 3600.
</p>

<p>
	تستخدم جافاسكربت شرطتين مائلتين <code>//</code> مثل محدد للتعليقات، ثم تتجاهل أي شيء بعدهما، كما تسمح بعض اللغات بتعليقات متعددة الأسطر بين زوجين من الرموز، لكن هذا قد يؤدي إلى بعض الأخطاء الخفية إذا لم يوضع رمز الإغلاق، وتسمح جافاسكربت بهذا النوع من التعليقات باستخدام الرمز <code>‎/*‎</code> متبوعًا برمز الإغلاق <code>‎*/‎</code> بعد نهاية التعليقات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_24" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"هذا السطر يُطبع\n"</span><span class="pun">);</span><span class="pln">

</span><span class="pun">//</span><span class="pln"> </span><span class="pun">تعليق</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">سطر</span><span class="pln"> </span><span class="pun">واحد</span><span class="pln">

</span><span class="pun">/*</span><span class="pln"> </span><span class="pun">هنا</span><span class="pln"> </span><span class="pun">تعليق</span><span class="pln"> </span><span class="pun">نقسمه</span><span class="pln"> </span><span class="pun">على</span><span class="pln"> </span><span class="pun">عدة</span><span class="pln"> </span><span class="pun">أسطر</span><span class="pln">
</span><span class="pun">فيحتوي</span><span class="pln"> </span><span class="pun">على</span><span class="pln"> </span><span class="pun">هذا</span><span class="pln"> </span><span class="pun">السطر</span><span class="pln">
</span><span class="pun">وهذا</span><span class="pln"> </span><span class="pun">السطر</span><span class="pln">
</span><span class="pun">وذا</span><span class="pln"> </span><span class="pun">أيضًا</span><span class="pln">
</span><span class="pun">ولن</span><span class="pln"> </span><span class="pun">يظهر</span><span class="pln"> </span><span class="pun">أي</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">هذا</span><span class="pln"> </span><span class="pun">في</span><span class="pln"> </span><span class="pun">خرج</span><span class="pln"> </span><span class="pun">السكربت</span><span class="pln">
</span><span class="pun">فإذا</span><span class="pln"> </span><span class="pun">أردنا</span><span class="pln"> </span><span class="pun">إنهاء</span><span class="pln"> </span><span class="pun">التعليق</span><span class="pln"> </span><span class="pun">نعكس</span><span class="pln"> </span><span class="pun">رمز</span><span class="pln"> </span><span class="pun">البدء</span><span class="pln"> </span><span class="pun">ليكون</span><span class="pln">
</span><span class="pun">كما</span><span class="pln"> </span><span class="pun">يلي:</span><span class="pln"> </span><span class="pun">*/</span><span class="pln">

document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"وهذا أيضًا"</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	تبرز أهمية التعليقات كما ذكرنا في أنها تشرح الشيفرة لأي شخص يحاول قراءتها، حيث يجب الحرص على توضيح الأقسام الغامضة مثل القيم العشوائية المستخدمة، أو المعادلات الحسابية المعقدة. تذكر أن ذلك القارئ المحتار في فهم شيفرتك قد يكون أنت نفسك بعد بضعة أسابيع أو أشهر.
</p>

<h2>
	التسلسلات باستخدام المتغيرات
</h2>

<p>
	لقد شرحنا مفهوم المتغيرات في مقال <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-r1287/" rel="">مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية</a>، وقلنا إنها عناوين نعلّم بها بياناتنا من أجل الإشارة إليها في المستقبل، ورأينا بعض الأمثلة عن استخدام المتغيرات في عدة أمثلة لقوائم ودفاتر عناوين، غير أن المتغيرات بالغة الأهمية في البرمجة إلى الحد الذي يجعلنا نعيد مراجعة كيفية استخدامها مرةً أخرى قبل أن ننتقل إلى جزء جديد.
</p>

<p>
	اكتب ما يلي في محث بايثون، سواءً في صدفة IDLE أو في نافذة أوامر دوس أو يونكس:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> w </span><span class="pun">=</span><span class="pln"> </span><span class="lit">18</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> v </span><span class="pun">+</span><span class="pln"> w    </span><span class="com"># استخدم متغيرنا في عملية حسابية</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> x </span><span class="pun">)</span></pre>

<p>
	ما حدث في الشيفرة أعلاه هو أننا أنشأنا المتغيرات <code>v وw وx</code> وعدّلناها، وهذا أشبه بزرّ M على حاسبة الجيب القديمة التي تخزن نتيجةً لاستخدامها لاحقًا، يمكن تحسين تلك الشيفرة باستخدام سلسلة تنسيق لطباعة النتيجة:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_28" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"The sum of %d and %d is: %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">v</span><span class="pun">,</span><span class="pln">w</span><span class="pun">,</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	إحدى مزايا سلاسل التنسيق هنا أننا نستطيع تخزينها في متغيرات أيضًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> </span><span class="str">"The sum of %d and %d is: %d"</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> s </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">v</span><span class="pun">,</span><span class="pln">w</span><span class="pun">,</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">   </span><span class="com"># هذا مفيد عند طباعة نفس الخرج بقيم مختلفة</span></pre>

<p>
	هذا يقصّر كثيرًا من طول تعليمة الطباعة، خاصةً حين تحتوي على قيم كثيرة، لكنه يجعلها أكثر غموضًا، وعندها تقرر بنفسك أيهما الأفضل من حيث القراءة: الأسطر الطويلة أم القصير؟ فإذا أبقينا سلسلة التنسيق هنا إلى جانب تعليمة الطباعة كما فعلنا فهذا حسن.
</p>

<p>
	يفضل تسمية المتغير بطريقة تشرح الغرض من وجوده، فبدلًا من تسمية سلسلة التنسيق باسم <code>s</code>، يفضل تسميتها <code>sumFormat</code> فتبدو الشيفرة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_7481_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> sumFormat </span><span class="pun">=</span><span class="pln"> </span><span class="str">"The sum of %d and %d is: %d"</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> sumFormat </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="pln">v</span><span class="pun">,</span><span class="pln">w</span><span class="pun">,</span><span class="pln">x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">   </span><span class="com"># هذا مفيد عند طباعة نفس الخرج بقيم مختلفة</span></pre>

<p>
	يمكن معرفة أي تنسيق تمت طباعته بمجرد النظر إليه في هذا البرنامج لأنه لا يحتوي على سلاسل تنسيق كثيرة، لكن لا تزال فكرة التسمية المنطقية للمتغيرات ساريةً هنا، وسنحاول قدر الإمكان استخدام أسماء ذات معنى في ما يلي من الشرح؛ أما المتغيرات التي ذكرناها إلى الآن فلم يكن لها معنىً يستحق التسمية.
</p>

<h2>
	أهمية الترتيب
</h2>

<p>
	قد يظن المرء أن بنية التسلسل تلك مبالغ فيها لبداهتها، ولعل هذا صحيح بما أنها بديهية فعلًا، لكن الأمر ليس بتلك البساطة التي يبدو عليها، فقد تكون هناك مشاكل خفية كما في حالة الرغبة في ترقية جميع الترويسات في ملف HTML مثلًا، بمقدار رتبة واحدة، انظر المثال التالي، حيث تُميَّز الترويسات في HTML بإحاطة النص بوسم يشير إلى أنها ترويسة مع رتبتها:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_7481_34" style=""><span class="tag">&lt;h1&gt;</span><span class="pln"> نص </span><span class="tag">&lt;/h1&gt;</span><span class="pln"> لترويسة المستوى الأول
</span><span class="tag">&lt;h2&gt;</span><span class="pln"> نص </span><span class="tag">&lt;/h2&gt;</span><span class="pln"> لترويسة المستوى الثاني
</span><span class="tag">&lt;h3&gt;</span><span class="pln"> نص </span><span class="tag">&lt;/h3&gt;</span><span class="pln"> لترويسة المستوى الثالث</span></pre>

<p>
	والمشكلة هنا أننا حين نصل إلى المستوى الخامس يصير نص الترويسة أصغر من نص المتن العادي نفسه، مما يبدو غريبًا على القارئ إذ يرى نص العنوان أصغر من متنه، وعلى ذلك نريد ترقية جميع الترويسات دفعةً واحدةً، يسهُل هذا بعملية بحث واستبدال في محرر نصي بسيط بأن نستبدل h2 بـ h1 مثلًا، لكن ماذا لو بدأنا بالأرقام الأكبر، مثل h4 إلى h3، ثم h3 إلى h2 وهكذا؛ سنجد في النهاية أن جميع الترويسات صارت من المستوى الأول h1، وهنا تبرز أهمية ترتيب الأحداث والإجراءات، وذلك ينطبق في حالة كتابتنا لبرنامج ينفذ عملية الاستبدال، وهو ما سنفعله على الأغلب بما أن ترقية الترويسات عملية واردة الحدوث، وقد رأينا أمثلةً أخرى نستخدم فيها المتغيرات والتسلسلات في مقالي مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية و<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A7%D9%84%D8%AA%D8%AC%D9%85%D9%8A%D8%B9%D8%A7%D8%AA-collections-r1288/" rel="">مدخل إلى البيانات وأنواعها: التجميعات Collections</a>، خاصةً أمثلة دفتر العناوين. جرب التفكير في أمثلة مشابهة لحلها، وإذا أتممت هذا فسننتقل إلى دراسة حالة جديدة نطورها بالتدريج كلما تقدمنا في هذه السلسلة، لنحسنها مع كل تقنية نتعلمها.
</p>

<h2>
	جدول الضرب
</h2>

<p>
	سنشرح الآن تدريبًا برمجيًا نطوره معنا أثناء دراسة المقالات التالية، وستتطور حلوله تدريجيًا مع تعلم تقنيات جديدة، ذكرنا أننا نستطيع كتابة سلاسل نصية طويلة بتغليفها بعلامات اقتباس ثلاثية، لنستخدم هذا الأسلوب لبناء جدول ضرب:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_7481_36" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> s </span><span class="pun">=</span><span class="pln"> </span><span class="str">"""</span><span class="pln">
</span><span class="lit">1</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">%</span><span class="pln">d
</span><span class="lit">2</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">%</span><span class="pln">d
</span><span class="lit">3</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">%</span><span class="pln">d
</span><span class="lit">4</span><span class="pln"> x </span><span class="lit">12</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">%</span><span class="pln">d
</span><span class="str">"""</span><span class="pln">   </span><span class="pun">#</span><span class="pln"> </span><span class="pun">احذر</span><span class="pln"> </span><span class="pun">وضع</span><span class="pln"> </span><span class="pun">تعليقات</span><span class="pln"> </span><span class="pun">في</span><span class="pln"> </span><span class="pun">السلاسل</span><span class="pln"> </span><span class="pun">النصية</span><span class="pln"> 
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln">   </span><span class="pun">#</span><span class="pln"> </span><span class="pun">إذ</span><span class="pln"> </span><span class="pun">ستكون</span><span class="pln"> </span><span class="pun">جزءًا</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">السلسلة</span><span class="pln"> </span><span class="pun">نفسها</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> s </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">*</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">*</span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">*</span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	إذا وسعنا الشيفرة السابقة فسنتمكن من طباعة جدول ضرب العدد 12 كاملًا من 1 إلى 12، لكن هل من طريقة أفضل؟ بالتأكيد، وهي ما سنراها في الجزئية الموالية من هذه السلسلة.
</p>

<h2>
	خاتمة
</h2>

<p>
	عرفنا في هذا المقال أن IDLE هي بيئة تطوير خاصة بكتابة برامج بايثون وتطويرها، وأن التعليقات تسهل قراءة البرامج وفهمها، ولا تأثير لها على سير العمليات في البرنامج، وأن المتغيرات تستطيع تخزين نتائج بينية من أجل استخدامها لاحقًا.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutseq2.htm" rel="external nofollow">للفصل السادس: More Sequences and Other Things من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AD%D9%84%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D8%AA%D9%83%D8%B1%D8%A7%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1306/" rel="">الحلقات التكرارية في البرمجة</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A7%D9%84%D8%AA%D8%AC%D9%85%D9%8A%D8%B9%D8%A7%D8%AA-collections-r1288/" rel="">مدخل إلى البيانات وأنواعها: التجميعات Collections</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81-%D8%AA%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r17/" rel="">كيف تتعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81-%D8%AA%D8%AA%D8%B9%D9%84%D9%91%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%86%D8%B5%D8%A7%D8%A6%D8%AD-%D9%88%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D9%84%D8%B1%D8%AD%D9%84%D8%AA%D9%83-%D9%81%D9%8A-%D8%B9%D8%A7%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r206/" rel="">كيف تتعلّم البرمجة: نصائح وأدوات لرحلتك في عالم البرمجة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1289</guid><pubDate>Fri, 20 Aug 2021 15:06:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x648;&#x623;&#x646;&#x648;&#x627;&#x639;&#x647;&#x627;: &#x627;&#x644;&#x62A;&#x62C;&#x645;&#x64A;&#x639;&#x627;&#x62A; Collections</title><link>https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A7%D9%84%D8%AA%D8%AC%D9%85%D9%8A%D8%B9%D8%A7%D8%AA-collections-r1288/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/610e431b581ab_-.png.d6123293b88dc9b1d2000641d66df2d6.png" /></p>
<p>
	أشرنا في <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-r1287/" rel="">المقال السابق</a> إلى عدة أنواع أساسية من البيانات البرمجية، وفي هذا المقال سنتابع مع ذكر نوع هام جدًا منها، وهو البيانات التجميعية collections.
</p>

<h2>
	التجميعات Collections
</h2>

<p>
	لقد شكلت <a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%88%D9%85-%D8%A7%D9%84%D8%AD%D8%A7%D8%B3%D9%88%D8%A8/" rel="">علوم الحاسوب</a> نظامًا كاملًا يدرس التجميعات وسلوكياتها المختلفة، والتي تسمى بالحاويات أحيانًا أو التسلسلات، وسننظر أولًا في التجميعات المدعومة في بايثون وجافاسكربت وVBScript، ثم نختم بملخص موجز لبعض أنواع التجميعات الأخرى التي قد نراها في لغات أخرى.
</p>

<h3>
	القوائم Lists
</h3>

<p>
	لا شك في أن القوائم غنية عن تعريفها، إذ نستخدمها في حياتنا كل يوم، فهي مجرد سلسلة من العناصر، حيث نستطيع إضافة عناصر إلى تلك السلسلة أو حذفها، وعادةً ما نضيف العناصر في نهاية القائمة إذا كانت مكتوبةً على الورق، فلا نستطيع إدخال عنصر في المنتصف مثلًا، على عكس القوائم الإلكترونية في برنامج معالج النصوص مثلًا، إذ نستطيع وضع العنصر الجديد في أي مكان، كما نستطيع البحث في القائمة لنتحقق من وجود شيء بعينه فيها، لكن يجب التنقل في القائمة من أعلاها لأسفلها عنصرًا عنصرًا متحققين من كل عنصر لنرى إذا كان ما نريده موجودًا أم لا، وتُعَد القوائم أحد أنواع التجميعات التي لا غنى عنها في أغلب لغات البرمجة الحديثة.
</p>

<p>
	لا تحتوي جافاسكربت ولا VBScript على قوائم مضمّنة فيها، لكن نستطيع محاكاة مزايا القوائم بواسطة المصفوفات في جافاسكربت، وبتجميعات بيانات أخرى في VBScript كما سنشرح لاحقًا؛ أما لغة بايثون فالقوائم مضمّنة تلقائيًا فيها، وتستطيع تنفيذ العمليات الأساسية التي تحدثنا عنها جميعًا، إضافةً إلى القدرة على فهرسة العناصر فيها، والفهرسة هي الإشارة إلى عنصر في القائمة برقم تسلسله، على فرض أن العنصر الأول يبدأ من الصفر، كما توفر بايثون عدة عمليات أخرى على التجميعات، وتنطبق كلها تقريبًا على القوائم، كما تنطبق مجموعة فرعية منها على أنواع أخرى من التجميعات بما في ذلك السلاسل النصية التي هي مجرد نوع خاص من القوائم، إذ هي قوائم من المحارف.
</p>

<p>
	تُستخدم الأقواس المربعة لإنشاء القوائم والوصول إليها في بايثون، ويمكن إنشاء قائمة فارغة باستخدام زوج من تلك الأقواس ليس بينهما شيء، أو إنشاء قائمة تحتوي على قيم تفصل بينها فاصلة إنجليزية "<code>,"</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_7" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> aList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> another </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> another </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">]</span></pre>

<p>
	نستطيع الوصول إلى العناصر المنفردة باستخدام رقم الفهرس، حيث يحمل العنصر الأول رقم 0 داخل الأقواس المربعة، فإذا أردنا الوصول إلى العنصر الثالث مثلًا -والذي سيحمل الترتيب 2 داخل الأقواس بما أننا نبدأ من الصفر-، فإننا نصل إليه كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> another</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">3</span></pre>

<p>
	كما نستطيع تغيير قيم العناصر في القائمة بطريقة مماثلة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_12" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> another</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> another </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]</span></pre>

<p>
	لاحظ كيف تغير العنصر الثالث -الذي فهرسه 2- من 3 إلى 7.
</p>

<p>
	يمكن استخدام أرقام الفهرس السالبة للوصول إلى عناصر القائمة من نهايتها، فإذا أردنا العنصر الأخير من القائمة نستخدم <code>‎-1</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_14" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> another</span><span class="pun">[-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">7</span></pre>

<p>
	وتضاف العناصر الجديدة ملحقةً إلى نهاية القائمة باستخدام العملية <code>append()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> aList</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> aList </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">42</span><span class="pun">]</span></pre>

<p>
	كما يمكن الاحتفاظ بقائمة داخل قائمة أخرى، فإذا ألحقنا القائمة الثانية بالقائمة الأولى فستكون على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_18" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> aList</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="pln">another</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> aList </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]]</span></pre>

<p>
	لاحظ كيف تكون النتيجة قائمةً من عنصرين، لكن العنصر الثاني عبارة عن قائمة بحد ذاته كما نرى من القوسين المحيطين به، ونستطيع الآن الوصول إلى العنصر 7 باستخدام فهرس مزدوج:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_20" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> aList</span><span class="pun">[</span><span class="lit">1</span><span class="pun">][</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">7</span></pre>

<p>
	حيث يستخرج الفهرس 1 -الفهرس الأول- العنصر الثاني من القائمة الأولى -الذي هو نفسه القائمة الثانية-، ثم يستخرج الفهرس 2 -الفهرس الثاني- العنصر الثالث في القائمة الثانية، وهو العنصر 7.
</p>

<p>
	هذا التداخل وإن بدا معقدًا إلا أنه مفيد للغاية، حيث يسمح ببناء جداول من البيانات بفعالية، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_22" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> row1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> row2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="str">'a'</span><span class="pun">,</span><span class="str">'b'</span><span class="pun">,</span><span class="str">'c'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> table </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">row1</span><span class="pun">,</span><span class="pln"> row2</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> table </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">],</span><span class="pln"> </span><span class="pun">[</span><span class="str">'a'</span><span class="pun">,</span><span class="str">'b'</span><span class="pun">,</span><span class="str">'c'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> element2 </span><span class="pun">=</span><span class="pln"> table</span><span class="pun">[</span><span class="lit">0</span><span class="pun">][</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> element2 </span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	يمكن استخدام هذه الطريقة في إنشاء دفتر عناوين يكون كل مدخل فيه عبارةً عن قائمة من الاسم والعنوان، ويوضح المثال التالي دفتر عناوين فيه مدخلان:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_24" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Samy'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9 Some St'</span><span class="pun">,</span><span class="str">' Anytown'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0123456789'</span><span class="pun">],</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11 Nother St'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SomePlace'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0987654321'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span></pre>

<p>
	لاحظ كيف أنه رغم إدخالنا لأربعة أسطر من النص، إلا أن بايثون تعاملت معها على أنها سطر واحد، كما نستنتج من محثات <code>...</code>، وهذا لأن بايثون ترى أن عدد الأقواس الافتتاحية لا يطابق عدد أقواس الإغلاق، ولهذا تستمر في قراءة المدخلات إلى أن يحدث ذلك التطابق. قد تكون هذه طريقةً فعالةً للغاية في بناء هياكل بيانات معقدة بسرعة مع جعل الهيكل العام -أي قائمة القوائم- واضحًا للقارئ.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		إذا كنت تستخدم أداة IDLE فلن ترى محث <code>...</code>، وإنما مجرد سطر فارغ.
	</p>
</blockquote>

<h4>
	تدريب
</h4>

<p>
	استخرج رقم هاتف سامي -العنصر 3 من الصف الأول-، وتذكر أن الفهارس تبدأ من الصفر وليس الواحد، ثم أضف بعض المدخلات من عندك باستخدام عملية <code>append()‎</code>.
</p>

<p>
	لاحظ أننا نفقد بياناتنا عند الخروج من بايثون، لكن سنرى كيفية الاحتفاظ بها عند شرح الملفات في هذا الكتاب.
</p>

<p>
	يُستخدم الأمر <code>del</code> لحذف العناصر من القائمة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> del aList</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> aList </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">42</span><span class="pun">]</span></pre>

<p>
	لاحظ أن <code>del</code> لا يحتاج إلى أقواس حول القيمة، على عكس دالة الطباعة، لأنه أمر وليس دالةً، قد يكون هذا الفرق طفيفًا، لكن إذا وضعت أقواسًا حول القيمة فلا بأس إذ ستظل صالحةً.
</p>

<p>
	إذا أردنا ضم قائمتين معًا لجعلهما قائمةً واحدةً، فسنتخدم عامل الضم <code>+</code> الذي رأيناه في ضم السلاسل النصية من قبل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_28" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> newList </span><span class="pun">=</span><span class="pln"> aList </span><span class="pun">+</span><span class="pln"> another
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> newList </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">42</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">]</span></pre>

<p>
	لاحظ اختلاف هذا المثال عن سابقه الذي ألحقنا فيها القائمتين معًا، فقد كان لدينا عنصران، وكان العنصر الثاني منهما عبارةً عن قائمة؛ أما هنا فلدينا أربعة عناصر لأن عناصر القائمة الثانية أضيفت عنصرًا عنصرًا إلى <code>newList</code>، فإذا أردنا الوصول إلى العنصر 1 هذه المرة فسنحصل على <code>1</code>، وهو العنصر الثاني هنا، بدلًا من الحصول على قائمة فرعية.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_30" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> newList</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span></pre>

<p>
	يمكن تطبيق إشارة عملية الضرب هنا مثل عامل تكرار لملء القائمة بمضاعفات نفس القيمة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_32" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> zeroList </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[</span><span class="lit">0</span><span class="pun">]</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> zeroList </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">]</span></pre>

<p>
	كما يمكن إيجاد فهرس عنصر ما في قائمة باستخدام العملية <code>index()‎</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_34" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">7</span><span class="pun">].</span><span class="pln">index</span><span class="pun">(</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">2</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">7</span><span class="pun">].</span><span class="pln">index</span><span class="pun">(</span><span class="lit">9</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">most recent call last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;stdin&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> in </span><span class="pun">&lt;</span><span class="pln">module</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">ValueError</span><span class="pun">:</span><span class="pln"> list</span><span class="pun">.</span><span class="pln">index</span><span class="pun">(</span><span class="pln">x</span><span class="pun">):</span><span class="pln"> x not in list</span></pre>

<p>
	لاحظ أن محاولة العثور على فهرس لشيء غير موجود في القائمة ينتج خطأً، فإذا أردنا التحقق من وجود شيء في تجميعة ما فسنستخدم العامل <code>in</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_36" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> in </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">7</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="lit">9</span><span class="pln"> in </span><span class="pun">[</span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">7</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">False</span><span class="pln"> </span></pre>

<p>
	النتائج قيم بوليانية كما نرى، إما True أو False، وسنرى كيف نستخدم تلك النتائج في فصل لاحق.
</p>

<p>
	أخيرًا، يمكن معرفة طول القائمة باستخدام الدالة المضمَّنة <code>len()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_38" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">aList</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">newList</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">4</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> len</span><span class="pun">(</span><span class="pln">zeroList</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">5</span></pre>

<p>
	لا تدعم جافاسكربت ولا VBScript نوع القائمة مباشرةً، وسنرى أن لديهما نوع بيانات يحاكي وظيفة القائمة هنا، وهو نوع المصفوفات arrays.
</p>

<h3>
	الصف Tuple
</h3>

<p>
	توفر بعض لغات البرمجة بنية بيانات اسمها صف tuple، وما هي إلا تجميعة عشوائية من القيم لكنها تعامَل مثل وحدة واحدة، وهي تشبه القوائم في نواحٍ كثيرة، لكن مع فرق أن وحدات tuple غير قابلة للتغيير، مما يعني أننا لا نستطيع التعديل عليها أو إلحاق شيء إليها بعد إنشائها أول مرة، تمثَّل وحدات tuple في بايثون بقائمة من القيم المفصول بينها بفواصل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_40" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> aTuple </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">5</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> aTuple</span><span class="pun">[</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> </span><span class="pun">استخدم</span><span class="pln"> </span><span class="pun">الفهرسة</span><span class="pln"> </span><span class="pun">مثل</span><span class="pln"> </span><span class="pun">القوائم</span><span class="pln">
</span><span class="lit">3</span><span class="pln">
</span><span class="pun">&gt;&gt;</span><span class="pln"> aTuple</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">   </span><span class="pun">#</span><span class="pln"> tuple </span><span class="pun">خطأ،</span><span class="pln"> </span><span class="pun">لا</span><span class="pln"> </span><span class="pun">يمكن</span><span class="pln"> </span><span class="pun">تعديل</span><span class="pln"> 
</span><span class="typ">Traceback</span><span class="pln"> </span><span class="pun">(</span><span class="pln">innermost last</span><span class="pun">):</span><span class="pln">
  </span><span class="typ">File</span><span class="pln"> </span><span class="str">"&lt;pyshell#20&gt;"</span><span class="pun">,</span><span class="pln"> line </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> in </span><span class="pun">?</span><span class="pln">
        aTuple</span><span class="pun">[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">
</span><span class="typ">TypeError</span><span class="pun">:</span><span class="pln"> object doesn</span><span class="str">'t support item assignment</span></pre>

<p>
	من المعتاد إحاطة التسلسل بأقواس، وهذا يضمن عدم إخراج القيم من السياق، إضافةً إلى التذكير المرئي بأنها وحدة واحدة، أي وحدة صف، توضح البيانات التالية هذا الأمر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_42" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> t1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> t2 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">t1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> t2 </span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	يطبَّق الضرب في الحالة الأولى على العنصر الأخير فقط في وحدة Tuple، أما في الحالة الثانية فتضاعَف المجموعة بالكامل، ولتجنب مثل هذا الغموض، سنستخدم الأقواس في كل مرة نصف فيها وحدات tuple.
</p>

<p>
	لعل أحد أهم الأمور التي يجب تذكرها هو أن الأقواس المربعة تستخدم لفهرسة وحدات tuple، بينما تُستخدم الأقواس العادية لتعريفها، ولا يمكن تغييرها بعد إنشائها؛ أما في سوى هذه الأمور فما ينطبق من العمليات على القوائم ينطبق أيضًا على الصفوف، ورغم أننا لا نستطيع تعديل وحدة الصف بعد إنشائها؛ إلا أننا نستطيع إضافة أعضاء جديدة إليها باستخدام عامل الإضافة، فهذا سينشئ صفًا جديدًا، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_45" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> tup1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> tup2 </span><span class="pun">=</span><span class="pln"> tup1 </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="lit">4</span><span class="pun">,)</span><span class="pln"> 
</span><span class="pun">#</span><span class="pln"> </span><span class="pun">وليس</span><span class="pln"> </span><span class="pun">عددًا</span><span class="pln"> </span><span class="pun">صحيحًا</span><span class="pln"> tuple </span><span class="pun">الفاصلة</span><span class="pln"> </span><span class="pun">تجعل</span><span class="pln"> </span><span class="pun">هذا</span><span class="pln"> </span><span class="pun">وحدة</span><span class="pln"> 

</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> tup2 </span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">)</span></pre>

<p>
	إذا لم نستخدم الفاصلة اللاحقة بعد العدد 4 فستفسره بايثون على أنه العدد الصحيح 4 داخل أقواس وليس على أنه صف، لكن سنحصل على خطأ بأي حال بما أنه لا يمكن إضافة أعداد صحيحة إلى الصفوف، لذا سنضيف الفاصلة لنخبر بايثون بأن تعامل الأقواس على أنها صف، فبإضافة الفاصلة الزائدة نقنع بايثون بأن وحدة الصف التي فيها مدخل واحد هي صف فعلًا؛ أما بالنسبة للغتي جافاسكربت وVBScript فليس لديهما أي مفهوم للصف tuple.
</p>

<h3>
	القاموس Dictionary أو Hash
</h3>

<p>
	يحتوي هذا النوع من البيانات على قيمة ترتبط بمفتاح، كما يربط القاموس اللغوي المعنى بكلمة، وقد تكون تلك القيمة سلسلةً نصيةً أو لا، وتُجلب تلك القيمة بفهرسة القاموس بالمفتاح، ولا يلزم أن يكون المفتاح سلسلةً من الأحرف -رغم أنه غالبًا كذلك-، وهذا على خلاف القاموس اللغوي، فقد يكون أي نوع غير قابل للتغير، بما في ذلك الأعداد والصفوف، كما قد تحتوي القيم المرتبطة بالمفاتيح على أي نوع من البيانات.
</p>

<p>
	تُستخدم القواميس داخليًا بواسطة تقنية برمجة متقدمة تسمى بجداول Hash، لهذا يشار أحيانًا إلى القاموس باسم Hash، ونظرًا لأننا نتوصَّل إلى قيم القاموس عبر المفتاح، فلا توضع إلا عناصر ذات مفاتيح فريدة، رغم أن المفتاح قد يشير إلى قائمة من القيم.
</p>

<p>
	تُعَد القواميس مفيدةً للغاية في هيئة هياكل للبيانات، ونجدها في بايثون مثل نوع بيانات مضمَّن في اللغة نفسها، لكن قد نحتاج في بعض اللغات الأخرى إلى استخدام وحدة module، أو بناء واحدة بأنفسنا إذا أردنا استخدام القواميس، وتُستخدم القواميس بعدة طرق سنراها كثيرًا في الأمثلة التالية من الكتاب؛ أما الآن فسنرى أولًا كيف ننشئ قاموسًا في بايثون، ثم نملؤه ببعض المدخلات ونقرؤها.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_47" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> dct </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> dct</span><span class="pun">[</span><span class="str">'boolean'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"A value which is either true or false"</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> dct</span><span class="pun">[</span><span class="str">'integer'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"A whole number"</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> dct</span><span class="pun">[</span><span class="str">'boolean'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
A value which is either </span><span class="kwd">true</span><span class="pln"> or </span><span class="kwd">false</span></pre>

<p>
	لاحظ أننا نبدأ القاموس بأقواس معقوصة ثم نستخدم الأقواس المربعة لإسناد القيم وقراءتها، كما تُستخدم دالة النوع <code>dict()‎</code> لإعادة قاموس فارغ، ويمكن بدء القاموس أثناء إنشائه كما فعلنا في حالة القوائم، باستخدام الصيغة التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_49" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="str">'Samy'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Samy'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9 Some St'</span><span class="pun">,</span><span class="str">' Anytown'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0123456789'</span><span class="pun">],</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="str">'Warda'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11 Nother St'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SomePlace'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0987654321'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span></pre>

<p>
	يُفصل المفتاح والقيمة بنقطتين رأسيتين، وتُفصل الأزواج بفواصل إنجليزية <code>,</code>، كما يمكن تخصيص القاموس باستخدام صيغة مختلفة -انظر أدناه-، ويمكنك اختيار إحدى الطريقتين لاستخدامها.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_51" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> book </span><span class="pun">=</span><span class="pln"> dict</span><span class="pun">(</span><span class="typ">Samy</span><span class="pun">=[</span><span class="str">'Samy'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'9 Some St'</span><span class="pun">,</span><span class="str">' Anytown'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0123456789'</span><span class="pun">],</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">             </span><span class="typ">Warda</span><span class="pun">=[</span><span class="str">'Warda'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11 Nother St'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SomePlace'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0987654321'</span><span class="pun">])</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> book</span><span class="pun">[</span><span class="str">'Samy'</span><span class="pun">][</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">0123456789</span></pre>

<p>
	لاحظ أننا لا نحتاج إلى علامات اقتباس حول المفتاح في التعريف، لأن بايثون تفترض أنها سلسلة نصية، لكننا نحتاج إليها بأي حال من أجل استخراج القيم، وهذا الأسلوب يَحُد من عملية الطريقة الثانية، لهذا يفضِّل المبرمجون استخدام الطريقة الأولى التي يستخدمون الأقواس المعقوصة فيها، وبهذا نكون قد أنشأنا دفتر عناوين من قاموس مفاتيحه هي الأسماء، ويخزن قوائمنا مثل قيم، ونريد أن نستخدم الاسم وحده لجلب كل المعلومات بدلًا من حساب الفهرس العددي، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_53" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> addressBook</span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'11 Nother St'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'SomePlace'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'0987654321'</span><span class="pun">]</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> addressBook</span><span class="pun">[</span><span class="str">'Samy'</span><span class="pun">][</span><span class="lit">3</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">0123456789</span></pre>

<p>
	في الحالة الثانية فهرسنا القيم المعادة من أجل الحصول على رقم هاتف فقط، لكن يمكن جعل هذا أسهل عبر إنشاء بعض المتغيرات وإسناد قيم الفهرسة المناسبة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_55" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> name </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> street </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> town </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> tel </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span></pre>

<p>
	نستطيع الآن استخدام تلك المتغيرات لنعرف اسم مدينة Warda:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_57" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> addressBook</span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">][</span><span class="pln">town</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">SomePlace</span></pre>

<p>
	لاحظ أن town ليست داخل علامات اقتباس لأنها اسم متغير، وستحوله بايثون إلى قيمة الفهرس التي أسندناها -وهي 2-، على عكس <code>'Warda'</code> المحاطة بعلامات اقتباس لأن المفتاح هو سلسلة نصية، وهنا بدأ دفتر العناوين يتحول إلى ما يشبه التطبيق القابل للاستخدام بسبب مزايا القواميس، حيث لن نحتاج إلى كثير من العمل الإضافي لحفظ البيانات واستعادتها وإضافة محث استعلام ليسمح لنا بتحديد البيانات التي نريدها.
</p>

<p>
	يمكن استخدام قاموس لتخزين البيانات، وسيكون دفتر العناوين حينها قاموسًا مفاتيحه الأسماء، وستكون القيم قواميس مفاتيحها هي حقول الأسماء، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_59" style=""><span class="pln">addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="str">'Samy'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln">      </span><span class="str">'Samy'</span><span class="pun">,</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'street'</span><span class="pun">:</span><span class="pln">    </span><span class="str">'9 Some St'</span><span class="pun">,</span><span class="pln">
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'town'</span><span class="pun">:</span><span class="pln">      </span><span class="str">'Anytown'</span><span class="pun">,</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'tel'</span><span class="pun">:</span><span class="pln">       </span><span class="str">'0123456789'</span><span class="pun">},</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="str">'Warda'</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="str">'name'</span><span class="pun">:</span><span class="pln">      </span><span class="str">'Warda'</span><span class="pun">,</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'street'</span><span class="pun">:</span><span class="pln">    </span><span class="str">'11 Nother St'</span><span class="pun">,</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'town'</span><span class="pun">:</span><span class="pln">      </span><span class="str">'SomePlace'</span><span class="pun">,</span><span class="pln"> 
</span><span class="pun">...</span><span class="pln">           </span><span class="str">'tel'</span><span class="pun">:</span><span class="pln">       </span><span class="str">'0987654321'</span><span class="pun">}</span><span class="pln">
</span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	لاحظ أن هذا التنسيق سهل القراءة رغم أنه يحتاج إلى الكثير من الكتابة، ويُشار إلى مثل هذه البيانات التي تخزَّن بتنسيق يجمع بين المعنى والمحتوى في تنسيق مقروء للبشر باسم البيانات الموثقة ذاتيًا.
</p>

<p>
	حين ندخِل هيكل بيانات داخل هيكل آخر مطابق له، كما في حالة إدخال قاموس داخل قاموس آخر هنا، فإنه يُسمى بالتداخل أو التشعب nesting، حيث يكون القاموس الداخلي قاموسًا متشعبًا من الخارجي، ويمكن الوصول إلى تلك البيانات بطريقة تشبه أسلوب القوائم ذات الفهارس المسماة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_61" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> addressBook</span><span class="pun">[</span><span class="str">'Warda'</span><span class="pun">][</span><span class="str">'town'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">SomePlace</span></pre>

<p>
	وليس ثمة اختلاف إلا في الاقتباس الإضافي حول كلمة <code>town</code> التي هي ليست موجودةً في حالة القوائم، وميزة هذا الأسلوب أننا نستطيع إدخال حقول جديدة دون تعطيل الشيفرة الحالية، بينما نضطر في حالة الفهارس المسماة إلى العودة لتغيير جميع قيم الفهارس، وتبرز أهمية هذا الأسلوب عند استخدام نفس البيانات في عدة برامج، فيكون بذل قليل من الجهد هنا موفرًا لكثير من العمل لاحقًا في المستقبل.
</p>

<p>
	لا تدعم القواميس كثيرًا من عوامل التجميعات التي رأيناها من قبل، فلا تدعم عامل الضم ولا التكرار ولا الإلحاق، رغم إمكانية إسناد أزواج من المفاتيح والقيم مباشرةً كما رأينا في بداية هذا القسم.
</p>

<p>
	وتُستخدم العملية <code>keys()‎</code> لتسهيل الوصول إلى مفاتيح القاموس، إذ تسمح لنا بالحصول على قائمة من جميع المفاتيح الموجودة في قاموس ما، فإذا أردنا الحصول على كل الأسماء الموجودة في دفتر العناوين الذي أنشأناه من قبل؛ فسيكون ذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_63" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> list</span><span class="pun">(</span><span class="pln">addressBook</span><span class="pun">.</span><span class="pln">keys</span><span class="pun">())</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="str">'Samy'</span><span class="pun">,</span><span class="str">'Warda'</span><span class="pun">]</span></pre>

<p>
	لاحظ أننا استخدمنا <code>list()‎</code> للحصول على قيم المفاتيح الحقيقية، أما إذا حذفنا <code>list()‎</code> فسنحصل على نتيجة غريبة بعض الشيء لن نذكرها الآن.
</p>

<p>
	لاحظ أن القواميس لا تخزِّن مفاتيحها بنفس ترتيب إدخالها، فقد نرى أن المفاتيح تظهر بترتيب غريب عن ترتيبها الأول، بل قد يتغير الترتيب بتغير الوقت، لكن هذا لا يهم بما أننا نستطيع استخدام المفاتيح للوصول إلى البيانات المرتبطة بها، إذ سنحصل على القيم الصحيحة في كل مرة.
</p>

<p>
	يمكن الحصول على قائمة بجميع القيم أيضًا باستخدام العملية <code>values()‎</code>، فجرب ذلك على دفتر العناوين وانظر إن استطعت تنفيذها بنجاح، استخدم مثال <code>keys()‎</code> السابق للاسترشاد به، ويمكن بصورة مماثلة استخدام العامل <code>in</code> على القاموس ليخبرنا هل توجد قيمة ما في صورة مفتاح للقاموس أم لا.
</p>

<h3>
	قواميس VBScript
</h3>

<p>
	توفر VBScript كائن قاموس يقدم تسهيلات تماثل قاموس بايثون، لكن استخدامه مختلف قليلًا عن حالة بايثون، حيث ننشئ القاموس هنا بالتصريح عن متغير يحمل الكائن، ثم ننشئ ذلك الكائن، وبعد ذلك نضيف المدخلات إلى القاموس الجديد كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_65" style=""><span class="typ">Dim</span><span class="pln"> dict     </span><span class="str">'</span><span class="pln"> </span><span class="typ">Create</span><span class="pln"> a variable</span><span class="pun">.</span><span class="pln">
</span><span class="typ">Set</span><span class="pln"> dict </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateObject</span><span class="pun">(</span><span class="str">"Scripting.Dictionary"</span><span class="pun">)</span><span class="pln">
dict</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"a"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Athens"</span><span class="pln"> </span><span class="str">'</span><span class="pln"> </span><span class="typ">Add</span><span class="pln"> some keys and items</span><span class="pun">.</span><span class="pln">
dict</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"b"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Belgrade"</span><span class="pln">
dict</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"c"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Cairo"</span></pre>

<p>
	لاحظ أن دالة <code>CreateObject</code> توضح أننا ننشئ كائن <code>"Scripting.Dictionary"</code>، وهو كائن <code>Dictionary</code> من وحدة <code>Scripting</code> الخاصة بلغة VBScript، وسندرس ذلك بالتفصيل حين نأتي على الكائنات، لكننا نأمل بذكرها هنا أن تتذكر مفهوم استخدام كائن من وحدة ما كما ذكرنا في فصل التسلسلات البسيطة.
</p>

<p>
	يجب كذلك استخدام كلمة <code>Set</code> المفتاحية عند إسناد كائن إلى متغير في VBScript. نستطيع الآن أن نصل إلى البيانات كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_67" style=""><span class="pln">item </span><span class="pun">=</span><span class="pln"> dict</span><span class="pun">.</span><span class="typ">Item</span><span class="pun">(</span><span class="str">"c"</span><span class="pun">)</span><span class="pln"> </span><span class="str">'</span><span class="pln"> </span><span class="typ">Get</span><span class="pln"> the item</span><span class="pun">.</span><span class="pln">
dict</span><span class="pun">.</span><span class="typ">Item</span><span class="pun">(</span><span class="str">"c"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Casablanca"</span><span class="pln"> </span><span class="str">' Change the item</span></pre>

<p>
	توجد عمليات أخرى لإزالة عنصر ما، والتحقق من وجود مفتاح ما، والحصول على قائمة بجميع المفاتيح وغير ذلك. كما يمكن تخزين أي نوع من الكائنات في القاموس إذ أن الأمر ليس مقصورًا على السلاسل النصية فقط، وهذا يعني أننا نستطيع إنشاء قواميس متشعبة بما أن القاموس نفسه ما هو إلا كائن.
</p>

<p>
	فيما يلي نسخة كاملة مبسطة عن مثال دفتر العناوين السابق، ولكن في VBScript:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_69" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/VBScript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> addressBook
</span><span class="typ">Set</span><span class="pln"> addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateObject</span><span class="pun">(</span><span class="str">"Scripting.Dictionary"</span><span class="pun">)</span><span class="pln">
addressBook</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"Samy"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Samy, 9 Some St, Anytown, 0123456789"</span><span class="pln">
addressBook</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"Warda"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Warda, 11 Nother St, SomePlace, 0987654321"</span><span class="pln">

</span><span class="typ">MsgBox</span><span class="pln"> addressBook</span><span class="pun">.</span><span class="typ">Item</span><span class="pun">(</span><span class="str">"Warda"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	ما فعلناه هنا هو تخزين جميع البيانات مثل سلسلة نصية واحدة بدلًا من استخدام قائمة -وهذا يصعّب استخراج الحقول المنفردة على عكس القائمة والقاموس-، ثم نستطيع الوصول إلى تفاصيل <code>Warda</code> ونطبعها في صندوق رسالة.
</p>

<h3>
	قواميس جافاسكربت
</h3>

<p>
	لا تحتوي جافاسكربت على كائن قاموس فيها، رغم أننا نستطيع الوصول إلى كائن <code>Scripting.Dictionary</code> الذي ذكرناه في VBScript باستخدام إنترنت إكسبلورر، لنتمكن حينئذ من استغلال جميع مزاياه، لكن لن نشرح ذلك هنا مرةً أخرى بما أنه نفس الكائن.
</p>

<p>
	تستطيع هنا الانتقال إلى الفصل التالي إذا كنت قد شعرت بالملل من طول هذا الفصل وتريد كتابة شيفرات وتجربتها، لكن تذكر أن تعود وتنهي هذا الفصل حين تتعرض لأنواع بيانات لم نذكرها حتى الآن.
</p>

<h3>
	المصفوفات أو المتجهات Arrays
</h3>

<p>
	المصفوفة هي أحد أنواع التجميعات التي يمتد تاريخها موازيًا لتاريخ الحوسبة، وما هي إلا مجموعة من العناصر المفهرسة بحيث يسهل جلبها بسرعة، والغالب أننا يجب أن نحدد عدد العناصر التي نريد تخزينها في المصفوفة مسبقًا، إذ يُخزَّن نوع واحد أيضًا من البيانات في المصفوفة عادةً، وهاتان الخاصيتان للمصفوفة هما اللتان تميزانها عن القوائم مثلًا. لاحظ أننا قد قلنا "عادة"، و"الغالب" للدلالة على غالب الحالات، ذلك أن لغات البرمجة المختلفة لها أساليبها الخاصة التي تصف المصفوفات، لذا يصعب وضع وصف يغطي جميع الحالات.
</p>

<p>
	تدعم لغة بايثون المصفوفات من خلال وحدة تسمى <code>array</code>، لكننا لا نحتاج إليها إلا نادرًا مع استثناء حالات الحساب الرياضي عالي الأداء؛ أما غير ذلك فنستخدم القوائم، وفي لغتي جافاسكربت وVBScript؛ تتكون المصفوفات مثل نوع بيانات، لذا سننظر في كيفية استخدامها فيهما.
</p>

<h3>
	مصفوفات VBScript
</h3>

<p>
	تكون المصفوفة في VBScript تجميعة بيانات ذات طول ثابت، حيث يمكن التوصَل إليها بواسطة فهرس عددي، ويصرَّح عنها ويوصَل إليها كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_71" style=""><span class="typ">Dim</span><span class="pln"> </span><span class="typ">AnArray</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln">    </span><span class="str">'</span><span class="pln"> A </span><span class="lit">43</span><span class="pun">!</span><span class="pln"> element array
</span><span class="typ">AnArray</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">27</span><span class="pln">    </span><span class="str">'</span><span class="pln"> index starts at </span><span class="lit">0</span><span class="pln">
</span><span class="typ">AnArray</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">49</span><span class="pln">
</span><span class="typ">AnArray</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">66</span><span class="pln">   </span><span class="str">'</span><span class="pln"> assign to last element
myVariable </span><span class="pun">=</span><span class="pln"> </span><span class="typ">AnArray</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln">  </span><span class="str">' read the value</span></pre>

<p>
	تُستخدم الكلمة المفتاحية <code>Dim</code> لتحديد أبعاد المتغير، وهي الطريقة التي نخبر بها VBScript عن المتغير، فهي تتوقع إذا بدأنا الشيفرة بـ <code>OPTION EXPLICIT</code>؛ أن نحدد أبعاد أي متغير نستخدمه من خلال <code>Dim</code>، وهذا سلوك محمود يؤدي إلى برامج ثابتة قوية الأداء، كما أننا حددنا آخر فهرس صالح <code>42</code>، وهذا يعني أن المصفوفة فيها 43 عنصرًا بما أنها تبدأ من الصفر.
</p>

<p>
	تُستخدم الأقواس في VBScript لحساب أبعاد المصفوفة وفهرستها، وهذا على خلاف الأقواس المربعة المستخدمة في بايثون وجافاسكربت، حيث لا يوجد في VBScript نوع بيانات إلا النوع <code>Variant</code>، والذي يخزِّن أي نوع من أنواع القيم، وبناءً عليه فلا تخزِّن المصفوفات في هذه اللغة إلا المتغيرات بما أن عناصر المصفوفة تكون من نوع واحد، لكن في نفس الوقت، فإن المتغير هنا قد يحمل أي نوع من أنواع القيم، مما يعني مرةً أخرى أن المصفوفات في VBScript تخزن أي شيء، وهذا أمر مربك عند التفكير فيه.
</p>

<p>
	نستطيع أيضًا الإسناد إلى أي موضع في المصفوفة بما في ذلك الموضع الأخير، من غير أن نملأ المواضع التي قبله، وسيُضبط أي عنصر غير مهيأ إلى القيمة الخاصة <code>Null</code>.
</p>

<p>
	كما يمكن التصريح عن عدة مصفوفات متعددة الأبعاد لنمذجة جداول بيانات كما في قوائم بايثون إذا استخدمنا تدريب دفتر العناوين مثلًا.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_73" style=""><span class="typ">Dim</span><span class="pln"> </span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">)</span><span class="pln">  </span><span class="str">'</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> rows</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> columns
</span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Samy"</span><span class="pln">  </span><span class="str">' Populate Samy'</span><span class="pln">s entry
</span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"9 Some Street"</span><span class="pln">
</span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Anytown"</span><span class="pln">
</span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"0123456789"</span><span class="pln">
</span><span class="typ">MyTable</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Warda"</span><span class="pln">  </span><span class="str">'</span><span class="pln"> </span><span class="typ">And</span><span class="pln"> now </span><span class="typ">Warda</span><span class="pun">...</span><span class="pln">
</span><span class="pun">...</span><span class="pln">and so on</span><span class="pun">...</span></pre>

<p>
	لكن لا توجد طريقة سهلة لملء البيانات دفعةً واحدةً كما فعلنا في قوائم بايثون، بل يجب أن نملأ كل حقل على حدة، وعلى الرغم من وجود الدالة <code>Array</code>في VBScript والتي تستطيع ملء مصفوفة دفعةً واحدةً -مما يعني الحاجة إلى جعلها متشعبةً-؛ فستصبح معقدةً وصعبة القراءة.
</p>

<p>
	إذا دمجنا قواميس VBScript مع هذه الخاصية لمصفوفاتها، فسنحصل على نفس النتيجة التي حصلنا عليها في بايثون، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_1114_75" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/VBScript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> addressBook
</span><span class="typ">Set</span><span class="pln"> addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateObject</span><span class="pun">(</span><span class="str">"Scripting.Dictionary"</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> </span><span class="typ">Samy</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Samy</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Samy"</span><span class="pln">
</span><span class="typ">Samy</span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"9 Some St"</span><span class="pln">
</span><span class="typ">Samy</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Anytown"</span><span class="pln">
</span><span class="typ">Samy</span><span class="pun">(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"0123456789"</span><span class="pln">
addressBook</span><span class="pun">.</span><span class="typ">Add</span><span class="pln"> </span><span class="str">"Samy"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Samy</span><span class="pln">

</span><span class="typ">MsgBox</span><span class="pln"> addressBook</span><span class="pun">.</span><span class="typ">Item</span><span class="pun">(</span><span class="str">"Samy"</span><span class="pun">)(</span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="str">' Print the Phone Number
&lt;/script&gt;</span></pre>

<p>
	وآخر ملاحظة متعلق بمصفوفات VBScript هو أنها لا تحتاج إلى أن تكون ثابتة الحجم، على أن هذا لا يعني استمرار إضافة العناصر إليها كما في القوائم، بل يجب أن نغير حجم المصفوفة صراحةً، بالتصريح عن مصفوفة ديناميكية، وذلك بإهمال ذكر الحجم ببساطة، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_77" style=""><span class="typ">Dim</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">()</span><span class="pln">  </span><span class="str">' no size specified</span></pre>

<p>
	ثم إذا أردنا تغيير حجمها نفعل ذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_79" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">()</span><span class="pln">
</span><span class="typ">ReDim</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">5</span><span class="pun">)</span><span class="pln">  </span><span class="str">'</span><span class="pln"> </span><span class="typ">Initial</span><span class="pln"> size </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln">
</span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">26</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"Before: "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln">  </span><span class="str">'</span><span class="pln"> prove that it worked
</span><span class="str">'</span><span class="pln"> </span><span class="typ">Resize</span><span class="pln"> to </span><span class="lit">21</span><span class="pln"> elements keeping the data we already stored
</span><span class="typ">ReDim</span><span class="pln"> </span><span class="typ">Preserve</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">20</span><span class="pun">)</span><span class="pln">
</span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">73</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"After Preserve: "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">15</span><span class="pun">)</span><span class="str">'</span><span class="pln"> </span><span class="typ">Old</span><span class="pln"> and </span><span class="kwd">new</span><span class="pln"> still there
</span><span class="str">'</span><span class="pln"> </span><span class="typ">Resize</span><span class="pln"> to </span><span class="lit">51</span><span class="pln"> items but lose all data
</span><span class="typ">Redim</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">50</span><span class="pun">)</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"Without Preserve: "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">DynArray</span><span class="pun">(</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" Oops, Where did it go?"</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	لاحظ أن السلوك الافتراضي هو حذف كل محتويات المصفوفة عند تغيير حجمها، فإذا أردنا الحفاظ على محتوياتها؛ فيجب أن نخبر VBScript أن تحفظ المحتويات باستخدام <code>Preserve</code>.
</p>

<p>
	هذا الأسلوب غير مريح موازنةً بالقوائم التي تغير حجمها تلقائيًا، لكنه يعطي المبرمج تحكمًا أفضل في كيفية تصرف البرنامج، مما يحسن الأمان -ضمن أمور أخرى- نظرًا لأن بعض الفيروسات قد تستغل مخازن البيانات القابلة لتغيير حجمها ديناميكيًا.
</p>

<h3>
	مصفوفات جافاسكربت
</h3>

<p>
	رغم أنه يطلَق على هذا النوع من البيانات في جافاسكربت مصفوفة؛ إلا أنها تسمية خاطئة، فهو مزيج غريب يجمع بين مزايا القوائم والقواميس والمصفوفات العادية، حيث نستطيع مثلًا التصريح عن مصفوفة من عشرة عناصر من نوع ما كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_81" style=""><span class="kwd">var</span><span class="pln"> items </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span></pre>

<p>
	لاحظ استخدام كلمة <code>new</code> المفتاحية، إذ تشبه دالة <code>CreateObject()‎</code> التي استخدمناها في VBScript لإنشاء قاموس، كذلك فقد استخدمنا الأقواس لتحديد حجم المصفوفة، نستطيع الآن أن نملأ المصفوفة ونصل إليها كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_1114_83" style=""><span class="pln">items</span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
items</span><span class="pun">[</span><span class="lit">7</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">21</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> aValue </span><span class="pun">=</span><span class="pln"> items</span><span class="pun">[</span><span class="lit">4</span><span class="pun">];</span></pre>

<p>
	وهنا نستخدم الأقواس المربعة للوصول إلى عناصر المصفوفة، وتبدأ الفهارس فيها من الصفر، لكن رغم هذا كله فمصفوفات جافاسكربت ليست مقيدة بتخزين نوع واحد من البيانات، بل يمكن إسناد أي شيء إلى عناصرها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_85" style=""><span class="pln">items</span><span class="pun">[</span><span class="lit">9</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"A short string"</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> msg </span><span class="pun">=</span><span class="pln"> items</span><span class="pun">[</span><span class="lit">9</span><span class="pun">];</span></pre>

<p>
	كما يمكن إنشاء مصفوفات من خلال توفير قائمة بالعناصر:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_87" style=""><span class="kwd">var</span><span class="pln"> moreItems </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="str">"one"</span><span class="pun">,</span><span class="str">"two"</span><span class="pun">,</span><span class="str">"three"</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">,</span><span class="lit">6</span><span class="pun">);</span><span class="pln">
aValue </span><span class="pun">=</span><span class="pln"> moreItems</span><span class="pun">[</span><span class="lit">3</span><span class="pun">];</span><span class="pln">  </span><span class="com">// -&gt; 4</span><span class="pln">
msg </span><span class="pun">=</span><span class="pln"> moreItems</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">   </span><span class="com">// -&gt; "one"</span></pre>

<p>
	كذلك يمكن تحديد طول المصفوفة باستخدام خاصية تدعى <code>length</code>، التي تستخدَم كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_92" style=""><span class="kwd">var</span><span class="pln"> size </span><span class="pun">=</span><span class="pln"> items</span><span class="pun">.</span><span class="pln">length</span><span class="pun">;</span></pre>

<p>
	وعلى غرار أسلوب بايثون في استدعاء الدوال في وحداتها، فإن الصياغة <code>name.property</code> هنا هي نفسها، لكن دون أقواس لاحقة.
</p>

<p>
	ورغم أن مصفوفات جافاسكربت تبدأ بالصفر كما ذكرنا؛ إلا أن فهارسها ليست مقصورةً على الأرقام وحدها، ولهذا يمكن استخدام السلاسل النصية أيضًا -والتي تكون هنا أشبه بالقواميس-، كما يمكن توسيع مصفوفة بإسناد قيمة إلى فهرس تكون أكثر من الحد الأقصى الحالي، مما يعني أننا لا نحتاج إلى تحديد الحجم عند إنشاء المصفوفة، رغم كون ذلك سلوكًا مستحسنًا في البرمجة، ويوضح المثال التالي خصائص مصفوفات جافاسكربت التي ذكرناها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_94" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> items </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="lit">10</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> moreItems </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> 
items</span><span class="pun">[</span><span class="lit">42</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
moreItems</span><span class="pun">[</span><span class="str">"foo"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
msg </span><span class="pun">=</span><span class="pln"> moreItems</span><span class="pun">[</span><span class="str">"foo"</span><span class="pun">];</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"msg = "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> msg </span><span class="pun">+</span><span class="pln"> </span><span class="str">" and items[42] = "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> items</span><span class="pun">[</span><span class="lit">42</span><span class="pun">]</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	إذا شغّلنا تلك الشيفرة في المتصفح فسنرى القيم مكتوبةً على الشاشة. تحقق إن كنت تستطيع متابعة الإسنادات في الشيفرة لتتأكد من سبب ظهور القيم التي تراها على الشاشة.
</p>

<p>
	لننظر أخيرًا في مثال دفتر العناوين مرةً أخرى، باستخدام مصفوفات جافاسكربت هذه المرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_96" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> addressBook </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">();</span><span class="pln">
addressBook</span><span class="pun">[</span><span class="str">"Samy"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="str">"Samy"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"9 Some St"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Anytown"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0123456789"</span><span class="pun">);</span><span class="pln">
addressBook</span><span class="pun">[</span><span class="str">"Warda"</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Array</span><span class="pun">(</span><span class="str">"Warda"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"11 Nother St"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"SomePlace"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"0987654321"</span><span class="pun">);</span><span class="pln">

document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">addressBook</span><span class="pun">.</span><span class="typ">Warda</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	يمكن الوصول إلى المفتاح كما لو كان خاصيةً مثل <code>length</code>، ويتبين مما سبق أن مصفوفات جافاسكربت ما هي إلا هياكل بيانات مرنة للغاية.
</p>

<h3>
	المكدس Stack
</h3>

<p>
	يكدِّس العاملون في المطاعم الأطباق النظيفة فوق بعضها، ثم تؤخَذ واحدًا تلو الآخرللعملاء بدءًا من الأعلى، فيكون الطبق الأخير هو آخر طبق يُستخدم، وفي نفس الوقت أقل طبق يُستخدم، يشبه هذا المثال مكدسات البيانات بالضبط، إذ نضع العنصر في قمة المكدس أو نأخذ عنصرًا منه، ويكون العنصر المأخوذ هو آخر عنصر مضاف إلى المكدس، ويطلَق على هذه الخاصية للمكدسات "آخرها دخولًا أولها خروجًا" أو LIFO - Last In First Out. من الخصائص المفيدة في المكدسات أننا نستطيع عكس قائمة العناصر عن طريق دفع القائمة في المكدس ثم إخراجها مرةً أخرى، فتكون النتيجة عكس القائمة الأولى.
</p>

<p>
	لا تأتي المكدسات مدمجةً في بايثون ولا VBScript ولا جافاسكربت، بل يجب كتابة بعض التعليمات البرمجية في البرنامج من أجل الحصول على سلوك المكدس، والقوائم هي أفضل نقطة بداية في الغالب للمكدسات بما أنه يمكن زيادة حجمها عند الحاجة.
</p>

<h4>
	تدريب
</h4>

<p>
	اكتب مكدسًا باستخدام قائمة في بايثون، وتذكر أننا نلحق العناصر في نهاية القائمة باستخدام <code>append()‎</code>، ونحذفها باستخدام فهارسها عن طريق <code>del()‎</code>، كما تستطيع استخدام <code>‎-1</code> مثل فهرس يشير إلى آخر عنصر في القائمة.
</p>

<p>
	يجب أن تكون قادرًا على كتابة برنامج -مستفيدًا من هذه الإرشادات- يدفع 4 محارف إلى قائمة ثم يخرجها مرةً أخرى، ثم اطبعها بعد ذلك. راقب الترتيب الذي تستدعي به <code>print</code> و <code>del</code>، وإذا نجحت في هذا، فجرب طباعتها بعكس الترتيب الذي أدخلتها به، استخدم العملية <code>pop()‎</code> الخاصة بقوائم بايثون والتي تعيد العنصر الأخير وتحذفه في خطوة واحدة، من أجل تسهيل التدريب.
</p>

<h3>
	الحقيبة Bag
</h3>

<p>
	في سياق الحديث عن البيانات؛ تُعَد الحقيبة تجميعةً من العناصر التي ليس لها ترتيب محدد، ويمكن أن تحتوي على عناصر مكررة، وتكون لها عادةً عوامل تمكننا من إضافة تلك العناصر وحذفها وإيجادها، فما هي إلا قوائم في اللغات الثلاث التي نستخدمها في الكتاب.
</p>

<h3>
	المجموعات Sets
</h3>

<p>
	تخزن المجموعة نوعًا واحدًا من العناصر، ونستطيع التحقق مما إذا كان العنصر موجودًا في المجموعة أم لا -أي عضوًا فيها-، إلى جانب إضافة تلك العناصر وحذفها، بالإضافة إلى دمج مجموعتين معًا بطرق شتى تتوافق مع نظرية المجموعات في الرياضيات، مثل الاتحاد والتقاطع وغيرها، لكن على هذا فالمجموعات لا تكون مرتبةً ولا تهتم للترتيب.
</p>

<p>
	لا تستخدم جافاسكربت ولا VBScript المجموعات مباشرةً، لكن يمكن تنفيذ سلوك قريب باستخدام القواميس التي لا تحتوي إلا على مفاتيح بقيم فارغة؛ أما بايثون فتدعم المجموعات مثل نوع من أنواع البيانات فيها، وأحد الاستخدامات البسيطة لها ما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_98" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> A </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">set</span><span class="pun">()</span><span class="pln">  </span><span class="pun">#</span><span class="pln"> </span><span class="pun">أنشئ</span><span class="pln"> </span><span class="pun">مجموعة</span><span class="pln"> </span><span class="pun">فارغة</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> B </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">set</span><span class="pun">([</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">])</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> </span><span class="pun">مجموعة</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">قائمة</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> C </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">,</span><span class="lit">5</span><span class="pun">}</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> </span><span class="pun">تهيئة</span><span class="pln"> </span><span class="pun">مثل</span><span class="pln"> </span><span class="pun">[]</span><span class="pln"> </span><span class="pun">في</span><span class="pln"> </span><span class="pun">القوائم</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> D </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">6</span><span class="pun">,</span><span class="lit">7</span><span class="pun">,</span><span class="lit">8</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> </span><span class="pun">جرب</span><span class="pln"> </span><span class="pun">الآن</span><span class="pln"> </span><span class="pun">بعض</span><span class="pln"> </span><span class="pun">عمليات</span><span class="pln"> </span><span class="pun">القوائم</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> B</span><span class="pun">.</span><span class="kwd">union</span><span class="pun">(</span><span class="pln">C</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> B</span><span class="pun">.</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">C</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="lit">3</span><span class="pun">}</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> B</span><span class="pun">.</span><span class="pln">issuperset</span><span class="pun">({</span><span class="lit">2</span><span class="pun">})</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">}.</span><span class="pln">issubset</span><span class="pun">(</span><span class="pln">C</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">True</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> C</span><span class="pun">.</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">D</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> A </span><span class="pun">)</span><span class="pln">
</span><span class="typ">True</span></pre>

<p>
	لاحظ أننا نستطيع تهيئة المجموعة باستخدام الأقواس المعقوصة، لكن هذا قد يتشابه مع القواميس، لذا نفضل استخدام الصيغة <code>set([...]])‎</code> رغم أنها تتطلب كتابةً أكثر، فيما يلي اختصارات لعمليات الاتحاد والتقاطع:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_100" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> B </span><span class="pun">&amp;</span><span class="pln"> C </span><span class="pun">)</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> B</span><span class="pun">.</span><span class="pln">intersection</span><span class="pun">(</span><span class="pln">C</span><span class="pun">)</span><span class="pln"> </span><span class="pun">كما</span><span class="pln"> </span><span class="pun">في</span><span class="pln">  
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> B </span><span class="pun">|</span><span class="pln"> C </span><span class="pun">)</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> B</span><span class="pun">.</span><span class="kwd">union</span><span class="pun">(</span><span class="pln">C</span><span class="pun">)</span><span class="pln"> </span><span class="pun">كما</span><span class="pln"> </span><span class="pun">في</span><span class="pln"> </span></pre>

<p>
	نستطيع أخيرًا التحقق من وجود عنصر ما في مجموعة باستخدام العامل <code>in</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_1114_102" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> in B </span><span class="pun">)</span><span class="pln">
</span><span class="typ">True</span></pre>

<p>
	هذه العمليات كافية إلى الآن لما نشرحه، رغم وجود عمليات أخرى على المجموعات.
</p>

<h3>
	الطابور Queue
</h3>

<p>
	يشبه الطابور أو قائمة الانتظار؛ المكدس، باستثناء أن العنصر الأول فيه الذي يخرج أولًا أيضًا، ويسمى هذا السلوك "الأول دخولًا الأول خروجًا" أو FIFO - First In First Out، ويُنشَأ الطابور باستخدام قائمة أو مصفوفة.
</p>

<h4>
	تدريب
</h4>

<p>
	جرب كتابة طابور باستخدام قائمة، وتذكر أنك تستطيع الإضافة إلى القائمة باستخدام <code>append()‎</code>، وأن تحذف من موضع ما باستخدام <code>del()‎</code>. أضف أربعة محارف إلى الطابور ثم استخرجها واطبعها، غذ يجب أن تُطبع المحارف بنفس الترتيب الذي دخلت به.
</p>

<p>
	توجد أنواع أخرى من تجميعات البيانات، لكن ما ذكرناه هنا يغطي أغلب الحالات التي ستراها أثناء البرمجة، بل لن نستخدم إلا قليلًا مما ذكرناه هنا في الشرح، لكن قد ترى بقية الأنواع في المقالات أو مجموعات النقاشات البرمجية.
</p>

<h2>
	الملفات Files
</h2>

<p>
	ينبغي أن يكون مستخدم الحاسوب معتادًا على التعامل مع الملفات بما أنها تمثل أساس كل شيء نفعله على الحواسيب، ولا غرو إذًا أن نكتشف أن أغلب لغات البرمجة توفر نوع file خاص من البيانات، لكن أهمية الملفات ومعالجتها ستجعلنا نرجئ الحديث عنها وشرحها إلى فصل لاحق خاص بها.
</p>

<p>
	وبهذا تكون قد تعرفت على أبرز البيانات البرمجية التي قد تحتاج إليها.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutdata.htm" rel="external nofollow">للفصل الخامس: The Raw Materials من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B9%D8%B6-%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D9%86%D8%B5%D9%8A%D8%A9-%D8%A7%D9%84%D9%85%D9%87%D9%85%D8%A9-%D9%84%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1289/" rel="">بعض التسلسلات النصية المهمة لتعلم البرمجة</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-r1287/" rel="">مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/html/html5/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-microdata-%D9%81%D9%8A-html5-r375/" rel="">مدخل إلى البيانات الوصفية microdata في HTML5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D9%87%D9%8A%D8%A7%D9%83%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1234/" rel="">هياكل البيانات: الكائنات والمصفوفات في جافاسكريبت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1288</guid><pubDate>Sat, 14 Aug 2021 15:00:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x648;&#x623;&#x646;&#x648;&#x627;&#x639;&#x647;&#x627;: &#x623;&#x646;&#x648;&#x627;&#x639; &#x627;&#x644;&#x628;&#x64A;&#x627;&#x646;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x633;&#x627;&#x633;&#x64A;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-r1287/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_08/610e3684f2e29_--.png.78a3b4b7142c6fba23e8e21bc3e09f03.png" /></p>
<h1>
	مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية
</h1>

<p>
	يحتاج أي عمل إبداعي إلى ثلاثة مكونات أساسية هي: الأدوات التي يُنجَز بها، والخامات التي يتكون منها، والأساليب والتقنيات التي تُستغل الأدوات والخامات بها لإنجاز ذلك العمل، فأدوات الرسم مثلًا هي الفرش والأقلام ولوحات الرسم، كما أن من أساليب الرسم الخلط والرش وغيرها، ثم تأتي الخامات التي هي الدهانات والأوراق والماء ونحو ذلك. وبصورة مماثلة نجد أن أدوات البرمجة هي لغات البرمجة ونظم التشغيل وعتاد الحواسيب التي ستعمل عليها البرامج؛ أما الأساليب والتقنيات فهي هياكل البرامج التي تحدثنا عنها في المقال السابق، والخامات هي البيانات التي نعدل فيها ونعالجها، وهي ما سننظر فيه في هذا المقال.
</p>

<p>
	هذا المقال طويل بسبب طبيعة البيانات نفسها، لكننا كتبناه بحيث لا تجب قراءته كله من أجل إدراك الفهم الكامل للبياناتوتستطيع البدء فيه من البداية التي نمر فيها على الأنواع البسيطة للبيانات.
</p>

<h2>
	البيانات Data
</h2>

<p>
	من المعلوم بالمشاهدة في عالم البرمجة أن البيانات هي أكثر المصطلحات المستخدمة حاليًا، رغم قلة من يفهمها على حقيقتها، وما يهمنا في هذه السلسلة في موضوع تعريف البيانات نفسها؛ هو أن تعلم أنها الحقائق أو الأرقام التي يمكن استخلاص النتائج والمعلومات المفيدة منها، ورغم أن هذا يكاد يكون تسطيحًا لمفهومها، إلا أنه يعطينا نقطةً نبدأ منها على الأقل، وسنرى فيما يلي إن كنا نستطيع توضيح ذلك بالنظر في كيفية استخدام البيانات في البرمجة.
</p>

<p>
	البيانات هي تلك المعلومات الخام التي يعدّل فيها البرنامج ويغيرها، فلا تستطيع البرامج تنفيذ أي وظيفة ولا مهمة ذات قيمة بغير تلك البيانات، وتتوقف أنواع التعديلات التي تجريها البرامج على البيانات على تلك الأنواع نفسها، فكل نوع له عدد من العمليات التي يمكن إجراؤها عليه، فقد رأينا مثلًا أننا نستطيع جمع الأعداد معًا، إذ تحدث عملية الجمع على النوع العددي من البيانات، مما يعني أن البيانات تأتي في عدة صور وأشكال، وسننظر في كل نوع من أشهر تلك الأنواع، إضافةً إلى العمليات المتاحة على ذلك النوع.
</p>

<h2>
	المتغيرات Variables
</h2>

<p>
	تخزَّن البيانات في ذاكرة الحواسيب، ويمكن تشبيه تلك الذاكرة بذاكرة مكاتب البريد القديمة، إذ توضع صناديق صغيرة على حوائط تلك المكاتب لتصنيف الرسائل البريدية، ويجب كتابة الوجهة التي تُرسَل إليها رسائل كل صندوق على الصندوق نفسه، إذ لا قيمة للرسائل من دون وجهة تُرسل إليها، وهنا نُسقط مثالنا على البرمجة، إذ إن المتغيرات هي العناوين التي تكتَب على الصناديق داخل ذاكرة الحاسوب.
</p>

<p>
	بهذا نكون قد عرفنا نوع البيانات الآن، لكننا لا نستطيع تعديلها قبل أن تكون لنا صلاحية الوصول إليها، وهذه هي وظيفة المتغيرات، فنحن ننشئ نسخًا من <a href="https://academy.hsoub.com/programming/general/%D8%AF%D9%84%D9%8A%D9%84%D9%83-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-r1726/" rel="">أنواع البيانات</a> ونسندها إلى المتغيرات، والنسخة instance هي مجرد جزء من البيانات وليكن 3 أو 5 مثلًا، وهي نُسخ لأعداد؛ أما المتغير فهو إشارة إلى منطقة محددة في ذاكرة الحاسوب تحتوي على البيانات.
</p>

<p>
	قد تتطلب بعض<a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel=""> لغات البرمجة</a> أن يُصرَّح عن المتغير declared ليطابق نوع البيانات التي يشير إليها، فإذا حاولنا إسناد نوع خاطئ من البيانات إليه، فسنحصل على خطأ، ويفضل بعض المبرمجين ذلك النوع المسمى بالكتابة الثابتة static typing، لأنه يحول دون ارتكاب الزلات البرمجية bugs الدقيقة التي يصعب اكتشافها، على أن جميع اللغات التي نستخدمها هنا مرنة إلى الحد الذي نستطيع معه إسناد أي نوع من البيانات إلى المتغيرات، وهو ما يُعرف بالكتابة الديناميكية dynamic typing.
</p>

<p>
	تتبع أسماء المتغيرات قواعدًا محددةً تختلف باختلاف لغة البرمجة التي تستخدمها، فلكل لغة قواعدها للأحرف التي يُسمح أو لا يُسمح بها، كما تشترط بعض اللغات مثل جافاسكربت وبايثون أن ينتبه المبرمج إلى حالة الأحرف التي يكتبها، بحيث تختلف <code>python</code> عن <code>Python</code> مثلًا، كما توجد لغات أخرى مثل VBScript لا تهتم لهذا، لكن يفضل أن يُتبَّع أسلوب ثابت في تسمية المتغيرات لتجنب الأخطاء الشائعة عند الانتقال من لغة لأخرى، ومن الأساليب المستخدمة في تسمية المتغيرات هو بدء اسم المتغير بحرف صغير، ثم استخدام حرف كبير لبداية كل كلمة تالية في اسمه، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_8" style=""><span class="pln">aVeryLongVariableNameWithCapitalisedStyle</span></pre>

<p>
	لن نتحدث هنا عن القواعد التي تحكم المحارف المسموح بها في لغات البرمجة التي سنستخدمها، لكن إذا كنت تستخدم الأسلوب الذي في المثال؛ فستجنب نفسك كثيرًا من المشاكل في هذا الشأن. ومن الأساليب المستخدمة في تسمية المتغيرات أيضًا فصل الكلمات في اسم المتغير بشرطة سفلية، كما في <code>another_variable_name</code>؛ أما في لغة بايثون فيأخذ المتغير نوع البيانات المسندة إليه، ويحتفظ بهذا النوع ويحذرك إذا حاولت خلط البيانات بطرق تختلف عنه، كأن تحاول إضافة سلسلة نصية إلى عدد مثلًا، وهي نفس حالة المثال الذي عرض لنا رسالة الخطأ في المقال السابق، ويمكن تغيير نوع البيانات التي يشير إليها المتغير عن طريق إعادة الإسناد إلى المتغير reassigning.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> q </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">  </span><span class="com"># عددًا الآن q صار</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> q </span><span class="pun">)</span><span class="pln">
</span><span class="lit">7</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> q </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Seven"</span><span class="pln">  </span><span class="com"># ليكون سلسلة نصية q أعد إسناد </span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> q </span><span class="pun">)</span><span class="pln">
</span><span class="typ">Seven</span></pre>

<p>
	لاحظ أن المتغير <code>q</code> ضُبط ليشير إلى العدد <code>7</code> ابتداءً، وقد حافظ على تلك القيمة إلى أن جعلناه يشير إلى سلسلة المحارف <code>"Seven"</code>، وعلى هذا نستنتج أن متغيرات بايثون تحافظ على النوع الذي تشير إليه، لكننا نستطيع تغيير ذلك عن طريق إعادة الإسناد إلى المتغير، وتلك هي الكتابة الديناميكية التي ذكرناها قبل قليل.
</p>

<p>
	ويمكن التحقق من نوع المتغير باستخدام الدالة <code>type()‎</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_14" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> type</span><span class="pun">(</span><span class="pln">q</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'str'</span><span class="pun">&gt;</span></pre>

<p>
	تُفقد البيانات الأصلية عند إعادة الإسناد، وتمسحها بايثون من الذاكرة ما لم يكن ثمة متغير آخر يشير إليها، وهذا المحو يُعرف باسم جمع المهملات Garbage Collection، والذي يمكن تشبيهه بموظف غرفة البريد الذي يأتي مرةً واحدةً كل فترة ويزيل أي طرود في صناديق البريد لا توجد عليها ملصقات، فإذا لم يستطع العثور على مالك لها أو لم يوجد عنوان على الطرد؛ فسيرميها في المهملات.
</p>

<p>
	لننظر الآن في بعض الأمثلة على أنواع البيانات.
</p>

<h3>
	متغيرات جافاسكربت و VBSCript
</h3>

<p>
	تختلف جافاسكربت عن أختها VBScript قليلًا في طريقة استخدام المتغيرات، فكلاهما ترى وجوب التصريح عن المتغير قبل استخدامه، وهي خاصية تشترك فيها اللغات المصرَّفة compiled مع اللغات ذات الكتابة الثابتة statically typed، بل حتى في اللغات الديناميكية مثل تلك التي نستخدمها، حيث نستفيد من التصريح عن المتغيرات في حالة حدوث خطأ إملائي عند استخدام متغير، إذ سسيدرك المترجم أن متغيرًا غير معروف قد استُخدم، وسيرفع خطأً؛ أما عيب هذا الأسلوب فهو الحاجة إلى مزيد من الكتابة من قِبل المبرمج.
</p>

<h4>
	VBScript
</h4>

<p>
	يصرَّح عن المتغير في لغة VBScript باستخدام التعليمة <code>Dim</code>، وهي اختصار لكلمة Dimension أو بُعد، وهي إشارة إلى الجذور الأولى للغة VBScript في لغة BASIC ولغات التجميع من قبلها، حيث كان يجب علينا إخبار المجمِّع بكمية الذاكرة التي سيستخدمها المتغير -أو أبعاده-، وظل الاختصار موجودًا حتى الآن. ويبدو التصريح عن المتغير في VBScript كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_951_23" style=""><span class="typ">Dim</span><span class="pln"> aVariable</span></pre>

<p>
	نستطيع بمجرد التصريح عن المتغير أن نعين قيمًا له كما فعلنا في بايثون، ويمكن التصريح عن عدة متغيرات في تعليمة <code>Dim</code> واحدة بسردها جميعًا مع فصلها بفواصل إنجليزية "<code>,"</code> كما يلي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_951_21" style=""><span class="typ">Dim</span><span class="pln"> aVariable</span><span class="pun">,</span><span class="pln"> another</span><span class="pun">,</span><span class="pln"> aThird</span></pre>

<p>
	ويبدو الإسناد بعدها كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_19" style=""><span class="pln">aVariable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln">
another </span><span class="pun">=</span><span class="pln"> </span><span class="str">"هذه جملة قصيرة."</span><span class="pln">
aThird </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159</span></pre>

<p>
	قد نرى كلمةً مفتاحيةً أخرى هي <code>Let</code>، وهي من جذور BASIC أيضًا، لكننا لن نراها إلا نادرًا لقلة الحاجة إليها، وهي تُستخدم كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_27" style=""><span class="typ">Let</span><span class="pln"> aVariable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">22</span></pre>

<p>
	ولن نستخدمها على أي حال في هذه السلسلة.
</p>

<h4>
	جافاسكربت
</h4>

<p>
	نستطيع التصريح عن المتغيرات مسبقًا في جافاسكربت باستخدام الكلمة <code>var</code>، كما يمكن التصريح عن عدة متغيرات كما في VBScript في تعليمة <code>var</code> واحدة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_29" style=""><span class="kwd">var</span><span class="pln"> aVariable</span><span class="pun">,</span><span class="pln"> another</span><span class="pun">,</span><span class="pln"> aThird</span><span class="pun">;</span></pre>

<p>
	كما تسمح جافاسكربت بتهيئة -أو تعريف- المتغيرات مثل جزء من تعليمة <code>var</code>، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_33" style=""><span class="kwd">var</span><span class="pln"> aVariable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> another </span><span class="pun">=</span><span class="pln"> </span><span class="str">"A short phrase"</span><span class="pun">,</span><span class="pln"> aThird </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3.14159</span><span class="pun">;</span></pre>

<p>
	يوفر هذا قليلًا من وقت الكتابة، لكنه لا يختلف عن أسلوب VBScript مع المتغيرات والمكون من خطوتين. يمكن التصريح عن متغيرات جافاسكربت وتهيئتها من غير استخدام <code>var</code>، بنفس الطريقة المتبعة في بايثون:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_31" style=""><span class="pln">aVariable </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span></pre>

<p>
	غير أن المتعصبين لجافاسكربت يرون أن استخدام <code>var</code> أفضل، لذا سيكون هذا أسلوبنا في هذه السلسلة أيضًا.
</p>

<p>
	نأمل أن تكون تلك النبذة المختصر عن متغيرات جافاسكربت وVBScript قد أوضحت الفرق بين التصريح عن المتغيرات وبين تعريفها، أما متغيرات بايثون، فتعريفها يعني ضمنيًا التصريح عنها كذلك.
</p>

<h3>
	أنواع الكتابة: صارمة أم متغيرة أم ثابتة
</h3>

<p>
	لقد أشرنا إلى الكتابة الثابتة والديناميكية فيما سبق من المقال، وتوجد أنواع أخرى من الكتابة مثل الكتابة الصارمة strict -أو القوية أحيانًا أخرى-، والكتابة الفضفاضة loose أو الضعيفة، وسنحاول هنا أن نوضح الاختلافات بينها.
</p>

<p>
	تُنشأ المتغيرات مثل أنواع بيانات مرنة أو ثابتة، ويقال أن النوع الثابت مكتوب كتابةً ثابتةً أي أنه لا يتغير أبدًا-، أما المتغير الذي قد يشير إلى عدة أنواع من البيانات فيُكتب ديناميكيًا، لذا تشير البيانات الثابتة والديناميكية إلى أنواع البيانات التي يمكن تخزينها داخل المتغير. ويمكن دمج المتغيرات في العمليات المختلفة عند البرمجة، حيث ستتطلب كل عملية احتواء متغيراتها على أنواع بعينها، مثل الأعداد أو المحارف، فإذا رفضت اللغة السماح لعملية ما باستخدام أنواع خاطئة؛ فسيقال أن هذا النوع من الكتابة كتابةٌ صارمة.
</p>

<p>
	تحاول بعض اللغات إجبار القيم على الأنواع الصالحة المسموح بها، بينما تسمح لغات أخرى بأي نوع ثم تفشل العملية وتخرِج خطأً، وتلك هي الكتابة الفضفاضة، وعلى هذا تشير كل من الكتابة الصارمة والفضفاضة إلى أسلوب التحقق من أنواع المتغيرات المستخدَمة في العمليات، وبالنسبة للغات التي سنستخدمها في هذه السلسلة، فجميعها تستخدم كتابةً ديناميكيةً قويةً.
</p>

<h2>
	الأنواع الأساسية للبيانات
</h2>

<p>
	تسمى أنواع البيانات الأساسية primitive data types بهذا الاسم لأنها أبسط أنواع البيانات التي يمكن معالجتها والتعامل معها، أما الأنواع الأعقد من البيانات فما هي في الواقع إلا تجميعات من الأنواع الأساسية، فهي اللبنات الأساسية التي تكوَّن منها جميع الأنواع الأخرى، وبناءً عليه تكون هي أساس الحوسبة كلها، وتشمل الأنواع الأساسية الأرقام والأحرف ونوعًا آخر اسمه النوع البولياني boolean type.
</p>

<h2>
	سلاسل المحارف Strings
</h2>

<p>
	لقد رأينا هذه السلاسل من قبل، وهي أي سلسلة من المحارف التي يمكن طباعتها على الشاشة، وقد توجد فيها محارف تحكم لا تُطبع ولا تُرى على الشاشة.
</p>

<p>
	تُعرض تلك السلاسل في صورة أحرف، لكن الحاسوب يخزنها في صورة تسلسلات من الأرقام، ويطلق على ربط تلك الأرقام بالمحارف اسم الترميز encoding، وتوجد العديد من الترميزات المختلفة، رغم أن المنتشر حاليًا منها هو واحد من ثلاثة ترميزات معرَّفة بواسطة معيار الترميز الموحد Unicode Standard، وسننظر في الترميز الموحد أو اليونيكود في مقال لاحق، لكن يجب أن تعلم أن غرضه توفير مخطط ترميز يمثل أي حرف من أي أبجدية في أي مكان في العالم، إضافةً إلى المحارف الخاصة التي تحتاجها الحواسيب مثل الأقواس والتحكم والتهريب وغيرها. لن نعير هذا الترميز كثير الانتباه أثناء العمل، لكن قد نحتاج إلى التحويل بين الرموز الرقمية والأحرف، كما في مشكلة الاقتباسات في مثال VBScript من المقال السابق.
</p>

<p>
	ويمكن تمثيل السلاسل النصية في بايثون بعدة طرق:
</p>

<ul>
	<li>
		باستخدام علامات اقتباس مفردة:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_951_35" style=""><span class="pln">  </span><span class="str">'هذه سلسلة نصية'</span></pre>

<ul>
	<li>
		أو باستخدام علامات اقتباس مزدوجة:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_951_37" style=""><span class="pln">  </span><span class="str">"وهذه سلسلة نصية تشبهها"</span></pre>

<ul>
	<li>
		أو بعلامات اقتباس ثلاثية مزدوجة:
	</li>
</ul>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_951_39" style=""><span class="pln">  </span><span class="str">"""</span><span class="pln"> </span><span class="pun">أما</span><span class="pln"> </span><span class="pun">هذه</span><span class="pln"> </span><span class="pun">فسلسلة</span><span class="pln"> </span><span class="pun">نصية</span><span class="pln"> </span><span class="pun">أطول</span><span class="pln">
      </span><span class="pun">ونستطيع</span><span class="pln"> </span><span class="pun">إطالتها</span><span class="pln"> </span><span class="pun">وتقسيمها</span><span class="pln"> </span><span class="pun">على</span><span class="pln"> </span><span class="pun">ما</span><span class="pln"> </span><span class="pun">نشاء</span><span class="pln"> </span><span class="pun">من</span><span class="pln"> </span><span class="pun">الأسطر</span><span class="pln">
      </span><span class="pun">وستحافظ</span><span class="pln"> </span><span class="pun">بايثون</span><span class="pln"> </span><span class="pun">على</span><span class="pln"> </span><span class="pun">هذه</span><span class="pln"> </span><span class="pun">الأسطر</span><span class="pln"> </span><span class="str">"""</span></pre>

<p>
	يُستخدم النوع الأخير في إنشاء توثيقات لدوال بايثون التي ننشئها بأنفسنا كما سنرى في مقال تال، ويمكن استخدام علامات اقتباس ثلاثية مفردة، لكننا لا ننصح بهذا، إذ قد يصعب تحديد ما إذا كانت العلامات ثلاثيةً مفردةً أم علامةً مزدوجةً داخل أخرى مفردة.
</p>

<p>
	نستطيع الوصول إلى المحارف المنفردة في السلسلة النصية بمعاملتها مثل مصفوفة من المحارف -انظر المصفوفات أدناه-، كما توجد بعض العمليات التي توفرها لغة البرمجة لتساعدنا في التعامل مع السلاسل، مثل العثور على سلسلة فرعية أو ربط سلسلتين معًا، ونسخ واحدة إلى أخرى، وهكذا.
</p>

<p>
	تجدر الإشارة إلى أن بعض اللغات فيها نوع منفصل للمحارف، أي لحرف واحد فقط، وفي تلك الحالة تكون السلاسل مجرد مجموعات من قيم تلك الأحرف، لكن بايثون -على نقيض هذا-ـ إذ تستخدم سلسلةً طولها وحدة واحدة لتخزين الحرف الواحد، ولا يلزم وجود صياغة خاصة.
</p>

<h3>
	العوامل النصية String Operators
</h3>

<p>
	توجد عدة عمليات يمكن إجراؤها على السلاسل النصية، وبعضها مضمّن مسبقًا في بايثون، لكن يمكن توفير عمليات إضافية باستخدام الوحدات المستورَدة كما فعلنا مع وحدة <code>sys</code> في المقال السابق حول  التسلسلات البسيطة.
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
} 

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<table>
	<thead>
		<tr>
			<th style="text-align:center">
				العامل
			</th>
			<th style="text-align:center">
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:center">
				S1 + S2
			</td>
			<td style="text-align:center">
				ضم كل من S1 و S2
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				S1 * N
			</td>
			<td style="text-align:center">
				تكرار قدره N من S1
			</td>
		</tr>
	</tbody>
</table>

<p>
	يمكننا أن نرى ذلك في الأمثلة التالية:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_41" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Again and '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">'again'</span><span class="pln"> </span><span class="pun">)</span><span class="pln">    </span><span class="com"># ضم السلسلة</span><span class="pln">
</span><span class="typ">Again</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> again
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Repeat '</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">)</span><span class="pln">                   </span><span class="com"># تكرار السلسلة</span><span class="pln">
</span><span class="typ">Repeat</span><span class="pln"> </span><span class="typ">Repeat</span><span class="pln"> </span><span class="typ">Repeat</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="str">'Again '</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="str">'and again '</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">   </span><span class="com"># '*' جمع '+' و    </span><span class="pln">
</span><span class="typ">Again</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> again </span><span class="kwd">and</span><span class="pln"> again </span><span class="kwd">and</span><span class="pln"> again</span></pre>

<p>
	كما يمكن إسناد سلاسل أحرف إلى متغيرات:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_43" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> s1 </span><span class="pun">=</span><span class="pln"> </span><span class="str">'Again '</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> s2 </span><span class="pun">=</span><span class="pln"> </span><span class="str">'and again '</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> s1 </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">s2 </span><span class="pun">*</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="typ">Again</span><span class="pln"> </span><span class="kwd">and</span><span class="pln"> again </span><span class="kwd">and</span><span class="pln"> again </span><span class="kwd">and</span><span class="pln"> again</span></pre>

<p>
	لاحظ أن المثالين الأخيرين أنتجا نفس الخرج.
</p>

<p>
	هناك الكثير من الأمور التي يمكن تنفيذها باستخدام السلاسل النصية، وسننظر فيها بتفصيل في مقالات تالية بعد أن نكتسب خبرةً جيدةً في المواضيع التي تسبقها.
</p>

<p>
	ربما تجب ملاحظة أن السلاسل النصية في بايثون لا يمكن تعديلها، أي أننا نستطيع إنشاء سلسلة نصية جديدة مع تغيير بعض الأحرف، لكن لا يمكن تعديل أي حرف داخل سلسلة تعديلًا مباشرًا، ويُعرف نوع البيانات ذاك الذي لا يمكن تغييره باسم النوع غير القابل للتغير immutable.
</p>

<h3>
	متغيرات السلاسل النصية في VBScript
</h3>

<p>
	تسمى المتغيرات في VBScript باسم المتغايرات variants، لأنها قد تحتوي على أي نوع من البيانات، وتحاول VBScript أن تحولها إلى النوع المناسب وفق الحاجة، وعليه فقد نسند عددًا إلى متغير ما، لكن إذا استخدمناه مثل سلسلة نصية فستحاول VBScript أن تحوله نيابةً عنا، وهذا يشبه -من الناحية العملية- سلوك أمر <code>print</code> في بايثون، غير أنه هنا يمتد إلى أي أمر VBSCript. ويمكن إعطاء VBScript لإشارة على أننا نريد قيمةً عدديةً في صورة سلسلة نصية من خلال تغليفها بعلامتي اقتباس مزدوجتين:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_45" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">MyString</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"42"</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="typ">MyString</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	يمكن دمج سلاسل VBScript معًا في عملية تسمى بالضم concatenation، باستخدام العامل <code>&amp;</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_47" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">MyString</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello"</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">"World"</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="typ">MyString</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<h3>
	سلاسل جافاسكربت النصية
</h3>

<p>
	تحاط سلاسل جافاسكربت النصية بعلامات اقتباس مفردة أو مزدوجة، ويجب أن نصرّح عن المتغيرات قبل استخدامها، وذلك بكلمة <code>var</code> المفتاحية. في المثال التالي سنصرح عن متغيري سلاسل نصية ونعرّفهما:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_49" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> aString</span><span class="pun">,</span><span class="pln"> another</span><span class="pun">;</span><span class="pln">
aString </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Hello "</span><span class="pun">;</span><span class="pln">
another </span><span class="pun">=</span><span class="pln"> </span><span class="str">"World"</span><span class="pun">;</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">aString </span><span class="pun">+</span><span class="pln"> another</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	كما تسمح لنا جافاسكربت بإنشاء كائنات سلاسل نصية، ويمكن القول بأنها سلاسل نصية مع بعض المزايا الإضافية، والاختلاف الرئيسي بينهما هو طريقة إنشائها، والتي هي بالشكل:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_51" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> aStringObj</span><span class="pun">,</span><span class="pln"> anotherObj</span><span class="pun">;</span><span class="pln">
aStringObj </span><span class="pun">=</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">"Hello "</span><span class="pun">);</span><span class="pln">
anotherObj </span><span class="pun">=</span><span class="pln"> </span><span class="typ">String</span><span class="pun">(</span><span class="str">"World"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">aStringObj </span><span class="pun">+</span><span class="pln"> anotherObj</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	قد تكون تلك كتابةً كثيرةً قياسًا على المثال السابق مع أنهما ينجزان العمل نفسه -وهذا صحيح نوعًا ما-، غير أن كائنات السلاسل تعطينا مزايا في بعض المواقف تجعلنا نفضل استخدامها عما سواها، كما سنرى لاحقًا.
</p>

<h2>
	الأعداد الصحيحة Integers
</h2>

<p>
	الأعداد الصحيحة هي الأعداد الكاملة غير الكسرية، من أكبر قيمة سالبة إلى أكبر قيمة موجبة، وهذا التحديد لمجال القيم مهم في البرمجة على عكس الرياضيات، إذ لا نعير اهتمامًا لقيمة العدد غالبًا طالما ينتمي إلى مجموعة أساسية أو المجموعة التي نعمل عليها، أو لم يكن يؤثر في الناتج؛ أما في البرمجة فهناك حدود عظمى وحدود دنيا، ويعرَف الحد الأعلى باسم MAXINT، كما يعتمد على عدد البتات bits المستخدَمة في حاسوبك لتمثيل عدد ما. يكون في أغلب الحواسيب ولغات البرمجة الحالية العدد 64-بت في المعماريات الحديثة، لذا فإن قيمة الحد الأعلى هنا MAXINT تساوي 10 مرفوعة إلى الأس 19، وتستطيع بايثون إخبارنا بقيمة maxint باستخدام وحدة <code>sys</code>، فإذا كانت معمارية النظام 64-بت مثلًا فستكون قيمة <code>sys.maxsize</code> هي <code>9223372036854775807</code>، وهو رقم كبير؛ أما في VBScript فتكون تلك القيمة محدودةً بـ (‎+/- 32000‎) لأسباب تاريخية.
</p>

<p>
	تُعرَف الأعداد التي تحمل إشارةً موجبةً أو سالبةً بالأعداد الصحيحة ذات الإشارة signed integers، ومن الممكن استخدام أعداد صحيحة لا إشارة لها، غير أن هذا مقصور على الأعداد الموجبة، بما في ذلك الصفر، وهذا يعني أن الأعداد الصحيحة التي لا إشارة لها ضعف عدد ذوات الإشارة، بما أننا سنستغل المساحة التي كانت مخصصةً للأعداد السالبة لضمها إلى الأعداد التي لا إشارة لها، مما يعني زيادة قيمة الحد الأقصى إلى الضعف أيضًا "‎2 * MAXINT"، ونظرًا لأن حجم الأعداد الصحيحة مقيد بقيمة MAXINT، فإذا جمعنا عددين صحيحين وكان ناتج الجمع أكبر من الحد الأقصى؛ فسنحصل على خطأ، لكن قد تعيد بعض الأنظمة واللغات تلك القيمة الخاطئة كما هي مع رفع راية سرية secret flag نستطيع التحقق من وجودها إذا كنا نشك في الإجابة، وفي مثل هذه الحالة يكون التحقق عادةً هو برفع حالة خطأ، فإما أن يكون البرنامج حينها قادرًا على معالجة ذلك الخطأ فيعالجه، أو ينهي البرنامج نفسه إذا لم يستطع.
</p>

<p>
	تحوّل كل من جافاسكربت وVBScript العدد إلى صيغة تستطيعان التعامل معها، ولا تهتمان بالدقة هنا، إذ قد تختلف الصيغة الجديدة اختلافًا طفيفًا؛ أما لغة بايثون فتستخدم شيئًا اسمه العدد الصحيح الطويل Long Integer، وهي ميزة خاصة لها تسمح بأعداد صحيحة غير محدودة الحجم.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_53" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> sys
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> sys</span><span class="pun">.</span><span class="pln">maxsize </span><span class="pun">*</span><span class="pln"> </span><span class="lit">1000000</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
</span><span class="lit">9223372036854775807000000</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print </span><span class="pun">(</span><span class="pln">type</span><span class="pun">(</span><span class="pln">x</span><span class="pun">))</span><span class="pln">
</span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="str">'int'</span><span class="pun">&gt;</span></pre>

<p>
	كما نرى فالنتيجة أكبر بكثير من القيمة التي تتوقعها من الحاسوب في العادة، رغم احتسابها <code>int</code>، أما إذا استخدمنا شيفرةً مكافئةً لهذا المثال في جافاسكربت وVBScript؛ فسيخرج لنا العدد بصيغة تختلف عن العدد الصحيح الذي نتوقعه، وسنتعلم المزيد عن هذا في قسم الأعداد الحقيقية.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_55" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> x
x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">123456700</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">34567338738999</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="typ">CStr</span><span class="pun">(</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<h3>
	العمليات الحسابية
</h3>

<p>
	رأينا معظم العمليات الحسابية التي نحتاج إليها في المقال السابق في التسلسلات البسيطة، ولكن للتلخيص نعيدها مرةً أخرىً:
</p>

<table>
	<thead>
		<tr>
			<th style="text-align:center">
				مثال العامل
			</th>
			<th style="text-align:center">
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:center">
				M + N
			</td>
			<td style="text-align:center">
				جمع M و N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M - N
			</td>
			<td style="text-align:center">
				طرح N من M
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M * N
			</td>
			<td style="text-align:center">
				ضرب M في N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M / N
			</td>
			<td style="text-align:center">
				قسمة M على N، سيكون الناتج عددًا حقيقيًا كما سنبين لاحقًا
			</td>
		</tr>
		<tr>
			<td style="text-align: center;">
				M // N
			</td>
			<td style="text-align:center">
				القسمة الصحيحة لـ M على N، ستكون النتيجة عددًا صحيحًا
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M % N
			</td>
			<td style="text-align:center">
				باقي القسمة: أوجد ما تبقى من قسمة M على N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M**N
			</td>
			<td style="text-align:center">
				الأس: M مرفوعًا إلى الأس N
			</td>
		</tr>
	</tbody>
</table>

<p>
	بما أننا لم نرى المتغير الأخير من قبل، فلننظر في مثال على إنشاء بعض متغيرات الأعداد الصحيحة ونستخدم عامل الأس:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_57" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> i1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln">     </span><span class="pun">#</span><span class="pln"> i1 </span><span class="pun">أنشئ</span><span class="pln"> </span><span class="pun">عددًا</span><span class="pln"> </span><span class="pun">صحيحًا</span><span class="pln"> </span><span class="pun">وأسنده</span><span class="pln"> </span><span class="pun">إلى</span><span class="pln"> 
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> i2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> i3 </span><span class="pun">=</span><span class="pln"> i1</span><span class="pun">**</span><span class="pln">i2  </span><span class="pun">#</span><span class="pln"> i3 </span><span class="pun">أسند</span><span class="pln"> </span><span class="pun">نتيجة</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">إلى</span><span class="pln"> </span><span class="pun">أس</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">إلى</span><span class="pln"> 
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> i3 </span><span class="pun">)</span><span class="pln">
</span><span class="lit">16</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="lit">2</span><span class="pun">**</span><span class="lit">4</span><span class="pln"> </span><span class="pun">)</span><span class="pln">  </span><span class="pun">#</span><span class="pln"> </span><span class="pun">أكد</span><span class="pln"> </span><span class="pun">النتيجة</span><span class="pln">
</span><span class="lit">16</span></pre>

<p>
	تحتوي الوحدة <code>math</code> في بايثون على بعض الدوال الرياضية الشائعة مثل <code>sin</code> و <code>cos</code> وغيرهما.
</p>

<h3>
	عوامل الاختصار
</h3>

<p>
	إحدى العمليات الشائعة في البرمجة هي زيادة قيمة المتغير التدريجية، فإذا كان لدينا المتغير <code>x</code> الذي قيمته <code>42</code>، ونريد زيادة تلك القيمة إلى <code>43</code>، فسيكون ذلك كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_59" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> x </span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> x </span><span class="pun">)</span></pre>

<p>
	لاحظ السطر التالي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_81" style=""><span class="pln">x </span><span class="pun">=</span><span class="pln"> x </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	لا معنىً لهذا السطر من حيث المنطق الرياضي، لكنه في البرمجة يعني أن <code>x</code> الجديدة تساوي قيمة <code>x</code> السابقة مضافًا إليها <code>1</code>، فإذا كنت معتادًا على المنطق الرياضي؛ فستستغرق بعض الوقت لتعتاد على هذا النمط الجديد، لكن الفكرة هنا أن علامة <code>=</code> تُقرأ "<strong>ستكون</strong>" وليست "<strong>تساوي</strong>"، وعليه فإن السطر يعني أن x <strong>ستصبح</strong> قيمتها الجديدة هي x+1، وهذا النوع من العمليات شائع جدًا في الممارسة العملية إلى حد أن بايثون وجافاسكربت توفران عاملًا مختصرًا له من أجل توفير الكتابة على المبرمج:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_61" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> x </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> x </span><span class="pun">)</span></pre>

<p>
	وهذان العاملان مساويان تمامًا لتعليمة الإسناد السابقة لكنهما أقصر، توجد عوامل اختصار لباقي العمليات الحسابية بنفس المنطق السابق، نبينها في الجدول التالي:
</p>

<table>
	<thead>
		<tr>
			<th style="text-align:center">
				مثال العامل
			</th>
			<th style="text-align:center">
				الوصف
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:center">
				M += N
			</td>
			<td style="text-align:center">
				M = M + N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M -= N
			</td>
			<td style="text-align:center">
				M = M - N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M *= N
			</td>
			<td style="text-align:center">
				M = M * N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M /= N
			</td>
			<td style="text-align:center">
				M = M / N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M //= N
			</td>
			<td style="text-align:center">
				M = M // N
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				M %= N
			</td>
			<td style="text-align:center">
				M = M % N
			</td>
		</tr>
	</tbody>
</table>

<h3>
	الأعداد الصحيحة في VBScript
</h3>

<p>
	لقد قلنا إن الأعداد الصحيحة في VBScript محدودة بقيمة عظمى أقل من بايثون وجافاسكربت، وهي تقابل 16-بت على خلاف 64-بت التي رأيناها من قبل، أي حوالي "‎+/- 32000"، فإذا احتجنا إلى عدد صحيح أكبر من هذا؛ فنستخدم العدد <code>long</code> الذي يساوي حجمه حجم العدد الصحيح من معمارية 32-بت (أي 2 مليار)، كذلك لدينا النوع <code>byte</code> الذي هو عدد ثماني البتات، وحجمه الأكبر يساوي 255، وسيتضح بالممارسة العملية أن النوع القياسي للعدد الصحيح كافٍ لأغلب العمليات، فإذا كانت نتيجة العملية أكبر من MAXINT؛ فستحول VBSCript النتيجة تلقائيًا إلى عدد ذي فاصلة عائمة أو حقيقي، كما سنبين لاحقًا.
</p>

<p>
	ورغم دعم VBScript لجميع العمليات الحسابية المعتادة، إلا أن عملية الباقي modulo تمثَّل تمثيلًا مختلفًا، باستخدام العامل <code>MOD</code>، وقد رأينا ذلك في فصل التسلسلات البسيطة، كذلك فإن تمثيل الأسس مختلف، إذ يُستخدم محرف الإقحام <code>^</code> بدلًا من <code>**</code> في بايثون.
</p>

<h3>
	أعداد جافاسكربت
</h3>

<p>
	تحتوي جافاسكربت على نوع عددي في صورة كائن كما سنصفه فيما بعد، وهي تسميه Number، لكن أحيانًا قد يكون عدد جافاسكربت "ليس عددًا" أو Not a Number، ويشار إليه بـ NaN اختصارًا، وهو ما نحصل عليه أحيانًا كنتيجة لبعض العمليات المستحيلة رياضيًا، والهدف منه هو السماح لنا بالتحقق من أنواع أخطاء بعينها دون تعطيل البرنامج، كما تحوي لغة بايثون كذلك النوع NaN أيضًا.
</p>

<p>
	تحتوي جافاسكربت على نسخ عددية خاصة لتمثيل اللانهاية الموجبة والسالبة، وهي ميزة نادرة نسبيًا في لغات البرمجة، وقد تكون كائنات جافاسكربت العددية إما أعدادًا صحيحةً أو حقيقيةً كما سنرى لاحقًا، وتَستخدم جافاسكربت نفس العوامل التي تستخدمها بايثون، باستثناء الإجراءات الأسية التي تستخدم كائنًا خاصًا بها اسمه <code>Math</code>.
</p>

<h2>
	الأعداد الحقيقية Real Numbers
</h2>

<p>
	الأعداد الحقيقية هي نفسها الأعداد الصحيحة لكن مع إضافة الكسور، وقد تمثل أعدادًا أكبر من الحد الأقصى MAXINT لكن مع دقة أقل، وهذا يعني أننا قد نرى عددين حقيقيين على أنهما متطابقين، لكن الحاسوب يراهما غير متطابقين عندما يوازنهما معًا، لأنه ينظر في أدق التفاصيل بينهما، حيث يمكن تمثيل العدد 5.0 في الحاسوب بإحدى الصورتين 4.9999999 أو (‎5.000000…01) مثلًا، وهذه التقاربات مناسبة لأغلب الاستخدامات، لكن قد نحتاج أحيانًا إلى تلك الدقة، فتذكر هذا الأمر إذا حصلت على نتيجة غريبة لا تتوقعها عند استخدام الأعداد الحقيقية.
</p>

<p>
	كما تُعرَف الأعداد الحقيقية أيضًا باسم أعداد الفاصلة العائمة floating point numbers، ولها نفس العمليات الحسابية التي تطبّق على الأعداد الصحيحة، مع زيادة هنا وهي قدرتها على اقتطاع العدد ليكون قيمة صحيحة.
</p>

<p>
	تدعم لغات البرمجة الثلاث بايثون وجافاسكربت وVBScript الأعداد الحقيقية، وننشئها في بايثون بتخصيص عدد بعلامة عشرية فيه كما رأينا في المقال السابق للتسلسلات البسيطة؛ أما جافاسكربت وVBScript فلا يوجد تمييز واضح بين الأعداد الصحيحة والحقيقية، فما عليك إلا استخدامها وستتعامل اللغة مع ما تدخله إليها وفق المناسب.
</p>

<h2>
	الأعداد المركبة أو التخيلية Complex numbers
</h2>

<p>
	إذا كانت لديك خلفية رياضية فقد تتساءل أين الأعداد المركبة complex في هذا الشرح، والواقع أننا لا نحتاج إليها غالبًا في البرمجة، لكن على أي حال فبعض اللغات مثل بايثون توفر دعمًا مضمّنا فيها للأعداد المركبة، بينما توفر بعض اللغات الأخرى مكتبةً من الدوال التي تستطيع التعامل مع الأعداد المركبة، ونفس الأمر ينطبق على المصفوفات.
</p>

<p>
	يمثَّل العدد المركب في بايثون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_63" style=""><span class="pun">(</span><span class="pln">real</span><span class="pun">+</span><span class="pln">imaginaryj</span><span class="pun">)</span></pre>

<p>
	وبناءً عليه تبدو عملية جمع بسيطة لعدد مركب كما يلي:
</p>

<pre class="ipsCode prettyprint lang-php prettyprinted" id="ips_uid_951_86" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> M </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pun">+</span><span class="lit">4j</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> N </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pun">+</span><span class="lit">6j</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> M </span><span class="pun">+</span><span class="pln"> N </span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">9</span><span class="pun">+</span><span class="lit">10j</span><span class="pun">)</span></pre>

<p>
	تنطبق جميع عمليات الأعداد الصحيحة على الأعداد المركبة كذلك، كما توجد وحدة <code>cmath</code> التي تحتوي بعض الدوال الرياضية الشائعة التي تعمل على قيم الأعداد المركبة، ولا توفِّر جافاسكربت وVBScript دعمًا للأعداد المركبة.
</p>

<h2>
	القيم البوليانية - True و False
</h2>

<p>
	سُمي هذا النوع من القيم بهذا الاسم نسبةً إلى عالم الرياضيات George Boole الذي كان يدرس المنطق في القرن التاسع عشر، ولا يحوي هذا النوع من البيانات إلا قيمتين فقط، هما <code>True</code> عند التحقق أو الصحة، و <code>false</code> عند عدم التحقق أو الخطأ، وتدعم بعض اللغات هذا النوع دعمًا مباشرًا، بينما تستخدم بعض اللغات الأخرى اصطلاحًا تمثل فيه قيمةً عدديةً القيمة false، وتكون تلك القيمة غالبًا هي الصفر؛ بينما تمثَّل القيمة true بالعدد (1) أو (‎-1)، وقد كان هذا سلوك بايثون حتى الإصدار 2.2، لكنها صارت تدعم القيم البوليانية مباشرةً بعد ذلك باستخدام القيمتين <code>True</code> و <code>False</code>، وهما كما ترى تبدآن بحرف كبير، فتذكر أن بايثون حساسة لحالة الأحرف.
</p>

<p>
	تعرَف القيم البوليانية أحيانًا باسم قيم الحقيقة لأنها تُستخدم للتحقق مما إذا كان شيء ما صحيحًا أم لا، فإذا كتبنا برنامجًا يأخذ نسخةً احتياطيةً من جميع الملفات في مجلد ما مثلًا، فنستطيع نسخ كل ملف على حدة ثم نطلب اسم الملف التالي من النظام، وإذا لم تتبق ملفات لنسخها، فسيعيد النظام سلسلةً نصيةً فارغةً، حيث سنتحقق هنا مما إذا كان الاسم هو سلسلةً فارغةً أم لا، ونخزن النتيجة مثل قيمة بوليانية تكون قيمتها <code>True</code> إذا كان الاسم سلسلةً فارغةً، و <code>False</code> إذا لم يكن كذلك، وسنرى كيفية استخدام تلك النتيجة لاحقًا في هذه السلسلة.
</p>

<h3>
	العوامل البوليانية أو المنطقية
</h3>

<table>
	<thead>
		<tr>
			<th style="text-align:center">
				العامل
			</th>
			<th style="text-align:center">
				الوصف
			</th>
			<th style="text-align:center">
				الأثر
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="text-align:center">
				A and B
			</td>
			<td style="text-align:center">
				الإضافة أو AND
			</td>
			<td style="text-align:center">
				صحيح إذا كان كل من A و B صحيحًا أو متحققًا، وخطأ في الحالات الأخرى
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				A or B
			</td>
			<td style="text-align:center">
				الاختيار أو OR
			</td>
			<td style="text-align:center">
				صحيح إذا كان أحدهما أو كلاهما صحيحًا، وخطأ إذا كان كل من A و B خاطئًا
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				A == B
			</td>
			<td style="text-align:center">
				التساوي
			</td>
			<td style="text-align:center">
				صحيح إذا كان A يساوي B
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				A != B
			</td>
			<td style="text-align:center">
				عدم التساوي
			</td>
			<td style="text-align:center">
				صحيح إذا كانت A لا تساوي B
			</td>
		</tr>
		<tr>
			<td style="text-align:center">
				not B
			</td>
			<td style="text-align:center">
				النفي
			</td>
			<td style="text-align:center">
				صحيح إذا لم يكن B صحيحًا
			</td>
		</tr>
	</tbody>
</table>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		<strong>لاحظ</strong> أن العامل الأخير يعمل على قيمة واحدة، بينما توازن بقية العوامل بين قيمتين.
	</p>
</blockquote>

<p>
	تدعم VBScript القيم البوليانية كما تفعل بايثون على الصورة <code>True</code> و <code>False</code>، أما جافاسكربت فتدعمها لكن على الصورة <code>true</code> و <code>false</code> -لاحظ حالة الأحرف الصغيرة هنا-. كما ستجد أسماءً مختلفةً لنوع البيانات البولياني أو المنطقي في كل لغة، ففي بايثون ستجدها باسم <code>bool</code>، أما في جافاسكربت وVBScript فاسمه <code>Boolean</code>، ولا تشغل بالك بهذا لأننا لن ننشئ متغيرات من هذا النوع، لكننا سنستخدم نتائجه في الاختبارات.
</p>

<h2>
	الوقت والتاريخ
</h2>

<p>
	يُعطى التاريخ والوقت في العادة أنواعًا خاصةً بهما في البرمجة، لكن قد يمثَّلان أحيانًا في صورة عدد كبير (عدد الثواني منذ وقت أو تاريخ قديم، مثل الوقت الذي كُتب فيه نظام التشغيل)، لكن قد يكون نوع البيانات في أحيان أخرى هو ما يُعرف بالنوع المعقد الذي سنذكره في الفصل التالي، وهو يسهل استخراج الشهر واليوم والساعة…
</p>

<p>
	سننظر في استخدام بايثون لوحدة <code>time</code> في مقال تالٍ، أما جافاسكربت وVBScript فلديهما آليات خاصة للتعامل مع الوقت، لكننا لن ندرسها.
</p>

<h2>
	النوع الذي يعرفه المستخدم User Defined Type
</h2>

<p>
	قد لا تكفي الأنواع التي ذكرناها سابقًا لاحتياجاتنا البرمجية حتى لو دمجناها معًا، فقد نريد جمع عدة أجزاء من البيانات معًا ثم نعاملها مثل عنصر واحد، كما في وصف العنوان مثلًا، حيث يكون على هيئة "رقم المنزل والشارع والمدينة ، ثم الرمز البريدي". تسمح أغلب اللغات بجمع مثل هذه المعلومات معًا في سجل أو هيكل بيانات أو في هيئة صنف Class، وهذا الأخير في البرمجة كائنية التوجه Object Oriented.
</p>

<h3>
	VBScript
</h3>

<p>
	تبدو تعريفات السجلات في VBScript كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_65" style=""><span class="typ">Class</span><span class="pln"> </span><span class="typ">Address</span><span class="pln">
     </span><span class="typ">Public</span><span class="pln"> </span><span class="typ">HsNumber</span><span class="pln">
     </span><span class="typ">Public</span><span class="pln"> </span><span class="typ">Street</span><span class="pln">
     </span><span class="typ">Public</span><span class="pln"> </span><span class="typ">Town</span><span class="pln">
     </span><span class="typ">Public</span><span class="pln"> </span><span class="typ">ZipCode</span><span class="pln">
</span><span class="typ">End</span><span class="pln"> </span><span class="typ">Class</span></pre>

<p>
	تعني الكلمة المفتاحية <code>Public</code> أن البرنامج يستطيع الوصول إلى البيانات، وعليه توجد كلمة <code>Private</code> التي يمكن استخدامها لجعل البيانات خاصةً ومقصورةً على أجزاء بعينها من البرنامج، كما سنرى لاحقا.
</p>

<h3>
	بايثون
</h3>

<p>
	يختلف الأمر قليلًا في بايثون:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_68" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">   </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Hs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">St</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Town</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Zip</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hs</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">St</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">Town</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Town</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">ZipCode</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Zip</span><span class="pln">
</span><span class="pun">...</span></pre>

<p>
	سنترك شرح معنى كل من <code>self</code> و <code>def __init__(...)‎</code> إلى حين الحديث عن البرمجة كائنية التوجه، أما الآن فنريد ملاحظة أن هناك شرطتين سفليتين حول <code>init</code>، وهذا أسلوب متبع في بايثون. لاحظ كذلك ضرورة استخدام المسافات الموضحة أعلاه، ذلك أن بايثون دقيقة في تحديد المسافات. قد يواجه البعض مشاكل أثناء كتابة ما يتشابه مع هذا المثال في محث بايثون، وستجد في نهاية هذا المقال شرحًا مختصرًا لهذه المشكلة، ثم سنشرحها بالتفصيل في جزء تالٍ من هذه السلسلة، فإذا أردت كتابة المثال أعلاه في محث بايثون؛ فتأكد من نسخ المسافات البادئة لكل سطر.
</p>

<p>
	والأمر الذي نريد التوكيد عليه هنا هو أننا جمعنا عدة أجزاء من بيانات مرتبطة ببعضها بعضًا ثم وضعناها في هيكل واحد هو <code>Address</code>، كما فعلنا في VBScript قبل قليل.
</p>

<h3>
	جافاسكربت
</h3>

<p>
	توفر جافاسكربت اسمًا غريبًا لهيكل بيانات العنوان في حالتنا، وهو <code>function</code>، إذ ترتبط الدوال عادةً بالعمليات وليس تجميعات البيانات، غير أن دوال جافاسكربت تستطيع التعامل مع كليهما، فإذا أردنا إنشاء كائن العنوان في جافاسكربت؛ فسنكتب الآتي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_71" style=""><span class="kwd">function</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">(</span><span class="typ">Hs</span><span class="pun">,</span><span class="typ">St</span><span class="pun">,</span><span class="typ">Town</span><span class="pun">,</span><span class="typ">Zip</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">HsNum</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hs</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">St</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">Town</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Town</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">this</span><span class="pun">.</span><span class="typ">ZipCode</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Zip</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	نريد مرةً أخرى تجاهل الصياغة واستخدام الكلمة <code>this</code> هنا، والنظر إلى النتيجة التي ستكون مجموعةً من عناصر البيانات التي نستطيع القول بأنها تصف عنوانًا، ويمكننا معاملته على أنه وحدة واحدة.
</p>

<p>
	والآن، كيف نصل إلى تلك البيانات بعد إنشاء هياكلها؟
</p>

<h2>
	الوصول إلى الأنواع التي يعرفها المستخدم
</h2>

<p>
	من الممكن إسناد نوع بيانات معقد إلى متغير، لكن لا يمكن الوصول إلى الحقول المنفردة دون استخدام بعض آليات الوصول الخاصة التي تحددها اللغة، وتكون نقطة <code>.</code> في الغالب.
</p>

<h3>
	VBScript
</h3>

<p>
	إذا استخدمنا حالة صنف العنوان الذي عرّفناه أعلاه، فسنكتب ما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_73" style=""><span class="typ">Dim</span><span class="pln"> </span><span class="typ">Addr</span><span class="pln">
</span><span class="typ">Set</span><span class="pln"> </span><span class="typ">Addr</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">New</span><span class="pln"> </span><span class="typ">Address</span><span class="pln">

</span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pln">
</span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"High St"</span><span class="pln">
</span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Town</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"Anytown"</span><span class="pln">
</span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">ZipCode</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"123 456"</span><span class="pln">

</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Town</span></pre>

<p>
	نحدد هنا بُعد متغير جديد هو <code>Addr</code> باستخدام <code>Dim</code>، ثم نستخدم الكلمتين <code>Set</code> و <code>New</code> لإنشاء نسخة جديدة من صنف <code>Address</code>، ثم نسند القيم إلى حقول نسخة العنوان الجديدة، ثم نطبع العنوان في صندوق رسالة.
</p>

<h3>
	بايثون
</h3>

<p>
	على فرض أننا كتبنا تعريف الصنف أعلاه:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_77" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="typ">Addr</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="str">"High St"</span><span class="pun">,</span><span class="str">"Anytown"</span><span class="pun">,</span><span class="str">"123 456"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Addr</span><span class="pun">.</span><span class="typ">Town</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">7</span><span class="pln"> </span><span class="typ">High</span><span class="pln"> </span><span class="typ">St</span><span class="pln"> </span><span class="typ">Anytown</span></pre>

<p>
	ينشئ هذا نسخةً من نوع <code>Address</code> ويسند إليه المتغير <code>Addr</code>، ونستطيع تمرير قيم الحقل إلى الكائن الجديد عند إنشائه في بايثون، ثم نطبع حقول <code>HsNumber</code> و <code>Street</code> للنسخة المنشأة حديثًا باستخدام عامل النقطة <code>.</code>.
</p>

<p>
	كما يمكن إنشاء نسخ عنوان متعددة لكل منها قيمه المستقلة لأرقام البيوت والشوارع وغيرها. جرب هذا بنفسك لتتدرب عليه، فهل تستطيع معرفة كيفية استخدام هذا في مثال دفتر العناوين؟
</p>

<h3>
	جافاسكربت
</h3>

<p>
	تشبه آلية جافاسكربت هنا ما سبق ذكره لكن مع بعض التعديل، غير أن الآلية الأساسية بسيطة ومباشرة:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_91" style=""><span class="kwd">var</span><span class="pln"> addr </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="pln"> </span><span class="str">"High St"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Anytown"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"123 456"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">addr</span><span class="pun">.</span><span class="typ">HsNum</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">Town</span><span class="pun">);</span></pre>

<p>
	إحدى الآليات التي يمكن استخدامها في جافاسكربت أيضًا هي معاملة الكائن مثل قاموس واستخدام اسم الحقل كمفتاح:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_93" style=""><span class="pln">document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln"> addr</span><span class="pun">[</span><span class="str">'HsNum'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> addr</span><span class="pun">[</span><span class="str">'Street'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="str">" "</span><span class="pln"> </span><span class="pun">+</span><span class="pln">  addr</span><span class="pun">[</span><span class="str">'Town'</span><span class="pun">]);</span></pre>

<p>
	وما لم نُعط اسم الحقل في هيئة سلسلة نصية كما في حالة قراءة ملف أو إدخال مستخدم للبرنامج، فلا ننصح باستخدام هذا النموذج.
</p>

<h2>
	العوامل التي يعرفها المستخدم
</h2>

<p>
	يمكن للأنواع التي يعرِّفها المستخدم أن تكون لها عمليات معرفة لها كذلك، وذلك أساس ما يعرف بالبرمجة كائنية التوجه. الكائن هو عبارة عن تجميعة من عناصر البيانات والعمليات المرتبطة بتلك البيانات، وهي مغلفة جميعًا في وحدة واحدة، حيث تستخدم بايثون الكائنات على نطاق واسع في مكتبتها القياسية للوحدات، كما تسمح لنا كوننا مبرمجين بإنشاء أنواع الكائنات الخاصة بنا.
</p>

<p>
	يحصل الوصول إلى عمليات الكائنات بنفس الطريقة التي يمكن الوصول بها إلى أعضاء البيانات لنوع معرَّف من قِبل المستخدم، أي من خلال عامل النقطة؛ أما غير هذا فتكون أشبه بالدوال، وتسمى تلك الدوال الخاصة بالتوابع methods، وقد رأيناها في حالة العملية <code>append()‎</code> في القوائم، أينما تذكر أنه من أجل استخدامها يجب أن نربط استدعاء الدالة باسم المتغير.
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_95" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> listObject </span><span class="pun">=</span><span class="pln"> </span><span class="pun">[]</span><span class="pln">    </span><span class="pun">#</span><span class="pln"> </span><span class="pun">قائمة</span><span class="pln"> </span><span class="pun">فارغة</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> listObject</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln"> </span><span class="pun">#</span><span class="pln"> </span><span class="pun">استدعاء</span><span class="pln"> </span><span class="pun">تابع</span><span class="pln"> </span><span class="pun">لكائن</span><span class="pln"> </span><span class="pun">القائمة</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> listObject </span><span class="pun">)</span><span class="pln">
</span><span class="pun">[</span><span class="lit">42</span><span class="pun">]</span></pre>

<p>
	يجب استيراد الوحدة عند توفير نوع كائن - يُسمى صنفًا- في وحدة بايثون كما فعلنا في <code>sys</code> من قبل، ثم كتابة اسم الوحدة قبل اسم نوع الكائن عند إنشاء نسخة يمكن تخزينها في متغير مع استخدام الأقواس طبعًا، بعد ذلك نستطيع استخدام المتغير دون استخدام اسم الوحدة، ولتوضيح هذا لنَعُد إلى وحدة <code>array</code> التي ذكرناها من قبل، فهي توفر الصنف <code>array</code>، ولنستورد هذه الوحدة ثم ننشئ نسخةً من <code>array</code>، ونسند اسم <code>myArray</code> إليها، ثم نستخدم <code>myArray</code> فقط للوصول إلى عملياتها وبياناتها كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_951_97" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> array
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> myArray </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">.</span><span class="pln">array</span><span class="pun">(</span><span class="str">'d'</span><span class="pun">)</span><span class="pln">  </span><span class="pun">#</span><span class="pln"> array of reals</span><span class="pun">(</span><span class="pln">d</span><span class="pun">),</span><span class="pln"> use module name
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> myArray</span><span class="pun">.</span><span class="pln">append</span><span class="pun">(</span><span class="lit">42</span><span class="pun">)</span><span class="pln">        </span><span class="pun">#</span><span class="pln"> use array operation
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> myArray</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]]</span><span class="pln"> </span><span class="pun">)</span><span class="pln">  </span><span class="pun">#</span><span class="pln"> access array content
</span><span class="lit">42.0</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> myArray</span><span class="pun">.</span><span class="pln">typecode </span><span class="pun">)</span><span class="pln">  </span><span class="pun">#</span><span class="pln"> access array attribute
</span><span class="str">'d'</span></pre>

<p>
	نستورد الوحدة <code>array</code> في السطر الأول إلى البرنامج، ثم نستخدم تلك الوحدة في السطر الثاني لإنشاء نسخة من صنف <code>array</code> باستدعائها مثل دالة، ونحتاج هنا إلى توفير سلسلة الرموز النوعية typecode string التي توضح نوع البيانات التي يجب تخزينها. تذكر أن المصفوفات الخالصة تخزن نوعًا واحدًا من البيانات، حيث سنصل في السطر الثالث إلى إحدى عمليات صنف المصفوفة، وهي <code>append()‎</code> التي تعامل الكائن <code>myArray</code> كأنه وحدة وكأن العملية داخل الوحدة، ثم نستخدم الفهرسة لجلب البيانات التي أضفناها، نستطيع في الأخير الوصول إلى بعض البيانات الداخلية، إذ يخزن <code>typecode</code> النوع الذي مررناه عند إنشاء المصفوفة، من داخل كائن <code>myArray</code> صياغةً تشبه صياغة الوحدة.
</p>

<p>
	لا يوجد فرق كبير بين استخدام الكائنات التي توفرها الوحدات، وبين الدوال الموجودة في الوحدات، باستثناء الحاجة إلى إنشاء نسخة instance، ويمكن النظر إلى اسم الكائن على أنه عنوان يحفظ الدوال والمتغيرات المرتبطة به مجموعةً معًا.
</p>

<p>
	إحدى الطرق الأخرى التي ننظر بها للأمر هي أن الكائنات تمثل أشياء من العالم الحقيقي ونحن نستخدمها أو نفعل بها أمورًا تنفعنا، وهذا المنظور على بساطته إلا أنه الفكرة التي نشأت بسببها الكائنات في البرمجة، فنحن نكتب -برمجيًا- محاكاةً لمواقف في العالم الحقيقي.
</p>

<p>
	تستطيع كل من جافاسكربت وVBScript أن تتعامل مع الكائنات، وقد كان هذا ما استخدمناه في كل أمثلة العناوين أعلاه، فقد عرفّنا صنفًا ثم أنشأنا نسخةً أسندناها إلى متغير كي نستطيع الوصول إلى خصائص تلك النسخة، ولهذا ارجع إن شئت إلى ما سبق من الشرح عن الأصناف والكائنات، وانظر كيف توفر الأصناف آليات لإنشاء أنواع جديدة من البيانات في برامجنا من خلال الربط بين بيانات النوع الجديد وعملياته معًا.
</p>

<h3>
	العوامل الخاصة ببايثون
</h3>

<p>
	إنّ الهدف من هذه السلسلة هو تعليم البرمجة للمبتدئين، ورغم أننا نستخدم بايثون في الشرح؛ إلا أنك تستطيع قراءة لغة برمجة أخرى واستخدامها بدلًا منها، بل إن هذا هو عين ما نتوقعه منك، إذ أنه لا توجد لغة برمجة بما فيها بايثون، تستطيع تنفيذ جميع المهام وحل كل المشاكل التي تواجهك برمجيًا، وبسبب ذات الهدف لن نشرح جميع الخصائص الموجودة في بايثون، بل سنركز على تلك التي يمكن إيجادها في لغات البرمجة الأخرى كذلك، ولهذا سنهمل شرح بعض الخصائص بالغة القوة في بايثون، والتي تميزها عما سواها، مثل العوامل الخاصة special operators، ذلك أن أغلب لغات البرمجة تدعم عمليات بعينها لا تدعمها لغات أخرى، وتلك العوامل الفريدة هي التي تسبب ظهور لغات برمجة جديدة، وهي من العوامل المهمة في تحديد شهرة تلك اللغات من حيث الاستخدام فيما بعد.
</p>

<p>
	حيث تدعم بايثون مثلًا عمليات غير شائعة نسبيًا في لغات البرمجة الأخرى، مثل تشريح القائمة <code>spam[X:Y]‎</code> (إلى شرائح) list slicing من أجل استخراج شريحة من وسط القائمة أو السلسلة النصية أو الصف tuple، كما تدعم إسناد الصف Tuple الذي يسمح لنا بإسناد عدة قيم متغيرات مرةً واحدةً: <code>X, Y = (12, 34)‎</code>. كما تسهل تنفيذ العمليات على كل عضو من أعضاء تجميعة ما باستخدام الدالة <code>map()‎</code> التي سنشرحها في مقال لاحق من هذه السلسلة، إضافةً إلى الكثير من الخصائص التي جعلت بايثون تشتهر بأنها تأتي "مع البطارية" إشارةً إلى كثرة الملحقات والمزايا التي تأتي معها. ارجع إلى توثيق بايثون للمزيد عن تلك المزايا.
</p>

<p>
	تجدر أخيرًا الإشارة إلى أنه رغم قولنا بأن تلك العوامل خاصة ببايثون؛ إلا أن هذا لا يعني أنها لا توجد في لغات برمجة أخرى، بل أنها لن توجد مجتمعةً في كل لغة، فالعوامل التي نشرحها في هذه السلسلة تكون متاحةً بشكل أو بآخر في أغلب لغات البرمجة الحديثة.
</p>

<p>
	يلخص هذا نظرتنا على المواد الخام للبرمجة، وسننتقل الآن إلى موضوع آخر نرى فيه كيف نستغل تلك المواد الخام في البرمجة الحقيقية.
</p>

<h2>
	شرح لمثال العناوين
</h2>

<p>
	رغم قولنا أننا سنشرح تفاصيل هذا المثال لاحقًا، إلا أننا رأينا صعوبة تنفيذ مثال بايثون من بعض القراء، ولهذا سيشرح هذا القسم شيفرة بايثون سطرًا سطرًا.
</p>

<p>
	ستبدو شيفرة المثال كاملة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_99" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">:</span><span class="pln">
</span><span class="pun">...</span><span class="pln">   </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Hs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">St</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Town</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Zip</span><span class="pun">):</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hs</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">St</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">Town</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Town</span><span class="pln">
</span><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">Zip_Code</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Zip</span><span class="pln">
</span><span class="pun">...</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> addr </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="str">"High St"</span><span class="pun">,</span><span class="str">"Anytown"</span><span class="pun">,</span><span class="str">"123 456"</span><span class="pun">)</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pun">,</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	وسنشرح الآن سطرًا سطرًا:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_101" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">:</span></pre>

<p>
	تخبر التعليمة <code>class</code> بايثون أننا على وشك تعريف نوع جديد اسمه <code>Address</code> في هذه الحالة، وتشير النقطتان الرأسيتان إلى أن أي أسطر مزاحة تالية ستكون جزءًا من تعريف الصنف، وينتهي التعريف عند أول سطر غير مزاح، فإذا كنت تستخدم IDLE؛ فسترى أن المحرر قد أزاح السطر التالي تلقائيًا، أما إذا كنت تعمل من محث بايثون في سطر أوامر DOS مثلًا، فسيكون عليك إزاحة الأسطر كما هو موضح أعلاه، ولا تهتم بايثون بمقدار الإزاحة طالما أنها نفسها لكل سطر.
</p>

<p>
	أما السطر الثاني:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_103" style=""><span class="pun">...</span><span class="pln">   </span><span class="kwd">def</span><span class="pln"> __init__</span><span class="pun">(</span><span class="pln">self</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Hs</span><span class="pun">,</span><span class="pln"> </span><span class="typ">St</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Town</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Zip</span><span class="pun">):</span></pre>

<p>
	يطلق على العنصر الأول في الصنف الخاص بنا "تعريف التابع method definition"، ويجب أن يكون حول الاسم شرطتان سفليتان على كل ناحية منه، وهي طريقة بايثون للأسماء التي لها أهمية خاصة، ويسمى ذلك التابع <code>__init__</code>، وهو عملية خاصة تنفذها بايثون حين ننشئ نسخةً من الصنف الجديد الخاص بنا كما سنرى بعد قليل؛ أما النقطتان الرأسيتان فتخبران بايثون أن مجموعة الأسطر المزاحة التالية ستكون هي التعريف الحقيقي للتابع.
</p>

<p>
	والسطر الثالث:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_105" style=""><span class="pun">...</span><span class="pln">     self</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Hs</span></pre>

<p>
	يُسنِد هذا السطر -والأسطر الثلاثة التالية- قيمًا إلى الحقول الداخلية للكائن الخاص بنا، وهذه الأسطر مزاحة من تعليمة <code>def</code> لتخبر بايثون أنها تشكل التعريف الحقيقي لعملية <code>__init__</code>، أما السطر الفارغ، فيخبر مفسر بايثون بأن تعريف الصنف قد انتهى، لنعود مرةً أخرى إلى محث بايثون المعتاد <code>‎&gt;&gt;&gt;‎</code>.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_107" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> addr </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Address</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="str">"High St"</span><span class="pun">,</span><span class="str">"Anytown"</span><span class="pun">,</span><span class="str">"123 456"</span><span class="pun">)</span></pre>

<p>
	ينشئ هذا نسخةً جديدةً من النوع <code>Address</code>، وتستخدم بايثون عملية <code>__init__</code> المعرَّفة أعلاه لإسناد القيم التي أعطيناها إلى الحقول الداخلية، وتسنَد النسخة إلى متغير <code>addr</code> كما تسنَد أي نسخة لأي نوع بيانات آخر.
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_951_109" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">HsNumber</span><span class="pun">,</span><span class="pln"> addr</span><span class="pun">.</span><span class="typ">Street</span><span class="pln"> </span><span class="pun">)</span></pre>

<p>
	نطبع الآن قيم حقلين من الحقول الداخلية مستخدمين عامل النقطة للوصول إليهما.
</p>

<h2>
	خاتمة
</h2>

<p>
	يُعَد هذا المقال دسمًا وغنيًا بالمعلومات النظرية التي تؤسس <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">لتعلم البرمجة </a>على أسس سليمة، وسنعود إلى ما فيه مرات كثيرة أثناء الشرح، بما أن البيانات وأنواعها هي اللبنات التي تُصنع منها البرامج، لكن نريد التذكير هنا بأن بايثون تسمح لنا بإنشاء أنواع البيانات التي نريدها بأنفسنا ونستخدمها مثل أي نوع مضمّن فيها، وأن المتغيرات تشير إلى بيانات، وقد نحتاج إلى التصريح عنها قبل تعريفها، وهي تأتي في أنواع شتى، ويتوقف نجاح العملية التي نجريها على نوع البيانات الذي نستخدمه.
</p>

<p>
	ومن أنواع البيانات البسيطة سلاسل المحارف والأعداد والقيم البوليانية أو قيم "الحقيقة"، كما تشمل أنوع البيانات المعقدة التجميعات والملفات والبيانات وأنواع البيانات المعرّفة من قِبل المستخدم.
</p>

<p>
	توجد أيضًا العديد من العوامل في كل لغة برمجة، وتيُعَد تعلّم تلك العوامل جزءًا من التعود على أنواع بياناتها وعلى العمليات المتاحة لتلك الأنواع، وقد يكون العامل الواحد متاحًا لعدة أنواع، غير أن النتيجة قد لا تكون هي نفسها في كل مرة، بل ربما تختلف اختلافًا كبيرًا.
</p>

<p>
	سنتابع مع المقال الموالي مع ذكر نوع أخر مهم من البيانات، وهو التجميعات Collections.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutdata.htm" rel="external nofollow">للفصل الخامس: The Raw Materials من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A7%D9%84%D8%AA%D8%AC%D9%85%D9%8A%D8%B9%D8%A7%D8%AA-collections-r1288/" rel="">مدخل إلى البيانات وأنواعها: التجميعات Collections</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1281/" rel="">التسلسلات البسيطة في البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/html/html5/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B5%D9%81%D9%8A%D8%A9-microdata-%D9%81%D9%8A-html5-r375/" rel="">مدخل إلى البيانات الوصفية (microdata) في HTML5</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/javascript/%D9%87%D9%8A%D8%A7%D9%83%D9%84-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D9%83%D8%A7%D8%A6%D9%86%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-%D8%AC%D8%A7%D9%81%D8%A7%D8%B3%D9%83%D8%B1%D9%8A%D8%A8%D8%AA-r1234/" rel="">هياكل البيانات: الكائنات والمصفوفات في جافاسكريبت</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1287</guid><pubDate>Mon, 09 Aug 2021 15:01:00 +0000</pubDate></item><item><title>&#x625;&#x639;&#x62F;&#x627;&#x62F; &#x627;&#x644;&#x62A;&#x643;&#x627;&#x645;&#x644; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x645;&#x631; &#x648;&#x627;&#x644;&#x646;&#x634;&#x631; &#x627;&#x644;&#x645;&#x633;&#x62A;&#x645;&#x631; &#x628;&#x627;&#x633;&#x62A;&#x62E;&#x62F;&#x627;&#x645; &#x627;&#x644;&#x62E;&#x62F;&#x645;&#x62A;&#x64A;&#x646; CircleCI &#x648;Coveralls</title><link>https://academy.hsoub.com/programming/general/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%AA%D9%83%D8%A7%D9%85%D9%84-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%85%D8%B1-%D9%88%D8%A7%D9%84%D9%86%D8%B4%D8%B1-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%85%D8%B1-%D8%A8%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85-%D8%A7%D9%84%D8%AE%D8%AF%D9%85%D8%AA%D9%8A%D9%86-circleci-%D9%88coveralls-r1276/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_07/6103a71f056a7_-------CircleCI-Coveralls-------CircleCI-Coveralls.png.9ccec13bc91b799c09ddc88b269c0ea2.png" /></p>

<p>
	يُعَد إعداد تطبيقات الويب لعمليتيْ <a href="https://ar.wikipedia.org/wiki/%D8%AA%D8%B1%D9%83%D9%8A%D8%A8_%D9%85%D8%AA%D9%88%D8%A7%D8%B5%D9%84" rel="external nofollow">التكامل المستمر</a> Continuous Integration والنشر المستمر Continuous Deployment مرحلةً بالغة الأهمية في مجال التطوير، ويُرمَز لها اختصارًا بـ CI/CD، فقد تتعرض جميع المشاريع البرمجية للأخطاء مهما كانت أحجامها وخاصةً عندما يجتمع الفريق البرمجي ليَعمَل على مشروعٍ واحدٍ، إذ يَسُهل إيجاد وإصلاح هذه الأخطاء إذا كان هناك تكاملٌ وإعدادٌ دائمٌ لنشر التطبيقات بصورةٍ مستمرةٍ وذلك باستخدام اختباراتٍ مُحكمَة الإعداد.
</p>

<p>
	سنتعرّف في هذا المقال على كيفية التحقق من تغطية الاختبار test coverage، كما سنُعِدّ تطبيقات الويب لعمليتيْ التكامل المستمر والنشر المستمرة CI/CD، وذلك باستخدام CircleCI وCoveralls، وسنتطرق كذلك إلى كيفية نَشْر تطبيق Vue <a href="https://ar.wikipedia.org/wiki/%D9%81%D9%8A%D9%88_%D8%AC%D9%8A_%D8%A3%D8%B3" rel="external nofollow">فيو جي إس</a> على منصة هيروكو Heroku، ستستفيد من هذا المقال حتى إذا كنت مِمن لا يُفضّل هذا الخليط من الأدوات، حيث يمكنك أن تَستخدِم إطار عملٍ مختلفٍ عن فيو جي إس مثلًا لكتابة جافاسكربت، إذ ستبقى المبادئ الأساسية هي ذاتها.
</p>

<p>
	وقبل ذلك إليك بعض المصطلحات.
</p>

<ul>
<li>
		<strong>التكامل المستمر Continuous integration</strong>: وفيها يُثبّت commit المُطوّرون الكود الذي يكتبونه مُبكرًا وبصورةٍ مستمرةٍ، مما يتيح إمكانية تطبيق اختباراتٍ وعمليات بناءٍ عديدةٍ قَبل الدمج أو النشر.
	</li>
	<li>
		<strong>النشر المستمر Continuous deployment</strong>: وفيه يَحرِص المُطوّرون على أن تَقبَل البرمجية النشْر في كل الأوقات.
	</li>
	<li>
		<strong>تغطية الاختبار Test Coverage</strong>: وهو مقياسٌ يَصِف درجة اختبار البرمجية، حيث يُشير مصطلح البرمجية ذات التغطية العالية إلى أن غالبية كود هذه البرمجية يَخضَع للاختبار.
	</li>
</ul>
<p>
	ولتحقيق أقصى استفادةٍ من هذا البرنامج التعليمي يُستحسَن أن يكون لديك ما يلي:
</p>

<ul>
<li>
		<strong>حساب في منصة CircleCI</strong>: وهي منصةٌ للتكامل المستمر والنشر المستمر CI/CD، وسنستفيد منها في برنامجنا التعليمي عن طريق استخدامها للنّشْر الآلي الذي يتضمن اختبار وبناء التطبيق قَبل النّشْر.
	</li>
	<li>
		<strong>حساب في موقع غيت هاب Github</strong>: وهو الموقع الذي سنُخزّن في مُستودَعٍ repository فيه كود المشروع واختباراته.
	</li>
	<li>
		<strong>حساب في منصة هيروكو Heroku</strong>: وهي منصةٌ خاصةٌ بنشر وتوسيع نطاق التطبيقات، وسنستخدمه من أجل نَشْر واستضافة hosting التطبيق.
	</li>
	<li>
		<strong>حساب في منصة Coveralls</strong>: وسنستخدم هذه المنصة لإظهار وتسجيل درجة وكفاءة تغطية الكود code coverage.
	</li>
	<li>
		<strong>حزمة NYC</strong>: وسنستخدم هذه الحزمة لنتحقق من خضوع الكود للتغطية بصورةٍ جيدةٍ.
	</li>
</ul>
<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		<strong>ملاحظة:</strong> يتَوفّر المُستودَع repository الذي يحتوي على المثال الموجود في هذا المقال على <a href="https://github.com/god-of-js/CI-CDtuts/tree/master" rel="external nofollow">غيت هاب</a>.
	</p>
</blockquote>

<h2>
	سنجهز الآن ما يلزمنا للعمل
</h2>

<p>
	سنبدأ بتثبيت حِزمة <a href="https://www.npmjs.com/package/nyc" rel="external nofollow">NYC</a> في مُجلد المشروع، هكذا:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_8" style="">
<span class="pln">npm i nyc</span></pre>

<p>
	بعدها سنُعدّل نصوص ملف <code>package.json</code> البرمجية لنتحقق من تغطية الاختبار، وإذا كنا سنتحقق من التغطية أثناء إجراء اختبارات الوِحدة unit tests، فسيتوجّب علينا تعديل النَّص البرمجي للاختبار، كما يأتي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8203_10" style="">
<span class="str">"scripts"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="str">"test:unit"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc vue-cli-service test:unit"</span><span class="pun">,</span><span class="pln">
</span><span class="pun">},</span></pre>

<p>
	لقد بُنَي الأمر السابق command على افتراض أننا سنبرمج تطبيق الويب باستخدام إطار عمل فيو Vue، إذ تُشير الخدمة <code>vue-cli-service</code> إليه، ولذلك إذا كنا سنستخدم إطار عملٍ آخرٍ في المشروع، فسيتعيّن علينا تغيير هذا الأمر؛ أما إذا كنا سنتحقق من التغطية بصورةٍ منفصلةٍ، فحينها سيتوجّب علينا إضافة سطرٍ آخرٍ إلى النصوص البرمجية، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_12" style="">
<span class="str">"scripts"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="str">"test:unit"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc vue-cli-service test:unit"</span><span class="pun">,</span><span class="pln">
  </span><span class="str">"coverage"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc npm run test:unit"</span><span class="pln">
</span><span class="pun">},</span></pre>

<p>
	وبعدها يمكننا التحقق من التغطية باستخدام أمر <code>npm run coverage</code> المُضّمن في واجهة سطر الأوامر terminal كالآتي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8203_15" style="">
<span class="pln">npm run coverage</span></pre>

<p>
	ثم سنُثبّت خدمة Coveralls، فهي مسؤولةٌ عن إيجاد وإظهار التغطية، هكذا:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8203_17" style="">
<span class="pln">npm i coveralls</span></pre>

<p>
	وبعد ذلك سنضيف خدمة <code>Coveralls</code> مثل نَّصٍ برمجيٍ في ملف <code>package.json</code>، حيث سيساعدنا هذا النَّص على حفظ تقرير تغطية الاختبار في Coveralls:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_8203_19" style="">
<span class="str">"scripts"</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
   </span><span class="str">"test:unit"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc vue-cli-service test:unit"</span><span class="pun">,</span><span class="pln">
       </span><span class="str">"coverage"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc npm run test:unit"</span><span class="pun">,</span><span class="pln">
       </span><span class="str">"coveralls"</span><span class="pun">:</span><span class="pln"> </span><span class="str">"nyc report --reporter=text-lcov | coveralls"</span><span class="pln">
</span><span class="pun">},</span></pre>

<p>
	كما سنستخدم هيروكو Heroku لاستضافة تطبيقنا، ولذلك سننتقل إلى لوحة إعداد dashboard هيروكو لنُسجّل التطبيق.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72922" href="https://academy.hsoub.com/uploads/monthly_2021_07/cavv1CkE.png.ec509a72459df4dbdd254b55b9116301.png" rel=""><img alt="cavv1CkE.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72922" data-unique="e745srlgg" src="https://academy.hsoub.com/uploads/monthly_2021_07/cavv1CkE.thumb.png.476cb14c935e1a273fbdd828b1f43cf8.png"></a>
</p>

<p>
	وسنستخدم منصة CircleCI لأتمتة عمليتيْ التكامل المستمر والنشر المستمر CI/CD، ولذلك سننتقل إلى لوحة إعداد CircleCI لنُهيّئ مشروعنا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72925" href="https://academy.hsoub.com/uploads/monthly_2021_07/GFXZcxtC.png.13395e0467a5411d6e8edeb503c3da43.png" rel=""><img alt="GFXZcxtC.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72925" data-unique="v9cumma3w" src="https://academy.hsoub.com/uploads/monthly_2021_07/GFXZcxtC.thumb.png.a687d75cc63b3dac32ffcce445453789.png"></a>
</p>

<p>
	ويمكننا استعراض قائمة مشاريعنا في غيت هاب بالانتقال إلى تبويب Projects في الشريط الجانبي لمنصة CircleCI، فبالنَّقر فوق زِرّ (أيقونة) Set Up Project أو إعداد المشروع، ستظهر صفحةٌ جديدةٌ تسألك عن ما إذا كنت تريد استخدام التهيئة config الموجودة مسبقًا أم لا، وبما أننا نمتلك تهيئةً مُعدّةً مسبقًا، فسنختار use an existing config أو استخدام تهيئةٍ موجودةٍ مسبقًا، وبعدها سننتقل إلى تبويب pipeline الخاص بالمشروع،
</p>

<p>
	بهذا نكون قد انتهينا من إعداد الاتصال بين مستودع repository غيت هاب ومنصة CircleCI، حيث حان دور إضافة متغيّرات البيئة إلى مشروع CircleCI.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72929" href="https://academy.hsoub.com/uploads/monthly_2021_07/MrClw8k4.png.8da3a2438f3eadcaeff6391b153db376.png" rel=""><img alt="MrClw8k4.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72929" data-unique="5a7ncv2xt" src="https://academy.hsoub.com/uploads/monthly_2021_07/MrClw8k4.thumb.png.5f2ced31eb79e1bb0f7314bfcae9eb1a.png"></a>
</p>

<p>
	ولإضافة متغيراتٍ جديدةٍ، يجب علينا الانتقال إلى إعدادات المشروع، هكذا.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72933" href="https://academy.hsoub.com/uploads/monthly_2021_07/ywfpjoFc.png.e09a3a97f0f25ec3ae8ba88445005961.png" rel=""><img alt="ywfpjoFc.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72933" data-unique="fp2i07a4m" src="https://academy.hsoub.com/uploads/monthly_2021_07/ywfpjoFc.thumb.png.d356efe805a19131437cda4457b5a045.png"></a>
</p>

<p>
	ستجد في الشريط الجانبي في إعدادات المشروع تبويب Environment Variables أو متغيّرات البيئة، وهو مكان تخزين المتغيّرات التي سنضيفها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72928" href="https://academy.hsoub.com/uploads/monthly_2021_07/maHAQR6Q.png.6d1954bf1b2c50618c8c980770cf19fa.png" rel=""><img alt="maHAQR6Q.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72928" data-unique="fpftz2z2b" src="https://academy.hsoub.com/uploads/monthly_2021_07/maHAQR6Q.thumb.png.74ad4c7fbf2018abf7768013555be0b8.png"></a>
</p>

<p>
	والمتغيّرات التي سنحتاجها في هذا البرنامج التعليمي هي:
</p>

<ul>
<li>
		HEROKU_APP_NAME: اسم تطبيق <a href="https://www.heroku.com/" rel="external nofollow">هيروكو</a>.
	</li>
	<li>
		HEROKU_API_KEY: مفتاح واجهة التطبيقات البرمجية <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> لمنصة هيروكو Heroku.
	</li>
	<li>
		COVERALLS_REPO_TOKEN: مفتاحٌ مساعدٌ token لمستودع Coveralls.
	</li>
</ul>
<p>
	ويمكننا إيجاد مفتاح واجهة التطبيقات البرمجية <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> لمنصة هيروكو Heroku في قسم <strong>account</strong> الموجود في <a href="https://dashboard.heroku.com/account" rel="external nofollow">لوحة إعداد هيروكو</a>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72926" href="https://academy.hsoub.com/uploads/monthly_2021_07/iDzf6rqg.png.5e557d1b36fea41966580c141f377cb2.png" rel=""><img alt="iDzf6rqg.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72926" data-unique="yd8ccen5y" src="https://academy.hsoub.com/uploads/monthly_2021_07/iDzf6rqg.thumb.png.81ccfbd31bbc571621ad91dfa4752a07.png"></a>
</p>

<p>
	ويوجد المفتاح المساعد token للمستودع repository في حساب Coveralls، ولذلك سنضيف المستودع إلى Coveralls أولًا، وهنا سنختار مستودع غيت هاب المناسب من قائمة المستودعات المتوفرة، كما هو موضح بالصورة الآتية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72924" href="https://academy.hsoub.com/uploads/monthly_2021_07/cjnAMj6I.png.598ad10957a1ae7b0f1b2a5a5d0f219e.png" rel=""><img alt="cjnAMj6I.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72924" data-unique="3anc81v1r" src="https://academy.hsoub.com/uploads/monthly_2021_07/cjnAMj6I.thumb.png.72bdef56dbffa29b84be0095f4d088a2.png"></a>
</p>

<p>
	والآن بعد أن أضفنا المستودع إلى Coveralls، يمكننا النقر على المستودع لجَلْب المفتاح المُساعد token.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72932" href="https://academy.hsoub.com/uploads/monthly_2021_07/ug_Ux80t.png.0684ed1821f52f2c8b009f1c05030d14.png" rel=""><img alt="ug_Ux80t.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72932" data-unique="5mmx2y91l" src="https://academy.hsoub.com/uploads/monthly_2021_07/ug_Ux80t.thumb.png.85a45df200218a3d0d7c640fd32989eb.png"></a>
</p>

<h2>
	دمج CircleCI
</h2>

<p>
	بعد أن أنهينا ربط CircleCI مع مستودع غيت هاب، فسيُبَلّغ CircleCI عند حدوث تغيير ٍأو إجراءٍ في مستودع غيت هاب، وسنتّبع الآن الخطوات المناسبة لإبلاغ CircleCI بالعمليات التي نريد تنفيذها بعد حدوث تغييرٍ في المستودع، بعد ذلكسننشئ مجلدًا باسم <code>circleci</code> في مجلد الجذر root لمشروعنا المحلي، وسنضع فيه ملفًا باسم <code>config.yml</code> وهو الملف الذي سيحتوي على كلّ عمليات CircleCI.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72923" href="https://academy.hsoub.com/uploads/monthly_2021_07/cGszd9c8.png.be33467725a87827c5fc76500ee86ebf.png" rel=""><img alt="cGszd9c8.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72923" data-unique="iw2rszh1m" src="https://academy.hsoub.com/uploads/monthly_2021_07/cGszd9c8.png.be33467725a87827c5fc76500ee86ebf.png"></a>
</p>

<p>
	وإليك الشيفرة البرمجية التي سنضعها في الملف:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_36" style="">
<span class="pln">version</span><span class="pun">:</span><span class="pln"> </span><span class="lit">2.1</span><span class="pln">
orbs</span><span class="pun">:</span><span class="pln">
 node</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">node@1</span><span class="pun">.</span><span class="lit">1</span><span class="pln"> </span><span class="com">// node orb</span><span class="pln">
 heroku</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">heroku@0</span><span class="pun">.</span><span class="lit">0.10</span><span class="pln"> </span><span class="com">// heroku orb</span><span class="pln">
 coveralls</span><span class="pun">:</span><span class="pln"> coveralls</span><span class="pun">/</span><span class="pln">coveralls@1</span><span class="pun">.</span><span class="lit">0.6</span><span class="pln"> </span><span class="com">// coveralls orb</span><span class="pln">
workflows</span><span class="pun">:</span><span class="pln">
 heroku_deploy</span><span class="pun">:</span><span class="pln">
   jobs</span><span class="pun">:</span><span class="pln">
     </span><span class="pun">-</span><span class="pln"> build
     </span><span class="pun">-</span><span class="pln"> heroku</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">-</span><span class="pln">via</span><span class="pun">-</span><span class="pln">git</span><span class="pun">:</span><span class="pln"> </span><span class="com"># Use the pre-configured job</span><span class="pln">
       requires</span><span class="pun">:</span><span class="pln">
         </span><span class="pun">-</span><span class="pln"> build
       filters</span><span class="pun">:</span><span class="pln">
         branches</span><span class="pun">:</span><span class="pln">
           only</span><span class="pun">:</span><span class="pln"> master
jobs</span><span class="pun">:</span><span class="pln">
 build</span><span class="pun">:</span><span class="pln">
   docker</span><span class="pun">:</span><span class="pln">
     </span><span class="pun">-</span><span class="pln"> image</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">node</span><span class="pun">:</span><span class="lit">10.16</span><span class="pun">.</span><span class="lit">0</span><span class="pln">
   steps</span><span class="pun">:</span><span class="pln">
     </span><span class="pun">-</span><span class="pln"> checkout
     </span><span class="pun">-</span><span class="pln"> restore_cache</span><span class="pun">:</span><span class="pln">
       key</span><span class="pun">:</span><span class="pln"> dependency</span><span class="pun">-</span><span class="pln">cache</span><span class="pun">-{{</span><span class="pln"> checksum </span><span class="str">"package.json"</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
     </span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln">
       name</span><span class="pun">:</span><span class="pln"> install</span><span class="pun">-</span><span class="pln">npm</span><span class="pun">-</span><span class="pln">dependencies
       command</span><span class="pun">:</span><span class="pln"> npm install
     </span><span class="pun">-</span><span class="pln"> save_cache</span><span class="pun">:</span><span class="pln">
       key</span><span class="pun">:</span><span class="pln"> dependency</span><span class="pun">-</span><span class="pln">cache</span><span class="pun">-{{</span><span class="pln"> checksum </span><span class="str">"package.json"</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
       paths</span><span class="pun">:</span><span class="pln">
         </span><span class="pun">-</span><span class="pln"> </span><span class="pun">./</span><span class="pln">node_modules
     </span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln"> </span><span class="com"># run tests</span><span class="pln">
       name</span><span class="pun">:</span><span class="pln"> test
       command</span><span class="pun">:</span><span class="pln"> npm run test</span><span class="pun">:</span><span class="pln">unit
     </span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln"> </span><span class="com"># run code coverage report</span><span class="pln">
       name</span><span class="pun">:</span><span class="pln"> code</span><span class="pun">-</span><span class="pln">coverage
       command</span><span class="pun">:</span><span class="pln"> npm run coveralls
     </span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln"> </span><span class="com"># run build</span><span class="pln">
       name</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Build</span><span class="pln">
       command</span><span class="pun">:</span><span class="pln"> npm run build
     </span><span class="com"># - coveralls/upload</span></pre>

<p>
	كما تلاحظ؛ تُعَد هذه الشيفرة البرمجية كبيرة ولذلك سنقسمها إلى أجزاءٍ لنشرح كلّ جزءٍ على حدةٍ.
</p>

<h2>
	حزم Orbs
</h2>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_23" style="">
<span class="pln">orbs</span><span class="pun">:</span><span class="pln">
 node</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">node@1</span><span class="pun">.</span><span class="lit">1</span><span class="pln"> </span><span class="com">// node orb</span><span class="pln">
 heroku</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">heroku@0</span><span class="pun">.</span><span class="lit">0.10</span><span class="pln"> </span><span class="com">// heroku orb</span><span class="pln">
 coveralls</span><span class="pun">:</span><span class="pln"> coveralls</span><span class="pun">/</span><span class="pln">coveralls@1</span><span class="pun">.</span><span class="lit">0.6</span><span class="pln"> </span><span class="com">// coveralls orb</span></pre>

<p>
	تُعَد <a href="https://circleci.com/docs/2.0/orb-intro/" rel="external nofollow">Orbs</a> حِزمًا مفتوحة المصدر، فهي تُستَخدم لتبسيط تكامل البرامج والحِزم في المشاريع، وقد سبق وأشرنا في الكود الخاص بنا إلى حِزم orbs التي نستخدمها في عمليتيْ التكامل المستمر والنشر المستمر CI/CD، وإلى حِزمة orbs التي تَحمِل الاسم <code>node</code> وذلك لأننا نستخدم جافاسكربت، وإلى هيروكو Heroku لأننا نُنفّذ النشر المؤتمت باستخدام سيْر عمل workflow من هيروكو، وأيضًا إلى حِزمة <code>coveralls</code> من orbs لأننا نُخَطّط لإرسال نتائج تغطية الاختبار إلى Coveralls.
</p>

<p>
	تُعَد حزمتيْ <code>Heroku</code> و<code>Coveralls</code> من orbs حزمًا خارجيةً، فعند تشغيل التطبيق عن طريق الاختبار، فسيؤدي ذلك إلى حدوث خطأ يمكننا التخلص منه بالانتقال إلى صفحة Organization Settings في حساب CircleCI.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72921" href="https://academy.hsoub.com/uploads/monthly_2021_07/5iSnVvuP.png.589ad059a273d36a41f716a545f11f1d.png" rel=""><img alt="5iSnVvuP.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72921" data-unique="geyu3smob" src="https://academy.hsoub.com/uploads/monthly_2021_07/5iSnVvuP.thumb.png.1aac9a423236b39d30ddcd4b5f4864d3.png"></a>
</p>

<p>
	بعد ذلك سننتقل إلى تبويب <strong>Security</strong> أو الأمان، بحيث نُفعّل حِزم orbs غير المعتمدة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72927" href="https://academy.hsoub.com/uploads/monthly_2021_07/k1HYPT9c.png.dd244a9165e7b53b4b1ec5176dd2498e.png" rel=""><img alt="k1HYPT9c.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72927" data-unique="v4oh4fanc" src="https://academy.hsoub.com/uploads/monthly_2021_07/k1HYPT9c.thumb.png.a647ebb939d0b06b614ae67e6f933ddd.png"></a>
</p>

<h2>
	سير العمل Workflow
</h2>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_33" style="">
<span class="pln">workflows</span><span class="pun">:</span><span class="pln">
   heroku_deploy</span><span class="pun">:</span><span class="pln">
       jobs</span><span class="pun">:</span><span class="pln">
           </span><span class="pun">-</span><span class="pln"> build
           </span><span class="pun">-</span><span class="pln"> heroku</span><span class="pun">/</span><span class="pln">deploy</span><span class="pun">-</span><span class="pln">via</span><span class="pun">-</span><span class="pln">git</span><span class="pun">:</span><span class="pln"> </span><span class="com"># Use the pre-configured job</span><span class="pln">
requires</span><span class="pun">:</span><span class="pln">
   </span><span class="pun">-</span><span class="pln"> build
filters</span><span class="pun">:</span><span class="pln">
   branches</span><span class="pun">:</span><span class="pln">
       only</span><span class="pun">:</span><span class="pln"> master</span></pre>

<p>
	يُستخدم <a href="https://circleci.com/docs/2.0/workflows/" rel="external nofollow">سير العمل</a> لتحديد مجموعةٍ من الوظائف ثم تشغيلها بالترتيب، وهذا القِسم من الكود مسؤول عن الاستضافة المؤتمتة، فهو يوعز إلى CircleCI ببناء المشروع ثم نشره، حيث تشير <code>requires</code> إلى أن وظيفة <code>heroku/deploy-via-git</code> تتطلب اكتمال البناء، مما يعني أن عملية النشر لن تَحصُل قبل اكتمال البناء.
</p>

<h2>
	الوظائف Jobs
</h2>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_31" style="">
<span class="pln">jobs</span><span class="pun">:</span><span class="pln">
   build</span><span class="pun">:</span><span class="pln">
       docker</span><span class="pun">:</span><span class="pln">
           </span><span class="pun">-</span><span class="pln"> image</span><span class="pun">:</span><span class="pln"> circleci</span><span class="pun">/</span><span class="pln">node</span><span class="pun">:</span><span class="lit">10.16</span><span class="pun">.</span><span class="lit">0</span><span class="pln">
steps</span><span class="pun">:</span><span class="pln">
   </span><span class="pun">-</span><span class="pln"> checkout
   </span><span class="pun">-</span><span class="pln"> restore_cache</span><span class="pun">:</span><span class="pln">
key</span><span class="pun">:</span><span class="pln"> dependency</span><span class="pun">-</span><span class="pln">cache</span><span class="pun">-{{</span><span class="pln"> checksum </span><span class="str">"package.json"</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
</span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln">
name</span><span class="pun">:</span><span class="pln"> install</span><span class="pun">-</span><span class="pln">npm</span><span class="pun">-</span><span class="pln">dependencies
command</span><span class="pun">:</span><span class="pln"> npm install
</span><span class="pun">-</span><span class="pln"> save_cache</span><span class="pun">:</span><span class="pln">
key</span><span class="pun">:</span><span class="pln"> dependency</span><span class="pun">-</span><span class="pln">cache</span><span class="pun">-{{</span><span class="pln"> checksum </span><span class="str">"package.json"</span><span class="pln"> </span><span class="pun">}}</span><span class="pln">
paths</span><span class="pun">:</span><span class="pln">
   </span><span class="pun">-</span><span class="pln"> </span><span class="pun">./</span><span class="pln">node_modules</span></pre>

<p>
	تُعَبر الوظيفة job عن مجموعةٍ من الخطوات، حيث سنستعيد في هذا القِسم من الكود التبعيات dependencies التي ثُبّتت أثناء عمليات البناء السابقة للمشروع وذلك من خلال الوظيفة <code>restore_cache</code> أو استعادة الذاكرة المؤقتة، ثم سنُثبّت التبعيات غير المخبّأة uncached dependencies، وسنحفظها كي لا نُعيد تثبيتها أثناء عملية البناء التالية. بعد ذلك سنطلب من CircleCI إجراء الاختبارات التي كتبناها للمشروع، بالإضافة إلى التحقق من التغطية الاختبارية للمشروع.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		لاحظ أن إجراء عملية تخبئة caching على التبعيات dependencies تجعل عمليات البناء اللاحقة أسرع، وذلك لأننا نُخزّن التبعيات، وبالتالي لا حاجة لإعادة تثبيت تلك التبعيات أثناء عملية البناء التالية.
	</p>
</blockquote>

<h2>
	رفع تغطية الكود الخاص بنا إلى منصة coveralls
</h2>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_8203_29" style="">
<span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln"> </span><span class="com"># run tests</span><span class="pln">
   name</span><span class="pun">:</span><span class="pln"> test
   command</span><span class="pun">:</span><span class="pln"> npm run test</span><span class="pun">:</span><span class="pln">unit
 </span><span class="pun">-</span><span class="pln"> run</span><span class="pun">:</span><span class="pln"> </span><span class="com"># run code coverage report</span><span class="pln">
   name</span><span class="pun">:</span><span class="pln"> code</span><span class="pun">-</span><span class="pln">coverage
   command</span><span class="pun">:</span><span class="pln"> npm run coveralls
</span><span class="com"># - coveralls/upload</span></pre>

<p>
	وستظهر قدرات coveralls بصورةٍ جليةٍ، بوصلنا إلى مكان إجراء اختبارات الوِحدة تَذكّر أننا أضفنا الأمر <code>nyc</code> إلى النص البرمجي الذي يُسمّى <code>test:unit</code> إلى ملف <code>package.json</code>، حيث ستَوفّر اختبارات الوِحدة تغطيةً الكود بفضل هذا الأمر.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		توفر اختبارات الوحدة تغطية للكود أيضًا، لذلك سنضمنها في تقرير التغطية، ما يفسّر سبب استدعائنا للأمر هنا.
	</p>
</blockquote>

<p>
	في النهاية، سيُشغّل الكود النَّص البرمجي الذي يُسمّى Coveralls والذي سبق وأضفناه إلى ملف <code>package.json</code>، حيث سيتولى هذا النَّص مَهمّة إرسال تقرير التغطية الخاص بنا إلى coveralls، ولعلك لاحظت عدم خضوع السطر <code>coveralls/upload</code> للتنفيذ (تعليق comment)، إذ كان من المفترض أن يكون السطر النهائي في العملية، ولكنه أصبح في النهاية مُعوّقًا كما يقول المطورون، وأوقفته عن التنفيذ بتعليقه (تعليق comment)، ولم أحذفه لأنه قد يكون ورقةً رابحةً لمطورٍ آخرٍ.
</p>

<h2>
	تجهيز الأمور ودمجها سوية
</h2>

<p>
	إليك تطبيقنا الجاهز بعد تطبيق كلّ من التكامل المستمر والنشر المستمر
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72930" href="https://academy.hsoub.com/uploads/monthly_2021_07/passimage.png.ed8b1e9654be33c5f387876905e9cc6b.png" rel=""><img alt="passimage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72930" data-unique="e6ne9njo8" src="https://academy.hsoub.com/uploads/monthly_2021_07/passimage.thumb.png.70d1c12f1811ab69f5ce38db2399371a.png"></a>
</p>

<p>
	حيث تظهر فائدة التكامل والنشر المستمر في كثيرٍ من الحالات، ومن الأمثلة الشائعة لها؛ الحالة التي تكون فيها البرمجيّة في طور الاختبار، ففي هذه المرحلة تَحدُث الكثير من عمليات التصحيح على الكود، مما يؤدي إلى عمليات تثبيتٍ commit كثيرةٍ للكود البرمجي، ولنكون واقعيين، ,ولتفادي التكرار، فلا نودّ تشغيل الاختبارات ونشر التطبيق بصورةٍ يدويةٍ بعد كلّ تغييرٍ طفيفٍ يحدث.
</p>

<p>
	في الواقع، لقد كنا على درايةٍ بالتكامل المستمر والنشر المستمر CI/CD منذ فترةٍ طويلةٍ نسبيًا، ومع ذلك تجاهلنا هاتين العمليتين لأن الأمر كان يبدو صعبًا للغاية أو قد يستغرق وقتًا طويلاً، ولكن الآن بعد أن رأيت مدى سهولة الإعداد والفوائد التي تنتج عنهما، فيمكنك تُجرّبهما في مشروعك القادم.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://css-tricks.com/a-continuous-integration-and-deployment-setup-with-circleci-and-coveralls/" rel="external nofollow">A Continuous Integration and Deployment Setup with CircleCI and Coveralls</a> من موقع <a href="https://css-tricks.com" rel="external nofollow">CSS Tricks</a>.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a href="https://academy.hsoub.com/programming/cpp/%D8%A7%D8%AE%D8%AA%D8%A8%D8%A7%D8%B1-%D8%A7%D9%84%D9%88%D8%AD%D8%AF%D8%A7%D8%AA-%D9%88%D8%A3%D8%AF%D9%88%D8%A7%D8%AA-%D8%AA%D9%86%D9%82%D9%8A%D8%AD-%D8%A7%D9%84%D8%B4%D9%8A%D9%81%D8%B1%D8%A7%D8%AA-%D9%88%D8%AA%D8%B5%D8%AD%D9%8A%D8%AD-%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D9%81%D9%8A-cpp-r1190/" rel="">اختبار الوحدات وأدوات تنقيح الشيفرات وتصحيح الأخطاء في Cpp</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/workflow/git/%D9%84%D9%85%D8%A7%D8%B0%D8%A7-%D8%B9%D9%84%D9%8A%D9%83-%D8%AC%D8%B9%D9%84-%D8%A7%D9%84%D8%A3%D8%B0%D9%88%D9%86%D8%A7%D8%AA-%D8%B9%D9%84%D9%89-%D8%A7%D9%84%D9%81%D8%B1%D8%B9-%D8%A7%D9%84%D8%B1%D8%A6%D9%8A%D8%B3%D9%8A-master-%D9%84%D9%84%D9%82%D8%B1%D8%A7%D8%A1%D8%A9-%D9%81%D9%82%D8%B7%D8%9F-r762/" rel="">لماذا عليك جعل الأذونات على الفرع الرئيسي master للقراءة فقط؟</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/devops/linux/%D8%A7%D9%84%D8%AA%D9%83%D8%A7%D9%85%D9%84-%D8%A7%D9%84%D9%85%D8%B3%D8%AA%D9%85%D8%B1-%D8%AA%D8%AB%D8%A8%D9%8A%D8%AA-concourse-ci-%D8%B9%D9%84%D9%89-%D8%A3%D9%88%D8%A8%D9%86%D8%AA%D9%88-1604-r356/" rel="">التكامل المستمر: تثبيت Concourse CI على أوبنتو 16.04</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1276</guid><pubDate>Fri, 30 Jul 2021 07:42:11 +0000</pubDate></item><item><title>&#x627;&#x644;&#x62A;&#x633;&#x644;&#x633;&#x644;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x633;&#x64A;&#x637;&#x629; &#x641;&#x64A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1281/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_07/610441a1b4f81_--.png.66b64f219da0648dee262abd6b14c2b6.png" /></p>
<p>
	يتكون أبسط برنامج يمكن كتابته من سلسلة من بعض التعليمات statements المتتالية، وأصغرها هو الذي يحتوي تعليمةً برمجيةً واحدةً، حيث تُدخَل التعليمة عادةً في سطر واحد، كما يمكن أن تُقسم على عدة أسطر، وتعرَّف التعليمة بأنها مجموعة من الكلمات والرموز المكتوبة بلغة طبيعية، وسننظر الآن في بعضها، إذ تُظهر الأمثلة التالية ما يجب أن نكتبه في محث بايثون <code>‎&gt;&gt;&gt;‎</code>، كما تُظهر النتيجة، ثم نشرح ما حدث.
</p>

<h3>
	عرض الخرج
</h3>

<p>
	يجب أن نتعلم أولًا كيف نجعل بايثون تعرض المعلومات التي نريدها، فإذا لم تعرض لنا اللغة شيئًا، فكيف نعرف ما فعله الحاسوب؟ وما فائدة الجهد الذي نبذله في البرمجة حينها إذا كنا لا نعرف هل أصبنا أم أخطأنا؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_10" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="str">'Hello there!'</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Hello</span><span class="pln"> there</span><span class="pun">!</span></pre>

<p>
	انتبه إلى الملاحظة الأولى في المثال أعلاه، وهي أن المسافة التي بين المحث وبين أمر <code>print</code> ليست ضرورية، إذ ستضعها بايثون تلقائيًا إذا نسيناها، وما سنكتبه هو السطر الأول فقط؛ أما السطر الثاني فهو نتيجة البرنامج الذي كتبناه في السطر الأول، وقد عرضه لنا المفسر.
</p>

<p>
	أما الملاحظة الثانية فهي أن بايثون حساسة لحالة الأحرف، حيث سنحصل على خطأ إذا كتبنا <code>Print</code> بدلًا من <code>print</code> لأن بايثون تراهما كلمتين مختلفتين، وكذلك الحال بالنسبة لجافاسكربت؛ أما لغة VBScript فلا تهتم لهذا، لكن يجب تعويد النفس على الاهتمام بحالة الأحرف كعادة برمجية حسنة لئلا تقع في أخطاء بسببها إذا انتقلت من لغة برمجية لأخرى.
</p>

<p>
	وقد عرض لنا المفسر النص المكتوب بين علامتي الاقتباس لأن الدالة <code>print()‎</code> تخبر بايثون بعرض تسلسل المحارف <code>H,e,l,l,o, ,t,h,e,r,e,!‎</code>، وهو ما يُعرَف في الأوساط البرمجية باسم السلسلة النصية string، أو سلسلة المحارف النصية، حيث يجب أن تكون تلك المحارف داخل أقواس، وندل على السلسلة النصية بوضعها بين علامات الاقتباس، كما يمكن استخدام علامات الاقتباس المفردة أو المزدوجة في بايثون دون حرج، مما يسمح لنا بإدخال أحد نوعي الاقتباس في سلسلة نصية محاطة بالنوع الآخر، وهذا مفيد في حالة الفاصلة الإنجليزية العليا <code>'</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6828_12" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="str">"Monty Python's Flying Circus has a ' within it..."</span><span class="pun">)</span><span class="pln">
</span><span class="typ">Monty</span><span class="pln"> </span><span class="typ">Python</span><span class="str">'s Flying Circus has a '</span><span class="pln"> within it</span><span class="pun">...</span></pre>

<p>
	أما جافاسكربت وVBScript فحساستان لنوع علامات التنصيص التي يجب استخدامها، لهذا يُنصح فيهما بالالتزام بالعلامات المزدوجة ما أمكن.
</p>

<h3>
	عرض النتائج الحسابية
</h3>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_14" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">6</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln">
</span><span class="lit">11</span></pre>

<p>
	يطبع لنا المثال أعلاه نتيجة العملية الحسابية التي في السطر الأول، والتي جمعنا فيها 5 إلى 6، وقد عرفت بايثون أن هذه المحارف أرقام وعاملتها على هذا الأساس، كما تعرفت على علامة الجمع التي بينهما، فجمعت العددين وأخرجت لنا الناتج، لذا يمكن القول أن بايثون مفيدة كحاسبة للجيب، وهو أحد استخداماتها الكثيرة جدًا، جرب الآن بعض الحسابات الأخرى واستخدم العوامل الحسابية التالية:
</p>

<ul>
	<li>
		الطرح (-).
	</li>
	<li>
		الضرب (*).
	</li>
	<li>
		القسمة (/).
	</li>
</ul>

<p>
	يمكن دمج عدة تعبيرات حسابية كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_16" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="pun">((</span><span class="lit">6</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">5</span><span class="pun">))</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">4.0</span></pre>

<p>
	لاحظ الطريقة التي استخدمنا بها الأقواس لوضع الأعداد في مجموعات، لقد رأت بايثون تلك العملية السابقة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_18" style=""><span class="pun">((</span><span class="lit">6</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">5</span><span class="pun">))</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">30</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">8</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">32</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">8</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">4</span></pre>

<p>
	فماذا يحدث لو كتبنا نفس العمليات دون الأقواس؟
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_20" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">6</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="lit">37.2857142857</span></pre>

<p>
	حصلنا على هذه النتيجة لأن بايثون تنفذ عمليتي الضرب والقسمة قبل الجمع والطرح، لذا رأتها على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_22" style=""><span class="pun">(</span><span class="lit">6</span><span class="pun">*</span><span class="lit">5</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="lit">5</span><span class="pun">/</span><span class="lit">7</span><span class="pun">)</span><span class="pln">  </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">30</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">0.7143</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">37</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">0.7143</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">38</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">0.7143</span><span class="pln">
</span><span class="pun">=&gt;</span><span class="pln"> </span><span class="lit">37.2857</span><span class="pun">...</span></pre>

<p>
	ومع أن ترتيب بايثون لمعالجة العمليات الحسابية هو نفسه الذي تقضيه قوانين الرياضيات، إلا أنه يختلف عما يجب عليك توقعه كونك مبرمجًا، لأن بعض لغات البرمجة لها قوانينها في ترتيب معالجة العمليات الحسابية، وهو ما يعرف بأسبقية العوامل operator precedence، لذا تأكد من النظر أولًا في توثيق لغة البرمجة التي تتعامل معها لترى أسلوبها الخاص؛ أما بايثون فقاعدتها العامة هي ما يقتضيه الحدس والمنطق، لكن هذا له استثناءاته، مما يجعل استخدام الأقواس خيارًا آمنًا لضمان حصولنا على النتيجة التي نريدها، خاصةً عند التعامل مع حسابات طويلة مثل التي رأيناها في المثال السابق، ومن الأمور التي يجب ملاحظتها أننا إذا استخدمنا عامل القسمة <code>/</code> فسنحصل على النتيجة الدقيقة للعملية، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_24" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">5</span><span class="pun">/</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">2.5</span></pre>

<p>
	فإذا أردنا الحفاظ على القسم الصحيح للناتج فقط فنستخدم عامليْ قسمة متتاليين <code>//</code> لنحصل على العدد الكامل في النتيجة، وستطبع بايثون ناتج القسمة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_26" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">5</span><span class="com">//2)</span><span class="pln">
</span><span class="lit">2</span></pre>

<p>
	أما إذا أردنا الحصول على باقي عملية القسمة فنستخدم محرف النسبة المئوية <code>%</code>:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_28" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">5</span><span class="pun">%</span><span class="lit">2</span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">7</span><span class="com">//4)</span><span class="pln">
</span><span class="lit">1</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="lit">7</span><span class="pun">%</span><span class="lit">4</span><span class="pun">)</span><span class="pln">
</span><span class="lit">3</span></pre>

<p>
	يُعرَف العامل <code>%</code> باسم عامل الباقي modulo، وقد يكون في بعض لغات البرمجة على الصورة <code>MOD</code> أو نحوها، أما في بايثون فنستطيع الحصول على ناتج القسمة والباقي معًا باستخدام الدالة <code>divmod()‎</code>:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6828_31" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> divmod</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="pun">(</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	هذه العمليات الحسابية للأعداد الصحيحة مهمة للغاية في البرمجة، فمنها نستطيع تحديد كون العدد زوجيًا أم فرديًا من خلال قسمته على 2 ورؤية الباقي (يكون زوجيًا إذا كان الباقي صفرًا)، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6828_33" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">print</span><span class="pun">(</span><span class="pln"> </span><span class="lit">47</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">)</span><span class="pln">
</span><span class="lit">1</span></pre>

<p>
	فنحن نعلم الآن أن العدد 47 هو عدد فردي، وقد يكون هذا أمرًا بدهيًا إذ يمكن معرفة هذا دون تكبد عناء لغة برمجية وانتظار خرج عملية فيها، لكن ماذا لو كنا نقرأ بيانات من ملف، أو كان المستخدم يدخل تلك البيانات، ثم يكون على برنامجنا معرفة هل العدد فردي أم زوجي من تلقاء نفسه، عندئذ لن نستطيع التدخل هنا لتقرير ذلك بالنظر في كل عدد، بل سنستخدم عامل الباقي كما فعلنا ليتحقق من المطلوب بدلًا منا، وتلك حالة واحدة فقط من الحالات التي تبرز فيها أهمية هذه العمليات، لذا تدرب عليها إلى أن تتقنها.
</p>

<h3>
	دمج السلاسل النصية والأعداد
</h3>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_35" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="str">'The total is: '</span><span class="pun">,</span><span class="pln"> </span><span class="lit">23</span><span class="pun">+</span><span class="lit">45</span><span class="pun">)</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> total is</span><span class="pun">:</span><span class="pln">  </span><span class="lit">68</span></pre>

<p>
	لقد طبعنا سلاسل نصيةً أوأعدادًا فيما سبق، أما الآن فسندمج الاثنين في تعليمة واحدة، فاصلين بينهما بفاصلة إنجليزية <code>,</code>، ويمكن توسيع تلك الميزة بجمعها مع إحدى خصائص بايثون في إخراج البيانات، وهي سلسلة التنسيق format string:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_37" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"The sum of %d and %d is: %d"</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="lit">18</span><span class="pun">,</span><span class="lit">7</span><span class="pun">+</span><span class="lit">18</span><span class="pun">))</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> sum of </span><span class="lit">7</span><span class="pln"> and </span><span class="lit">18</span><span class="pln"> is</span><span class="pun">:</span><span class="pln"> </span><span class="lit">25</span></pre>

<p>
	تحتوي سلسلة التنسيق على علامات <code>%</code>، غير أنها تختلف عن عامل الباقي الذي تحدثنا عنه من قبل، بل يكون لها معنىً خاص حين تُستخدم في سلسلة كالتي بين أيدينا، وحالات الاستخدام المتعددة تلك تعني أن علينا قراءة المكتوب بانتباه لتحديد سياقه، ثم تحديد وظيفة <code>%</code> فيه، حيث يخبر الحرف <code>d</code> الذي بعد محرف <code>%</code> بايثون بوجوب وضع عدد عشري مكانه، والذي نحصل على قيمته -التي سنستخدمها لتحل محله- من القيم الموجودة داخل التعبير الذي بين الأقواس، والذي كتِب بعد علامة <code>%</code> المنفردة في نهاية العبارة، ومن المهم أن يكون عدد القيم التي في القوس النهائي مطابقًا لعدد علامات <code>%</code> الموجودة في السلسلة النصية.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		<strong>تدريب:</strong> جرب التدرب على عدة صور من السطر السابق والبيانات التي تليه كي تفهم القاعدة فهمًا أفضل.
	</p>
</blockquote>

<p>
	توجد حروف أخرى يمكن وضعها بعد علامة <code>%</code>، ويستعمَل كل منها لغرض مختلف، منها:
</p>

<ul>
	<li>
		<code>‎%S</code> للسلاسل النصية.
	</li>
	<li>
		<code>‎%x</code> للأعداد الست عشرية hexadecimal.
	</li>
	<li>
		<code>%0.2f</code> للأعداد الحقيقية التي لها منزلتان عشريتان كحد أقصى.
	</li>
	<li>
		<code>%04d</code> لإزاحة العدد بأصفار قبله ليكون من أربعة منازل عشرية.
	</li>
</ul>

<p>
	انظر <a href="https://docs.python.org/3/library/stdtypes.html#old-string-formatting" rel="external nofollow">توثيق بايثون</a> للمزيد من المعلومات.
</p>

<p>
	ونستطيع طباعة أي كائن بايثون باستخدام دالة الطباعة، حتى لو كانت النتيجة على غير ما كنا نريد، فربما تكون وصفًا لنوع الكائن، لكننا نستطيع طباعة ذلك على أي حال.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<h3 data-gramm="false">
		أسلوب تنسيق السلسلة النصية
	</h3>

	<p>
		لقد غيرت بايثون أسلوب تنسيق السلاسل النصية في إصدارها الثالث عما ذكرناه في الفقرة السابقة إلى أسلوب قوي -على الرغم من تعقيده- باستخدام عملية <code>format</code>، مع استمرار استخدام الأسلوب القديم، وهو ما سنستخدمه في هذا الكتاب، يمكن النظر في <a href="https://docs.python.org/3/library/string.html#formatstrings" rel="external nofollow">التوثيق</a> إذا أردت النظر في الأسلوب الجديد، ولكن عمومًا لا يختلف الأسلوبان عن بعضهما في الحالات البسيطة، فإذا نفذنا المثال السابق بالأسلوب الجديد فسيبدو بالشكل:
	</p>
</blockquote>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_39" style=""><span class="pln">  </span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> print</span><span class="pun">(</span><span class="pln"> </span><span class="str">"The sum of {:d} and {:d} is: {:d}"</span><span class="pun">.</span><span class="pln">format</span><span class="pun">(</span><span class="lit">7</span><span class="pun">,</span><span class="lit">18</span><span class="pun">,</span><span class="lit">7</span><span class="pun">+</span><span class="lit">18</span><span class="pun">)</span><span class="pln">
</span><span class="typ">The</span><span class="pln"> sum of </span><span class="lit">7</span><span class="pln"> and </span><span class="lit">18</span><span class="pln"> is</span><span class="pun">:</span><span class="pln"> </span><span class="lit">25</span><span class="pln"> </span></pre>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		كما ترى فقد استبدلنا القوسين المعقوصين <code>{}</code> بعلامات <code>%</code>، وقد نُسقت رموز أنواع البيانات تنسيقًا مختلفًا، كما يجب هنا استدعاء العملية <code>format</code> الخاصة بالسلسلة النصية التي تمرر القيم، تمامًا كما في المرة السابقة. يحتوي الأسلوب الجديد على بعض الخصائص الأخرى أيضًا لتحسين التخطيط العام وتمرير البيانات، لكننا لن نذكرها هنا وإنما يمكن الاطلاع عليها في توثيق بايثون، وننصحك بتأجيل النظر فيها إلى أن تتمرس في فصول هذا الكتاب كي تستوعب الشرح التقني لها.
	</p>
</blockquote>

<h3>
	زيادة إمكانيات اللغة
</h3>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_41" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> sys</span></pre>

<p>
	إذا كتبنا السطر أعلاه في محث بايثون ثم ضغطنا على زر الإدخال، فلن نرى شيئًا على الشاشة، غير أن هذا لا يعني عدم حدوث شيء ما في الخلفية، ولشرح ما حدث بعد كتابة هذه الأمر سننظر أولًا إلى معمارية بايثون نفسها، وحتى لو لم تكن تستخدم بايثون فتابع الشرح، إذ ستكون ثمة آليات مشابهة في اللغة التي تستخدمها.
</p>

<p>
	عند بدء لغة بايثون تتاح لنا عدة دوال وأوامر، وهذه الأوامر مدمجة في اللغة وتسمى بالمضمَّنات built-ins، لأنها مبنية داخل نسيج اللغة نفسها، غير أن بايثون تستطيع توسيع قائمة الدوال المتاحة بدمج وحدات توسيع extension modules فيها، وهو يشبه شراء المرء لأداة جديدة من متجر العُدد والآلات ليضيفها إلى مجموعته المنزلية، وفي مثالنا فإن الآلة هي <code>sys</code>، وقد وضعتها العملية <code>import</code> داخل صندوق الآلات الذي سنستخدمه؛ أما حقيقة ما يفعله هذا الأمر فهو إتاحة "أدوات" جديدة على شكل دوال للغة بايثون، تُعرَّف داخل وحدة اسمها <code>sys</code>، وتلك طريقة توسيع بايثون لتنفيذ أي شيء غير مدمج في النظام الأساسي، وستجد أكثر من مئة وحدة في المكتبة القياسية standard library التي تحصل عليها مع بايثون، كما يمكنك إنشاء وحداتك الخاصة واستيرادها واستخدامها مثل الوحدات التي وفرتها بايثون عند تثبيتها بالضبط، وسنعود إلى هذا الأمر لاحقًا. كذلك ستجد مزيدًا من الوحدات التي يمكن تحميلها من الإنترنت، فإذا بدأت مشروعًا لا تغطيه الوحدات التي في المكتبة القياسية، فانظر في الإنترنت أولًا فلعلك تجد شيئًا يساعدك.
</p>

<h3>
	الخروج السريع
</h3>

<p>
	لننظر الآن في كيفية استخدام تلك الأدوات التي أدخلناها، فإذا كتبنا الأمر التالي في محث بايثون؛ فسنجعل بايثون تنهي نفسها وتخرج، لأننا نكون قد نفّذنا الدالة <code>exit</code> المعرَّفة في وحدة <code>sys</code>.
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_6828_43" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> sys</span><span class="pun">.</span><span class="kwd">exit</span><span class="pun">()</span></pre>

<p>
	لاحظ أننا نخرج من بايثون عادةً بكتابة محرف نهاية الملف End Of File واختصاره EOF في محث بايثون، وهو CTRL+Z على ويندوز أو CTRL+D على أنظمة يونكس Unix؛ أما إذا كنت تستخدم بيئة تطوير فتخرج من قائمة File ثم Exit، وإذا حاولنا تنفيذ هذا في أداة تطوير مثل IDLE؛ فإن الأداة تنتبه لمحاولة الخروج وتعرض رسالةً تقول شيئًا ما حول SystemExit، لكن لا تشغل بالك بها، فهذا يعني أن البرنامج يعمل وأن الأداة تحاول توفير الوقت عليك لئلا تبدأ من الصفر مرةً أخرى.
</p>

<p>
	لاحظ أن <code>exit</code> لها أقواس حولها، وذلك لأنها دالة معرفة في وحدة <code>sys</code>، حيث سنحتاج إلى وضع هذه الأقواس عند استدعاء دالة بايثون حتى لو لم تحتوي الأقواس نفسها على أي شيء، فإذا كتبنا <code>sys.exit</code> دون الأقواس، فستستجيب بايثون لنا بإخبارنا أن <code>exit</code> دالةٌ، بدلًا من تنفيذ الدالة نفسها.
</p>

<p>
	أخيرًا، لاحظ أن التعليمتين الأخيرتين مفيدتان عند استخدامهما معًا، أي أننا سنكتب ما يلي للخروج من بايثون بدلًا من EOF:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6828_45" style=""><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span><span class="kwd">import</span><span class="pln"> sys
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> sys</span><span class="pun">.</span><span class="pln">exit</span><span class="pun">()</span></pre>

<p>
	هكذا نكون قد كتبنا تسلسلًا بسيطًا من تعليمتين، ونكون قد خطونا قليلًا نحو البرمجة الحقيقية.
</p>

<h3>
	استخدام جافاسكربت
</h3>

<p>
	لا توجد طريقة سهلة في جافاسكربت لنكتب الأوامر ونراها تنفَّذ مباشرةً كما في بايثون، لكن نستطيع كتابة جميع الأوامر البسيطة أعلاه في ملف HTML واحد ثم تحميلها إلى المتصفح، وسنرى كيف تبدو حينئذ في جافاسكربت:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6828_47" style=""><span class="tag">&lt;html&gt;&lt;body&gt;</span><span class="pln">
</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span><span class="tag">&gt;</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello there!&lt;br /&gt;'</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"Monty Python\'s Flying Circus has a \' within it&lt;br /&gt;"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="lit">6</span><span class="pun">+</span><span class="lit">5</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"&lt;br /&gt;"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln">  </span><span class="pun">((</span><span class="lit">8</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln">  </span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"&lt;br /&gt;"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln"> </span><span class="lit">5</span><span class="pun">/</span><span class="lit">2</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"&lt;br /&gt;"</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
</span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;&lt;/html&gt;</span></pre>

<p>
	سيكون الخرج كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_6828_49" style=""><span class="typ">Hello</span><span class="pln"> there</span><span class="pun">!</span><span class="pln">
</span><span class="typ">Monty</span><span class="pln"> </span><span class="typ">Python</span><span class="str">'s Flying Circus has a '</span><span class="pln"> within it
</span><span class="lit">11</span><span class="pln">
</span><span class="lit">6</span><span class="pln">
</span><span class="lit">2.5</span><span class="pln">
</span><span class="lit">1</span></pre>

<p>
	نستخدم <code>document.write</code> لإخراج النص إلى نافذة المتصفح، وهذا يكافئ تقريبًا دالة <code>print</code> في بايثون، وسنرى قريبًا طريقةً مختلفةً قليلًا في VBSCript لعرض المخرجات في المتصفح في المثال التالي.
</p>

<p>
	لاحظ كيف اضطررنا إلى كتابة <code>‎&lt;br /&gt;‎</code> كي نجبر البرنامج أن يعرض الخرج التالي في سطر جديد، وذلك لأن جافاسكربت تكتب مخرجاتها في صورة HTML، والتي تعرض السطر بأقصى عرض تسمح به نافذة المتصفح لديك، فإذا أردنا قسرها على إنهاء السطر وبدء سطر جديد، فسنستخدم رمز HTML الخاص بالسطر الجديد، وهو <code>‎&lt;br /&gt;‎</code>.
</p>

<p>
	لاحظ كيف هرّبنا محارف الاقتباس المفردة بوضع شرطة مائلة خلفية <code>\</code> قبل الاقتباس، سنشرح ذلك بالتفصيل حين نتحدث عن السلاسل النصية في فصل البيانات وأنواعها.
</p>

<h3>
	VBScript
</h3>

<p>
	كما ذكرنا بخصوص جافاسكربت؛ فيجب أن ننشئ ملفًا لوضع أوامر VBScript فيها ثم نفتحه في المتصفح، وإذا كتبنا الأوامر السابقة باستخدام VBScript فستبدو كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_6828_51" style=""><span class="tag">&lt;html&gt;&lt;body&gt;</span><span class="pln">
</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/vbscript"</span><span class="tag">&gt;</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"Hello There!"</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"Monty Python's Flying Circus has a ' in it"</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">5</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="pun">((</span><span class="lit">8</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="lit">7</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3</span><span class="pun">))</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pun">)</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="lit">5</span><span class="pun">/</span><span class="lit">2</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> MOD </span><span class="lit">2</span><span class="pln">
</span><span class="tag">&lt;/script&gt;</span><span class="pln">
</span><span class="tag">&lt;/body&gt;&lt;/html&gt;</span></pre>

<p>
	سنرى في الخرج كثيرًا من الصناديق الحوارية، يعرض كل منها خرجًا من أحد الأسطر التي في البرنامج، فإذا أردنا أن نجعل جافاسكربت تخرج لنا مثل تلك الصناديق الحوارية فسنستخدم <code>alert("Hello There!")‎</code> بدلًا من <code>document.write("Hello there!&lt;br&gt;")‎</code>، فقد استخدمنا <code>alert</code> هنا بدلًا من <code>MsgBox</code> التي في VBScript.
</p>

<p>
	لاحظ أننا لا نستطيع بدء سلسلة نصية باستخدام علامة اقتباس مفردة في VBScript، لكن يمكننا إدراج اقتباسات مفردة داخل سلاسل نصية ذات علامات اقتباس مزدوجة، باستخدام الدالة <code>Chr</code> التي إذا أعطيناها رمزًا لمحرف أعادت لنا ذلك المحرف، وبما أن هذا المثال يبدو فوضويًا للغاية، لنلق نظرةً على المثال التالي الذي يوضح كيفية عملها:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_53" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/vbscript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Dim</span><span class="pln"> qt
qt </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Chr</span><span class="pun">(</span><span class="lit">34</span><span class="pun">)</span><span class="pln">
</span><span class="typ">MsgBox</span><span class="pln"> qt </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">"Go Away!"</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> qt </span><span class="pun">&amp;</span><span class="pln"> </span><span class="str">" he cried"</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	لمعرفة رمز أي محرف تريده؛ تستطيع الاسترشاد <a href="http://online-toolz.com/tools/character-map.php" rel="external nofollow">بهذا الموقع</a>، وأخذ الرمز العشري decimal منه، أو بالنظر في خريطة المحارف التي يوفرها نظام التشغيل الخاص بك، إذ توفر أغلب نظم التشغيل المشهورة بريمجًا لذلك؛ أما إذا لم ترد استخدام هذا ولا ذاك لسبب ما؛ فاستخدم الجزء التالي من لغة جافاسكربت واستبدل المحرف الذي تريده بمحرف الاقتباس المزدوج الذي في المثال:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_6828_55" style=""><span class="pun">&lt;</span><span class="pln">script type</span><span class="pun">=</span><span class="str">"text/javascript"</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> code</span><span class="pun">,</span><span class="pln"> chr </span><span class="pun">=</span><span class="pln"> </span><span class="str">'"'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// put the character of interest here</span><span class="pln">
code </span><span class="pun">=</span><span class="pln"> chr</span><span class="pun">.</span><span class="pln">charCodeAt</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">"&lt;br /&gt;The character code of  "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> chr </span><span class="pun">+</span><span class="pln"> </span><span class="str">"  is "</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> code</span><span class="pun">);</span><span class="pln">
</span><span class="pun">&lt;/</span><span class="pln">script</span><span class="pun">&gt;</span></pre>

<p>
	لا تشغل بالك الآن بمعنى الأرقام التي في المثال، إذ سنعود إليها في الفصل التالي، وإنما سقناها الآن من أجل استخدامها إذا اضطررنا إلى إيجاد قيمة محرف ما.
</p>

<h2>
	خاتمة
</h2>

<p>
	تلك كانت نظرتنا الأولى على البرمجة، ولعلها كانت سهلة الفهم والإدراك، لكن سنحتاج إلى أن ننظر في أنواع البيانات التي سنقابلها في البرمجة وسنحتاج إليها قبل الشروع في البرمجة الحقيقية، كما سنرى الأمور والعمليات التي سنجريها على تلك البيانات.
</p>

<p>
	وقد عرفنا في هذا الفصل أن البرنامج قد يكون صغيرًا للغاية، لذا فلا مانع من أن يكون مجرد أمر واحد، وأن أسلوب بايثون في إجراء العمليات الحسابية هو نفسه الأسلوب المتبع في الرياضيات، وإذا أردنا الحصول على نتيجة كسرية فيجب أن نستخدم أعدادًا كسريةً كذلك، وأننا نستطيع دمج النصوص والأرقام باستخدام عامل التنسيق <code>%</code>، وأخيرًا عرفنا أننا نخرج من بايثون بكتابة <code>import sys; sys.exit()‎</code>.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutseq1.htm" rel="external nofollow">للفصل الرابع من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D9%88%D8%A3%D9%86%D9%88%D8%A7%D8%B9%D9%87%D8%A7-%D8%A3%D9%86%D9%88%D8%A7%D8%B9-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9-r1287/" rel="">مدخل إلى البيانات وأنواعها: أنواع البيانات الأساسية</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D8%B1%D8%AD%D9%84%D8%A9-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1280/" rel="">بداية رحلة تعلم البرمجة </a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9%D8%9F-r1279/" rel="">ما هي البرمجة؟</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1281</guid><pubDate>Sun, 25 Jul 2021 15:00:00 +0000</pubDate></item><item><title>&#x628;&#x62F;&#x627;&#x64A;&#x629; &#x631;&#x62D;&#x644;&#x629; &#x62A;&#x639;&#x644;&#x645; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D8%B1%D8%AD%D9%84%D8%A9-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1280/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_07/61043c664ec1f_-.png.b48a14695f371b3cd2fad9c165d94be7.png" /></p>
<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		رغم أننا نستخدم ثلاث لغات برمجية هنا إلا أنك لست مضطرًا إلى الكتابة بها جميعًا، فهذا سيشتتك ويؤثر سلبًا على قدرتك على التعلم، فربما تود تجربتها كلها من أجل التمرس فيها، لكن يجب أن تستقر على لغة واحدة فقط بعد الفصول الأولى، لذا اختر أيها شئت لتتمرن بها على الأمثلة التي في السلسلة (وإن كنا ننصحك ببايثون)، ثم إن مجرد قراءة الأمثلة المكتوبة باللغات الأخرى يُظهر أوجه الاختلاف والتشابه بين اللغات الثلاثة، كما يفيد في تعلم قراءة الشيفرات من ناحية أخرى، إلى جانب فهم الأفكار المشتركة بين لغات البرمجة المختلفة.
	</p>
</blockquote>

<h2>
	استخدام بايثون
</h2>

<p>
	سنفترض أنك قد ثبّتّ إحدى إصدارات بايثون على حاسوبك، فإذا لم تفعل فاذهب إلى <a href="http://www.python.org/" rel="external nofollow">موقع بايثون</a> واجلب النسخة الأحدث منها واتبع إرشادات التثبيت على حاسوبك، لاحظ أن بايثون متاحة لأغلب أنواع الحواسيب المتوفرة في السوق، وستجد ملفات تثبيت لنسختي 64 بت و 32 بت من ويندوز، وكذلك نظام MacOS؛ أما لينكس فستجدها من خلال مدير الحزم في توزيعتك، فإذا لم تكن تعلم معمارية حاسوبك فاختر نسخة 32 بت، وانتبه عند التثبيت إلى خيار إضافة بايثون إلى <code>Path</code>، وهو متغير بيئة سنحتاج أن نضيف بايثون إليه كي يراها ويندوز في سطر الأوامر، بالشكل التالي:
</p>

<p style="text-align: center;">
	<img alt="add.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="72960" data-unique="4m03umj3i" src="https://academy.hsoub.com/uploads/monthly_2021_07/add.PNG.566adb4218764c5ec8c41ca7910e2e8b.PNG">
</p>

<p>
	أما إذا لم تفعل ذلك أو نسيته أو لم تكن نسخة التثبيت تحتوي على ذلك الخيار، فاتبع الإرشادات التي نذكرها في الفقرة التالية.
</p>

<h2>
	سطر أوامر ويندوز
</h2>

<p>
	لقد بدا منذ كتابة هذه السلسلة -بنسخته الأجنبية لأصلية- أن العديد من مستخدمي ويندوز ليسوا معتادين على التعامل مع سطر أوامر MS Dos، لذا سنشرح كيف يمكن الوصول إلى تلك الأداة دون الاستغراق في التفاصيل غير الضرورية. توجد عدة طرق للوصول إلى سطر الأوامر أبسطها الضغط باستمرار على زر ويندوز وحرف R من أجل فتح نافذة Run، ثم كتابة <code>cmd</code> في مربع الحوار الذي سيظهر لك ثم الضغط على <code>OK</code>، وهنا يجب أن ترى نافذةً سوداء فيها نص أبيض مثل هذا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3872_15" style=""><span class="pln">C</span><span class="pun">:</span><span class="pln">\WINDOWS</span><span class="pun">&gt;</span></pre>

<p>
	يشير السطر أعلاه إلى المجلد الذي نحن فيه، فإذا كتبنا <code>DIR</code> وضغطنا على زر الإدخال <code>Enter</code>؛ فستعرَض لنا قائمة بجميع الملفات التي في ذلك المجلد؛ أما إذا كتبنا <code>python</code> فيجب أن نرى المحث <code>‎‎&gt;&gt;&gt;‎</code> الخاص ببايثون. قد لا تستطيع CMD العثور على بايثون بسبب بعض إصداراته الأخيرة التي لم تأتي بتلك الإعدادات، ولهذا فإنا لم تستطع إيجادها فستحتاج إلى ضبط متغير بيئة اسمه <code>Path</code>، وذلك بفتح مدير الملفات في ويندوز إما بالطريقة العادية، أو بضغط زر ويندوز مع حرف E (لفتح المتصفح)، ثم الذهاب إلى قسم This PC، والنقر بالزر الأيمن لاختيار Properties التي ستفتح نافذة About الخاصة بحاسوبك، والتي تحوي المعلومات الأساسية عنه.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="72964" href="https://academy.hsoub.com/uploads/monthly_2021_07/properties.PNG.e0d99945cee09e70af661352b4b3593e.PNG" rel="" data-fileext="PNG"><img alt="properties.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="72964" data-unique="thbz78r4l" src="https://academy.hsoub.com/uploads/monthly_2021_07/properties.thumb.PNG.377ce53b8870513b7ef87de90be1a8c8.PNG"></a>
</p>

<p>
	ستجد في تلك الصفحة خيار Advaned System Settings، اضغط عليه لتفتح لك نافذة أخرى ثم اختر تبويب Advanced.
</p>

<p style="text-align: center;">
	<img alt="advanced.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="72961" data-unique="kpamw9nsa" src="https://academy.hsoub.com/uploads/monthly_2021_07/advanced.PNG.01b948058db34f4acb5c7f5e89654294.PNG">
</p>

<p>
	سترى زر Environment Variables في أسفل النافذة، اضغط عليه لتذهب إلى نافذة جديدة، وسترى أن Path معرَّف بالفعل كمتغير للنظام. اختره ثم انقر على زر Edit في يمين النافذة.
</p>

<p style="text-align: center;">
	<img alt="env.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="72963" data-unique="137y6mpyn" src="https://academy.hsoub.com/uploads/monthly_2021_07/env.PNG.254c6e5dfde8f609e231d44fa00e8fb7.PNG">
</p>

<p>
	انتبه في هذه الخطوة لئلا تحذف المسار الموجود بالخطأ، فإذا مسحت شيئًا من غير قصد فاضغط زر Esc في لوحة المفاتيح، أو استخدم زر Cancel في النافذة المفتوحة لتخرج منها وتعيد المحاولة.
</p>

<p style="text-align: center;">
	<img alt="edit.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="72962" data-unique="9sy4oe757" src="https://academy.hsoub.com/uploads/monthly_2021_07/edit.PNG.51460e120cd5ef193a923101fc33f30c.PNG">
</p>

<p>
	اذهب إلى نهاية الحقل Variable Value وأضف فاصلةً منقوطة <code>;</code>، ثم المسار الكامل لمجلد بايثون التنفيذي لديك، بعد ذلك اضغط زر الإدخال Enter لتكتمل العملية، فإذا لم تعرف المسار الكامل إلى بايثون فابحث في مدير الملفات عن الملف python3.exe، وستكون محتويات العمود In Folder الذي في شاشة البحث هي المسار الكامل، وقد تضطر إلى إعادة التشغيل كي يعتمد نظام التشغيل الإعدادات الجديدة.
</p>

<p>
	اكتب <code>python</code> في سطر الأوامر لنظام تشغيلك من أي مجلد شئت وسترى المحث الثلاثي لبايثون، ونستطيع من هنا كتابة <code>CD</code> إلى المجلد الحامل للسكربت الخاص بنا لننتقل إليه -حيث تشير CD إلى Change Directory-، كما ستجد قائمةً من الأوامر المتاحة التي يمكن كتابتها في سطر الأوامر في نظام المساعدة المدمج في CMD نفسها، من خلال كتابة <code>help</code> في سطر الأوامر؛ أما إذا أردت معرفة المزيد من العلومات عن أحد الأوامر، فاكتب اسم الأمر متبوعًا بـ <code>‎/?‎</code>، فإذا أردنا مثلًا عرض صفحة المساعدة الخاصة بالأمر <code>DIR</code> فسنكتب ما يلي:
</p>

<pre class="ipsCode">C:\WINDOWS&gt; DIR /?
</pre>

<p>
	أخيرًا يمكن إنشاء اختصار على سطح المكتب بالنقر بالزر الأيمن على سطح المكتب، ثم اختيار <code>جديد New</code>، ثم <code>اختصار Short-cut</code>، واكتب <code>cmd</code> في صندوق الموقع location داخل صندوق الحوار الذي يظهر لك، ثم انقر على <code>التالي Next</code>، ثم غير الاسم إلى شيء مثل Command Prompt أو نحوها. حين تنتهي انقر على <code>Finish</code> لتظهر أيقونة جديدة على سطح المكتب مثل اختصار إلى سطر الأوامر.
</p>

<p>
	خذ وقتك في استعراض هذه الأداة، فرغم أنها قد تبدو بدائيةً إلا أنها أقوى مما تتخيل، وخاصةً في إنجاز المهام المتكررة، على عكس الأدوات ذات الواجهة الرسومية مثل مدير الملفات، حيث يمكنك قراءة المزيد عنها في <a href="https://www.computerhope.com/issues/chusedos.htm" rel="external nofollow">Computer Hope</a> للبدء في تعلمها.
</p>

<h2>
	عودة إلى بايثون
</h2>

<p>
	بما أن مستخدمي ويندوز قد ثبتوا بايثون باتباع الخطوات السابقة، فسنفترض أن مستخدمي لينكس متعودون على استخدام الطرفية، أما مستخدمي نظام ماك فيمكنهم تشغيل برنامج الطرفية بالنقر على الأيقونة كالمعتاد، وهنا يجب أن يظهر محث بايثون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-py prettyprinted" id="ips_uid_3872_13" style=""><span class="typ">Python</span><span class="pln"> </span><span class="lit">3.6</span><span class="pun">.</span><span class="lit">2</span><span class="pln"> </span><span class="pun">(</span><span class="pln">default</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Jul</span><span class="pln"> </span><span class="lit">29</span><span class="pln"> </span><span class="lit">2017</span><span class="pun">,</span><span class="pln"> </span><span class="lit">00</span><span class="pun">:</span><span class="lit">00</span><span class="pun">:</span><span class="lit">00</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">[</span><span class="pln">GCC </span><span class="lit">4.8</span><span class="pun">.</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> on linux
</span><span class="typ">Type</span><span class="pln"> </span><span class="str">"copyright"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"credits"</span><span class="pln"> </span><span class="kwd">or</span><span class="pln"> </span><span class="str">"license()"</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> more information</span><span class="pun">.</span><span class="pln">
</span><span class="pun">&gt;&gt;&gt;</span><span class="pln"> </span></pre>

<p>
	وفي خيار بديل لسطر الأوامر ذاك؛ قد تجد اختصارًا إلى شيء اسمه IDLE، أو Python GUI في قائمة ابدأ لديك، وهو بيئة برمجة مخصصة لبايثون، وتوفر كثيرًا من الأدوات والأوامر المفيدة للمبرمجين، فإذا شغلته بدلًا من سطر الأوامر فستحصل على نافذة مستقلة لسطر الأوامر مع بعض الألوان المميزة للخطوط، وقد كتب Danny Yoo <a href="http://hkn.eecs.berkeley.edu/~dyoo/python/idle_intro/index.html" rel="external nofollow">دليلًا مفصلًا</a> لهذه البيئة يمكنك قراءته والاطلاع عليه إذا أردت استخدامه بدلًا من سطر الأوامر العادي، وهو يكرر بعض المعلومات التي ذكرناها من قبل، لكن تكرار التعليم لا يضر، كما تستطيع الاطلاع على <a href="https://docs.python.org/3/library/idle.html#" rel="external nofollow">التوثيق الرسمي لبيئة IDLE</a> كذلك إن شئت.
</p>

<p>
	أما إذا كنت تفضل التدريب المرئي بالفيديو، فهناك الكثير من الفيديوهات المتعلقة بالبرمجة على يوتيوب، ويُرى أن تعلم المفاهيم واستخدام الأدوات من الفيديو أمر ممكن، شرط أن توقِف الفيديو مع كل سطر أوامر يُكتَب كي تتابع الشرح جيدًا، كما يوصى بكتابة الشيفرة وتشغيلها بنفسك لتتذكر ما تتعلمه، لذا فإن أردت مشاهدة الفيديو لفهم المبدأ فلا بأس، لكن عد إلى هنا مرةً أخرى واقرأ حول ذلك المفهوم واكتب الشيفرة وجربها بنفسك، ثم عدل فيها وجرب إلى أن تصل إلى توقع التغييرات التي ستحدث، وتلك هي الطريقة الوحيدة <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">لتعلم البرمجة </a>في رأيي.
</p>

<p>
	المثير في بيئة IDLE أنها برنامج مكتوب ببايثون، فهي تبين لك قوة اللغة بمثال حي، وتوضح ما يمكن تنفيذه بها؛ أما إذا حصلت على بايثون من <a href="https://www.activestate.com/products/python/" rel="external nofollow">ActiveState</a> أو كنت قد حمّلت نسخًا مخصصةً لويندوز -مثل حزمة PyWin32-؛ فيمكنك الوصول إلى بيئة برمجة رسومية أخرى تشبه IDLE لكنها أكثر أناقةً منها تسمى Pythonwin.
</p>

<p>
	لا شك أن كلا البيئتين تسهلان البرمجة أكثر من سطر الأوامر العادي، لكننا نفضل استخدام الأدوات البسيطة في بداية التعلم لإدراك المفاهيم التي نشرحها إدراكًا أعمق.
</p>

<h2>
	كلمة حول رسائل الخطأ
</h2>

<p>
	سترى أثناء كتابة التعليمات البرمجية ببايثون رسائل خطأ لا محالةً، وستبدو مثل هذه:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3872_17" style=""><span class="pln">&gt;&gt;&gt; print( 'fred' + 7 )
Traceback (most recent call last):
  File "</span><span class="tag">&lt;input&gt;</span><span class="pln">", line 1, in ?
TypeError: cannot concatenate 'str' and 'int' objects</span></pre>

<p>
	لا تشغل بالك بالمعنى الدقيق لهذه الرسالة الآن، وإنما نريدك أن تنظر إلى هيكلها، فسطر <code>‎'&gt;&gt;&gt; print ...'‎</code> مثلًا هو السطر الخاطئ، أما السطران التاليان فيصفان مكان الخطأ، وقد تتكون رسالة الخطأ من عدة أسطر في البرامج المعقدة، فقد تقترح كلمة <code>Traceback</code> مثلًا أن الرسالة تتضمّن أثرًا أو سجلًا لكل ما كان البرنامج يفعله عند وقوع الخطأ، وقد يكون هذا مربكًا للمبتدئين، لكن ثق أنك مع الخبرة ستسعد بوجود رسالة الخطأ تلك، وستعلم أن الأسلوب الأمثل لقراءتها حينئذ سيكون من الأسفل، وتصعد لأعلى بقدر حاجتك من الرسالة.
</p>

<p>
	نعود إلى رسالة الخطأ السابقة حيث يشير <code>‎'line 1 in ?'‎</code> إلى السطر رقم 1 في التعليمة التي نكتبها، فلو كان برنامجًا أطول وكان مخزّنًا في ملف مصدري فسيحل اسم الملف الحقيقي محل <code>&lt;input&gt;</code>، بينما يخبرنا السطر <code>‎'TypeError...'‎</code> بالخطأ الذي يراه المفسر، وقد يوجد أحيانًا محرف إقحام <code>^</code> يشير إلى الجزء الذي تراه بايثون خطأً، لكن هذا التقرير يكون غير صحيح في العادة، فقد يكون الخطأ الحقيقي في مكان سابق للموضع الذي أشارت إليه بايثون، أو حتى قبله بسطر أو سطرين، فالحواسيب آلات غبية بأي حال كما قلنا من قبل.
</p>

<p>
	تُستخدم بيانات الأخطاء تلك لمعرفة ما يحدث في الشيفرة التي بين أيدينا، وقد يكون سبب الخطأ البرمجي بشريًا في الغالب، فرغم أن الحواسيب آلات غبية، إلا أنها آلات غاية في الدقة، فلعلنا أخطأنا في كتابة كلمة أو تعليمة أو نسينا علامة اقتباس أو فاصلةً منقوطةً مثلًا، ولدينا عمومًا ثلاثة أنواع من الخطأ التي سنواجهها:
</p>

<ul>
	<li>
		الخطأ اللغوي syntax error، وهو يعني أن بايثون لا ترى أن ما أُدخل إليها صالح، وقد يكون سببه نسيان علامة ترقيم أو خطأً في هجاء كلمة.
	</li>
	<li>
		خطأ وقت التشغيل runtime error، وذلك حين يكون البرنامج صالحًا لكن لا يمكن تنفيذه لسبب ما، كما في محاولة تنفيذ عملية غير مسموح بها أو غير صالحة، مثل طلب قراءة ملف غير موجود.
	</li>
	<li>
		خطأ دلالي semantic، حيث يعمل البرنامج ولا تظهر أي رسالة خطأ، لكنه يخرج لنا مخرجات خاطئةً غير التي يفترض به إخراجها، فإذا كتبنا مثلًا برنامجًا ليخبرنا بعدد كلمات الملف الذي تقرؤه الآن، وأخرج لنا أنه يحوي خمس كلمات فقط، فستكون هذه النتيجة خاطئةً قولًا واحدًا، فهنا يكون خطأ البرنامج دلاليًا.
	</li>
</ul>

<p>
	ستكون أغلب الأخطاء التي تتعرض لها في البداية أخطاءً لغويةً أو أخطاء وقت تشغيل إلى أن تبدأ بتصميم برامجك الخاصة، فحينها سترتكب أخطاء دلالية، وتسمى تلك العملية حينئذ بالتنقيح debugging، وتُسمى الأخطاء التي سترتكبها آنذاك بالزلات البرمجية bugs، لكن الترجمة الحرفية لاسمها الأجنبي bug هي عثة، وهي حشرة صغيرة سميت الأخطاء البرمجية باسمها لأسباب تاريخية، فقد كانت أولى الأخطاء التي حدثت في الحواسيب الأولى بسبب عثة علقت داخل الحاسوب وتسببت في حرق بعض داراته الكهربائية، وعلى الرغم أن الكلمة نفسها قد استُخدمت للدلالة على الأخطاء البرمجية قبل هذا بعدة عقود، لكنها لم تثبت إلا مع تلك الحادثة، لكننا سنستخدم اصطلاح الزلات البرمجية لقربها من المفهوم العربي للفعل ذاته.
</p>

<p>
	وبالعودة إلى الخطأ الذي ارتكبناه في المثال السابق والذي تسبب في إخراج رسالة الخطأ لنا، فقد كان محاولة إضافة عدد إلى سلسلة محارف، وهو خطأ دلالي، لكنه ينتج لنا خطأ وقت تشغيل أيضًا، فليس هذا مسموحًا لك في بايثون، لذا كانت رسالة الخطأ تمثل اعتراضًا من اللغة على ما فعلناه، فأخبرتنا أن هناك <code>TypeError</code>، وسنتحدث عن هذه الأنواع في مقال لاحق من هذه السلسلة.
</p>

<p>
	وبغض النظر عن الأداة التي تريد استخدامها سواء كانت سطر الأوامر أو بيئة IDLE أو Pythonwin، فنحن الآن جمعنا عدتنا وجاهزون للبدء في إنشاء بعض البرامج البسيطة باستخدام بايثون.
</p>

<h2>
	جافاسكربت
</h2>

<p>
	إذا أردنا إنشاء برامج جافاسكربت في متصفح، فسنحتاج إلى مزيد من الإجراءات التي علينا تنفيذها، حيث سنحتاج مثلًا إلى إنشاء ملف HTML نستطيع تحميله إلى متصفح، وهذا الملف لا يحوي إلا نصًا مجردًا نستطيع إنشاءه في محرر نصي بسيط مثل Notepad أو أي محرر نصي آخر، ثم حفظه بالامتداد <code>‎.htm</code> أو <code>‎.html</code>، وسيبدو بالشكل الآتي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3872_19" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">

</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span><span class="tag">&gt;</span><span class="pln">

document</span><span class="pun">.</span><span class="pln">write</span><span class="pun">(</span><span class="str">'Hello World\n'</span><span class="pun">);</span><span class="pln">

</span><span class="tag">&lt;/script&gt;</span><span class="pln">

</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	سيكون الجزء الواقع بين بداية الوسم <code>&lt;script&gt;</code> ونهايته هو برنامجنا، ولن تعرض جميع وسوم HTML في كل مرة أثناء شرحنا في هذه السلسلة، لذا عليك أن تنسخ هذا الملف في كل مرة مثل قالب ثم تستبدل الشيفرة التي تريد تجربتها بما هو موجود بين الوسمين <code>&lt;script&gt;</code> و<code>‎&lt;/script&gt;‎</code>، ثم افتح ملف HTML ذاك في متصفح ويب عن طريق النقر عليه في مدير ملفاتك، يجب أن يشغّل نظامك عندئذ برنامج المتصفح ويحمّل الملف الذي سيتسبب بالتبعية في تنفيذ برنامجنا.
</p>

<h2>
	VBScript
</h2>

<p>
	يمكن القول أن VBScript هي نفسها جافاسكربت لكن مع استبدال الاسم "vbscript" الذي في <code>type=‎</code> بالنص القديم الموجود "javascript"، كما يلي:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3872_21" style=""><span class="tag">&lt;html&gt;</span><span class="pln">
</span><span class="tag">&lt;body&gt;</span><span class="pln">

</span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">"text/vbscript"</span><span class="tag">&gt;</span><span class="pln">

</span><span class="typ">MsgBox</span><span class="pln"> </span><span class="str">"Hello World"</span><span class="pln">

</span><span class="tag">&lt;/script&gt;</span><span class="pln">

</span><span class="tag">&lt;/body&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	لاحظ أن متصفح إنترنت إكسبلورر الخاص بمايكروسوفت هو الوحيد القادر على تشغيل VBScript، أما المتصفحات الأخرى فلا تدعم إلا جافاسكربت بما في ذلك متصفح Edge الخاص بويندوز، والذي استبدلت إنترنت إكسبلورر به، لذا يبدو أن أيام VBScript صارت معدودةً.
</p>

<h3>
	أخطاء VBScript وجافاسكربت
</h3>

<p>
	سنحصل على صندوق حوار في كل من جافاسكربت وVBScript يخبرنا برقم السطر الذي فيه الخطأ، كما سيكون لدينا عدة أخطاء غامضة غير معروفة، ويجب معاملة رقم السطر المذكور بأنه قد لا يكون دقيقًا في الغالب كما فعلنا مع بايثون، وسنحتاج بعد إصلاح الخطأ إلى إعادة تحميل الصفحة التي هو فيها. توجد في المتصفحات أدوات تنقيح متقدمة وموجهة للمطورين المحترفين، لكنها مخبأة داخل المتصفحات ولا تناسب احتياجاتنا الحالية بعد.
</p>

<h2>
	خاتمة
</h2>

<p>
	بغض النظر عن اللغة التي ستستخدمها في متابعة الشرح في هذه السلسلة، فنرجو أن تخرج من هذا المقال وأنت تعلم أنك تستطيع بدء <a href="https://academy.hsoub.com/programming/python/%D8%A7%D9%84%D9%85%D8%B1%D8%AC%D8%B9-%D8%A7%D9%84%D8%B4%D8%A7%D9%85%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B9%D9%84%D9%85-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-r735/" rel="">بايثون </a>بكتابة <code>python</code> في سطر الأوامر، وألا تخشى رسائل الخطأ، بل اقرأها بعناية، فهي تعطينا عادة المفاتيح التي نحتاجها لإصلاح الخطأ الواقع في البرنامج، غير أنها لا زالت مجرد مفاتيح، فإذا شككت في دقتها فانظر إلى الأسطر السابقة للسطر الذي تخبرك أن الخطأ فيه.
</p>

<p>
	ترجمة -بتصرف- <a href="http://www.alan-g.me.uk/l2p2/tutstart.htm" rel="external nofollow">للفصل الثالث من كتاب Learning To Program</a> لصاحبه Alan Gauld.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%AA%D8%B3%D9%84%D8%B3%D9%84%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B3%D9%8A%D8%B7%D8%A9-%D9%81%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1281/" rel="">التسلسلات البسيطة في البرمجة</a>
	</li>
	<li>
		المقال السابق: <a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9%D8%9F-r1279/" rel="">ما هي البرمجة؟ </a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D9%84%D9%85%D8%A7%D8%B0%D8%A7-%D8%AA%D8%B5%D8%A8%D8%AD-%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8B%D8%A7-r659/" rel="">ما هي البرمجة ولماذا تصبح مبرمجًا</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1280</guid><pubDate>Thu, 22 Jul 2021 15:00:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x647;&#x64A; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629; &#x648;&#x645;&#x62A;&#x637;&#x644;&#x628;&#x627;&#x62A; &#x62A;&#x639;&#x644;&#x645;&#x647;&#x627;&#x61F;</title><link>https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D9%85%D8%AA%D8%B7%D9%84%D8%A8%D8%A7%D8%AA-%D8%AA%D8%B9%D9%84%D9%85%D9%87%D8%A7%D8%9F-r1279/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2021_07/610438c5db1e4_--.png.e0180ba5e34d320fb487790f336d8e1c.png" /></p>
<p id="-">
	يمكن القول إنك لن تحتاج لأكثر من اتصال بالإنترنت لتتعلم البرمجة من هذه السلسلة، ومع أن هذا يكفي من الناحية التقنية إلا أنه غير كافٍ لتعلم البرمجة، إذ يجب التنويه إلى أسلوب التفكير الذي ستتبعه في البرمجة، فلابد أن تتمتع بفضول للتعلم مع أسلوب منطقي لتفكير، وهما أمران لازمان لأي مبرمج ناجح.
</p>

<p>
	تبرز أهمية الفضول في البحث عن إجابات للمشاكل، وفي قدرتك على التجربة والتنقيب في الملفات بحثًا عن الأفكار والمعلومات المطلوبة لتنفيذ مهمة معينة، كما أن التفكير المنطقي مهم لأن الحواسيب آلات غبية بطبيعتها، ولا تستطيع فعل أي شيء سوى إضافة أرقام مفردة إلى جانب بعضها البعض، وتحريك بايتات من مكان لآخر.
</p>

<p>
	لقد كتب كثير من المبرمجين المهرة -لحسن الحظ- برمجيات تُخفي غباء الحواسيب هذا، لكنك بصفتك مبرمجًا ستتعرض لمواقف تواجه فيها ذلك الغباء الذي لم يعالجه أو يتعامل معه أحد قبلك، وهنا يجب أن تضع نفسك مكان الحاسوب وتفكر بدلًا عنه، وأن تعرف تحديدًا ما يجب عمله ببياناتك وزمن ذلك أيضًا. قد يكون هذا سردًا فلسفيًا لأمر يبدو تقنيًا وإلكترونيًا محضًا، غير أنك تحتاج إلى مثل تلك الفلسفة لتفهم هذا الشرح فهمًا جيدًا.
</p>

<p>
	بعد ذلك يأتي الجزء الخاص بالتدريب العملي الذي ستحتاج فيه إلى كتابة الأمثلة بيدك، أو نسخها من الكتاب إلى المحرر النصي عندك، ثم تشغيلها ورؤية النتائج، وستحتاج هنا إلى تثبيت بايثون Python على حاسوبك، وإلى متصفح قادر على تشغيل لغتي VBScript وJScript، مع الإشارة إلى أن أي متصفح حديث قادر على تشغيل جافاسكربت.
</p>

<h3 id="-python">
	بايثون Python
</h3>

<p>
	يُعَد أحدث إصدار من لغة بايثون وقت كتابة هذه الكلمات -بلغتها الأصلية- هو 3.9، وحجم ملف تحميله من <a href="https://www.activestate.com/products/python/" rel="external nofollow">ActiveState</a> يقارب 29 ميجا بايت لنسخة إصدار ويندوز (لا زالت ActiveState في الإصدار 3.8)، غير أنها تشمل كامل التوثيق والكثير من الأدوات التي سننظر في بعضها لاحقًا في هذه السلسلة، لذا تأكد من اختيار النسخة الموافقة لنظام تشغيلك.
</p>

<p>
	أما بالنسبة لنظام لينكس أو الأنظمة الشبيهة بيونكس عمومًا، فاطلب من مدير نظامك تثبيت النسخة المصدرية لبايثون على حاسوبك، لكن قد لا تحتاج إلى ذلك لأنها تأتي مدمجةً مسبقًا، ومثبتةً تلقائيًا في أغلب توزيعات لينكس، كما ستجدها في الإصدارات بتحزيمات موجهة للتوزيعات المشهورة مثل ريدهات Red Hat وديبيان Debian وأوبنتو Ubuntu وغيرها، بل قد تجد أن أغلب أدوات إدارة النظام في لينكس مكتوبة بلغة بايثون، ولا تقلق إذا كان إصدارك أقل من 3.6، فأي إصدار بعد 3.4 سيكون مناسبًا.
</p>

<p>
	تستطيع النظر في نسخ التحميل المختلفة لاختيار ما يناسبك من موقع <a href="http://www.python.org/download" rel="external nofollow">التحميل الرئيسي لبايثون</a>، أما مستخدمو ويندوز وماك فقد يفضلون نسخة <a href="https://www.activestate.com/activepython/downloads" rel="external nofollow">ActiveState.com</a> التي تأتي غالبًا مع بعض الأدوات الإضافية المدمجة في البرنامج نفسه، وقد تكون ActiveState متأخرةً قليلًا في إصدار نسخها الجديدة بسبب برنامجهم الخاص في التحزيم والاختبار، غير أنها تستحق الانتظار.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة Python
		</p>

		<p class="banner-subtitle">
			احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/python-application-development" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة Python" src="https://academy.hsoub.com/learn/assets/images/courses/python-application-development.png">
	</div>
</div>

<h3 id="vbscript-">
	VBScript وجافاسكربت
</h3>

<p>
	لقد سبق وأن قلنا إن أغلب المتصفحات تستطيع تشغيل جافاسكربت دون مشاكل، لكن VBScript عكس ذلك، فهي لن تعمل إلا في متصفح إنترنت إكسبلورر من مايكروسوفت، ولن تحتاج إلى تثبيت أي شيء إضافي لهاتين اللغتين، فإما أن تكونا لديك معًا إذا كنت تستخدم ويندوز، أو لن تكون لديك VBScript إذا كنت تستخدم ماك أو لينكس، والأمر الوحيد الذي عليك الانتباه إليه هنا هو أن بعض مديري الأنظمة القلقين بشأن الأمان قد يغلقون خاصية تشغيل السكربتات scripts في المتصفح لدواع أمنية، لكن هذا نادر الآن لأن أغلب المتصفحات تشغّل جافاسكربت.
</p>

<p>
	برمجة الحواسيب هي فن نجعل فيه الحاسوب ينفذ ما نرغب فيه بالضبط، وهي تتكون في أبسط صورها من سلسلة أوامر نعطيها للحاسوب لينفذها من أجل تحقيق هدف ما، وقد كان المستخدمون قديمًا أيام نظام دوس الخاص بويندوز، ينشئون ملفات نصيةً تحوي قوائم من تلك الأوامر، تُسمى ملفات الرُّقع أو باتش batch files (تدعى غالبًا سكربتات أو سكربت باتش)، وسبب تسميتها بذلك هو أنها تنفذ الأوامر مثل مجموعة أو رقعة واحدة، وكان امتدادها هو <code>‎.BAT</code>، لذا أُطلق عليها اسم ملفات بات BAT، ولا يزال بإمكاننا كتابة مثل تلك الملفات في بيئات ويندوز هذه الأيام رغم ندرة استخدامها، فمثلًا إذا كنت تكتب مستند HTML مكوَّن من ملفات كثيرة مثل الدليل الذي تقرؤه الآن، فسينشئ برنامج معالجة النصوص الذي تستخدمه نسخًا احتياطيةً من كل ملف كلما حفظ نسخةً جديدةً منه. فإذا رغبت في أن تضع النسخة الحالية من المستند -وهي الإصدارات الأخيرة من جميع ملفاته- في مجلد نسخ احتياطي <code>backup</code> في آخر كل يوم ثم حذف النسخ الاحتياطية التي لدى معالج النصوص؛ فيمكن كتابة ملف BAT بسيط لتنفيذ لك، وسيكون كما يلي:
</p>

<pre class="ipsCode prettyprint lang-css prettyprinted" id="ips_uid_44_6" style=""><span class="pln">COPY </span><span class="pun">*.</span><span class="pln">HTM BACKUP
DEL </span><span class="pun">*.</span><span class="pln">BAK</span></pre>

<p>
	إذا كان اسم الملف هو <code>SAVE.BAT</code> فسنكتب <code>SAVE</code> في محث DOS (يطلق على المحث أيضًا موجه أوامر) في نهاية اليوم بعد انتهاء العمل، وستُحفظ الملفات وتُحذف النسخ الاحتياطية تلقائيًا، وهكذا تكون قد رأيت مثالًا عمليًا لبرنامج بسيط.
</p>

<p>
	لاحظ أن مستخدمي نظام لينكس وغيره، بل حتى مستخدمي الإصدارات الحديثة من ويندوز، لديهم نسختهم الخاصة بهم من أمثلة تلك الملفات، والتي تُعرف عادةً باسم سكربتات الصدفة shell scripts، وهي أقوى بكثير من ملفات BAT الخاصة بنظام دوس، وتدعم أغلب التقنيات البرمجية التي سنتحدث عنها في هذا المقال.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة تطوير التطبيقات باستخدام لغة JavaScript
		</p>

		<p class="banner-subtitle">
			تعلم البرمجة بلغة جافا سكريبت انطلاقًا من أبسط المفاهيم وحتى بناء تطبيقات حقيقية.
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/javascript-application-development/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة تطوير التطبيقات باستخدام لغة JavaScript" src="https://academy.hsoub.com/learn/assets/images/courses/javascript-application-development.png">
	</div>
</div>

<h2>
	تعريف البرنامج مرة أخرى
</h2>

<p>
	لقد ذكرنا أعلاه مثالًا عن برنامج، لنبين بساطة مفهوم البرمجة في حد ذاته، لكن إذا خشيت عدم فهم البرمجة، فاعلم أن البرنامج ما هو إلا مجموعةً من التعليمات التي تخبر الحاسوب كيف ينفذ مهمةً ما، وهو يشبه وصفة الطعام التي تتكون من مجموعة من التعليمات التي تخبر الطاهي كيف يصنع طبقًا ما، فهي تصف مقادير المكونات (البيانات) وترتيب خطوات التنفيذ (العملية) المطلوبة لتحويل تلك المكونات إلى كعكة أو غيرها، فالبرنامج يشبهها كثيرًا في هذا.
</p>

<h2>
	نظرة تاريخية
</h2>

<p>
	نحن نستخدم لغةً للحديث مع الحواسيب، كما نستخدم لغات بيننا نحن البشر، غير أن اللغة الوحيدة التي يتحدثها الحاسوب تسمى اللغة الثنائية binary والتي توجد عدة نسخ منها، لهذا لا يعمل برنامج موجه لنظام ماك على ويندوز والعكس. ويُعَد تعلّم هذه اللغة صعبًا جدًا بالنسبة للبشر، سواءً قراءتها أو كتابة برامج بها، لذلك يجب أن نستخدم لغةً وسيطةً ثم نترجمها إلى اللغة الثنائية، تمامًا مثل شخصين من دولتين مختلفتين يتحدثان معًا وبينهما مترجم وسيط يفسر كلام كل منهما للآخر، فقد يتحدث أحدهما العربية والآخر الإنجليزية، فيترجم المترجم الكلام العربي إلى الإنجليزية وينقله إلى متحدث الإنجليزية، ثم يعكس العملية إذا تحدث الإنجليزي مخاطبًا الشخص العربي، وما سنستخدمه ليترجم لغتنا البرمجية إلى الحاسوب يسمى مترجمًا أو مفسرًا interpreter. وكما نحتاج مفسرًا لكل لغة من لغات البشر، فإننا نحتاج مفسرًا لكل لغة برمجية ليترجمها إلى لغة الحاسوب، فنحتاج مفسرًا من بايثون إلى لغة الآلة الثنائية binary، وآخر من VBScript إلى لغة الآلة كذلك، غير أن المبرمجين الأوائل كانوا مضطرين إلى كتابة الشيفرات الثنائية تلك بأنفسهم، أي بلغة الآلة التي ذكرناها قبل قليل وهي صعبة الكتابة والتعلم.
</p>

<p>
	بعد ذلك أتت المرحلة التالية التي أُنشئ فيها مفسر يحول كلمات مكتوبةً بأحرف بشرية إلى ما يقابلها من اللغة الثنائية، فبدلًا من تذكر أن الرمز <code>‎001273 05 04‎</code> يعني جمع 4 إلى 5، نستطيع الآن أن نكتب شيئًا مثل <code>ADD 5 4</code>، وقد سهلت تلك النقلة البسيطة الكثير من عمل البرمجة والتطوير، حيث كانت تلك الأنظمة البسيطة من الشيفرات هي لغات البرمجة الأولى التي كانت تختلف باختلاف نوع الحاسوب، وتسمى باسم اللغات المجمِّعة Assembler Languages، ولا زالت البرمجة بلغة التجميع مستخدَمةً هذه الأيام في بعض المهام المتخصصة، لكن هذا التطور كان بدائيًا في أسلوب إخبار الحاسوب بما يجب فعله، مثل نقل البيانات من هذا الموضع من الذاكرة إلى ذلك الموضع، وإضافة هذا البايت إلى ذلك البايت وغيرها من العمليات.
</p>

<p>
	البايت Byte هو وحدة بيانات تتكون من ثمانية بتّات bits أصغر منه ومجموعة فيه، وتلك البتات تكون إما 1 أو 0، وقد استُخدم البايت في البداية لتمثيل محارف النصوص، بحيث يمثل كل بايت حرفًا واحدًا.
</p>

<p>
	وبما أن هذا النمط من البرمجة لا زال صعبًا في تعلمه والعمل به لإنجاز أبسط المهام، فقد طور علماء الحوسبة مع الوقت لغات تسهل عملية البرمجة، وكأن ذلك جاء في وقته إذ تطورت المشاكل التي يواجهها المستخدمون في ذلك الوقت بسبب تطور المهام في أعمالهم اليومية، وهم يريدون للحواسيب أن تحل لهم تلك المشاكل.
</p>

<p>
	ولا زال هذا التنافس قائمًا، كما لا زالت <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">لغات البرمجة</a> الجديدة تظهر على الساحة. هذا ومع جعل البرمجة أمرًا مثيرًا يتغير كل يوم، إلا أنه يجعلك كونك مبرمجًا في حاجة إلى استيعاب المفاهيم البرمجية وطرق تنفيذها وتطبيقها في لغة واحدة بعينها، وسنناقش بعض تلك المفاهيم فيما يلي، لكن يجب أن تجعلها حاضرةً عندك تعود إليها دائمًا أثناء قراءتك للسلسلة.
</p>

<h2>
	المزايا المشتركة لجميع البرامج
</h2>

<p>
	خرج إدزجر ديكسترا Edsger Dijkstra قبل زمن بمفهوم اسمه البرمجة الهيكلية Structured Programming، يتحدث فيه عن إمكانية هيكلة جميع البرامج بأربعة طرق، هي الآتية:
</p>

<ul>
	<li>
		سلاسل من التعليمات: يتحرك فيها البرنامج من خطوة لأخرى في تسلسل صارم.
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72956" href="https://academy.hsoub.com/uploads/monthly_2021_07/sequence.png.23b6e4ac5f5e0ab6056c3004865cd2d5.png" rel=""><img alt="sequence.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72956" data-unique="tbqr6335x" src="https://academy.hsoub.com/uploads/monthly_2021_07/sequence.png.23b6e4ac5f5e0ab6056c3004865cd2d5.png"></a>
</p>

<ul>
	<li>
		الفروع Branches: هنا يصل البرنامج إلى نقطة اتخاذ قرار، فإذا تحققت نتيجة الاختبار -أي كانت القيمة <code>true</code>-، فإن البرنامج سينفذ التعليمات التي في المسار 1، وإذا كانت <code>false</code> فسينفذ الإجراءات التي في المسار 2، ويُعرف هذا بالبنية الشرطية لأن سير البرنامج يتوقف على نتيجة اختبار شرطي.
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72952" href="https://academy.hsoub.com/uploads/monthly_2021_07/branch.png.6016db450f59f6a771d3a50485fc9c0b.png" rel=""><img alt="branch.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72952" data-unique="odf7wd7s1" src="https://academy.hsoub.com/uploads/monthly_2021_07/branch.png.6016db450f59f6a771d3a50485fc9c0b.png"></a>
</p>

<ul>
	<li>
		الحلقات التكرارية Loops: تُكرَّر خطوات البرنامج في هذه الطريقة إلى أن نصل إلى اختبار شرطي ما، ينتقل تحكم البرنامج بعدها من الحلقة التكرارية إلى الجزء التالي من منطق البرنامج.
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72954" href="https://academy.hsoub.com/uploads/monthly_2021_07/loop.png.8753e63a781c0f7a6ca463407e73b8ad.png" rel=""><img alt="loop.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72954" data-unique="4tpg8jw5q" src="https://academy.hsoub.com/uploads/monthly_2021_07/loop.png.8753e63a781c0f7a6ca463407e73b8ad.png"></a>
</p>

<ul>
	<li>
		الوحدات Modules: هنا ينفذ البرنامج تسلسلًا متطابقًا من الخطوات عدة مرات، فتُجمع تلك الإجراءات في وحدة واحدة، وهي برنامج صغير الحجم يمكن تنفيذه من داخل البرنامج الرئيسي، وقد تُسمى الوحدات بأسماء أخرى مثل الدوال functions أو الإجراءات procedures أو البرامج الفرعية sub-routines.
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72955" href="https://academy.hsoub.com/uploads/monthly_2021_07/module.png.4483f139fcebd6418b4180b7e9b68864.png" rel=""><img alt="module.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72955" data-unique="814ggm3ky" src="https://academy.hsoub.com/uploads/monthly_2021_07/module.png.4483f139fcebd6418b4180b7e9b68864.png"></a>
</p>

<p>
	احتاجت البرامج إلى بعض المزايا الأخرى، إضافةً إلى ما سبق كي تكون مفيدة:
</p>

<ul>
	<li>
		البيانات
	</li>
	<li>
		العمليات: مثل الجمع والطرح والموازنة وغيرها.
	</li>
	<li>
		إمكانية الإدخال والإخراج: مثل عرض النتائج على شاشة مثلًا.
	</li>
</ul>

<p>
	وبمجرد أن تستطيع استيعاب المفاهيم أعلاه، والتعرُّف على كيفة تنفيذ اللغة البرمجية التي تستخدمها لها، فستكون قادرًا على كتابة برامج بتلك اللغة.
</p>

<h2>
	توضيح بعض المصطلحات
</h2>

<p>
	إذا قلنا إن البرمجة هي الفن الذي نجعل فيه الحواسيب تنفذ ما نريده منها، فما هو البرنامج إذًا؟
</p>

<p>
	في الواقع لدينا مفهومان مختلفان عن البرنامج، أولهما من منظور المستخدم، وهو ملف تنفيذي يثبَّت على الحاسوب ثم يمكن تشغيله لتنفيذ مهمة ما، فمثلًا يقول المستخدم أنه "يشغِّل" برنامج معالجة النصوص؛ أما المفهوم الثاني فهو من منظور المبرمج، وهو هنا مجموعة من التعليمات النصية الموجهة إلى الحاسوب المكتوبة بلغة برمجة ما، ويمكن ترجمتها إلى ملف تنفيذي. لهذا يجب أن تكون مدركًا عن أي المفهومين تتحدث حين تستخدم كلمة برنامج.
</p>

<p>
	يكتب المبرمجون برامجهم عادةً بلغة برمجة عالية المستوى تفسَّر إلى بايتات يفهمها الحاسوب، أي يكتب المبرمج شيفرةً مصدريةً source code؛ أما المفسر فيولد تعليمات مُصرَّفة object code، وقد يطلق على هذه التعليمات الناتجة عن التصريف أسماء أخرى مثل ملف تنفيذي أو شيفرة تنفيذية أو محمولة P-Code أو بايت كود Byte Code أو شيفرة ثنائية binary code، أو شيفرة الآلة machine code.
</p>

<p>
	كما يطلق على المترجم الذي يترجم لغة البرمجة العالية إلى لغة الآلة عدة أسماء، فقد يسمى بالمفسر interpreter أحيانًا، وبالمصرِّف compiler أحيانًا أخرى، وتشير هذه المصطلحات إلى نوعين من التقنيات المستخدمة في توليد الشيفرات الكائنية من الشيفرة المصدرية، فالمصرِّفات تنتج شيفرةً كائنيةً يمكن تشغيلها مستقلةً بذاتها دون الحاجة إلى المصرِّف في كل مرة يعمل فيها البرنامج، ويكون البرنامج في صورة ملف تنفيذي executable file؛ أما المفسِّرات فيجب أن تكون حاضرةً لتشغيل برامجها أثناء تنفيذها. لكن الفرق بين هذين المصطلحين صار ضبابيًا هذه الأيام بما أن بعض المصرفات تحتاج إلى مفسرات تكون حاضرةً لتنفيذ التحويل النهائي، كما تصرِّف بعض المفسرات شيفرتها المصدرية إلى شيفرة كائنية مؤقتة وتنفذها؛ أما من منظور المبرمجين فليس هناك فرق حقيقي، إذ تُكتب الشيفرة المصدرية وتُستخدَم أداة تسمح للحاسوب بقراءة الشيفرة وترجمتها وتنفيذها.
</p>

<h2>
	هيكل البرنامج
</h2>

<p>
	يعتمد الهيكل الدقيق للبرنامج على لغة البرمجة والبيئة التي يعمل فيها، لكن توجد بعض المبادئ الأساسية عمومًا:
</p>

<ul>
	<li>
		المحمِّل Loader: يحتاج كل برنامج أن يُحمّله نظام التشغيل إلى الذاكرة، وهذه وظيفة المحمل الذي يُنشأ عادةً بواسطة المفسر.
	</li>
	<li>
		تعريفات البيانات: تعمل أغلب البرامج بناءً على بيانات، وسنحتاج في مرحلة ما في شيفرتنا المصدرية إلى تعريف نوع البيانات الذي نعمل معه تعريفًا دقيقًا، وهذا يختلف من لغة برمجة لأخرى.
	</li>
	<li>
		التعليمات statements: وهي صلب البرامج، وهي تعدّل البيانات التي نعرّفها وتنفذ الحسابات وتطبع الخرج لنا..
	</li>
</ul>

<p>
	تتبع أغلب البرامج إحدى الهيكلين التاليين:
</p>

<h3>
	برامج باتش Batch Programs
</h3>

<p>
	تُبدأ تلك البرامج عادةً من سطر الأوامر أو بواسطة أداة جدولة، وتتبع النمط التالي في الغالب.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72951" href="https://academy.hsoub.com/uploads/monthly_2021_07/batch.png.0a9456c4af14cb627362f57ab8d4cd86.png" rel=""><img alt="batch.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72951" data-unique="qj94htx24" src="https://academy.hsoub.com/uploads/monthly_2021_07/batch.png.0a9456c4af14cb627362f57ab8d4cd86.png"></a>
</p>

<p>
	يبدأ البرنامج بتعيين حالته الداخلية كأن يعين الإجماليات totals إلى صفر، ويفتح الملفات المطلوبة، وبمجرد أن يكون جاهزًا للعمل، فإنه يقرأ البيانات من المستخدم بعرض موجهات الأوامر أو المحثات على الشاشة أو من ملف بيانات، أو بالطريقتين معًا، حيث يعطي المستخدم اسم ملف البيانات ثم تُقرأ البيانات الفعلية من الملف، بعد ذلك يعالج البرنامج البيانات معالجةً تتضمن عمليات رياضيةً أو تحويلات للبيانات أو غير ذلك، أخيرًا، تُخرج النتائج إلى شاشة عرض أو تُكتب إلى ملف، وستكون جميع البرامج التي نكتبها في الأجزاء الأولى من السلسلة من هذا النوع، أي برامج باتش أو رُقع.
</p>

<h3>
	البرامج الحدثية Event driven programs
</h3>

<p>
	تُعَد أغلب الأنظمة ذات الواجهة الرسومية مثل ويندوز أو أندرويد، وأنظمة التحكم المدمجة Embedded control systems مثل جهاز المايكروويف لديك أو الكاميرا أو غيرهما، من البرامج الحدَثية، أي يتوقف سيرها على وقوع أحداث معينة، بحيث يرسِل نظام التشغيل أحداثًا إلى البرنامج فيستجيب لها وفقًا لوصولها إليه، وقد تكون تلك الأحداث أمورًا يفعلها المستخدم مثل نقر زر الفأرة أو ضغط زر ما، أو أمورًا يفعلها النظام نفسه مثل تعديل الساعة أو تحديث الشاشة، وتبدو البرامج الحدثية في الغالب كما يلي:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="png" data-fileid="72953" href="https://academy.hsoub.com/uploads/monthly_2021_07/eventloop.png.5178327161c20e90054a504a43663fe0.png" rel=""><img alt="eventloop.png" class="ipsImage ipsImage_thumbnailed" data-fileid="72953" data-unique="6mu7rmeqm" src="https://academy.hsoub.com/uploads/monthly_2021_07/eventloop.png.5178327161c20e90054a504a43663fe0.png"></a>
</p>

<p>
	يبدأ البرنامج هنا بتعيين حالته الداخلية، ثم ينتقل التحكم إلى بيئة التشغيل (تسمى أحيانًا وقت التشغيل runtime)، ويوفر نظام التشغيل تلك البيئة في الغالب، كما ينتظر البرنامج حلقة الحدث لتلتقط تفاعل المستخدم الذي يترجَم إلى أحداث بعدها، ثم ترسَل تلك الأحداث إلى البرنامج كي يتعامل معها حدثًا حدثًا، وينفذ المستخدِم الإجراء النهائي الذي ينهي البرنامج، فيُنشَأ حدث خروج ويُرسَل إلى البرنامج. 
</p>

<h2>
	خاتمة
</h2>

<p>
	ذكرنا في هذا المقال أنك تحتاج إلى التفكير المنطقي والفضول من أجل تعلم البرمجة، ويمكن الرجوع في هذا إلى مقال <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">الدليل الشامل في تعلم البرمجة</a> من أكاديمية حسوب، ومقال <a href="https://academy.hsoub.com/programming/general/%D8%AD%D9%84-%D8%A7%D9%84%D9%85%D8%B4%D9%83%D9%84%D8%A7%D8%AA-%D9%88%D8%A3%D9%87%D9%85%D9%8A%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D8%A7%D8%AD%D8%AA%D8%B1%D8%A7%D9%81-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r760/" rel="">حل المشكلات وأهميتها في احتراف البرمجة</a> من الأكاديمية أيضًا، كما يجب أن نذكر أن كل لغات البرمجة المذكورة أعلاه متاحة للتحميل مجانًا، وبهذا لا يبقى سوى أن تأتي بذهن حاضر، مع قليل من حس الدعابة والمرح لنبدأ البرمجة، إذ تسمح لنا لغات البرمجة بالتحدث مع الحواسيب بلغة قريبة من لغات البشر المنطوقة، لكنها تختلف عن الطريقة التي تتحدث الحواسيب أو تفكر بها، وقد قلنا إن البرامج تعمل وفقًا للبيانات، وأنها إما برامج رُقع batch programs أو برامج حدثية Event driven تتصرف وفقًا للأحداث التي تُرسل إليها.
</p>

<p>
	ترجمة -بتصرف- للفصلين  <a href="http://www.alan-g.me.uk/l2p2/tutneeds.htm" rel="external nofollow">?What do I need </a> و<a href="http://www.alan-g.me.uk/l2p2/tutwhat.htm" rel="external nofollow">?What is Programming</a>  من كتاب Learning to Program لصاحبه Alan Gauld. <a href="http://www.alan-g.me.uk/l2p2/tutwhat.htm" rel="external nofollow"> </a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		المقال التالي: <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%AF%D8%A7%D9%8A%D8%A9-%D8%B1%D8%AD%D9%84%D8%A9-%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r1280/" rel="">بداية رحلة تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">تعلم البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%A3%D8%B3%D9%87%D9%84-%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">أسهل لغات البرمجة</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D9%87%D9%8A-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D9%88%D9%84%D9%85%D8%A7%D8%B0%D8%A7-%D8%AA%D8%B5%D8%A8%D8%AD-%D9%85%D8%A8%D8%B1%D9%85%D8%AC%D9%8B%D8%A7-r659/" rel="">ما هي البرمجة ولماذا تصبح مبرمجا</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">1279</guid><pubDate>Fri, 16 Jul 2021 15:00:00 +0000</pubDate></item><item><title>&#x645;&#x642;&#x627;&#x631;&#x646;&#x629; &#x628;&#x64A;&#x646; &#x628;&#x627;&#x64A;&#x62B;&#x648;&#x646; &#x648; PHP &#x648;&#x631;&#x648;&#x628;&#x64A;</title><link>https://academy.hsoub.com/programming/general/%D9%85%D9%82%D8%A7%D8%B1%D9%86%D8%A9-%D8%A8%D9%8A%D9%86-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86-%D9%88-php-%D9%88%D8%B1%D9%88%D8%A8%D9%8A-r630/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_07/Ruby-vs.-Python-vs.-PHP.png.dd7e66a200bf69111a2d4e44bced1879.png" /></p>
<p id="-php-">
	يُقدر أنّ عدد لغات البرمجة الإجمالي يتجاوز 9000 لغة برمجة، منها حوالي 50 لغة تُستخدم على نطاق واسع من قبل المبرمجين <a href="https://careerkarma.com/blog/how-many-coding-languages-are-there/" rel="external nofollow">[1]</a>. هذا العدد الهائل قد يربك المبتدئ الذي يريد دخول عالم البرمجة، بل وحتى المبرمجين الذين يرغبون في تعلم لغات برمجة أخرى.
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<p>
	إنّ أسئلة من قبيل: أيّ لغة برمجة ينبغي أن أتعلم؟ أو ما هي أفضل لغة برمجة؟ أو هل اللغة الفلانية خير من اللغة الفلانية؟ هي من الأسئلة الجدلية. يكفي أن تبحث على جوجل على مثل هذه الأسئلة وستجد ما يشبه حربا ضروسا على شبكة الإنترنت. فهذا يقول إنّ لغة البرمجة الفلانية هي أفضل اللغات، والآخر يقول بل اللغة الفلانية الأخرى خير.
</p>

<p>
	هناك سبب وجيه لهذا الاختلاف، ذلك أنّه لا توجد لغة برمجة تناسب الجميع، أو تتفوق على غيرها في كل المجالات. لكل لغة برمجة نقاط قوة ونقاط ضعف.
</p>

<p>
	سنحاول في هذه المقالة أن نساعد المبتدئ، وحتى من له خبرة سابقة في البرمجة ويريد تعلم لغات برمجة إضافية، على اختيار لغة البرمجة المناسبة ليتعلمها ويبدأ بها. سنركز في هذه المقالة على ثلاث من أشهر لغات <a href="https://academy.hsoub.com/programming/general/%D9%84%D8%BA%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9/" rel="">البرمجة</a> وأكثرها شعبية، وهي <a href="https://wiki.hsoub.com/Python" rel="external">بايثون</a> و<a href="https://wiki.hsoub.com/Ruby" rel="external">روبي</a> و <a href="https://wiki.hsoub.com/PHP" rel="external">PHP</a>. سنوازن بين هذه اللغات ونستعرض أهم مميزات كل منها من الجوانب التالية:
</p>

<ul>
	<li>
		استخدامات اللغة وتطبيقاتها
	</li>
	<li>
		سهولة التعلم
	</li>
	<li>
		الشعبية
	</li>
	<li>
		الدعم والاستقرَار
	</li>
	<li>
		الأمان
	</li>
	<li>
		المكتبة وإطارات العمل
	</li>
	<li>
		الطلب في سوق العمل
	</li>
	<li>
		محاسن ومساوئ كل لغة باختصار
	</li>
</ul>

<p>
	سنختم هذه المقالة بخلاصة لنجيب فيها عن سؤال أيّ هذه لغات البرمجة أنسب لكي تتعلمها وتبدأ بها.
</p>

<h2 id="-">
	استخدامات اللغة وتطبيقاتها
</h2>

<h3 id="-">
	بايثون
</h3>

<ul>
	<li>
		بايثون هي لغة برمجة متعددة الأغراض، أي أنّه يمكن استخدامها لتطوير كافة أنواع التطبيقات، من تطبيقات الويب، وحتى الألعاب وتطبيقات سطح المكتب.
	</li>
	<li>
		<strong>تطوير الويب</strong>: يمكن استخدام بايثون لتطوير المواقع وتطبيقات الويب، إذ توفّر عددا من إطارات العمل المتقدمة، مثل Django و Flask. لكن شعبيتها لدى مطوري الويب أقل عموما من روبي و PHP.
	</li>
	<li>
		<strong>تطوير تطبيقات سطح المكتب</strong>: بايثون مثالية <a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8/" rel="">لتطبيقات سطح المكتب</a>، إذ أنّها لغة مستقلة عن المنصات وأنظمة التشغيل، فبرامج بايثون يمكن أن تعمل دون جهد إضافي على ويندوز وأنظمة يونيكس.
	</li>
	<li>
		<strong>الذكاء الاصطناعي</strong>: نحن نعيش ثورة جديدة ستغير كل شيء من حولنا، وهي ثورة<a href="https://academy.hsoub.com/programming/artificial-intelligence/%D8%A7%D9%84%D8%B0%D9%83%D8%A7%D8%A1-%D8%A7%D9%84%D8%A7%D8%B5%D8%B7%D9%86%D8%A7%D8%B9%D9%8A/" rel=""> الذكاء الاصطناعي</a> وتعلم الآلة التي أصبحت تطبيقاتها في كل مكان، في السيارات ذاتية السياقة وأجهزة التلفاز الذكية وروبوتات الدردشة والتعرف على الوجوه وغيرها من التطبيقات. تُعد بايثون أنسب لغات البرمجة للذكاء الاصطناعي كما يراها 57% من المطورين <a href="https://www.cuelogic.com/blog/role-of-python-in-artificial-intelligence" rel="external nofollow">[2]</a>. إذ توفر للباحثين في هذا المجال مكتبات متقدمة في مختلف مجالات البحث العلمي، مثل Pybrain لتعلم الآلة، وكذلك TensorFlow، وهي مكتبة يمكن استخدامها في الشبكات العصبونية والتعرف على الصور ومعالجة اللغات الطبيعية وغيرها .
	</li>
	<li>
		<strong>البحث العلمي</strong>: توفر بايثون للباحثين مكتبات عملية متقدمة تساعدهم على أبحاثهم، مثل مكتبة Numpy الخاصة بالحوسبة العلمية، و Scipy الخاصة بالتحليل العددي.
	</li>
	<li>
		بايثون تُستخدم بكثافة في القطاعات الأكاديمية والتجارية، هذه بعض المشاريع والشركات التي طُوِّرت باستخدامها:
		<ul>
			<li>
				جوجل: لدى جوجل قاعدة عامة تقول: "استخدم بايثون ما أمكن، واستخدم C++‎ عند الضرورة".
			</li>
			<li>
				انستغرام: إحدى أكبر الشبكات الاجتماعية
			</li>
			<li>
				Netflix: أكبر منصة لبث الأفلام والمسلسلات على الشبكة
			</li>
			<li>
				Uber: أكبر تطبيق للتوصيل
			</li>
		</ul>
	</li>
</ul>

<h3 id="-">
	روبي
</h3>

<ul>
	<li>
		تشبه روبي بايثون في العديد من الجوانب، من ذلك أنّها لغة برمجة متعددة الأغراض، إذ يمكن استخدامها في كافة أنواع التطبيقات.
	</li>
	<li>
		روبي هي لغة كائنية خالصة، أي أنّ كل شيء في روبي هو كائن له توابعه وخاصياته. يجعلها هذا مثالية للبرامج التي تعتمد بكثافة على نمط البرمجة الكائنية.
	</li>
	<li>
		<strong>تطبيقات الويب</strong>: روبي مثالية لتطوير تطبيقات الويب، إذ توفر إحدى أشهر وأفضل منصات تطوير الويب، وهي <a href="https://wiki.hsoub.com/Rails" rel="external">Ruby on Rails</a>. والدليل على ذلك أنّ بعض أكبر المنصات والمواقع تستخدم Ruby on Rails، مثل منصة التجارة الإلكترونية Shopify.
	</li>
	<li>
		<strong>المشاريع الكبيرة</strong>: تُستخدم روبي في المشاريع الكبيرة والمعقدة والتي تستغرق مدة طويلة، وتتطلب تغييرات مستمرة.
	</li>
	<li>
		<strong>لغة نمذجة</strong>: تُستخدم روبي في تطوير نماذج أولية للبرامج ( prototypes) قبل البدء بتطويرها الفعلي.
	</li>
	<li>
		<strong>لغة سكريبتات</strong>: تُستخدم روبي (وبايثون كذلك) لبرمجة السكربتات، وهي ملفات تحتوي مجموعة من الأوامر التي يمكن تنفيذها دون الحاجة إلى تصريفها.
	</li>
	<li>
		من أكبر المشاريع والمواقع التي طُوِّرت باستخدام روبي نذكر على سبيل المثال لا الحصر:
		<ul>
			<li>
				Sass: أحد أفضل امتدادات لغة CSS.
			</li>
			<li>
				Hulu: منصة لبث الأفلام والمسلسلات والوثائقيات
			</li>
			<li>
				Github : أكبر منصة لاستضافة المشاريع البرمجية
			</li>
		</ul>
	</li>
</ul>

<h3 id="php">
	PHP
</h3>

<ul>
	<li>
		على خلاف روبي وبايثون، PHP ليست متعددة الأغراض، وإنما هي لغة متخصصة في برمجة الخوادم.
	</li>
	<li>
		الاستخدام الأساسي للغة PHP هو تطوير الواجهات الخلفية للمواقع وتطبيقات الويب، سواء الساكنة أو الديناميكية.
	</li>
	<li>
		<strong>تطبيقات سطح المكتب</strong>: صحيح أنّ PHP لغة متخصصة في برمجة الخوادم، إلا أنّه يمكن استخدامها لتطوير تطبيقات سطح المكتب باستخدام مكتبة PHP-GTK.
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/php/%D8%AA%D8%B9%D8%B1%D9%81-%D8%B9%D9%84%D9%89-%D9%84%D8%BA%D8%A9-php-r2040/" rel="">لغة PHP</a> لغة قوية، وقد طُوِّرت بها بعض أكبر المواقع على شبكة الإنترنت، مثل:
		<ul>
			<li>
				فيسبوك: أكبر شبكة اجتماعية
			</li>
			<li>
				ياهو: محرك بحث
			</li>
			<li>
				ويكيبيديا: تستخدم هذه الموسوعة الضخمة PHP ضمن مجموعة من اللغات الأخرى
			</li>
			<li>
				ووردبريس: أكبر منصة لإدَارة المحتوى
			</li>
		</ul>
	</li>
</ul>

<h2 id="-">
	سهولة التعلم
</h2>

<p>
	إحدى أهم عوامل المفاضلة بين لغات البرمجة هي سهولة تعلمها، خصوصا لدى المبتدئين. تعد بايثون على العموم أبسط وأسهل للتعلم موازنة بلغة روبي أو PHP. بايثون لغة مختصرة وبعيدة عن الإسهاب، في الحقيقة يُقدّر أنّ بايثون تختصر في المتوسط حوالي 80% من الشفرات المكتوبة موازنة بلغات البرمجة الكائنية الأخرى <a href="https://w3techs.com/technologies/details/pl-php" rel="external nofollow">[3]</a>. أضف إلى ذلك أن كتابة شيفرة برمجية بلغة بايثون أشبه بكتابة قصيدة أو قصة باللغة الإنجليزية الأمر الذي لا يجعل كتابة شيفرات بايثون عملية سهلة وممتعة، بل حتى قراءتها أيضًا.
</p>

<p>
	<a href="https://academy.hsoub.com/php/" rel="">تعلم PHP</a> أصعب عمومًا من تعلم بايثون، ذلك أنّ بايثون لغة متعددة الأغراض، أما PHP فهي لغة متخصصة تتطلب معرفة أولية بلغات أخرى، مثل <a href="https://wiki.hsoub.com/HTML" rel="external">HTML</a> و <a href="https://wiki.hsoub.com/CSS" rel="external">CSS</a> و <a href="https://wiki.hsoub.com/JavaScript" rel="external">Javascript</a>. لكن إن كنت تريد تعلم PHP، فأتوقع أنك تريد أن تتعلم تطوير المواقع، ما يعني أنّك غالبا تعرف أساسيات هذه اللغات. فيما يخص روبي، فهي أصعب قليلا، وقد تحتاج إلى معرفة أولية بأساسيات البرمجة قبل تعلمها.
</p>

<h2 id="-">
	الشعبية
</h2>

<p>
	تحل بايثون في المرتبة الرابعة <a href="https://insights.stackoverflow.com/survey/2020" rel="external nofollow">كأكثر لغات البرمجة شعبية</a> أثناء تحديث هذا المقال، كما تتربع على عرش لغات البرمجة متعددة الأغراض، إذ يستخدمها حوالي 44% من المبرمجين. ثمّ تأتي لغة PHP في المرتبة الثامنة في قائمة أكثر لغات البرمجة شعبية، إذ يستخدمها حوالي 26% من المطورين، أما روبي فتأتي في المرتبة الرابع عشرة بنسبة استخدام تقارب 7%.
</p>

<p>
	لا تتمتع بايثون بالشعبية وحسب، ولكنها محبوبة أيضا لدى مجتمع المبرمجين، ففي <a href="https://insights.stackoverflow.com/survey/2020" rel="external nofollow">الاستطلاع نفسه</a> لعام 2020، جاءت بايثون في المرتبة الثالثة كأحب لغات البرمجة إلى المبرمجين، إذ أنّ أكثر من ثلثي المبرمجين المُستطلَعين قالوا أنّهم يحبونها. بالمقابل أتت كل من روبي و PHP في المرتبتين 19 و 20 على التوالي في هذه القائمة، حيث أنّ 43% من المبرمجين قالوا أنّهم يحبون روبي، و37% منهم قالوا أنهم يحبون PHP.
</p>

<p>
	هناك فرق واضح بين بايثون وبين PHP وروبي من حيث الشعبية وحب المبرمجين. بايثون بلا شك تتفوق في هذا الجانب تفوقا واضحا. لكن تجدر الإشارة إلى أنّ لغة PHP متخصصة، فهي تكاد تُستخدم حصرا في برمجة الخوادم، على خلاف بايثون وروبي متعدّدتي الأغراض، واللتان تُستخدمان في كل المجالات تقريبا. لذا رغم أنّ شعبية PHP أقل من بايثون، إلا أنّ هذا لا يقلل من قيمتها، ولا يعني أنّها غير مفيدة أو أنّه ليس لها مستقبل. بل على العكس، فهذا دليل على قوتها، لتتأكد من هذا حاول مقارنة شعبية PHP بلغة البرمجة ASP المتخصصة في المجال نفسه (برمجة الخوادم). لغة ASP ليست موجودة حتى في قائمة أكثر 25 لغة البرمجة استخدامًا. وهذا يعطيك فكرة عن قوة PHP وشعبيتها رغم أنّها لغة متخصصة في مجال واحد فقط.
</p>

<p>
	من جهة أخرى، لغتا PHP وروبي ليست محبوبتين للمبرمجين، إذ احتلّتا مرتبتين متأخرتين في قائمة أكثر اللغات المحبوبة.
</p>

<h2 id="-">
	الدعم والاستقرار
</h2>

<p>
	لغات بايثون وروبي PHP لغات مفتوحة المصدر، وتتمتع بمجتمع كبير من المبرمجين، وتُستخدم على نطاق واسع في المشاريع البحثية والتجارية.
</p>

<p>
	ظهرت هذه اللغات الثلاث في أوقات متقاربة:
</p>

<ul>
	<li>
		PHP: ظهرت سنة 1995، وهي في الإصدار 7.3 حاليا.
	</li>
	<li>
		بايثون: ظهرت سنة 1991، وهي في الإصدار 3.8 حاليا
	</li>
	<li>
		روبي: ظهرت سنة 1995، وهي في الإصدار 2.7 حاليا
	</li>
</ul>

<p>
	ما فتئت هذه اللغات تتطور منذ تأسيسها، خصوصا بايثون و PHP اللتان تُحدَّثان بوتيرة سريعة. كما تتمتع هذه اللغات بمجتمعات كبيرة وحيوية تدعمها، سواء عبر المكتبات أو المقالات أو الدروس والشروح.
</p>

<p>
	هناك مسألة يجدر الانتباه لها، وهي أّنه يوجد من بايثون إصداران: الإصدار ‎2.x‎ والإصدار ‎3.x‎. وهما إصداران غير متوافقين، فالبرامج المكتوبة ببايثون ‎2.x‎، لن تعمل على بايثون ‎3.x‎، والعكس صحيح. هذا الأمر يمكن أن يكون مزعجا، خصوصا للمبتدئين. ولكن لا ينبغي أن تقلق من هذا، إذ أنّ دعم بايثون ‎2.x‎ توقف سنة 2020، وسيبقى الإصدار بايثون ‎3.x‎‎ وحسب.
</p>

<p>
	هناك ملاحظة أخرى مهمة، وهي أنّ لغة PHP انتقلت من الإصدار 5 إلى الإصدار 7 مباشرة، إذ أنّه ليس هناك إصدار سادس من هذه اللغة. السبب في ذلك هو أنّه كانت هناك خلافات كثيرة عليها، لذلك انتقل المطورون إلى الإصدار السابع مباشرة، والذي جاء بتعديلات كثيرة وجذرية على اللغة. يُفضل على العموم العمل بهذا الإصدار، لأنه الأحدث، كما أنّ بعض أنظمة إدارة المحتوى، مثل ووردبريس، تتطلب استخدام الإصدار السابع.
</p>

<p>
	هذه اللغات الثلاث على العموم مستقرة وتتمتع بدعم كبير وتُحدَّث باستمرار. وستبقى كذلك على الأرجح لمدة طويلة.
</p>

<h2 id="-">
	الأمن
</h2>

<p>
	لقد أصبح موضوع الأمن الرقمي والخصوصية من المواضيع المهمّة في الوقت الحالي. فكل يوم نسمع عن حالات اختراق وسرقة للبيانات الحساسة، حتى لدى الشركات الكبيرة مثل فيسبوك وجوجل. لهذا السبب ينبغي أن يحرص المبرمج على تأمين تطبيقاته وبرامجه وحماية خصوصيات المستخدمين وبياناتهم الحساسة.
</p>

<p>
	لا توجد عمومًا لغة برمجة آمنة تماما، فالأمر لا يعود إلى اللغة أو المنصة المُستخدمة، ولكن يعود إلى مدى احترام المبرمج لمعايير الأمن وكتابة شيفرات نظيفة وخالية من الثغرات الأمنية.
</p>

<p>
	قد تجد البعض يقول أنّ PHP أقل أمانا من بايثون وروبي، أو أنها لغة غير آمنة، وهذا أمر مردود. فلو كانت PHP غير آمنة، أنظنّ أنّ أكبر شبكة اجتماعية في العالم، وهي فيسبوك التي تخزن أكبر قاعدة بيانات للبيانات الشخصية للمستخدمين ستستخدم PHP؟ هذا غير ممكن. PHP مثلها مثل بايثون أو روبي، هي لغة مستقرة ويسهر عليها آلاف المطورين الذين يحدثونها باستمرار ويحرصون على سد أيّ ثغرة تظهر فيها. ربما كان السبب الذي يجعل البعض يقول هذا هو أنّ صياغة بايثون البسيطة تقلل من احتمال وجود ثغرات في الشفرة، وذلك على خلاف PHP التي تُعد أعقد من بايثون. قد يكون هذا الأمر صحيحا نسبيا، لكنّ الأمر يعود في النهاية إلى المبرمج، إن كان المبرمج يرتكب أخطاء ولا يحترم معايير الأمن، فلن تكون برامجه آمنة مهما كانت اللغة التي يكتب بها.
</p>

<h2 id="-">
	الأداء والسرعة
</h2>

<p>
	سرعة التنفيذ هي إحدى العوامل الأساسية لاختيار لغات البرمجة، خصوصا في المجالات التي تحتاج إلى إجراء حسابات مكثّفة، مثل الرسوميات وتطوير الألعاب. هناك نوعان من لغات البرمجة: لغات البرمجة المُفسّرة (interpreted): هي لغات برمجة يتم تنفيذ الشفرات المكتوبة بها مباشرة. لغات البرمجة الُمصرّفة (compiled): هي لغات برمجة تُصرّف (تُترجم) شفراتها إلى لغة المُجمّع أو أيّ لغة وسيطة قبل تنفيذها. على العموم، لغات البرمجة المصرّفة أسرع من لغات البرمجة المفسّرة. تُعد كل من بايثون وروبي لغتين مفسرتين، أما PHP فرغم أنّها مفسرة على العموم، إلا أنّ أنّ البرنامج الذي يسمح لك بتفسير تعليمات PHP مُصرَّف إلى رُقامة (bytecode) وسيطة. لهذا السبب فإنّ PHP عموما أسرع من بايثون، كما أنّ بايثون عموما أسرع من روبي.
</p>

<h2 id="-">
	المكتبات وإطارات العمل
</h2>

<p>
	تُقاس قوة كل لغة برمجة بالمكتبات التي توفرها. المكتبات هي حُزم من الشفرات الجاهزة والمنظمة التي تقدم دوالا وأصنافًا جاهزة لحل مشاكل معينة، أو إنشاء تطبيقات في مجال معين. أما إطارات العمل فهي منصات للبرمجة والتطوير، وعادة ما توفر أدوات تساعد على إنشاء المشاريع وإدارتها، وتنفيذ الشفرات وتنقيح الأخطاء وغيرها من المهام اليومية التي تسهل عمل المبرمجين.
</p>

<p>
	سوف نستعرض في هذه الفقرة بعض المكتبات وإطارات العمل الشهيرة للغات بايثون وروبي و PHP.
</p>

<h3 id="-">
	بايثون
</h3>

<ul>
	<li>
		Django: هو إطار عمل مجاني ومفتوح المصدر لتطوير المواقع. يوفر Django العديد من المزايا، مثل إدارة قواعد البيانات والمصادقة (authentication) وإدارة المستخدمين وغيرها.
	</li>
	<li>
		pycharm: هو إطار عمل لكتابة البرامج بلغة بايثون، يتولى pycharm التفاصيل الروتينية، ويتيح لك أن تركز على المهام الكبيرة والمعقدة. pycharm هو بيئة تطوير متكاملة، ويوفر العديد من المزايا، مثل الإكمال التلقائي للشفرات وفحص الأخطاء وإدارة المشاريع وغيرها.
	</li>
	<li>
		TensorFlow: هي مكتبة مجانية ومفتوحة المصدر للذكاء الاصطناعي من تطوير شركة جوجل. تُستخدم TensorFlow لكتابة وتقديم خوارزميات الذكاء الاصطناعي والتعلم الآلي والعصبونات. تُستخدم TensorFlow في العديد من مشاريع الذكاء الاصطناعي، مثل البحث الصوتي في جوجل.
	</li>
	<li>
		PyGame: مكتبة لتطوير ألعاب الفيديو، وتوفر العديد من المكتبات لمعالجة الصوت والصورة وكل الجوانب الضرورية لتطوير الألعاب.
	</li>
</ul>

<h3 id="-">
	روبي
</h3>

<ul>
	<li>
		Ruby on Rails: هو إطار عمل لتطوير تطبيقات الويب، ويوفر كل المزايا والوظائف التي تحتاجها لتطوير تطبيقات ومواقع ويب متقدمة. هذا الإطار مفتوح المصدر ومجاني.
	</li>
	<li>
		Bundler: هي بيئة متكاملة لإدارة مشاريع روبي تمكن من تثبيت المكتبات ومعالجة الإصدارات بسهولة.
	</li>
	<li>
		Better_errors: مكتبة لاختبار الشفرات المكتوبة بلغة روبي وتنقيح الأخطاء.
	</li>
</ul>

<h3 id="php">
	PHP
</h3>

<ul>
	<li>
		Laravel: أحد أشهر إطارات العمل الخاصة بلغة PHP. يُسرّع Laravel وتيرة العمل على المشاريع الكبيرة، إذ يوفر الكثير من المزايا الجاهزة، مثل المصادقة على المستخدمين وإدارة الجلسات والتخزين المؤقت وغيرها من المهام الأساسية لتطوير تطبيقات الويب.
	</li>
	<li>
		ووردبريس: ووردبريس هو أشهر نظام لإدارة المحتوى، ويُشغِّل ملايين المواقع على الشبكة. هذه المنصة مبنية على PHP.
	</li>
	<li>
		Ratchet: تمكّن هذه المكتبة من إنشاء تطبيقات ثنائية الاتجاه بين الخادم والعميل.
	</li>
</ul>

<p>
	تتوفر بايثون وروبي و PHP على المئات إن لم أقل الآلاف من المكتبات وإطارات العمل، وكل سنة تظهر مكتبات وإطارات عمل جديدة تستبدل القديمة أو تنافسها. مهما كانت اللغة التي اخترتها، ومهما كان المجال الذي تعمل فيه، فستجد حتمًا مكتبات جاهزة لمساعدتك على كتابة برامجك.
</p>

<h2 id="-">
	الطلب في سوق العمل
</h2>

<p>
	الطلب في سوق العمل هو أحد المؤشرات الأساسية للموازنة بين لغات البرمجة، خصوصا لمن كان يبحث عن وظيفة.
</p>

<p>
	بحسب استطلاع stackoverflow، فإنّ مطوري روبي يحصلون على أعلى أجر موازنة بمطوري بايثون و PHP. إذ يحصل مطور روبي في المتوسط على 71 ألف دولار سنويا، أما مطور بايثون فيحصل على 59 ألف دولار سنويا، بالمقابل لا يحصل مطور PHP إلا على 39 ألف دولار سنويا. من الواضح أنّ روبي هي الأفضل من حيث الأجور وفرص العمل، وقد يعود ذلك إلى قلة من يتقنون روبي، فقد رأينا من قبل أنّ شعبيتها بين المبرمجين قليلة موازنة ببايثون أو حتى PHP. هذه الأرقام تُحسب على صعيد عالمي، لكن قد يختلف الواقع من دولة إلى أخرى، مثلا في السعودية يحصل مطور PHP سنويا على حوالي 16 ألف دولار <a href="https://www.payscale.com/research/SA/Job=PHP_Developer/Salary" rel="external nofollow">[4]</a>، فيما يحص مطور بايثون على حوالي 18 ألف دولار سنويا <a href="https://www.payscale.com/research/SA/Skill=Python/Salary" rel="external nofollow">[5]</a>.
</p>

<p>
	أجور مطوّري PHP على العموم أقل من أجور مطوري بايثون وروبي، لكنّ الرواتب لا تُحدد بلغة البرمجة وحسب، إذ يمكن أن يحصل مطوّر PHP محترف وذو خبرة على أكثر مما يحصل عليه مطورو بايثون أو روبي، فالعبرة هنا بالاحترافِية وإتقان العمل.
</p>

<h2 id="-">
	محاسن ومساوئ كل لغة
</h2>

<h3 id="-">
	بايثون
</h3>

<table>
	<tbody>
	</tbody>
	<thead>
		<tr>
			<th>
				محاسن
			</th>
			<th>
				مساوئ
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				سهلة التعلم ومناسبة للمبتدئين
			</td>
			<td>
				هناك إصداران غير متوافقان منها
			</td>
		</tr>
		<tr>
			<td>
				صياغة بايثون بسيطة وقريبة من اللغة الطبيعية
			</td>
			<td>
				التعامل مع الأخطاء ليس مثاليا
			</td>
		</tr>
		<tr>
			<td>
				مختصرة وموجزة
			</td>
			<td>
				غير مناسبة لتطبيقات الجوال
			</td>
		</tr>
		<tr>
			<td>
				تتمتع بشعبية كبيرة لدى المبرمجين
			</td>
			<td>
				ليست مثالية للبرامج التي تعتمد على الاستخدام المكثف للذاكرة
			</td>
		</tr>
		<tr>
			<td>
				مكتبة ضخمة تساعد على تطوير كافة أنواع التطبيقات
			</td>
			<td>
				ليست مناسبة للبرامج المتوازية التي تعمل على المعالجات المتعددة
			</td>
		</tr>
	</tbody>
</table>

<h3>
	روبي
</h3>

<table>
	<tbody>
	</tbody>
	<thead>
		<tr>
			<th>
				محاسن
			</th>
			<th>
				مساوئ
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				مناسبة للبرامج الكبيرة
			</td>
			<td>
				صعبة على المبتدئين
			</td>
		</tr>
		<tr>
			<td>
				تمكن من تطوير التطبيقات بسرعة
			</td>
			<td>
				مصادر تعلم روبي على العموم أقل من بايثون و PHP
			</td>
		</tr>
		<tr>
			<td>
				مجتمع نشيط وحيوي ومكتبة كبيرة
			</td>
			<td>
				بطيئة موازنة باللغات الأخرى
			</td>
		</tr>
		<tr>
			<td>
				تتوفر على إحدى أفضل منصات تطوير تطبيقات الويب: ruby on rails
			</td>
			<td>
				التطوير والتحديث بطيئ
			</td>
		</tr>
	</tbody>
</table>

<h3 id="php">
	PHP
</h3>

<table>
	<tbody>
	</tbody>
	<thead>
		<tr>
			<th>
				محاسن
			</th>
			<th>
				مساوئ
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>
				سهلة التعلم
			</td>
			<td>
				صياغتها ليست ببساطة بايثون
			</td>
		</tr>
		<tr>
			<td>
				تدعم جميع خوادم الويب الرئيسية مثل: أباتشي ومايكروسوفت و Netscape
			</td>
			<td>
				أسماء الدوال مربكة وغير متناسقة
			</td>
		</tr>
		<tr>
			<td>
				لها شعبية كبيرة جدا لدى مطوري الويب
			</td>
			<td>
				بطيئة موازنة باللغات الأخرى
			</td>
		</tr>
		<tr>
			<td>
				مدعومة من أكبر نظام لإدارة المحتوى، وهو ووردبريس
			</td>
			<td>
				لا تدعم التطبيقات المتوازية
			</td>
		</tr>
	</tbody>
</table>

<h2 id="-">
	خلاصة القول
</h2>

<p>
	لقد استعرضنا مميزات لغات بايثون وروبي و PHP، ووازنّا بينها من عدة جوانب، وذكرنا بعض مساوئ ومحاسن كل منها. خلاصة القول أنّه لا توجد لغة مثالية تصلح للجميع. لكن إن كنت مبتدئا ولم تكن لك خبرة سابقة بالبرمجة، فإني أنصحك بأن تبدأ بلغة بايثون، فبساطتها وسهولتها ستساعدك على هضم المفاهيم البرمجية بسرعة وبعدها يمكنك أن تنتقل إلى تعلم اللغة التي تريدها بخطى ثابتة وأنت متمكن من المفاهيم البرمجية الأساسية التي تشترك بها كل لغات البرمجة. أما إن كانت لك خبرة سابقة في البرمجة وأردت أن تطور مستواك وتعمل على مشاريع كبيرة، فيمكن أن تتعلم روبي. وإن كنت تريد أن تتخصص في تطوير تطبيقات الويب أو تريد العمل بووردبريس، فالأولَى أن تتعلم PHP.
</p>

<p>
	 
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/programming/python/%D9%85%D9%85%D9%8A%D8%B2%D8%A7%D8%AA-%D9%84%D8%BA%D8%A9-%D8%A8%D8%A7%D9%8A%D8%AB%D9%88%D9%86/" rel="">تعرف على أبرز مميزات لغة بايثون</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/programming/general/%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D9%8A%D8%A7%D9%86%D8%A7%D8%AA/" rel="">علم البيانات Data science: الدليل الشامل</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">630</guid><pubDate>Wed, 08 Jul 2020 10:00:00 +0000</pubDate></item><item><title>&#x645;&#x627; &#x627;&#x644;&#x645;&#x642;&#x635;&#x648;&#x62F; &#x628;&#x645;&#x635;&#x637;&#x644;&#x62D; &#x645;&#x641;&#x62A;&#x648;&#x62D; &#x627;&#x644;&#x645;&#x635;&#x62F;&#x631; (open source)&#x61F;</title><link>https://academy.hsoub.com/programming/general/%D9%85%D8%A7-%D8%A7%D9%84%D9%85%D9%82%D8%B5%D9%88%D8%AF-%D8%A8%D9%85%D8%B5%D8%B7%D9%84%D8%AD-%D9%85%D9%81%D8%AA%D9%88%D8%AD-%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1-open-source%D8%9F-r885/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_05/What-is-open-source-software.jpg.1f625eb28b316f3719bfba34e5e4fe8b.jpg" /></p>
<p>
	يشير مصطلح <a href="https://opensource.com/article/18/2/coining-term-open-source-software" rel="external nofollow">مفتوح المصدر</a> (open source) لأي شيء يمكن لأي شخص تعديله ومشاركته لأن تصميمه متاح للجميع.
</p>

<p>
	نشأ هذا المصطلح في سياق <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA/" rel="">تطوير البرمجيات</a> للدلالة على نهج خاص لإنشاء برامج للحاسوب. أما اليوم، فإن مصطلح "مفتوح المصدر" يشير لمجموعة أوسع من القيم - والّتي نسميها "<a href="https://opensource.com/open-source-way" rel="external nofollow"><strong>الثقافة مفتوحة المصدر</strong></a>. تتبنى المشاريع، أو المنتجات، أو المبادرات مفتوحة المصدر مبادئ التبادل المفتوح والمشاركة التعاونية والنماذج الأولية السريعة والشفافية العالية والجدارة والتنمية الموجهة للمجتمع.
</p>

<h2>
	ما هي البرمجية مفتوحة المصدر؟
</h2>

<p>
	البرمجيات مفتوحة المصدر: هي برمجيات يمكننا رؤية شيفرتها البرمجية وفحصها وتعديلها وتحسينها.
</p>

<p>
	"الشيفرة البرمجية" هي جزء من برمجية لا يراه معظم مستخدمي الحاسوب على الإطلاق، ويتلاعب مبرمجو الحاسوب بالشيفرة لتغيير طريقة عمل البرمجية - سواءً أكانت "برنامج" أو "تطبيق". يمكن للمبرمجين الّذين يستطيعون الوصول للشيفرة البرمجية لبرنامج الحاسوب تحسين هذا البرنامج من خلال إضافة ميزات إليه أو إصلاح الأجزاء الّتي لا تعمل دائمًا عملًا صحيحًا.
</p>

<h2>
	ما الفرق بين البرمجيات مفتوحة المصدر والأنواع أخرى؟
</h2>

<p>
	هناك بعض البرمجيات الّتي لا تُملكُ شيفرتها أو يمكن التعديل عليها سوى الجهة الّتي أنشأتها سواءً أكانت ممثلة بشخص أو فريق أو مؤسسة وتحتفظ هذه الجهة بالسيطرة الحصرية عليها. ويطلق الناس على هذا النوع من البرمجيات "بالبرمجيات المحتكرة" (proprietary) أو "مغلقة المصدر" (closed source).
</p>

<p>
	يمكن لأصحاب البرمجيات المحتكرة وحدهم نسخ هذه البرمجيات، وفحصها وتغييرها بطريقة قانونية. ولاستخدام البرمجيات المحتكرة لابد أن يوافق مستخدمي الحاسوب (للتوقيع على الترخيص المعروض والّذي يعرض عادةً عند التشغيل للمرة الأولى للبرمجيات) والّتي تنص على أنهم لن يفعلوا أي شيء للبرمجية مخالف صراحةً لما يسمح به منشئي هذه البرمجية. ومن هذه البرمجيات نذكر Microsoft Office وAdobe Photoshop.
</p>

<p>
	تختلف البرمجيات مفتوحة المصدر عن نظيرتها المحتكرة. إذ يتيح منشئي البرمجيات المفتوحة المصدر عرض الشيفرة البرمجية، ونسخها، والتعلم منها، وتغييرها، ومشاركتها أيضًا. ومن هذه البرمجيات نذكر محرر النصوص ليبر أوفيس <a href="https://www.libreoffice.org/" rel="external nofollow">LibreOffice</a> وبرنامج التلاعب بالصور <a href="http://www.gimp.org" rel="external nofollow">Gimp</a>.
</p>

<p>
	وكما هو الحال مع البرمجيات المحتكرة يجب على المستخدمين عند استخدامهم البرمجيات مفتوحة المصدر الموافقة على شروط الترخيص بيدَ أن هذه الشروط تختلف اختلافًا كبيرًا عن شروط البرمجيات المحتكرة.
</p>

<p>
	تحدّد تراخيص البرمجيات مفتوحة المصدر طريقة استخدام البرمجيات، وتعديلها، وتوزيعها. وعمومًا تَمنحُ هذه التراخيص إذنًا باستخدام البرمجيات لأي غرض يرغب به المستخدم. إلا أن البعض الأخر من التراخيص والّتي يسميها البعض "الحقوق المتروكة" تنص على وجوب عرض الشيفرة البرمجية الخاصة لكلّ نُسخة مُعدلة من هذه البرمجية علنيًا. علاوة على ذلك بعض التراخيص تُوجبُ على أي شخص يعدلّ البرمجية ويشاركها مع الآخرين أن يشارك أيضًا المصدر الأصلي للشيفرة بدون فرض رسوم الترخيص عليها.
</p>

<p>
	تعمدُ تراخيص البرمجيات مفتوحة المصدر على تعزيز روح التعاون والمشاركة لأنها تسمح للجميع بإجراء تعديلات على الشيفرات البرمجية، ودمج هذه التغييرات في مشاريعهم الخاصة. وهم بذلك يشجعون مبرمجي الحاسوب بالوصول إلى البرمجيات مفتوحة المصدر وعرضها وتعديلها بأي وقت يحلو لهم، طالما أنهم سمحوا للآخرين بفعل نفس الشيئ عندما يشاركون برمجياتهم.
</p>

<h2>
	هل البرمجيات مفتوحة المصدر مهمة لمبرمجي الحاسوب فقط؟
</h2>

<p>
	بالتأكيد لا. بل إن التكنولوجيا مفتوحة المصدر والعقلية المنفتحة للمصادر المفتوحة عمومًا تفيد كلًا من المبرمجين وغير المبرمجين.
</p>

<p>
	لأن المخترعين الأوائل للإنترنت شيدوا جزءًا كبيرًا منه على تقنياتٍ مفتوحة المصدر - مثل: نظام التشغيل Linux و<a href="http://httpd.apache.org/" rel="external nofollow">تطبيق خادم الوِب المحلي Apache</a> - وبذلك أي شخص يستخدم الانترنت فهو في الحقيقة يستفيد من البرمجيات مفتوحة المصدر.
</p>

<p>
	عند كلّ عملية استعراض لصفحة وِب أو التحقق من البريد الإلكتروني، أو الدردشة مع الأصدقاء، أو استخدام منصات البث الموسيقي عبر الإنترنت، أو اللعب بألعاب فيديو متعددة اللاعبين فإن حاسوب المستخدم، أو هاتفه المحمول، أو طرفيات الألعاب ستتصل بشبكة عالمية من الحواسيب من خلال برمجيات مفتوحة المصدر من أجل توجيه ونقل البيانات إلى أجهزتهم "المحلية" الموجودة أمام أعينهم. عادةً ما تتواجد هذه الحواسيب الّتي تؤدي كلّ هذا العمل الهام في أماكن بعيدة عن أنظار المستخدمين أو لا يستطيعون الوصول إليها فعليًا - وهذا هو السبب في أن بعض الأشخاص يطلقون على هذه الحواسيب "بالحواسيب البعيدة".
</p>

<p>
	يعتمد الناس أكثر فأكثر على الحواسيب البعيدة عند أداء مهامهم بدلًا من أجهزتهم المحلية. فمثلًا، قد يستخدمون برمجيات معالجة الكلمات وإدارة البريد الإلكتروني وتحرير الصور وهي غير مثبتة على حواسيبهم الشخصية. وإنما، ببساطة يصلون لها عبر الحواسيب البعيدة من خلال متصفح الوِب أو تطبيق على الهاتف محمول. وعندما يفعلون ذلك، فهم ينخرطون في "الحوسبة عن بُعد".
</p>

<p>
	يطلق بعض الأشخاص على الحوسبة عن بُعد "<a href="https://academy.hsoub.com/devops/cloud-computing/" rel="">بالحوسبة السحابية</a>" وذلك لأنها تتضمن أنشطة (مثل: تخزين الملفات أو مشاركة الصور أو مشاهدة مقاطع الفيديو) والّتي لا تتضمن حواسيب محلية فقط وإنما شبكة عالمية من الحواسيب البعيدة أيضًا الّتي تشكل سحابة.
</p>

<p>
	تتوالى أهمية الحوسبة السحابية يومًا بعد يوم وخصيصًا في الحياة اليومية للأجهزة المتصلة بالإنترنت. ومن بعض تطبيقات الحوسبة السحابية المحتكرة Google Apps. أما بعض التطبيقات الأخرى مفتوحة المصدر نذكر: ownCloud وNextcloud.
</p>

<p>
	تعمل تطبيقات الحوسبة السحابية "على قمة" من البرمجيات الإضافية المساعدة لها لتعمل بسلاسة وكفاءة، لذلك غالبًا ما سيقول الناس أن البرمجيات الّتي تعمل "تحت" تطبيقات الحوسبة السحابية تعمل بمثابة "منصة" لتطبيقات الحوسبة السحابية، وتكون هذه المنصات إما مفتوحة المصدر أو مغلقة المصدر. فمثلًا المنصة OpenStack هي منصة مفتوحة المصدر.
</p>

<h2>
	لماذا يفضل الناس استخدام برمجيات مفتوحة المصدر؟
</h2>

<p>
	يفضل الناس البرمجيات مفتوحة المصدر على حساب البرمجيات المحتكرة لعدد من الأسباب:
</p>

<h3>
	زيادة السيطرة على البرمجية
</h3>

<p>
	يفضل كثير من الناس البرمجيات مفتوحة المصدر لأنها تعطيهم مزيدًا من السيطرة والتحكم. إذ يمكنهم فحص الشيفرة البرمجية للتأكد من أنها ستؤدي نفس المهمة الّتي يريدونها، بل ويمكنهم حتى تغيير أي جزء منها لا يحبونه. كما يستفيد غير المبرمجين من هذه البرمجيات أيضًا، لأنهم يمكنهم استخدام هذه البرمجية لأي غرض يرغبون فيه - وبذلك لا تُفرض عليهم الطريقة الّتي يعتقد شخص ما -صاحب البرمجية مثلًا- بأنه يجب عليهم استخدام البرمجية وفقًا لها (كما يحدث في البرمجيات المحتكرة).
</p>

<h3>
	التعلم والتدرب من هذه البرمجيات
</h3>

<p>
	يحبُ البعض الآخر من الناس هذه البرمجيات لأنها تساعدهم ليصبحوا مبرمجين أفضل. نظرًا لأن الشيفرة البرمجية متاحة للجميع، وبذلك يمكن للطلاب دراستها بسهولة أثناء تعلمهم لإنشاء برمجية أفضل. يمكن للطلاب مشاركة عملهم مع الآخرين أيضًا، ودعوتهم للتعليق والنقد البناء، وبذلك يصقل الطلاب مهاراتهم. عندما يكتشف الأشخاص أخطاءً في الشيفرات البرمجية لبرامجهم، يمكنهم مشاركة هذه الأخطاء مع الآخرين لمساعدتهم على تجنب ارتكاب نفس هذه الأخطاء.
</p>

<h3>
	الحماية والأمان
</h3>

<p>
	يُفضل بعض الأشخاص هذه البرمجيات لأنهم يرونها أكثر أمانًا واستقرارًا من البرمجيات المحتكرة. نظرًا من كون الجميع يستطيع عرض وتعديل البرمجيات مفتوحة المصدر، فيمكن لأي شخص أن يكتشف خطأ غفِلَ عنه أصحاب البرمجية أنفسهم بل ويمكن أن يصحح أو يحذف هذا الخطأ. ولأن العديد من المبرمجين يمكنهم العمل على جزء معين من البرمجية بدون طلب إذن من أصحابها، فسيُسرّع ذلك من وتيرة إصلاح البرمجية وتحديثها وترقيتها أكثر من البرمجيات المحتكرة.
</p>

<h3>
	الاستقرار والثبات
</h3>

<p>
	يفضل العديد من المستخدمين البرمجيات مفتوحة المصدر على نظيرتها المحتكرة للمشاريع المهمة وطويلة الأمد. نظرًا لتوزيع المبرمجين الشيفرة البرمجية علنًا للبرمجيات مفتوحة المصدر، فيمكن للمستخدمين الّذين يعتمدون على هذه البرمجيات في المهام الحرجة التأكد من أن أدواتهم لن تختفي أو تتعطل إذا توقف أصحابها عن تطويرها -وذلك لأن لديها عدة مبرمجين آخرين مهتمين بها- علاوة عن ذلك، تميل البرمجيات مفتوحة المصدر للاندماج والعمل وفقًا للمعايير المفتوحة.
</p>

<h3>
	المجتمع الداعم للبرمجية
</h3>

<p>
	غالبًا ما تستقطب البرمجيات مفتوحة المصدر جمهورًا من المستخدمين والمطورين المحبين لها. وهذا ليس حكرًا على هذه البرمجيات بل العديد من التطبيقات الشعبية لها مجتمعات كبيرة ومواضيع يناقشونها في لقاءاتهم واجتماعاتهم. غير أن في البرمجيات مفتوحة المصدر يكون المجتمع ليس مجرد قاعدة جماهيرية تشتري (سواء عاطفيًا بالدعم أو ماليًا بسعر البرمجية) وتكوّن بذلك مجموعة مميزة من المستخدمين وحسب، وإنما مجموعة من الأشخاص الّذين ينتجون ويختبرون ويستخدمون ويروجون بل ويؤثرون تأثيرًا جوهريًا على البرمجية الّتي يحبونها.
</p>

<h2>
	هل يعني مصطلح "مفتوح المصدر" بأنه مجاني؟
</h2>

<p>
	لا. هذا مفهوم خاطئ ومنتشر حول ما يعنيه مصطلح "مفتوح المصدر"، وممكن ألا يتعلق هذا المصطلح بالمال.
</p>

<p>
	يمكن لمبرمجي هذه البرمجيات أن يتقاضوا المال مقابل البرمجيات مفتوحة المصدر الّتي يصنعونها أو يساهمون فيها. ولكن في بعض الحالات، نظرًا لأن ترخيص المصدر المفتوح يتطلب منهم إصدار الشيفرة البرمجية علنًا عندما يبيعون هذه البرمجيات للآخرين، ولذلك يجدُ بعض المبرمجين أن فرض رسوم على المستخدمين مقابل الخدمات والدعم الفني للبرمجية (بدلًا من البرمجية بحد ذاتها) أكثر ربحًا. وبهذا تظل برمجياتهم مجانية، ويكسبون المال من مساعدة الآخرين في تثبيتها واستخدامها واستكشاف أخطائها وإصلاحها.
</p>

<p>
	على الرغم من كون بعض البرمجيات مفتوحة المصدر مجانية، إلا أن مهارة البرمجة واستكشاف الأخطاء وإصلاحها في البرمجيات مفتوحة المصدر يمكن أن تكون ذات قيمة كبيرة. يسعى الكثير من أرباب العمل لتوظيف مبرمجين لديهم خبرة سابقة بالعمل على برمجيات مفتوحة المصدر تحديدًا.
</p>

<h2>
	ما هي الثقافة مفتوحة المصدر "أي أبعد من الشيفرة البرمجية"؟
</h2>

<p>
	إن التعامل مع جميع جوانب الحياة بثقافة مفتوحة المصدر يعني التعبير عن الرغبة في المشاركة والتعاون مع الآخرين بشفافية (ليتمكن الآخرين من المشاهدة أو حتى الانضمام أيضًا)، واحتضان الفشل كوسيلة للتطوّر، وتوقع -أو حتى تشجيع- الجميع ليشاركوا وينضموا إلى هذه الثقافة.
</p>

<p>
	ويعني الالتزام أيضًا بدور فعّال في تحسين العالم، وهو أمر ممكن في حال تمكن الجميع من الوصول للطريقة الّتي صُمّم بها هذا العالم.
</p>

<p>
	إن العالم مليء "بالشيفرات البرمجية" - المخططات والوصفات والقواعد - الّتي توجه طريقة تفكيرنا وتشكلها من أجل أن نتصرف على أساسها. نؤمن تمامًا بأن هذه الشيفرة الضمنية (مهما كان شكلها) يجب أن تكون مفتوحةً وقابلة للوصول والمشاركة من قِبل الجميع — ليتمكنوا من تغييرها للأفضل.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://opensource.com/resources/what-open-source" rel="external nofollow">What is open source software?</a>‎
</p>
]]></description><guid isPermaLink="false">885</guid><pubDate>Sun, 31 May 2020 18:05:00 +0000</pubDate></item><item><title>&#x643;&#x644; &#x645;&#x627; &#x62A;&#x631;&#x64A;&#x62F; &#x645;&#x639;&#x631;&#x641;&#x62A;&#x647; &#x639;&#x646; WebAssembly</title><link>https://academy.hsoub.com/programming/general/%D9%83%D9%84-%D9%85%D8%A7-%D8%AA%D8%B1%D9%8A%D8%AF-%D9%85%D8%B9%D8%B1%D9%81%D8%AA%D9%87-%D8%B9%D9%86-webassembly-r869/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_04/WebAssembly.jpg.24d095b5dd477bd38bcc8b279cb01caa.jpg" /></p>

<p>
	إذا لم تسمع بعد عن WebAssembly، فستسمع عنه قريبًا على رغم من وجوده في كل مكان، فهو مدعوم من أغلب المتصفحات (وسيدعم الخادم قريبًا) وهو سريع ويُستخدم في الألعاب، وهو معيار مفتوح من اتحاد شبكة الويب العالميّة (W3C)، والتي هي المنظمة الدولية للمعايير الرئيسيّة لشبكة الإنترنت.
</p>

<p>
	ستندهش على الأغلب من ذلك، وسترغب في تعلم البرمجة به، لكن هذا ليس صحيح تمامًا، فأنت لا تكتب شيفرات باستخدام WebAssembly، لنأخذ بعض الوقت ونتعلم حول هذه التكنولوجيات التي تختصر في العادة إلى "Wasm".
</p>

<h2>
	من أين أتت؟
</h2>

<p>
	إذا عدنا لعشرة سنوات إلى الوراء، سنجد أن جافاسكربت لم يكن سريعًا كفاية للكثير من الأشياء، فلغة الجافاسكربت كانت بلا شك ناجحة ومناسبة، فهي تعمل على أي متصفّح وتضيف للصفحات الحيويّة التي نعتبرها أمرًا عاديًا الآن، لكنه كان لغة عاليّة المستوى وهي غير مصمّمة للعمل على أعمال تستهلك الكثير من الحسابات.
</p>

<p>
	ومع ذلك، على الرغم من أن المهندسين المسؤولين عن متصفحات الويب الشهيرة كانوا متفقين بشكل عام على مشكلة الأداء، فلم يتفقوا حول حل لها. فلقد ظهر معسكران، بدأت جوجل مشروع عميل Native وبعد ذلك نسخة محمولة منه للتركيز على السماح للألعاب وبقيّة البرامج المكتوبة بلغة C و ‎C++‎ للعمل في مكان آمن في كروم Chrome. وفي نفس الوقت، حصلت Mozilla على دعم Microsoft لـ asm.js، وهو أسلوب لتحديث المتصفح للعمل على مجموعة فرعية من تعليمات جافا سكربت منخفضة المستوى بسرعة كبيرة (ظهر مشروع آخر مكّن من تحويل شيفرات C و C++‎ إلى هذه التعليمات).
</p>

<p>
	لم يحصل أي معسكر على تبني واسع، لذلك اتفقوا جميعًا على التعاون في 2015 حول معيار جديد يدعى WebAssembly مبني على نهج بسيط مأخوذ من asm.js، وكما كتب Stephen Shankland في CNET:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"في الويب اليوم، سيحوّل جافا سكربت المتصفح هذه التعليمات إلى شيفرات الآلة. لكن مع WebAssembly، سيقوم المبرمج بالكثير من العمل في وقت سابق لإنشاء برنامج بين هاتين الحالتين، وسيحرر هذا المتصفح من الكثير من العمل لإنشاء شيفرة الآلة، لكنه في نفس الوقت سيفي بوعد الويب، والذي هو أن البرنامج سيعمل على أي جهاز مع متصفح مهما كانت تفاصيل المعدات."
	</p>
</blockquote>

<p>
	أعلنت موزيلا في 2017 عن منتج الحد الأدنى (Minimum viable product) للتجربة، وجميع المتصفحات تبنته في نهاية ذلك العام، وفي ديسمبر 2019، أطلقت مجموعة عمل WebAssembly مواصفات WebAssembly الثلاثة كتوصيات W3C.
</p>

<p>
	يعرّف WebAssembly صيغة شيفرة بصيغة ثنائية (binary code) محمولة للبرامج التنفيذيّة، و مقابلها بلغة التجميع، وواجهات لتسهيل التفاعل بين هذه البرامج والبيئة المستضيفة. تعمل شيفرة البرمجية لـ WebAssembly في آلات افتراضية ذات مستوى منخفض الذي يحاكي وظائف العديد من المعالجات الدقيقة التي يمكن تشغيلها عن طريق ترجمة فوريّة - Just-In-Time‏ (JIT) - أو تفسير - interpretation -، يمكن لمحرّك WebAssembly العمل بنفس السرعة تقريبًا للترجمة في منصة Native.
</p>

<h2>
	لماذا الاهتمام الآن؟
</h2>

<p>
	يأتي بعض من الإهتمام الأخير بـ WebAssembly من الرغبة في تشغيل شيفرات تستهلك الكثير من الحسابات في المتصفحات، فمستخدمي الحاسوب المحمول على وجه الخصوص، يقضون أغلب أوقاتهم في المتصفح (أو في حالة Chromebooks، كامل وقتهم)، لذلك خلق هذا الاتجاه إلحاحا حول إزالة الحواجز التي تحول دون تشغيل مجموعة كبيرة من التطبيقات في المتصفح، وواحدة من هذه الحواجز هي الأداء، والتي صمم WebAssembly في الأصل لمعالجتها.
</p>

<p>
	ومع ذلك، فإن WebAssembly ليس للمتصفحات فقط، ففي عام 2019، أعلنت موزيلا عن مشروع يدعى WASI اختصارًا للعبارة WebAssembly System Interface أي واجهة نظام WebAssembly لوضع معيار لكيفية تعامل شيفرة WebAssembly مع نظام التشغيل خارج سياق المتصفح، وبالجمع ما بين دعم المتصفح لـ WebAssembly و WASI ستتمكن من تشغيل ملفات الثنائيّة المترجمة في داخل وخارج المتصفحات، عن طريق مختلف الأجهزة وأنظمة التشغيل، بسرعة الآلة (Native) تقريبًا.
</p>

<p>
	بسبب أعباء WebAssembly المنخفضة سيكون من العملي استخدامه خارج المتصفحات، لكن هنالك العديد من الطرق الأخرى التي يمكننا من خلالها تشغيل تطبيقات بنفس الكفائة، فلماذا نستخدم WebAssembly تحديدًا؟
</p>

<p>
	أهم سبب لهذا هو المحمولية، فاللغات المترجمة المستخدمة اليوم مثل C++‎ و Rust هي الأكثر ارتباطًا بـ WebAssembly اليوم. ومع ذلك، العديد من اللغات الأخرى تترجم إلى أو تملك آلاتها الافتراضيّة في WebAssembly، وعلاوة على ذلك، على الرغم من افتراض WebAssembly لبعض الشروط المسبقة لبيئات التنفيذ، فإنه مصمم للعمل بكفاءة على مجموعة واسعة من أنظمة التشغيل والبنيات، لذلك يمكن كتابة شيفرة WebAssembly باستخدام مجموعة واسعة من اللغات على نطاق واسع من أنظمة التشغيل وأنواع المعالجات.
</p>

<p>
	تنبع ميّزة WebAssembly أخرى، من حقيقة أن الشيفرة البرمجية تعمل في آلة افتراضيّة، ونتيجة لذلك، كل وحدة WebAssembly تنفذ في بيئة منعزلة عن وقت تنفيذ المضيف باستخدام تقنية عزل الخطأ (fault isolation). ويتضمن هذا من الأشياء الأخرى، أن تنفّذ التطبيقات في منعزل عن بقيّة بيئة المضيف ولا يمكنها الهروب من البيئة المنعزلة دون المرور عن طريق <abbr title="Application Programming Interface | واجهة برمجية">API</abbr>.
</p>

<h2>
	أمثلة عمليّة WebAssembly
</h2>

<p>
	مثال على WebAssembly هو <a href="https://enarx.io/" rel="external nofollow">Enarx</a>.
</p>

<p>
	يوفّر مشروع Enarx استقلاليّة الأجهزة لتأمين التطبيقات باستخدام بيئات التنفيذ الموثوق (Trusted Execution Environments)، فيسمح لك هذا الأخير بتسليم تطبيق مترجم إلى WebAssembly بشكل آمن إلى مزود السحابي (cloud) وتشغيله عن بعد، وكما يقول مهندس الأمن في Red Hat المهندس Nathaniel McCallum:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		"الطريقة لفعل ذلك هي عن طريق أخذ البرنامج كمُدخل ومن ثم نجري عمليّة تصديق مع الأجهزة البعيدة حتى نتأكد من أن ذلك هو الجهاز الذي يدعي أنه هو باستخدام تقنيات التشفير، ولن تكون النتيجة زيادة مستوى الأمن والثقة في الأجهزة التي نتعامل معها فقط، بل هي مفتاح الجلسة، والتي يمكننا بعد ذلك استخدامها لإيصال شيفرة برمجيّة مشفّرة وبيانات إلى هذه البيئة التي طلبنا عمليّة التصديق معها باستخدام التشفير."
	</p>
</blockquote>

<p>
	ومثال آخر لذلك هو OPA أي عميل السياسة المفتوحة (Open Policy Agent)، والذي أعلن في نوفمبر 2019 أنه يمكنك ترجمة لغة تعريف السياسة الخاصة بهم Rego إلى WebAssembly، يسمح لك Rego بكتابة المنطق للبحث والجمع بين بيانات JSON/YAML من مختلف المصادر لسؤال عن أسئلة مثل "هل <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> هذا متاح؟".
</p>

<p>
	أستخدمت OPA لتطبيقات تفعيل السياسة (policy-enable software) والتي من بينها Kubernetes، ويُعتبر تبسيط السياسة باستخدام أدوات مثل OPA خطوة مهمة لتأمين نشر Kubernetes بشكل جيّد بين البيئات المختلفة، فمحمولية وميزات الأمن المدمجة في WebAssembly تعتبر أسلحة ممتازة لهذه الأدوات.
</p>

<p>
	آخر مثال على ذلك هو Unity، لقد ذكرنا في بداية المقال عن أنه WebAssembly يُستخدم في الألعاب، فيعتبر يونتي Unity والذي هو محرّك ألعاب متعدّد المنصات من أوائل المتبنين للـ WebAssembly، حيث وفروا أول نسخة تجريبيّة لـ Wasm في المتصفحات، ومنذ الشهر الثامن من سنة 2018، تُستخدم WebAssembly كهدف للمخرجات لهدف بناء <a href="https://academy.hsoub.com/programming/javascript/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D8%A5%D9%84%D9%89-webgl-%D8%AA%D8%B9%D8%B1%D9%8A%D9%81-r481/" rel="">Unity WebGL</a>.
</p>

<h2>
	نظرة أعمق على WebAssembly
</h2>

<p>
	إن WebAssembly هو ملف ثنائي يمكن تشغيله من قبل جميع المتصفحات (باستثناء IE 11) عبر الأجهزتها الافتراضيّة، ولديه القدرة على البدء والعمل بشكل أسرع من جافا سكربت لأن الملف الثنائي يمكن فهمه بسهولة من قبل المتصفحات وسيعمل بطريقة مثاليّة، وإذا كنت مهتم بالتفاصيل التقنيّة التي تجعل من WebAssembly مميّز، فأنصحك <a href="https://hacks.mozilla.org/2017/02/a-cartoon-intro-to-webassembly/" rel="external nofollow">بهذا المقال</a>.
</p>

<p>
	وعلى الرغم من أنني بدأت بالبحث في WebAssembly عند بحثي عن طريقة كتابة Rust في بيئات أخرى (على سبيل المثال المتصفّح)، لكن ليس هذا ما يجعل WebAssembly مميّز، فأنا أستمتع بكتابة جافا سكربت (TypeScript على وجه الخصوص)، وبيئة تطوير الويب المبنيّة على جافا سكربت كبيرة للغاية ولا يمكن إلغاؤها، فيمكنك اعتبار WebAssembly كإضافة إلى جافا سكربت حيث يمكنك استخدامه في المهام التي يكون أداء جافا سكربت ضعيف.
</p>

<p>
	يمكن استخدام WebAssembly لكتابة تطبيقات ويب كاملة أو استبدال أجزاء من تطبيقات يكون أدائها غير جيّد كفاية ببديل يعمل بسرعة أكبر، وبالإضافة إلى ذلك، بما أن WebAssembly ملف تجميع مشابه للغة الآلة، فيمكن استخدام العديد من اللغات للترجمة إليه، أي مشاركة الشيفرة البرمجية مع المنصات الأخرى والويب أصبح الآن أكثر عملية.
</p>

<h2>
	لغات تدعم WebAssembly
</h2>

<p>
	يمكن استخدام العديد من اللغات للترجمة إلى WebAssembly، بما في ذلك C#‎ وGo، فلماذا لا نستخدمهم بدلًا من Rust؟ على الرغم من أن استخدام لغات البرمجة هو أمر شخصي يختلف حسب تفضيلات الشخص، إلا أن هنالك العديد من الأسباب التي تجعل من Rust أفضل أداة لهذا العمل، فهذه اللغات تملك وقت تشغيل كبير يجب وضعه في ملف الثنائي لـ WebAssembly، لذلك فهي مناسبة فقط للمشاريع الجديدة غير المبنيّة على مشاريع أخرى (على سبيل المثال، فهي مناسبة كبديل لجافا سكربت)، <a href="https://github.com/golang/go/wiki/WebAssembly" rel="external nofollow">هذا المقال</a> ستجد في قسم Wasm في ويكي لغة GO يقول أن أصغر حجم ملف ثنائي غير مضغوط يمكن عمله هو 2 ميغابايت، بالنسبة للغة Rust، والتي تملك أجزاء وقت التشغيل صغيرة للغاية (مجرّد allocator)، فمثال "أهلا بالعالم" يُترجم إلى ملف بحجم 1.6 كيلوبايت على حاسوبي بدون تحسينات لخفض الحجم (والتي يمكنها تصغيره أكثر).
</p>

<p>
	أنا لا أقول أن للغات Go وC#‎ مستقبل سيء بالنسبة لتطبيقات الويب، فأنا متشوّق حول جديدها، لكنني أعتقد أنها ستكون مناسبة للمشاريع الجديدة غير مبنيّة على مشاريع أخرى.
</p>

<p>
	على الرغم من أن لغات C و C++‎ تملك وقت تشغيل صغير للغاية مثل Rust وهي مناسبة لوضعها داخل التطبيقات والمكتبات الموجودة بالفعل، فإن Rust ستجعل من إنشاء ملفات WebAssembly ثنائيّة التي تستخدم واجهات جافا سكربت اصطلاحيّة إلى حد ما باستخدام الأدوات التي سنكتشفها في المقالات هذه السلسلة، في حين أن المعالجة في لغات C و C++‎ أكثر يدويّة. إن استخدام الأدوات في لغة Rust جميل للغاية وأعتقد أنها تجعل كامل التجربة ممتعة بشكل أكبر، وتمتاز لغة Rust بأنها لغة آمنة للذاكرة لذا فإن هذا الصنف من الأخطاء الموجودة في لغات C و C++‎ يستحيل وجوده في Rust، وإذا استخدمت لغات تملك ذاكرة آمنة مثل جافا سكربت وجافا وC#‎ (وحتى إذا لم تستخدمها) سترغب باستخدام لغة Rust.
</p>

<p>
	لنسمي لغات C و C++‎ و Rust بلغات النظام، لأن هدفهم برمجة الأنظمة وتطبيقات عاليّة الأداء. تتشارك هذه اللغات بمميزات تجعلهم منسابين للترجمة إلى WebAssembly، سنتعرف في القسم القادم على المزيد من التفاصيل وسنعد أمثلة لشيفرات برمجية كاملة بلغات C و TypeScript مع عينات من لغة صيغة نص WebAssembly.
</p>

<h2>
	أنواع البيانات الصريحة وجامع القمامة
</h2>

<p>
	تتطلّب لغات الأنظمة أنواع بيانات صريحة مثل int وdouble للتصريح عن متغيرات القيم المرجعة من الدوال، فعلى سبيل المثال، توضح هذه الشيفرة البرمجية عملية جمع 64 بت في لغة السي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3129_6" style="">
<span class="kwd">long</span><span class="pln"> n1 </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> n2 </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">long</span><span class="pln"> sum </span><span class="pun">=</span><span class="pln"> n1 </span><span class="pun">+</span><span class="pln"> n2</span><span class="pun">;</span></pre>

<p>
	دوال المكتبة random تعرّف نوع long للإرجاع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3129_8" style="">
<span class="kwd">long</span><span class="pln"> random</span><span class="pun">();</span><span class="pln"> </span><span class="com">/* returns a long */</span></pre>

<p>
	في أثناء الترجمة، تتحول الشيفرة المكتوبة بلغة C إلى لغة التجميع (أسمبلي) ومن ثم إلى لغة الآلة، تتحول الشيفرة البرمجيّة السابقة في لغة التجميع لـ Intel (نوع AT&amp;T)، إلى ما يشبه هذا (حيث أن ## هي التعليقات):
</p>

<pre class="ipsCode">
addq %rax, %rdx ## %rax = %rax + %rdx (64-bit addition)
</pre>

<p>
	إن ‎%‎rax و ‎%‎rdx هي سجلات 64 بت، وتعليمة addq تعني أجمع quadwords، حيث أن quadwords هي 64 بت، والذي هو المعيار لنوع long في لغة سي، تترجم لغة التجميع التعليمات السابقة إلى لغة الآلة بما في ذلك الأنواع، حيث أن في العادة يقدم النوع من خلال خليط بين التعليمات والمعاملات، وفي هذه الحالة، تعليمة add هي addq (عملية جمع 64 بت)، وهنالك أيضًا addl والتي تجمع قيم 32 بت، أي نوع int في لغة السي. السجلات هي من نوع 64 بت (حرف r في ‎%rax و ‎%rdx) بدلًا من قطع 32 بت منه (على سبيل المثال ‎%eax هو النسخة المنخفضة من 32بت من ‎%rax و ‎%edx هي النسخة 32بت المنخفضة من ‎%rdx).
</p>

<p>
	تنفّذ عملية الجمع في لغة التجميع بأداء عالي لأن المعاملات مخزنة في سجلات CPU، ومترجم لغة C العادي (حتى لو استخدم تحسينات الوضع الافتراضي) سينتج شيفرة برمجيّة بلغة أسمبلي مشابهة للسابق.
</p>

<p>
	تعتبر لغات الأنظمة الثلاثة هي خيارات جيّدة للترجمة إلى WebAssembly بسبب تركيزها على أنواع صريحة كما في WebAssembly: i32 لقيمة عدد صحيح 32 بت و f64 لقيمة الفاصلة العائمة، وهكذا…
</p>

<p>
	تشجع أنواع البيانات الصريحة تحسين استدعاءات الدالة، فتملك الدالة مع نوع بيانات صريح توقيع يحدد أنواع البيانات للمعاملات والقيمة التي ستعود من الدالة (إذا كانت موجودة)، وفي الأسفل توقيع لدالة WebAssembly تسمى ‎$add، وهي مكتوبة بشكل نص لغة WebAssembly كما سنتحدث عليها لاحقًا، تأخذ الدالة عددين صحيحين 32 بت كمعاملات وترجع عدد صحيح 64 بت:
</p>

<pre class="ipsCode">
(func $add (param $lhs i32) (param $rhs i32) (result i64))
</pre>

<p>
	يجب أن يملك مترجم JIT للمتصفح على معاملات أعداد صحيحة 32 بت ويرجع قيمة 64 بت مخزنة في سجلات بالحجم المناسب.
</p>

<p>
	عندما نتحدث عن شيفرة برمجيّة عالية الأداء فإن WebAssembly تتربع على عرش ذلك، فعلى سبيل المثال asm.js هي لغة برمجة مشابهة لجافا سكربت لزيادة الأداء وجعلها مقاربة لسرعة الآلة، فتدعو هذه اللغة إلى تحسين الشيفرة البرمجيّة لتحاكي أنواع البيانات الصريحة الموجودة في لغات النظام، هذا المثال بلغة C وآخر بلغة asm.js، فعينة الدالة في لغة C هي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3129_12" style="">
<span class="typ">int</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">       </span><span class="com">/** C **/</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> n </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	فكل من معامل n و نوع الإرجاع من نوع int بصراحة، والدالة المقابلة لذلك في asm.js ستكون هذه :
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3129_14" style="">
<span class="kwd">function</span><span class="pln"> f</span><span class="pun">(</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">      </span><span class="com">/** asm.js **/</span><span class="pln">
  n </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">|</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">|</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	فلغة جافا سكربت لا تعلن صراحة عن أنواع البيانات، لكن عملية OR بتيّة في جافا سكربت ترجع عدد صحيح، هذا مثال لعملية OR البتيّة عديمة الجدوى:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3129_16" style="">
<span class="pln">n </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">|</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">  </span><span class="com">/* bitwise-OR of n and zero */</span></pre>

<p>
	عمليّة OR البتيّة بين n و صفر تساوي n، لكن هدفنا هنا أن n يحتوي على عدد صحيح، فتعليمة return تخدعك عن طريق التحسين.
</p>

<p>
	يتميّز TypeScript بين أنواع جافا سكربت بتبني أنواع البيانات الصريحة، والتي ستجعل من هذه اللغة جذابة للترجمة إلى لغة WebAssembly (ستجد شيفرة برمجية تفسر هذا في الأسفل).
</p>

<p>
	الميّزة المشتركة الثانية بين أنظمة اللغات الثلاثة أنها تنفّذ دون جامع القمامة garbage collector (GC)‎، فمترجم لغة Rust لتخصيص الذاكرة بشكل حيوي يكتب شيفرات البرمجيّة الخاصة بالتخصيص وإلغاء التخصيص (allocation/deallocation) وبالنسبة لبقية اللغات، يقع هذا العمل على المبرمج حيث أن من مهامه تخصيص وإلغاء التخصيص بشكل صريح في هذه الذاكرة، لذلك فلغات الأنظمة تتجنّب تعقيدات جامع القمامة التلقائي.
</p>

<p>
	يمكن تلخيص ما عرفناه على WebAssembly في أن أي مقال على لغة WebAssembly تقريبًا يذكر سرعته القريبة من سرعة الآلة كأهم ميزة فيه، لذلك فإن هذه اللغات الثلاثة كانوا أول مشرحين للترجمة إلى WebAssembly.
</p>

<h2>
	فصل المخاوف بين جافا سكربت و WebAssembly
</h2>

<p>
	على عكس جميع الإشاعات، فلقد صممت لغة WebAssembly لدعم جافا سكربت وليس لاستبداله عن طريق توفير أداء أفضل في المهام الصعب، ولهذه اللغة أفضلية عند التنزيل، فالمتصفح يحصل على وحدة جافا سكربت كنص، وفي WebAssembly يحصل على صيغة ثنائيّة مضغوطة لتسريع التنزيل.
</p>

<p>
	من المهم معرفة كيف جافا سكربت وWebAssembly يعملان معًا، فجافاسكربت مصمم لقراءة وكتابة نموذج كائن المستند (Document Object Model - DOM)، الشجرة التي تمثل صفحة الويب، وعلى نقيض ذلك، لا يأتي WebAssembly على أي وظائف مدمجة لـ DOM، لكن يمكن لـ WebAssembly استيراد الدوال من جافا سكربت واستدعاءها حسب الحاجة، يفسر هذا كيفية عمل ذلك:
</p>

<pre class="ipsCode">
DOM&lt;-----&gt;JS&lt;-----&gt;WebAssembly
</pre>

<p>
	سيبقى جافا سكربت في أي نوع من أنواعه يدير DOM، لكن يمكنه استخدام وظائف الأغراض العامة من وحدات WebAssembly، كما في الشيفرة البرمجية السابقة.
</p>

<h2>
	تسلسل Hailstone وتخمين Collatz
</h2>

<p>
	هنالك أمثلة عديدة لشيفرة WebAssembly في وضع الإنتاج عند عملها بأداء عالي، مثل إنشاء أزواج مفاتيح تشفير كبيرة أو استخدام هذه المفاتيح للتشفير وفك تشفير، ومثال على ذلك يمكن اتباعه بسهول، هنالك عملية صعبة بأعداد كبيرة ويمكن لجافا سكربت التعامل معها بسهولة.
</p>

<p>
	هذه دالة hstone (اختصار لـ Hailstone)، تأخذ عدد صحيح كمعامل. تعريف هذه الدالة كالتالي:
</p>

<pre class="ipsCode">
             3N + 1 إذا كان N عدد فردي
hstone(N) =
             N/2 إذا كان N عدد زوجي
</pre>

<p>
	على سبيل المثال، hstone(12)‎ ترجع 6 في حين hstone(11)‎ ترجع 34، إذا كان N عدد فردي، فإن 3N+1 هو عدد زوجي، وإذا كان N عدد زوجي، فإن N/2 إما عدد زوجي (مثال 4/2=2) أو فردي (مثال 6/2=3).
</p>

<p>
	يمكن استخدام دالة hstone بطريقة عودية عن طريق تمرير قيمة العودة كالمعامل التالي، وستكون النتيجة هي تسلسل hailstone مثل هذه، والتي تبدأ برقم 24 كمعامل أول، وترجع القيمة 12 كمعامل التالي وهكذا:
</p>

<pre class="ipsCode">
24,12,6,3,10,5,16,8,4,2,1,4,2,1,...
</pre>

<p>
	يتطلب الأمر 10 استدعاءات للدالة حتى تستقر على الرقم واحد، وسيبقى التسلسل 4,2,1 يتكرر إلى ما لا نهاية لأن (3x1)+1 هو 4، لذلك يقسم على 2 ليعود 2، والذي يقسم على 2 ليكون 1 وهكذا دواليك، ولمزيد من المعلومات يمكنك الإطلاع على تفسير مجلة Plus حول <a href="https://plus.maths.org/content/mathematical-mysteries-hailstone-sequences" rel="external nofollow">لماذا اسم hailstone هو الاسم المناسب لهذا التسلسل</a>.
</p>

<p>
	لاحظ أن أس 2 تتلاقى بسرعة كبيرة، حيث أنها تتطلّب N تقسيمات على 2 للوصول إلى 1، فعلى سبيل المثال 32 = 2<sub>5</sub> لديها طول تقارب 5 و 64 = 2<sub>6</sub> لديها طول تقارب 6 ، نهتم هنا بطول التسلسل من المعامل الأول إلى أول ظهور لرقم 1، فشيفرتي البرمجية بلغة C و TypeScript تحسب طول تسلسل hailstone.
</p>

<p>
	تخمين Collatz هو تسلسل hailstone يتقارب إلى 1 مهما كان المعامل N&gt;0، فلم يستطع أحد تفنيد تخمين Collatz ولم يتمكن أي أحد الحصول على إثبات لجعل التخمين نظرية، فالتخمين، على الرغم من سهولة تجربته ببرنامج، يبقى مشكلة صعبة في الرياضيات.
</p>

<h2>
	من C إلى WebAssembly في خطوة واحدة
</h2>

<p>
	برنامج hstoneCL أسفله هو تطبيق ليس ويب يمكن ترجمته باستخدام مترجم Cعادي (على سبيل المثال GNU أو Clang)، يولّد هذا البرنامج عدد صحيح عشوائي قيمته N&gt;0 ثمانية مرات ويحسب طول تسلسل hailstone بداية من N، دالتين مهمتين وهما main وhstone عند ترجمة التطبيق إلى WebAssembly.
</p>

<h3>
	المثال 1 - دالة hstone في لغة السي
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3129_18" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdio.h&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdlib.h&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;time.h&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> hstone</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="typ">int</span><span class="pln"> len </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">          </span><span class="com">/* halt on 1 */</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">/* if n is even */</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">       </span><span class="com">/* if n is odd  */</span><span class="pln">
    len</span><span class="pun">++;</span><span class="pln">                      </span><span class="com">/* increment counter */</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> len</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">#define</span><span class="pln"> </span><span class="typ">HowMany</span><span class="pln"> </span><span class="lit">8</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  srand</span><span class="pun">(</span><span class="pln">time</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">));</span><span class="pln">  </span><span class="com">/* seed random number generator */</span><span class="pln">
  </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln">
  puts</span><span class="pun">(</span><span class="str">"  Num  Steps to 1"</span><span class="pun">);</span><span class="pln">
  </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">HowMany</span><span class="pun">;</span><span class="pln"> i</span><span class="pun">++)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> num </span><span class="pun">=</span><span class="pln"> rand</span><span class="pun">()</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">100</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">/* + 1 to avoid zero */</span><span class="pln">
    printf</span><span class="pun">(</span><span class="str">"%4i %7i\n"</span><span class="pun">,</span><span class="pln"> num</span><span class="pun">,</span><span class="pln"> hstone</span><span class="pun">(</span><span class="pln">num</span><span class="pun">));</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن ترجمة الشيفرة البرمجية وتشغيلها من سطر الأوامر (حيث أن % موجه لسطر الأوامر) على أي نظام مشابه ليونكس:
</p>

<pre class="ipsCode">
% gcc -o hstoneCL hstoneCL.c  ## compile into executable hstoneCL
% ./hstoneCL                  ## execute
</pre>

<p>
	هذا مثال لمخرجات عند التشغيل:
</p>

<pre class="ipsCode">
  Num  Steps to 1
  88      17
   1       0
  20       7
  41     109
  80       9
  84       9
  94     105
  34      13
</pre>

<p>
	تتطلّب لغات الأنظمة (بما في ذلك لغة السي) أداة مخصصّة لترجمة الشيفرة البرمجية إلى وحدة WebAssembly، بالنسبة للغات C وC++‎، يعتبر <a href="https://emscripten.org/" rel="external nofollow">Emscripten</a> هو الخيار الأكثر الانتشارًا مبني على بنية مترجم LLVM (Low-Level Virtual Machine)‎، استخدمت في امثلتي بلغة C على EmScripten، والذي يمكنك تثبيته بمساعدة <a href="https://github.com/emscripten-core/emsdk" rel="external nofollow">هذا الدليل</a>.
</p>

<p>
	يمكن جعل برنامج hstoneCL يعمل على الويب باستخدام Emscription لترجمة الشيفرة البرمجيّة - دون تغيير - إلى وحدة WebAssembly، تُنشئ أداة Emscription صفحة HTML مع جافا سكربت (في asm.js) الذي يتوسط بين DOM ووحدة WebAssembly التي تحسب دالة hstone، وهذه هي الخطوات:
</p>

<p>
	1- ترجمة برنامج hstoneCL الذي لا يعمل على الويب إلى WebAssembly:
</p>

<pre class="ipsCode">
% emcc hstoneCL.c -o hstone.html  ## generates hstone.js and hstone.wasm as well
</pre>

<p>
	يحتوي ملف <code>hstoneCL.c</code> على الشيفرة البرمجيّة الموجودة في الأعلى، و معامل <code>‎-o</code> لراية المخرجات والتي ستحدد اسم ملف HTML وسيحمل كل من شيفرة جافا سكربت المولّدة وملف ثنائي WebAssembly نفس الاسم (في هذه الحالة، <code>hstone.js</code> و <code>hstone.wasm</code> على التوالي)، النسخ الأقدم من Emscription (قبل الاصدار 13)، قد يتطلّب تضمين راية <code>-s WASM=1</code> في أمر الترجمة.
</p>

<p>
	2- استخدم خادم ويب Emscription (أو ما يعادله) لاستضافة تطبيق الويب:
</p>

<pre class="ipsCode">
% emrun --no_browser --port 9876 .   ## . is current working directory, any port number you like
</pre>

<p>
	لتجاوز رسائل التحذيريّة، يمكنك تضمين راية <code>‎--no_emrun_detect</code>. يشغّل هذا الأمر خادم الويب، والذي يستضيف جميع الموارد في مجلد العمل الحالي، على وجه الخصوص <code>hstone.html</code> و <code>hstone.js</code> و <code>hstone.wasm</code>.
</p>

<p>
	3- افتح المتصفح مع تفعيل WebAssembly (على سبيل المثال Chrome أو Firefox) وانتقل إلى العنوان : <a href="http://localhost:9876/hstone.html." ipsnoembed="false" rel="external nofollow">http://localhost:9876/hstone.html.</a>
</p>

<p>
	تظهر هذه الصورة المخرجات من حاسوبي باستخدام متصفح Firefox:
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="36390" data-unique="4rvk3yzyw" src="https://academy.hsoub.com/uploads/monthly_2020_04/webified-1.png.99ae82ffa268cbb785bd6a458f1da64f.png" alt="webified-1.png"></p>

<p>
	النتيجة رائعة خاصة أنك كتبت سطر واحد فقط دون أي تغييرات على برنامج C الأصلي.
</p>

<h2>
	تحسين برنامج hstone للويب
</h2>

<p>
	تترجم أداة Emscription برنامج C إلى وحدة WebAssembly وتولّد جافا سكربت المطلوب، لكن هذه الأداة مناسبة لشيفرة برمجيّة ولّدتها اللآلة، على سبيل المثال، ينتج <code>asm.js</code> ملف بحجم 100 كيلوبايت تقريبًا، تتعامل شيفرة البرمجيّة للجافا سكربت عدة سيناريوهات ولا تستخدم <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> الأخير الخاص بـ WebAssembly. نسخة مصغّرة من برنامج hstone للويب ستجعل من السهل التركيز على كيف تتعامل وحدة WebAssembly (الموجودة في ملف hstone.wasm) مع جافا سكربت (الموجود في ملف hstone.js).
</p>

<p>
	هنالك مشكلة أخرى: الشيفرة البرمجيّة لـ WebAssembly لا تملك حدود دالية في مصدر البرنامج كما في لغة السي، فعلى سبيل المثال، يملك برنامج ChstoneCL دالتين معرفتين من قبل المستخدم وهما main و hstone، ستكون النتيجة تصدير وحدة WebAssembly دالة تسمى <code>‎_main</code> لكنها لا تصدر دالة اسمها <code>‎_hstone</code> (حيث أن دالة main هي نقطة الدخول في برنامج سي). جسم دالة Chstone سيكون في دالة غير مصدّرة أي ملفوفة بـ <code>‎_main</code>، دوال WebAssembly المصدّرة هي نفسها التي يمكن لجافا سكربت استدعاؤها باسمها، وعلى الرغم من ذلك، من الأفضل تحديد أي دوال لغة المصدر يجب تصديرها بالاسم في شيفرة البرمجيّة لـ WebAssembly.
</p>

<h3>
	المثال الثاني - برنامج hstone المنقح
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3129_20" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdio.h&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdlib.h&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;time.h&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;emscripten/emscripten.h&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> EMSCRIPTEN_KEEPALIVE hstone</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  </span><span class="typ">int</span><span class="pln"> len </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">          </span><span class="com">/* halt on 1 */</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">/* if n is even */</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">       </span><span class="com">/* if n is odd  */</span><span class="pln">
    len</span><span class="pun">++;</span><span class="pln">                      </span><span class="com">/* increment counter */</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> len</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	برنامج hstoneWA المنقح المعروض أعلاه، لا يملك دالة main، فلا حاجة له، لأن البرنامج ليس مصمم للعمل كبرنامج مستقل بل مخصص لوحدة WebAssembly مع دالة تصدير واحدة. يشير توجيه EMSCRIPTEN_KEEPALIVE (المعرّف في الملف الرأCemscripten.h) إلى المترجم لتصدير دالة <code>‎_hstone</code> في وحدة WebAssembly، إتفاقية الاسم واضحة للغاية: يبقى اسم دالة Cمثل hstone، لكن مع شرطة السفليّة كحرف أول في WebAssembly (أي <code>‎_hstone</code> في هذه الحالة)، وتتبع مترجمات WebAssembly أخرى اتفاقيات أسماء مختلفة.
</p>

<p>
	للتأكد من عمل ذلك، يمكنك اختصار خطوة الترجمة إلى إنتاج وحدة WebAssembly و جافا سكربت، لكن بدون HTML:
</p>

<pre class="ipsCode">
% emcc hstoneWA.c -o hstone2.js  ## we'll provide our own HTML file
</pre>

<p>
	يمكن اختصار الملف HTML إلى هذا:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3129_22" style="">
<span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">src</span><span class="pun">=</span><span class="atv">"hstone2.js"</span><span class="tag">&gt;&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body/&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يحمل ملف HTML ملف جافا سكربت، والذي يقوم بجلب وتحميل ملف WebAssembly الثنائي الذي يسمى <code>hstone2.wasm</code>، وبالمناسبة ملف WASM الجديد بنصف حجم الملف الأصلي تقريبًا.
</p>

<p>
	يمكن ترجمة الشيفرة البرمجية للتطبيق كالسابق ومن ثم تشغيله مع خادم الويب المدمج:
</p>

<pre class="ipsCode">
% emrun --no_browser --port 7777 .  ## new port number for emphasis
</pre>

<p>
	بعد طلب وزيارة ملف HTML في المتصفح (في هذه الحالة Chrome)، يمكن استخدام كونسول ويب للتأكّد من تصدير دالة hstone على أنها <code>‎_‎‎hstone</code>. هذا مقتطف من جلستي في كونسول الويب، مع ## للتعليقات:
</p>

<pre class="ipsCode">
&gt; _hstone(27)   ## invoke _hstone by name
&lt; 111           ## output
&gt; _hstone(7)    ## again
&lt; 16            ## output
</pre>

<p>
	يعتبر استخدام موجه EMSCRIPTEN_KEEPALIVE هو طريقة واضحة لجعل مترجم Emscripten وحدة WebAssembly تصدّر أي دالة إلى جافا سكربت، وهذا ما يقوم به هذا المترجم، وأي مستند HTML مخصّص مع جافا سكربت يدوي مناسب يمكنه استدعاء دوال من وحدة WebAssembly وذلك بفضل Emscripten.
</p>

<h2>
	ترجمة TypeScript إلى WebAssembly
</h2>

<p>
	مثال شيفرة البرمجيّة التالية بلغة TypeScript، والتي هي جافا سكربت مع أنواع بيانات صريحة، ويتطلب هذا Node.js مع مدير الحزم الخاص به npm، يثبت أمر npm التالي AssemblyScript والذي هو مترجم WebAssembly لشيفرة برمجية TypeScript:
</p>

<pre class="ipsCode">
% npm install -g assemblyscript  ## install the AssemblyScript compiler
</pre>

<p>
	يتكون برنامج TypeScript hstone.ts من دالة واحدة، والتي تسمى hstone أيضًا، وسيسبق نوع البيانات i32 (عدد صحيح 32 بت) المعاملات وأسماء المتغيرات المحليّة (في هذه الحالة، n و len على التوالي):
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3129_25" style="">
<span class="kwd">export</span><span class="pln"> </span><span class="kwd">function</span><span class="pln"> hstone</span><span class="pun">(</span><span class="pln">n</span><span class="pun">:</span><span class="pln"> i32</span><span class="pun">):</span><span class="pln"> i32 </span><span class="pun">{</span><span class="pln"> </span><span class="com">// will be exported in WebAssembly</span><span class="pln">
  let len</span><span class="pun">:</span><span class="pln"> i32 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
  </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">break</span><span class="pun">;</span><span class="pln">          </span><span class="com">// halt on 1</span><span class="pln">
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="lit">0</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">))</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">  </span><span class="com">// if n is even</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">       </span><span class="com">// if n is odd</span><span class="pln">
    len</span><span class="pun">++;</span><span class="pln">                      </span><span class="com">// increment counter</span><span class="pln">
  </span><span class="pun">}</span><span class="pln">
  </span><span class="kwd">return</span><span class="pln"> len</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	تأخذ دالة hsotne معامل واحد من نوع i32 وترجع قيمة من نفس النوع، ويشبه جسم الدالة ذلك الموجود في مثال لغة سي، ويمكن ترجمة الشيفرة المصدريّة إلى WebAssembly كالتالي:
</p>

<pre class="ipsCode">
% asc hstone.ts -o hstone.wasm  ## compile a TypeScript file into WebAssembly
</pre>

<p>
	حجم ملف WASM hstone.wasm حوالي 14 كيلوبايت.
</p>

<p>
	لإيضاح كيف تحمّل وحدة WebAssembly، يتضمن ملف HTML في الأسفل (index.html في موقعي) سكربت جلب وتحميل وحدة WebAssembly hstone.wasm ومن ثم إنشاء مثيل لهذه الوحدة حتى يمكن استدعاء دالة hstone في كونسول المتصفح.
</p>

<h3>
	المثال 3 - صفحة HTML لشيفرة TypeScript
</h3>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3129_27" style="">
<span class="dec">&lt;!doctype html&gt;</span><span class="pln">
</span><span class="tag">&lt;html&gt;</span><span class="pln">
  </span><span class="tag">&lt;head&gt;</span><span class="pln">
    </span><span class="tag">&lt;meta</span><span class="pln"> </span><span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">/&gt;</span><span class="pln">
    </span><span class="tag">&lt;script&gt;</span><span class="pln">
      fetch</span><span class="pun">(</span><span class="str">'hstone.wasm'</span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="pln">response </span><span class="pun">=&gt;</span><span class="pln">           </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      response</span><span class="pun">.</span><span class="pln">arrayBuffer</span><span class="pun">()</span><span class="pln">                          </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      </span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="pln">bytes </span><span class="pun">=&gt;</span><span class="pln">                                 </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      </span><span class="typ">WebAssembly</span><span class="pun">.</span><span class="pln">instantiate</span><span class="pun">(</span><span class="pln">bytes</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln">imports</span><span class="pun">:</span><span class="pln"> </span><span class="pun">{}})</span><span class="pln">   </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      </span><span class="pun">).</span><span class="pln">then</span><span class="pun">(</span><span class="pln">results </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">{</span><span class="pln">                             </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      window</span><span class="pun">.</span><span class="pln">hstone </span><span class="pun">=</span><span class="pln"> results</span><span class="pun">.</span><span class="pln">instance</span><span class="pun">.</span><span class="pln">exports</span><span class="pun">.</span><span class="pln">hstone</span><span class="pun">;</span><span class="pln"> </span><span class="pun">&lt;!--</span><span class="pln"> </span><span class="typ">Line</span><span class="pln"> </span><span class="lit">6</span><span class="pln"> </span><span class="pun">--&gt;</span><span class="pln">
      </span><span class="pun">});</span><span class="pln">
    </span><span class="tag">&lt;/script&gt;</span><span class="pln">
  </span><span class="tag">&lt;/head&gt;</span><span class="pln">
  </span><span class="tag">&lt;body/&gt;</span><span class="pln">
</span><span class="tag">&lt;/html&gt;</span></pre>

<p>
	يمكن تفسير عنصر script في HTML السابق سطرً سطرًا، فيستخدم استدعاء fetch في السطر الأول وحدة fetch للحصول على وحدة WebAssembly من خادم الويب الذي يستضيف صفحة HTML، وعند وصول إجابة HTTP، ستعمل وحدة WebAssembly كتسلسل من البيتات، والتي ستكون مخزّنة في arrayBuffer من السكربت في السطر 2، تتكوّن هذه البايتات من وحدة WebAssembly، والتي هي كامل الشيفرة البرمجيّة مترجمة من ملف TypeScript، هذه الوحدة لا تملك أي استدعاءات، كما هو مبيّن في نهاية السطر 4.
</p>

<p>
	في بداية السطر الرابع، سينشئ مثيل وحدة WebAssembly وتشبه هذه الوحدة لصنف غير ثابت مع أعضاء غير ثابتين في لغة كائنيّة التوجه مثل جافا. تحتوي الوحدة من متغيرات، دوال، وأدوات دعم مختلفة (artifacts)، لكن يجب إنشاء مثيل للوحدة قبل استخدامها كما في الصنف غير ثابت، وفي هذه الحالة في كونسول الويب، لكن بصفة عامة في شيفرة جافاسكربت مناسبة.
</p>

<p>
	يصدّر السطر السادس من السكربت دالة hstone من TypeScript الأصليّة بنفس الاسم، وستكون دالة WebAssembly متاحة لأي شيفرة جافا سكربت، كما ستؤكد جلسة أخرى في كونسول المتصفح.
</p>

<p>
	يملك WebAssembly <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> أكثر إيجازًا لجلب وإنشاء مثيل وحدة، يقلل <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> الجديد السكربت السابق لعمليتي جلب وإنشاء مثيل، بالنسبة إلى النسخة التي عرضناها هنا لإيضاح فائدة التفاصيل، وبشكل خاص، عرض وحدة WebAssembly كمصفوفة بايت التي ينشئ مثيلها ككائن مع دوال المصدّر.
</p>

<p>
	الهدف هو الحصول على صفحة ويب تحمّل وحدة WebAssembly بنفس طريقة وحدة JS ES2015:
</p>

<pre class="ipsCode prettyprint lang-html prettyprinted" id="ips_uid_3129_29" style="">
<span class="tag">&lt;script</span><span class="pln"> </span><span class="atn">type</span><span class="pun">=</span><span class="atv">'module'</span><span class="tag">&gt;</span><span class="pun">...</span><span class="tag">&lt;/script&gt;</span></pre>

<p>
	سيعمل جافا سكربت على جلب وترجمة ومعالجة وحدة WebAssembly كما لو كانت مجرّد واحدة JS أخرى.
</p>

<h2>
	لغة صيغة النص (text format language)
</h2>

<p>
	يمكن ترجمة الشيفرة الثنائيّة لـ WebAssembly من وإلى مرادفها بصيغة النص، فالشيفرة الثنائيّة تكون موجودة في ملفات بصيغة WASM، في حين أن نصوص قابلة للقراءة من قبل المبرمجين تكون موجودة بملفات بصيغة WAT. إن <a href="https://github.com/WebAssembly/wabt" rel="external nofollow">WABT</a> هي مجموعة من عشرات الأدوات للتعامل مع WebAssembly، بما في ذلك للترجمة من وإلى صيغ مثل WASM و WARK ومن بين أدوات التحويل wasm2wat و wasm2c و wat2wasm.
</p>

<p>
	تتبنى لغة صيغة النص صياغة ‎S-expression‎ ‎(S تعني رمزي symbolic) الشائعة في Lisp، تمثل S-expression واختصارها sexpr شجرة كقائمة مع العديد من القوائم الفرعية بشكل اعتباطي، فعلى سبيل المثال، يحدث هذا sexpr بالقرب من نهاية ملف WAT لمثال TypeScript:
</p>

<pre class="ipsCode">
(export "hstone" (func $hstone)) ## export function $hstone by the name "hstone"
</pre>

<p>
	الشجرة التي تمثله هي التاليّة:
</p>

<pre class="ipsCode">
        export      ## root
          |
     +----+----+
     |       |
  "hstone"    func    ## left and right children
               |
            $hstone   ## single child
</pre>

<p>
	في الصيغة النصيّة، وحدة WebAssembly هي sexpr حيث أن الجزء الأول هي الوحدة module والتي هي جذر الشجرة.
</p>

<p>
	هذا مثال ثاني لوحدة معرّفة ومصدّرة كدالة فرديّة، والتي لا تأخذ أي معامل لكنها ترجع ثابت 9876:
</p>

<pre class="ipsCode">
(module
  (func (result i32)
    (i32.const 9876)
  )
  (export "simpleFunc" (func 0)) // 0 is the unnamed function's index
)
</pre>

<p>
	تعرّف هذه الدالة دون اسم (كما في lambda) وتصدّر بالإشارة إلى مؤشر 0، والذي هو مؤشر أول sexpr متداخل في الوحدة، وإن اسم دالة التصدير هي السلسلة النصيّة "simpleFunc".
</p>

<p>
	الدوال في صيغة النص تملك نمط قياسي، والذي يمكن تفسيره على النحو التالي:
</p>

<pre class="ipsCode">
(func &lt;signature&gt; &lt;local vars&gt; &lt;body&gt;)
</pre>

<p>
	يحدّد التوقيع المعاملات (إذا كانت موجودة) ويرجع قيمة العودة (إذا كانت موجودة)، فعلى سبيل المثال، هذا توقيع لدالة لا تملك اسم تأخذ معاملين من نوع عدد صحيح 32 بت وتعيد قيمة عدد صحيح 64 بت:
</p>

<pre class="ipsCode">
(func (param i32) (param i32) (result i64)...)
</pre>

<p>
	يمكن إعطاء الأسماء إلى الدوال والمعاملات والمتغيرات المحليّة، حيث يبدأ الأسم بعلامة دولار:
</p>

<pre class="ipsCode">
(func $foo (param $a1 i32) (param $a2 f32) (local $n1 f64)...)
</pre>

<p>
	يعكس جسد دالة WebAssembly بنية الآلة الأساسية لهذه اللغة، فتخزين المكدس هو الأساس، ومثال ذلك دالة تضاعف معامل عددها الصحيح وتعيد القيمة الجديدة:
</p>

<pre class="ipsCode">
(func $doubleit (param $p i32) (result i32)
  get_local $p
  get_local $p
  i32.add)
</pre>

<p>
	تدفع كل واحدة من عمليات get_local، والتي تعمل على المتغيرات المحلية والمعاملات المشابهة، معامل 32 بت إلى المكدس، وستخرج عملية i32.add أعلى قيمتين (والتي هي في هذه الحالة، القيم الوحيدة) من المكدس بجمعهم، وستكون النتيجة هي القيمة الوحيدة الموجودة في المكدّس وبالتالي سترجع من دالة ‎$doubleit.
</p>

<p>
	عند ترجمة شيفرة WebAssembly إلى لغة الآلة، يجب استبدال أساس مكدس WebAssembly عند الإمكان بسجلات الأغراض العامة، وهذه مهمة مترجم JIT، والتي تترجم شيفرة آلة المكدس الافتراضية لـ WebAssembly إلى شيفرة آلة حقيقيّة.
</p>

<p>
	لا يفضل مبرمجو الويب كتابة WebAssembly بصيغة النص، حيث أن الترجمة من لغة عالية المستوى يعتبر خيار أفضل لهم على عكس كتّاب المترجم، حيث سيجدون من المفيد العمل عليها.
</p>

<h2>
	الخاتمة
</h2>

<p>
	على الرغم من إحراز الكثير من هدف WebAssembly للوصول إلى سرعة مقاربة لآلة (Native)، لكن لايزال مترجم JIT لجافا سكربت يتحسن مع ظهور أنواع مناسبة للتحسين (مثل TypeScript) تقترب من سرعة الآلة (native)، فهل هذا يعني أن WebAssembly هو مضيعة للوقت؟ لا أعتقد ذلك.
</p>

<p>
	يعالج WebAssembly هدفًا تقليديًا آخر في الحوسبة: إعادة استخدام الشيفرة البرمجية ذات معنى، كما توضح الأمثلة المختصرة في هذا المقال، فإن الشيفرة البرمجيّة بلغة C أو TypeScript، تترجم بسهولة إلى وحدة WebAssembly والتي تعمل بشكل جيّد مع شيفرة برمجيّة خاصة بجافا سكربت وهو الرابط بين التقنيات المستخدمة في الويب، وبالتالي يدعو WebAssembly إلى إعادة استخدام الشيفرة البرمجيّة وتوسيع استخدام التعليمات الجديدة، على سبيل المثال، قد يكون برنامج عالي الأداء لمعالجة الصور مكتوب كتطبيق سطح المكتب مفيدًا أيضا في تطبيق ويب، لذلك سيكون من الأفضل استخدام WebAssembly (بالنسبة لوحدات الويب الجديدة ذات صلة بالحسابات، سيكون WebAssembly هو خيار جيّد). وحدسي يقول أن WebAssembly ستزدهر بنفس القدر لإعادة استخدام للأداء.
</p>

<p>
	ترجمة -وبتصرف- للمقالات:
</p>

<ul>
<li>
		<a href="https://opensource.com/article/19/8/webassembly-speed-code-reuse" rel="external nofollow">WebAssembly for speed and code reuse</a> لصاحبه Marty Kalin
	</li>
	<li>
		<a href="https://opensource.com/article/20/1/webassembly" rel="external nofollow">Why everyone is talking about WebAssembly</a> لصاحبيه Gordon Haff وMike Bursell
	</li>
	<li>
		<a href="https://opensource.com/article/19/2/why-use-rust-webassembly" rel="external nofollow">Why should you use Rust in WebAssembly?</a> لصاحبه Ryan Levick
	</li>
</ul>
]]></description><guid isPermaLink="false">869</guid><pubDate>Thu, 09 Apr 2020 07:17:05 +0000</pubDate></item><item><title>&#x627;&#x62D;&#x645; &#x645;&#x648;&#x642;&#x639;&#x643; &#x645;&#x646; &#x627;&#x644;&#x627;&#x62E;&#x62A;&#x631;&#x627;&#x642;</title><link>https://academy.hsoub.com/programming/general/%D8%A7%D8%AD%D9%85-%D9%85%D9%88%D9%82%D8%B9%D9%83-%D9%85%D9%86-%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%B1%D8%A7%D9%82-r864/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_04/4--preventing-website-hack.jpg.64c8cb30f51643c85b97e460735df65b.jpg" /></p>

<p>
	طُوّرت على مدار تاريخ الإنترنت العديد من الأدوات والطرق للتأكد من حماية المواقع من الاختراق، أو على الأقل جعله مستعدًا لمجابهة ذلك الخطر. أيًا كان مشروعك، متجرًا إلكتروني، أو مدونة عصرية أو حتى موقعًا لإحدى الشركات، تجب مراعاة تدابير الحماية في كل الأوقات.
</p>

<p>
	إذا كنت مطور/مصمم ويب، فمهمتك لم تعد تقتصر على بناء صفحات ويب جميلة، بل عليك المحافظة عليها محمية من جميع الجهات التي قد ترغب باختراقك واستغلال موقعك. ستحتاج لإجراء تدابير أمنية لمنع حصول شيء كذلك.
</p>

<p>
	هنالك العديد من الطرق لاختراق المواقع، لذلك يجب وضع تدابير حماية متعددة لقطع جميع تلك الطرق. لكن لا وجود لطريقة محددة قادرة على حمايتك بالكامل من المخترقين، أفضل ما يمكنك فعله هو تصعيب المهمة على المخترقين على نحو كافِ لدرجة تجعلهم ييأسون من المحاولة.
</p>

<h2>
	طرق الاختراق الشائعة
</h2>

<p>
	كما أسلفنا، هناك العديد من الطرق يستعملها المخترقون لتخطي حماية الموقع بهدف تدميره أو التلاعب به. سنذكر هذه الطرق حتى يمكنك إجراء تدابير وقائية للتصدي لهذه المحاولات.
</p>

<h3>
	حقن استعلامات SQL
</h3>

<p>
	لا يمكن إنكار أن حقن استعلامات SQL‏ (SQL Injection) هي إحدى أكثر طرق الاختراق خطرًا على كل من المواقع والأنظمة. على نحو عام، تتضمن هذه الطريقة إدخال استعلامات SQL في حقول الإدخال مثل حقول تسجيل الدخول أو حتى شريط العناوين الخاص بالمتصفح. بفعل ذلك يتمكن المخترق من الوصول لقواعد البيانات الخاصة بالموقع أو النظام.
</p>

<p>
	عندما تدخل اسم المستخدم وكلمة السر في حقل تسجيل الدخوليُدرَج النص الذي أدخلته إلى استعلام SQL. ذلك الاستعلام سيفحص البيانات التي أدخلتها ويوازنها بقاعدة بيانات الموقع أو النظام.
</p>

<p>
	بمجرد تطابق القيم المدخلة مع المسجلة ستحصل على تصريح دخولك، إذا لم تتطابق فلا يسعك الدخول.
</p>

<p>
	حقن قواعد البيانات يحدث عندما يحاول المخترق إدراج استعلامات SQL في حقول الإدخال الخاصة بموقعك. في العادة سيفحص الموقع البيانات المدرجة ويتأكد من صلاحيتها.
</p>

<p>
	إذا حدث واحتوت بياناتك مجرد علامة اقتباس (‘) بنهاية بيانات اسم المستخدم قد تفسرها قاعدة البيانات كاستعلام SQL بنَّاء، وهكذا سيُعدُّ استعلامًا صحيحا.
</p>

<p>
	قد لا يدخل المخترقون إلى موقعك عن طريق ذلك الاستعلام بالتحديد، لكن هذه الطريقة ستسمح لهم بالوصول إلى اسم قاعدة بياناتك، والجداول وحقول المفاتيح. وبامتلاك هذه البيانات سيحتاجون فقط إلى إدخال استعلام SQL في أحد حقول موقعك، عندها سيتمكنون من رؤية كامل محتويات قاعدة بياناتك.
</p>

<h4>
	كيف يمكن التصدي لحقن SQL
</h4>

<ul>
<li>
		التأكد من إدخال نوع البيانات الصحيح
	</li>
	<li>
		الاستعلام باستخدام الوسائط (Parameters)
	</li>
	<li>
		تحديد الصلاحيات
	</li>
	<li>
		ترشيح IIS موحَّد
	</li>
	<li>
		تفعيل توثيق طلبات الاستعلام
	</li>
	<li>
		فكر باستخدام إطار لربط العلاقات بالكائنات (ORM)
	</li>
</ul>
<h3>
	هجمات XSS
</h3>

<p>
	الهجمات بالسكربتات العابرة للمواقع Cross Site Scripting، التي تُعرف اختصارًا بهجمات XSS، هي إحدى أكثر طرق الاختراق التى يصعب التصدي لها. في الأعوام السابقة، واجه كلٌّ من Microsoft، و MySpace، و Google صعوبات كبيرة في التعامل مع تلك الهجمات.
</p>

<p>
	تعتمد هجمات XSS على إرفاق سكربتات خبيثة مكتوبة بلغة جافا سكربت بالروابط الداخلية بهدف التحكم بسجلات الجلسات (Sessions) الخاصة بالموقع، أو اختطاف الإعلانات أو سرقة المعلومات الشخصية.
</p>

<p>
	لابد أنك تذكر حدوث هذا: قمت بالضغط خطأً على إعلان غريب الشكل، فأرسلك إلى صفحة شبيهة بتطبيقات الدردشة. ثم ترى رسالة من فتاة لطيفة تطلب منك الضغط على رابط ما للدردشة معها. وعند الضغط على الرابط يظهر لك عنوان URL غريب الشكل مثل العنوان التالي:
</p>

<pre class="ipsCode">
[%63%61%74%69%6f%6e%3d%274%74%70%3a%2f%2f%77%7…]
</pre>

<p>
	قد تعتقد أن لا شئ قد حدث ولكن لا، أنت مخطئ بالتأكيد. هذه الروابط تساعد على سرقة ملفات تعريف الارتباط (Cookies) والتي بدورها تعين المخترق على سرقة معلوماتك الشخصية.
</p>

<h4>
	كيف يمكنك التعامل مع برمجيات تخطي المواقع
</h4>

<ul>
<li>
		لا تسمح بإدخال بيانات غير موثوقة إلا إذا تطلب الأمر ذلك
	</li>
	<li>
		خلّص (Escape) وسوم HTML عند معالجة البيانات المدخلة للحقول
	</li>
	<li>
		خلّص خصائص العناصر قبل إدراج البيانات على الموقع
	</li>
	<li>
		خلّص نصوص JavaScript من الحقول حتى تتفادى تسلل بيانات غير موثوقة إلى قيم جافاسكريبت.
	</li>
</ul>
<h3>
	تخطي الاستيثاق
</h3>

<p>
	كما يوحي الاسم، تخطي الاستيثاق مخيف. يستهدف عادةً التطبيقات أو أنظمة إدارة المحتوى سيّئة التصميم، ويمكن له إحداث فوضى عارمة بموقعك.
</p>

<p>
	يحدث الاختراق على نحو مشابه للتالي:
</p>

<ul>
<li>
		البحث وإيجاد صفحة تسجيل دخول ضعيفة الحماية.
	</li>
	<li>
		فتح الشفرات المصدرية للصفحة.
	</li>
	<li>
		نسخ الشفرات إلى محرر نصِّي.
	</li>
	<li>
		حذف تعليمات JavaScript الخاصة بإدارة التصاريح وتعديل رابط أو اثنين.
	</li>
	<li>
		حفظ التغييرات على النص البرمجي.
	</li>
	<li>
		فتح الملف البرمجي الجديد على متصفحك، سجل الدخول كما لو أنك تمتلك الموقع. وهكذا نجح الاختراق!
	</li>
</ul>
<h4>
	هل موقعك عُرضة لهذا الاختراق؟
</h4>

<p>
	هذا يعتمد على إجابة الأسئلة التالية:
</p>

<ul>
<li>
		هل يقوم خادم موقعك بتشغيل العمليات مستعملًا صلاحيات الجذر، أو مدير النظام، أو النظام المحلي أو حسابات إدارية أخرى؟
	</li>
	<li>
		هل يُمنح موقعك/تطبيقك صلاحيات الوصول لقاعدة البيانات عبر حساب SA (بالنسبة لأوراكل) أو حسابات أخرى مشابهة؟
	</li>
	<li>
		هل يمتلك تطبيقك القدرة على الوصول لقاعدة البيانات عبر حسابات تمتلك صلاحيات أعلى من المطلوب؟
	</li>
	<li>
		هل تعمل الحوسبة الافتراضية بخادم موقعك باستعمال كل الصلاحيات أو بثقة كاملة ببيئات عمل J2EE و NET.؟
	</li>
	<li>
		هل بالإمكان تحديد إمكانية الوصول لموارد موقعك باستعمال قدرات المنصة المستعملة؟
	</li>
</ul>
<p>
	إذا أجبت بنعم ولو على سؤال واحد فموقعك معرَّض للخطر.
</p>

<h4>
	كيف يمكنك حماية موقعك
</h4>

<ul>
<li>
		تطوير الموقع، واختبارات الأداء ومنهجية التطوير يجدر القيام بها باستعمال أقل صلاحيات ممكنة.
	</li>
	<li>
		تأكد من أن الحسابات التى تدير بيئة العمل محدودة الإمكانات بأقصى قدر ممكن. لا يجوز أن يستخدم خادم موقعك صلاحيات مدير النظام، أو صلاحيات الجذر، أو غيرها من الحسابات الحسّاسة.
	</li>
	<li>
		حدّدد صلاحيات حسابات المستخدمين بموقعك على نحو يتناسب مع حاجتهم.
	</li>
	<li>
		لا يجوز أن تحظى حسابات الشركاء بصلاحيات إدارية والعكس صحيح. عليك استخدام حسابات مختلفة لمهام مختلفة.
	</li>
</ul>
<h2>
	التدابير الشائعة لمنع الاختراق
</h2>

<h3>
	حافظ على الملحقات والبرامج محدَّثة باستمرار
</h3>

<p>
	لا شيء يسعد المخترق أكثر من برمجية/ملحق منتهي الصلاحية. عادةً هذه هي أهدافهم المفضلة لاحتوائها على أعطال، أو خلل أو ثغرة أمنية. هذا هو السبب الرئيسي لتحديثها أساسا.
</p>

<p>
	لنقلها بهذه الطريقة، أنت تستخدم نوعًا ما من أقفال الأبواب تم التحايل عليه ألاف المرات. هل تتوقع أن يواجه اللص التالي مشكلة في التعامل معها؟ لذا استمع لهذه النصيحة، حدّث الآن!
</p>

<h3>
	استخدم كلمات مرور قوية
</h3>

<p>
	كم مرة تمت التوصية بهذا؟ من المهم للغاية استعمال كلمات مرور قوية. ربما لا تدرك أن المخترقين يحاولون سرقة كلمات مرورك باستمرار.
</p>

<p>
	إذن، كيف ننشىء كلمة مرورفعّالة؟
</p>

<h4>
	طريقة التبديل
</h4>

<p>
	هذه طريقة جيدة للحفاظ على كلمات مرورك آمنة. حسب المبدأ، عليك استبدال الأحرف والأرقام بأحرف خاصة باستخدام طريقتك الشخصية. مثلاً:
</p>

<ul>
<li>
		استعمل رمز '@' عوضًا عن حرف 'a'
	</li>
	<li>
		استعمل رمز '$' عوضًا عن حرف 's'
	</li>
	<li>
		استعمل رمز '%' عوضًا عن المسافات
	</li>
	<li>
		استعمل الرقم '0' عوضًا عن حرف 'o'
	</li>
	<li>
		استعمل رمز '!' عوضًا عن حرف 'i'
	</li>
</ul>
<p>
	بهذه الطريقة قمنا بتحويل كلمة سر بسيطة مثل ‘whoisjohngalt’ إلى كلمة أكثر تعقيدًا ‘wh0!$j0hng@lt’.
</p>

<h4>
	طريقة Business Insider
</h4>

<p>
	ابتكرت مجلة Business Insider مؤخرًا طريقة لتشكيل كلمة مرور قوية يسهل تذكرها. طبقًا للمجلة عليك إنشاء كلمة مرور طويلة لأنها تجعل الحواسيب تستغرق وقتًا طويلًا لتكتشفها.
</p>

<p>
	المبدأ الرئيسي لهذه الطريقة هو إنشاء كلمات مرور طويلة جدًا باستخدام كلمات غير ذات علاقة بك أو ببعضها.
</p>

<h3>
	استخدم أداة Google Webmaster
</h3>

<p>
	لدى Google طريقة لمساعدتك في تأمين موقعك. باستعمال أدوات Webmaster ستحظى بتنبيهات في حال العثور على برمجيات خبيثة.
</p>

<p>
	في حال اختراقك وعدم قدرتك على إزالة الاختراق، ستساعدك غوغل عن طريق إضافة موقعك للقائمة السوداء مما يمنحك متسعًا من الوقت للتعامل مع البرمجيات الخبيثة بموقعك، أيضًا هذه الخدمة تتيح لك رؤية تفاصيل المشكلة المرصودة.
</p>

<h3>
	لا تعرض رقم إصدار WordPress
</h3>

<p>
	بجانب تحديثك لمنصة التدوين، عليك دائمًا منع المخترقين من معرفة أي من إصدارات WordPress تستعمله. فعل ذلك سيمنعهم من استغلال ثغرات الحماية في موقعك. يمكنك فعل ذلك بتعديل ملف <code>functions.php</code> الخاص بموقعك وإضافة التعليمات التالية:
</p>

<pre class="ipsCode prettyprint lang-javascript prettyprinted" id="ips_uid_3234_6" style="">
<span class="kwd">function</span><span class="pln"> remove_version</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="str">''</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
add_filter</span><span class="pun">(</span><span class="str">'the_generator'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'remove_version'</span><span class="pun">);</span></pre>

<h3>
	تشديد الحماية على ملف <code>htaccess.</code>
</h3>

<p>
	عادةً، حماية ملف htaccess متساهلة افتراضيًّا، لكن يمكنك تخصيصها لحمايتك من الاختراق عبر التلاعب بعناوين URL، أو حقن قواعد البيانات أوغيرها.
</p>

<p>
	هنالك الكثير من الطرق لتعديل ملف <code>htaccess.</code> لكننا سنشير إلى أكثرها جدوى. تذكّردائمًا أخذ نسخ حتياطية من الملف.
</p>

<ul>
<li>
		<code>order allow,deny</code>
	</li>
	<li>
		<code>deny from all</code>
	</li>
</ul>
<p>
	أضف الاستعلامات التالية لمنحك مزيدًا من الأمان، علمًا أنه لن يُسمَح بالوصول غير المرغوب فيه، وستمنع زواحف محركات البحث من الوصول إلى ملف <code>wp-admin.php</code>. يمكن تطبيق تعليمات مماثلة على ملفات أخرى مثل <code>install.php</code> و <code>eror_log</code>.
</p>

<pre class="ipsCode">
RewriteEngine On

RewriteBase /

RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]RewriteRule ^(.*)$ - [F,L]RewriteCond %{QUERY_STRING} \.\.\/ [NC,OR]RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]RewriteCond %{QUERY_STRING} tag\= [NC,OR]RewriteCond %{QUERY_STRING} ftp\: [NC,OR]RewriteCond %{QUERY_STRING} http\: [NC,OR]RewriteCond %{QUERY_STRING} https\: [NC,OR]RewriteCond %{QUERY_STRING} (\|%3E) [NC,OR]RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)||ê|&amp;amp;quot;|;|\?|\*|=$).* [NC,OR]RewriteCond %{QUERY_STRING} ^.*(&amp;amp;quot;|'|&amp;amp;amp;lt;|&amp;amp;amp;gt;|\|{||).* [NC,OR]RewriteCond %{QUERY_STRING} ^.*(%24&amp;amp;amp;amp;x).* [NC,OR]RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127\.0).* [NC,OR]RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare).* [NC]RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$

RewriteRule ^(.*)$ - [F,L]
</pre>

<h2>
	الخاتمة
</h2>

<p>
	التعرض للاختراق بالتأكيد محبط. أنت ترى ثمرة جهودك تنهار مثل برج رملي. لكن درهم وقاية سيكون دائمًا أفضل من دينار علاج، لذا بينما كل شيء على ما يرام قم بتحسين وإصلاح كل ما يمكن إصلاحه تحسبًا لوقوع الكوارث.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a data-ss1618065327="1" href="https://1stwebdesigner.com/preventing-website-hack/" rel="external nofollow">Security Advice for Preventing Your Website from Being Hacked</a> من إعداد فريق موقع 1stwebdesigner
</p>
]]></description><guid isPermaLink="false">864</guid><pubDate>Sun, 03 May 2020 18:03:00 +0000</pubDate></item><item><title>&#x62A;&#x635;&#x645;&#x64A;&#x645; &#x627;&#x644;&#x645;&#x648;&#x627;&#x642;&#x639; &#x644;&#x644;&#x62C;&#x648;&#x627;&#x644;: &#x645;&#x627; &#x628;&#x64A;&#x646; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A;&#x647; &#x648;&#x643;&#x64A;&#x641; &#x62A;&#x635;&#x628;&#x62D; &#x627;&#x644;&#x645;&#x648;&#x627;&#x642;&#x639; &#x635;&#x62F;&#x64A;&#x642;&#x629; &#x644;&#x647;</title><link>https://academy.hsoub.com/programming/general/%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D8%A7%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%84%D9%84%D8%AC%D9%88%D8%A7%D9%84-%D9%85%D8%A7-%D8%A8%D9%8A%D9%86-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA%D9%87-%D9%88%D9%83%D9%8A%D9%81-%D8%AA%D8%B5%D8%A8%D8%AD-%D8%A7%D9%84%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D8%B5%D8%AF%D9%8A%D9%82%D8%A9-%D9%84%D9%87-r841/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e563ba1dae1f_--------.jpg.77e341c3dfc0cc6574f6c8d23aec2516.jpg" /></p>

<p>
	هل تحتاج إلى تطبيق في متجر التطبيقات؟ هل يجب أن تكون أصلية (Native) أم مُهجّنة (Hybrid)؟ ما الفرق بين تطبيق جوال وتطبيق ويب وموقع متجاوب؟ هل تعتقد أن يكون الموقع متجاوبًا (Responsive Website)، فهذا يجعله متوافقًا مع الجوال (Mobile Friendly)؟
</p>

<p>
	كل هذه الاسئلة عليك أن تُجيب عنها إذا ما أردت التعامل مع الأجهزة المحمولة كمُطوِّر، وهذا ما سنسلط عليه الضوء في هذا المقال.
</p>

<h2>
	أنواع تطبيقات الجوال
</h2>

<p>
	هناك الكثير من الالتباس بين المؤسسات حول كيفية التعامل مع الأجهزة المحمولة. ومع ذلك، عندما يتعلق الأمر بهذا فلديك 4 خيارات كالتالي:
</p>

<ul>
<li>
		التطبيقات الأصلية أو الأصيلة (Native Applications).
	</li>
	<li>
		تطبيقات الويب (Web Application).
	</li>
	<li>
		التطبيقات المُهجّنة (Hybird Application).
	</li>
	<li>
		المواقع المُتجاوبة (Responsive Websites).
	</li>
</ul>
<h3>
	التطبيقات الأصلية (Native Applications)
</h3>

<p>
	التطبيقات الأصلية هي تطبيقات تعمل فعليًا على الجهاز المحمول ويتم ترميزها خصيصًا لنظام تشغيل الجهاز. هذه هي التطبيقات التي تجدها عادةً في متجر تطبيقات Google Play أو iOS. هذا هو أفضل نهج حيث السرعة والميزات الأصلية (Native Features) مطلوبة.
</p>

<h3>
	تطبيقات الويب (Web Application)
</h3>

<p>
	هناك خصائص مشتركة بين كلٍ من تطبيقات الويب، التطبيقات الأصلية، والمواقع المُتجاوبة.
</p>

<p>
	كما هو الحال مع الموقع المتجاوب، تُصمَّم تطبيقات الويب باستخدام HTML و CSS و Javascript ويكون بالكامل على الإنترنت. ومع ذلك، عندما يكون الموقع المُتجاوب موجَّهًا للمحتوى (Content Oriented)، فإن تطبيق الويب يركز على المهمة بنفس طريقة التطبيق الأصلي.
</p>

<p>
	ومن الأمثلة على ذلك تطبيق <a href="https://boagworld.com/mobile-web/mobile-app-vs-mobile-website-design/m.blackpoolpleasurebeach.com" rel="external nofollow">Blackpool Pleasure Beach</a> للهاتف المحمول. التطبيق متاح عبر الإنترنت ولكنه ليس موقع ويب غني بالمحتوى. بدلاً من ذلك، إنه تطبيق حجز يسمح للمستخدمين بشراء تذاكرهم وبطاقاتهم.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="34295" data-unique="yflgk7d3t" src="https://academy.hsoub.com/uploads/monthly_2020_02/2-TheBlackpoolPleasureBeachBookingApplication.PNG.d6a850a20240b85697c0d6e8245f7b1a.PNG" alt="2-TheBlackpoolPleasureBeachBookingApplication.PNG"></p>

<p>
	نظرًا لأنه يتطلب اتصالًا مستمرًا بالخادم(Server)، ولم يستخدمه المستخدمون بشكل منتظم ولا يحتاج إلى ميزات أصلية، فلا فائدة من جعله تطبيقًا أصليًا.
</p>

<h3>
	التطبيقات الهجينة (Hybird Application)
</h3>

<p>
	ربما يكون التطبيق المُهجّن أو الهجين هو الأصعب في شرح الخيارات. يُعَد التطبيق المُهجّن تطبيقًا أصليًا أُنشئ باستخدام HTML و CSS و Javascript. فمن خلال بناء هذه التطبيقات باستخدام تقنية الويب، يكون تطويرها أسرع وأسهل للنشر على منصات متعددة (مثل iOS أو Android). الجانب السلبي هو أن الأداء لا يميل إلى أن يكون جيدًا ويفتقر إلى نمط التصميم لكل منصة.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="34296" data-unique="7uavabgfm" src="https://academy.hsoub.com/uploads/monthly_2020_02/3-ButterflyCountingApp.png.bf6eb9669beb9cd7370130129c08c9fc.png" alt="3-ButterflyCountingApp.png"></p>

<p>
	مثال على هذا النوع من التطبيقات هو إثبات مفهوم تطبيق "فراشة العد butterfly counting" الذي طوّرته Headscape. تم بناء هذا التطبيق المُهجَّن في <a href="http://phonegap.com/" rel="external nofollow">PhoneGap </a> وسمح للمستخدمين بتحديد وحساب الفراشات في الحقل حتى مع عدم وجود اتصال بالانترنت. كان قرار إنشاء هذا كتطبيق هجين لأنه إثباتًا للمفهوم وأرادت الشركة إنتاجه بسرعة وبأقل تكلفة.
</p>

<h3>
	المواقع المتجاوبة (Responsive Websites)
</h3>

<p>
	الموقع المُتجاوب هو الذي يتكيف مع أي جهاز يتم عرضه عليه. سواء كان ذلك عبارة عن جهاز سطح مكتب أو جهاز لوحي أو جهاز محمول، سيعرض موقع الويب نفسه المحتوى نفسه باستخدام تصميم مرئي يناسب هذا الجهاز.
</p>

<p>
	خذ على سبيل المثال <a href="http://www.macmillanenglish.com/" rel="external nofollow">Macmillian English</a>. فهو موقعٌ غنيٌّ جدًا بالمعلومات. يُنقِّب مستخدمو الموقع عن المعلومات بدلاً من إتمام المهام.
</p>

<p>
	يضمن موقع الويب المتجاوب أن يتمكنوا من العثور على نفس المعلومات مهما كان الجهاز الذي يستخدمونه.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="34297" data-unique="635sqh51i" src="https://academy.hsoub.com/uploads/monthly_2020_02/5e563cb881855_4-TheMacmillianEnglish.PNG.png.49bddf893f9e7953658cc22e17725cf4.png" alt="4-The Macmillian English.PNG.png"></p>

<p>
	المواقع المُتجاوبة جيدة لـ :
</p>

<ul>
<li>
		المواقع الغنيّة بالمعلومات.
	</li>
	<li>
		المستخدمين الذين يتطلعون إلى جمع المعلومات.
	</li>
</ul>
<p>
	إذا كنت لست متأكدًا من الخيار الذي تحتاجه، فعادةً ما يكون الموقع المُتجاوب نقطة انطلاقٍ جيدة. هذا ما نعتقده عادًًة، أن تكون المواقع مُتجاوبة، فهذا يجعلها متوافقة مع الجوال (Mobile Friendly)، لكن هذا ليس كل ما في الأمر. لا تزال هناك طرق كثيرة تُمكّننا من إفساد تجربة المُستخدم والإضرار بموضعنا في نتائج البحث.
</p>

<hr>
<p>
	ألق نظرة على دورة <a href="https://academy.hsoub.com/learn/hybrid-mobile-application-development/" rel="">تطوير تطبيقات الجوال باستخدام تقنيات الويب</a> والتي ستتعلم فيها تطوير تطبيقات جوال لأنظمة أندرويد وأيفون و ويندوز فون باستخدام تقنيات الويب البسيطة JavaScript, HTML, CSS مما يمكنك من تطوير تطبيق واحد يعمل مباشرة على جميع المنصات.
</p>

<p>
	<iframe frameborder="0" height="315" src="https://player.vimeo.com/video/243144336" width="100%"></iframe>
</p>

<hr>
<h2>
	إنشاء موقع متجاوب متوافق تمامًا مع الجوال
</h2>

<p>
	ندرك جيدًا أهمية أن يكون الموقع متوافقًا مع الجوال، ويميل معظمنا إلى التفكير في "التصميم المتجاوب <a href="https://academy.hsoub.com/programming/css/%D9%85%D9%82%D8%AF%D9%85%D8%A9-%D9%81%D9%8A-%D8%AA%D8%B5%D9%85%D9%8A%D9%85-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D9%85%D8%AA%D8%AC%D8%A7%D9%88%D8%A8-%D8%A7%D9%84%D8%B9%D9%86%D8%A7%D8%B5%D8%B1-%D8%A7%D9%84%D8%B2%D8%A7%D8%A6%D9%81%D8%A9-%D9%88%D8%A7%D8%B3%D8%AA%D8%B9%D9%84%D8%A7%D9%85%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D8%B3%D8%A7%D8%A6%D8%B7-%D9%88%D8%BA%D9%8A%D8%B1%D9%87%D8%A7-r787/" rel="">Responsive Website</a>" كحل لهذا. لا ريب أن "التصميم المُتجاوب" قد أحدث طفرةً في تطبيقات الويب على الهواتف الذكيّة. فبوجٍه عام، لقد حسّنَ "<a href="https://academy.hsoub.com/design/user-experience/" rel="">تجربة المُستخدم User Experience</a>" وسهّل علينا إدارة المواقع وجنّبنا الحفاظ على إصدارات متعددة لنفس الموقع.
</p>

<p>
	دعني أقدم لك بعض الأمثلة عن "أين يمكن أن تسوء الأمور" بدءًا من المشكلة الأكبر على الإطلاق "المواقع شبه المتجاوبة".
</p>

<h3>
	هل موقعك مُتجاوب بالكامل؟
</h3>

<p>
	عندما نقوم بإعادة تصميم موقع ويب من البداية، فإن بناءه حيث يصبح "موقعًا متجاوبًا" أمرًا منطقيًا تمامًا. لكن تعديل لموقع موجود بالفعل (خاصةً إذا كان موقعًا كبيرًا) حيث يصبح "موقعًا متجاوبًا"، يمكن لهذا أن يتحول إلى كابوس.
</p>

<p>
	العديد من العملاء واجهوا هذه المشكلة، تحتوي معظم المواقع الإلكترونية الخاصة بهم على عشرات الآلاف من الصفحات على الأقل، تم إنشاؤها على مدار سنوات. مما جعل أمر أن تكون هذه المواقع "صديقة للهواتف الذكيّة" تحديًا بشكل لا يُصدَّق.
</p>

<p>
	لتقليل العمل الذي ينطوي عليه الأمر، فهم يتخذون قرارًا بالتركيز على الصفحات الأساسية وجعلها سهلة الاستخدام على الهواتف الذكيّة ومٌتجاوبة أيضًا، متجاهلين البقية.
</p>

<p>
	بالرغم من أنني أستطيع فهم هذا القرار إلا أنه سيء جدًا من منظور "تجربة المستخدم". ليس هناك ما هو أكثر إحباطًا من التورط في التفكير بأنّك تتصفح موقعًا صديقًا للهاتف، فقط لتجد نفسك عالقًا في صفحة مُحسّنة لسطح المكتب لا يمكنك قراءتها أو تصفّحها.
</p>

<p>
	تحتاج هذه المنظمات إلى التفكير بتمعن ولفترة طويلة حول ما إذا كانت تحتاج لمثل هذه المواقع الكبيرة. من واقع خبرتي، نادرًا ما يقومون بذلك، ويقومون فقط بترحيل المحتوى بشكلٍ أعمى من إصدارٍ لآخر.
</p>

<h3>
	هل قلصت وظائفية الموقع؟
</h3>

<p>
	يواجه المصممون مشكلة مماثلة عندما يصطدمون ببعض الوظائف الشاقة للموقع. شيء يبدو معقدًا جدًا لدرجة لا تمكّنه من صداقة الهواتف المحمولة ويكون التعامل مع الموقع على الهاتف شاقًا جدًا على المُستخدم.
</p>

<p>
	بدلًا من مضاعفة الجهود والتوصل لحل مُبتكر، نسهل الطريق الأقل صعوبة ومقاومة. نحن نقنع أنفسنا بأن مُستخدمي الهواتف لن يحتاجوا إلى هذه الوظائف وسيُزيلونها من الموقع.
</p>

<p>
	هذا بالطبع، أمرٌ ساذج بشكل لا يُصدّق. لا يختلف مُستخدمو الهواتف المحمولة بطريقة سحرية. هم نفس المُستخدمين الذين يستخدمون موقعك على "سطح المكتب Desktop". لقد بدّلوا الأجهزة فقط. لقد رأيتُ حتى أن الناس يستخدمون الهواتف المحمولة أثناء الجلوس في متناول اليد من أجهزة الحاسوب الخاصة بهم. لا يمكننا وضع افتراضات حول متطلباتهم بناءً على الجهاز.
</p>

<h3>
	هل تؤيد إشارات اللمس؟
</h3>

<p>
	لا تتعلق الأخطاء الصديقة لأجهزة الهاتف فقط بإزالة الأشياء، يمكن أن يكون الفشل في إضافة شيء ما بنفس الخطورة. خذ على سبيل المثال "دعم إشارات اللمس". لا عجب أن كثيرًا من المُستخدمين يفضلون أحيانًا تطبيقات الأجهزة المحمولة عندما لا يُمكنهم التحرك والضغط على موقع إلكتروني على الهاتف.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="34298" data-unique="ml7gm25fw" src="https://academy.hsoub.com/uploads/monthly_2020_02/5-TouchGestures.png.f9c4e76c22c387bd122f792099c4b8c2.png" alt="5-TouchGestures.png"></p>

<p>
	يجب حقًا على مصممي المواقع السماح للمستخدمين بتحريك الصور الدائرية والضغط عليها. فغالبًا ما يتم التغاضي عن هذا النوع من الوظائف لأننا نركز على تكييف التصميم لنقاط التوقف المختلفة.
</p>

<h3>
	هل يتكيف المحتوى وكذلك التصميم؟
</h3>

<p>
	أن يكون الموقع صديقًا للهاتف المحمول، فهذا لا يعني تغيير التصميم فقط، إنّه يتعلق أيضًا بتغيير المحتوى نفسه. خذ "الجدول" على سبيل المثال. فقط لأننا نعرض البيانات كجدول بأحجام شاشات أكبر، فهذا لا يعني أن علينا أن نفعل ذلك على الهواتف أيضًا. قد نستنتج أن عرض "مخطط تفاعلي interactive chart" أو شكل من أشكال الآلة الحاسبة أكثر صداقة للهاتف "Mobile Friendly". نحتاج إلى تعديل المحتوى وليس فقط التصميم والجداول ومخططات المعلومات البيانية، إلى شيء يسهل التعامل معه على الهاتف
</p>

<p>
	ثم يأتي دور "الرسوم البيانية infographics"، التي تبدو رائعة على الشاشات الكبيرة لكنها تصبح غير قابلة للقراءة على أجهزة الهاتف. نستطيع بالتأكيد أن نسمح للمُستخدم بتكبير الشاشة وندّعي بذلك أننا قمنا بعملنا على أكمل وجه، أو يمكننا أن نعيد تخيلهم. ربما يجب علينا أن نُقسِّم هذه الرسوم البيانية إلى "لوحة رسوم Storyboard" أو نستخدم فيديو عوضًا عن ذلك.
</p>

<h3>
	هل موقعك مقروءًا على الهاتف بقدر الإمكان؟
</h3>

<p>
	لا تقتصر مشاكل الوضوح فقط على الصور والجداول، إنما ينطبق الأمر بنفس القدر على النص. لن تُخلق تجربة ودية ومقروءة مع الهاتف بمجرد إضافة نقاط توقف إلى عناصر إعادة الموضع. انها غالبًا ما تُقصِّر أطوال الخطوط لدرجة تجعل القراءة صعبة للغاية.
</p>

<p>
	يبذل المصممون جهدًا في هذا الصدد بجعل حجم الخط يتناسب مع <a href="https://academy.hsoub.com/programming/html/%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF-%D8%B5%D9%88%D8%B1-%D9%85%D8%AA%D8%AC%D8%A7%D9%88%D8%A8%D8%A9-r687/" rel="">نقطة التوقف</a> (breakpoint)، وبتقليص حجمه وفقًا لذلك.
</p>

<p>
	لكنني زرتُ العديد من المواقع على الأجهزة المحمولة حيث أصبحت أحجام الخطوط صغيرة جدًا مما يجعل النص غير مقروء.
</p>

<p>
	وأخيرًا، هناك قضية "اللون". غالبًا ما يفشل المصممون في أن يأخذوا بعين الاعتبار وهج الشاشة التي يعاني منها مستخدمو الهواتف المحمولة، ومن ثَمَّ يصنعون لوحات الألوان الدقيقة التي تُصعِّب تجربة القراءة على الهاتف وهذا على أقل تقدير.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2020_02/7-ReadabilityProblem.png.00fc1bff1aed2726067109886d19dc48.png" data-fileid="34299" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="34299" data-unique="tkajwsfb5" src="https://academy.hsoub.com/uploads/monthly_2020_02/7-ReadabilityProblem.thumb.png.3765a3d7bb49ec6577210102d86d1bc0.png" alt="7-ReadabilityProblem.png"></a>
</p>

<h3>
	هل تركز بشكل كبير على أحدث وأفضل الهواتف الذكيّة؟
</h3>

<p>
	بالطبع، بعض مشاكل الوضوح هذه غير مرئية لنا حتى عند اختبارها على جهاز محمول. ذلك لأن لدينا أحدث وأكبر هاتف ذكي. إنه يحتوي على شاشة شبكية (retina screen)، ذات دقة عالية جدًا، وسطوع لا يمكن حتى للشمس أن تجاريها! ولكن ليس الجميع لديه أجهزة كهذه. حتى لو تجاهلت الهواتف المميزة كبندٍ للمقارنة، فقد تختلف التجارب بشكل كبير.
</p>

<p>
	ثم، بالطبع، هناك نقاط توقف. ما زلت أرى أن المصممين يقومون بتعيين نقاط التوقف استنادًا على الجهاز، بدلًا من المكان المناسب في المحتوى. لديهم تصميم بحجم iPad، وتصميم بحجم iPhone وما إلى ذلك. ولكن في الحقيقة، الأحجام متنوعة بشكل كبير، ونحتاج إلى التوقف عن التفكير في أجهزة معينة.
</p>

<h3>
	هل أداؤك صديقًا للهاتف؟
</h3>

<p>
	الأداء هو ما يجب أن نفكر به. في الواقع، ربما تكون هذه هي المنطقة الأكبر الوحيدة حيث يخذلنا "التصميم المتجاوب". لا تسيئ فهمي أنا لا أقول أن "التصميم المتجاوب" يجعل مواقعنا أبطأ. إنه فقط لا يفعل شيئًا لتحسينه وهو شيء تحتاجه الأجهزة المحمولة.
</p>

<p>
	حجم الصورة بالتأكيد هو السبب. قد يؤدي استخدام "استعلامات الوسائط media queries" إلى تصغير الصورة بصريًا، لكنه لن يؤثر في تقليل حجم الصورة أو أوقات التحميل. هذا ليس جيدًا عند استخدام شبكة خلوية. أضف إلى ذلك الخطوط والمكتبات والأطر وجميع العناصر الأخرى التي تنتفخ في مواقع الويب الحالية ولديك أوقات تحميل سيئة.
</p>

<p style="text-align: center;">
	<img class="ipsImage ipsImage_thumbnailed" data-fileid="34300" data-unique="oqqj6sexl" src="https://academy.hsoub.com/uploads/monthly_2020_02/8-Performance.png.095a440bf62a0b826cc420a41ee22ce2.png" alt="8-Performance.png"></p>

<p>
	يمكن أن يؤدي اختبار أداء موقعك على الأجهزة المحمولة إلى قراءة محبطة! لكن هذه ليست مجرد مشكلة في حجم التنزيل وسرعة الشبكة الخلوية. الأداء هو مشكلة في الجهاز أيضًا. تفتقر العديد من الأجهزة المحمولة إلى قدرة معالجة أجهزة الحاسوب المحمولة أو أجهزة الحاسوب المكتبية أو الأجهزة اللوحية. والنتيجة هي أنها لا تستطيع التعامل مع قالب مُكثف من كود الجافاسكريبت "intensive javascript" موجود على العديد من المواقع الحديثة.
</p>

<h3>
	هل ملء البيانات سهلًا على الهواتف؟
</h3>

<p>
	بعد ذلك، نأتي إلى مجموعة معينة من الأخطاء تحدث عندما نقوم بإدخال البيانات على الأجهزة المحمولة. فهل لك أن تتخيل كيف يمكن لأحد إدخال كم كبير من البيانات عبر لوحة مفاتيح هاتفه الصغير خلال فترة زمنية قصيرة؟ الأمر مريع حقًا، خصوصًا إن كان المستخدم مسنًا.
</p>

<p>
	كمصممي ويب، يبدو أننا نجعل المشكلة أسوأ بمئة مرة على مواقع الويب. عند إدخال بيانات رقمية، نفشل في عرض لوحة مفاتيح رقمية. عند إدخال كلمات المرور، نخفي ما يكتبه المستخدم، على الرغم من حقيقة أن الأخطاء المطبعية أمرًا شائعًا على الأجهزة المحمولة. في الواقع، لا ينبغي لنا أن نتوقع من مستخدمي الجوال ملء كلمات المرور على الإطلاق. هناك العديد من البدائل الأخرى مثل الإشعارات النصية أو روابط البريد الإلكتروني أو "معرف اللمس Touch ID".
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2020_02/9-Data.png.997fcc31f73c82ae0d36fb0ab2b4662f.png" data-fileid="34301" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="34301" data-unique="sta25qd7y" src="https://academy.hsoub.com/uploads/monthly_2020_02/9-Data.thumb.png.823fede800a6a349d6d134b53103ca9a.png" alt="9-Data.png"></a>
</p>

<p>
	هناك العديد من المواقف التي يمكن فيها تجنب إدخال البيانات أو تبسيطها. سيكون تذكر اسم المستخدم لتسجيل الدخول بين الجلسات بداية جيدة. ولكن يجب علينا أيضًا تحسين تصميم النموذج وتجنب عناصر الأشكال المملوءة مثل منتقي التواريخ أو القوائم المنسدلة الطويلة.
</p>

<h3>
	هل الروابط معبأة بإحكام أيضًا؟
</h3>

<p>
	عند الحديث عن التفاعلات المزعجة، أشعر بالدهشة إزاء قلة الاهتمام الذي يبديه المصممون للتحديات المحيطة باستخدام شاشة تعمل باللمس. أجد أن العديد من مواقع الويب التي تدّعي أنها صديقة للهاتف، ليست كذلك عندما تبدأ بالتفاعل معها. غالبًا ما يتم تجميع الارتباطات والأزرار معًا لزيادة حجم الشاشة إلى الحد الأقصى، بحيث يصبح من المستحيل النقر عليها.
</p>

<p>
	مرةً أخرى، مجرد تغيير موضع المحتوى لا يكفي. نحتاج إلى ضمان أن المساحة حول العناصر تتّسع للسماح بنقص الدقة الذي يحدث جرّاء استخدام الإصبع. من المسلَّم به أن المساحة هي ميزة استثنائية، ولكن إذا استخدمنا المساحة المتوفرة لدينا بحكمة، فلا يوجد سبب يمنع اختيار الروابط بسهولة أكبر. فقط إلقِ نظرة على متوسط التطبيق المحمول الخاص بك.
</p>

<h3>
	هل يتعين على المستخدمين تحمُّل محتوى ثابت الموضع؟
</h3>

<p>
	بالحديث عن قلة المساحة، لماذا على الرغم من رغبة جميع المصممين في إنشاء موقع ويب سهل الاستخدام للهاتف المحمول، فإننا نعتبر أنه من المقبول إضافة محتوى موقع ثابت إلى الصفحة. هذا يقلل بشكل كبير من المساحة المتاحة لعناصر المحتوى الأخرى.
</p>

<p>
	فكر بتمعُّن قبل نقل تنقلاتك الثابتة إلى منظور موقعك الإليكتروني على الهاتف. بالمثل، قم بإبعاد تلك الطبقات ونوافذ الحوار، وكذلك رموز مواقع التواصل الاجتماعي الثابتة. ليس لديهم مكان على موقع إليكتروني على الهاتف.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2020_02/10-FixedPosition.png.e332819f7e7ffe9f191a8837a8485058.png" data-fileid="34302" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="34302" data-unique="m9clcqesa" src="https://academy.hsoub.com/uploads/monthly_2020_02/10-FixedPosition.thumb.png.cad2673cd2e0a20874748383d27ac4a3.png" alt="10-FixedPosition.png"></a>
</p>

<p>
	يكاد يكون من المستحيل قراءة المحتوى الموجود على Mashable على جهاز محمول نظرًا لحجم عناصر الموضع الثابت.
</p>

<h2>
	ما المناسب لك؟
</h2>

<p>
	كلٌ من الخيارات الأربعة التي تمت مناقشتها في هذا المنشور له مكانه المناسب الذي سيختلف بناءً على الاحتياجات الخاصة بك. ومع ذلك، فإن نقطة الانطلاق الجيدة هي السؤال عمّا إذا كان المستخدمون يقومون في المقام الأول بإكمال مهمة أو الوصول إلى المعلومات.
</p>

<p>
	إذا كان الوصول إلى المعلومات هو الهدف، فمن المؤكّد أنّ المواقع المُتجاوبة هي الحل الأمثل. أمّا اذا كان "إكمال مهمة" هو الهدف، فعليك أن تسأل عمّا إذا كانت السرعة أم الوصول إلى الميزات الأصلية أيهما أهم. إذا كان الأمر كذلك، فستحتاج إلى تطبيق أصلي أو مُهجّن، وإلاّ سيكون تطبيق الويب مثاليًا.
</p>

<p>
	ترجمة -وبتصرف- للمقالين <a href="https://boagworld.com/mobile-web/mobile-friendly/" rel="external nofollow">Is your site as mobile friendly as you think</a> و <a href="https://boagworld.com/mobile-web/mobile-app-vs-mobile-website-design/" rel="external nofollow">Mobile app vs mobile website design: Your four options</a> لصاحبهما Paul Boag
</p>
]]></description><guid isPermaLink="false">841</guid><pubDate>Wed, 26 Feb 2020 09:47:44 +0000</pubDate></item><item><title>&#x645;&#x641;&#x647;&#x648;&#x645; Service Worker &#x648;&#x62A;&#x623;&#x62B;&#x64A;&#x631;&#x647; &#x641;&#x64A; &#x623;&#x62F;&#x627;&#x621; &#x648;&#x628;&#x646;&#x64A;&#x629; &#x645;&#x648;&#x627;&#x642;&#x639; &#x648;&#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628;</title><link>https://academy.hsoub.com/programming/general/%D9%85%D9%81%D9%87%D9%88%D9%85-service-worker-%D9%88%D8%AA%D8%A3%D8%AB%D9%8A%D8%B1%D9%87-%D9%81%D9%8A-%D8%A3%D8%AF%D8%A7%D8%A1-%D9%88%D8%A8%D9%86%D9%8A%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r833/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e50eaf573c11_---------Service-Worker.jpg.1f8545eaf4902b7e2e8d04680dc209b6.jpg" /></p>

<p>
	دخل إلى مجال الويب مؤخرًا العديد من الأفكار والتقنيات والإضافات لغاية خدمة تجربة المستخدم في تطبيقات الويب، مثل دعم الإشعارات وتوافر أيقونة على سطح المكتب وإتاحة التحكم بالـ <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> والعمل بشاشة كاملة وأهم عناصر وأركان هذه التقنيات والإضافات "عامل أو منجز خدمة" Service Worker وما يقدمه من عمل التطبيق بدون الاتصال في الشبكة والتخزين المؤقت وغيرها مما ساهم بإنجاح تجربة المستخدم لهذه <a data-ss1631101939="1" href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%82%D8%AF%D9%85%D9%8A%D8%A9-pwa-r832/" rel="">التطبيقات</a>.
</p>

<h2>
	مفهوم Service Worker
</h2>

<p>
	منجز خدمة هو سكريبت (script) ينفذ في خلفية مشروع الويب (موقع أو تطبيق)، غير مرتبط بصفحة معينة. مسؤول عن الأحداث التي تجري بالمشروع مثل طلبات الشبكة الصادرة من الصفحة المسؤول عنها والاستجابات لهذه الطلبات، له عدة غايات من أهمها اتاحة استخدام التطبيق مع الشبكة أو بانقطاعها أو ببطئها. فلو افترضنا شخصًا يستخدم موقعًا وكان متصلًا بالشبكة وأثناء تصفحه للموقع انقطع اتصاله بالشبكة ولكن أراد الرجوع للصفحة السابقة عند إذٍ لن تفتح الصفحة السابقة وستظهر له شاشة تعلمه بإنقطاعه عن الشبكة، لكن إن كان ذلك الموقع يملك Service Worker فلن يحدث هذا، بل ستظهر الصفحة السابقة أو على الأقل جزء منها.
</p>

<p>
	ومن اللطيف ذكره أن أي موقع ويب بإمكانه أن يمتلك Service Worker وأن يُفعله مستفيدًا من مزاياه الرائعة، لكن في حالة <a data-ss1631101939="1" href="https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%82%D8%AF%D9%85%D9%8A%D8%A9-pwa-r832/" rel="">تطبيقات الويب التقدمية PWA</a> <strong>يجب أن تمتلكه</strong> وأن يكون مسجلًا وفعالًا فهو من شروط عملها.
</p>

<h2>
	أهم الميزات التي يضفيها على مشروعك
</h2>

<h3>
	سرعة كبيرة
</h3>

<p>
	يركز ال Service Worker في فكرته بشكل كبير على السرعة والأداء المثالي في التحميل وذلك في حالة اتصال الشبكة أو بدونها أو ببطئها وتكون أطول فترة تحميل في المرة الأولى وأما في الزيارات المتكررة يتم تحميلها بشكل أسرع. انظر المثال في الصورة حيث كان وقت التحميل في المرة الأولى 2.5 ثانية وفي الزيارات الأخرى 0.8 ثانية أي انخفضت إلى أقل من الثلث وهذا مثال بسيط. (بإمكانك اختبار أداء فاعلية مشروعك من خلال هذه الأداة <a data-ss1631101939="1" href="https://www.webpagetest.org/" rel="external nofollow">WEBPAGETSET</a>).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34050" data-ss1631101939="1" href="https://academy.hsoub.com/uploads/monthly_2020_02/time.jpg.30a462bc9f5aa5499a90c3e3b86914ec.jpg" rel=""><img alt="time.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="34050" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/time.thumb.jpg.2ddbc63e6990e5573f760146477ffc62.jpg" style="width: 600px; height: auto;"></a>
</p>

<h3>
	العمل بدون شبكة
</h3>

<p>
	كانت تتميز التطبيقات (العادية) عن الويب إمكانية عملها من غير اتصال شبكة، لكن الآن مع الـ Service Worker يمكن لمواقع وتطبيقات الويب أن تعمل بدون اتصال شبكة والذي يقوم بتخزين الموارد والعناصر التي ترتبط بالأحداث والتفاعل لاستخدامها بدون اتصال شبكة أو ببطئها.
</p>

<h3>
	التحديث المستمر للتطبيق
</h3>

<p>
	يعتبر Service Worker المسؤول عن التحديثات في تطبيقات الويب، بل يتميز عن تحديثات أنواع البرامج والتطبيقات الأخرى <strong>بالسلاسة والاستمرارية والسهولة</strong> وذلك من خلال تخزين وتثبيت الموارد المحدثة فقط وبشكل تلقائي ويظهر شارة صغيرة للمستخدم عند فتح التطبيق بأن التطبيق تم تحديثه.
</p>

<h3>
	سيطرة أعلى
</h3>

<p>
	يمنح Service Worker لمطورين المواقع والتطبيقات سيطرة كاملة وأفضل على تجربة المستخدم للتطبيق.
</p>

<h3>
	تجربة تطبيقات حقيقية
</h3>

<p>
	يدعم Service Worker ويحسن تجربة <strong>المستخدم</strong> في التطبيقات ومحاكاتها من خلال ما يوفر من السرعة والعمل بدون اتصال الشبكة والتخزين المؤقت وهيكل التطبيق (الذي سنفصل فيه) وغيرها.
</p>

<p>
	وكذلك يمنح تجربة تطبيقات حقيقية ويحسنها <strong>للجوال</strong> حيث تكون منفصلة ومستقلة عن المتصفحات لا يشترط أن تكون مبنية عليها.
</p>

<h2>
	بنية هيكل التطبيق application shell architecture
</h2>

<p>
	عند تكرار زيارة الموقع أو عند تحميل التطبيق يتم تخزين حد معين من الشيفرات المصدرية HTML، و CSS، و JavaScript مؤقتًا ليتم استعمالها بدون اتصال الشبكة أو حتى مع اتصالها ولكن بشكل فوري وأسرع. وصلب الفكرة هنا أننا نملك هيكل يمثل جزءًا معينًا من التطبيق أو الموقع موجود على جهاز المستخدم يُحمل ويُبنى فورًا عند فتحه سواء مع اتصال شبكة أو بدون ثم يبدأ إضافة المحتوى غير المشمول فيها من الشبكة على هذا الهيكل إذ هو بمثابة الوعاء الفارغ الذي يوضع فيه شيء ما.(يعني نحافظ على واجهة المستخدم الأساسية على جهاز المستخدم ولا داعي لتحميلها كل مرة).
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34049" data-ss1631101939="1" href="https://academy.hsoub.com/uploads/monthly_2020_02/shell.jpg.8875e544389b1837ca4af16140d274b8.jpg" rel=""><img alt="shell.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="34049" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/shell.thumb.jpg.821010e2ae3060c31df8a34ddcb0877e.jpg" style="width: 600px; height: auto;"></a>
</p>

<p>
	وبهذا فإنها تخدم التجربة كثيرًا بغض النظر عن اتصال الشبكة أو سرعتها. وحتى إن كانت فكرة التطبيق/الموقع تعتمد بشكل كامل على اتصال الشبكة فإن المستخدم سيحصل على هيكل وشكل جذاب ومناسب بعدم اتصال الشبكة ويتوافق مع شكل التطبيق الأصلي ولن تظهر له شاشة عدم الاتصال، فهذا الهيكل يلعب دورًا عظيمًا في الأداء المثالي للموقع أو التطبيق من سرعة وخفة وتجربة مثالية. بعد فتح الموقع في المرة الأولى وتحميل الـ Service Worker لهذا الهيكل تظهر شارة أن البرنامج جاهز للعمل بدون اتصال شبكة.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34048" data-ss1631101939="1" href="https://academy.hsoub.com/uploads/monthly_2020_02/ready.jpg.cd75ea3576bcadb19660d7b9d74b9b3f.jpg" rel=""><img alt="ready.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="34048" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/ready.thumb.jpg.7727ef228807864076fd89131c0eaea3.jpg" style="width: 300px; height: auto;"></a>
</p>

<p>
	والمسؤول عن هذا الهيكل هو Service Worker وفي حال عدم دعم المتصفح لـ Service Worker لا داعي للقلق، فإن الهيكل والصفحة كاملة ستعتمد في تحميلها على استراتيجية الويب الشهيرة <a data-ss1631101939="1" href="https://alistapart.com/article/understandingprogressiveenhancement/" rel="external nofollow">Progressive Enhancement </a> بدون مشاكل.
</p>

<p>
	ومن الأمثلة الناجحة في استخدام فكرة هذا الهيكل: <a data-ss1631101939="1" href="https://www.google.co.uk/inbox/" rel="external nofollow">Google’s Inbox </a> و <a data-ss1631101939="1" href="https://wiki-offline.jakearchibald.com/wiki/Rick_and_Morty" rel="external nofollow">offline Wikipedia app</a> و<a data-ss1631101939="1" href="https://nuqayah.com/" rel="external nofollow">معظم مشاريع نقاية</a>.
</p>

<h2>
	آلية عمل الـ Service Worker وحدود إمكانياته
</h2>

<p>
	عند الزيارة الأولى للموقع أو عند تثبيت التطبيق يتم بناء الـ Service Worker وأخذ المحتوى والهيكل وكل البيانات والموارد من الخادم، وفي المرات التالية يتم سحب بيانات وعناصر محددة من الخادم ولكن كيف يتم تنظيم هذا السحب؟ كيف يتم تحميل بعض العناصر من Service worker وأخرى من الخادم؟
</p>

<p>
	يعترض Service Worker طلبات الشبكة الصادرة من الصفحة وهنا يقوم بالاستجابة لهذه الطلبات بواحدة مما يلي:
</p>

<ul>
<li>
		جلب المطلوب من الخادم عبر الشبكة.
	</li>
	<li>
		جلب المطلوب من الذاكرة المؤقتة على جهاز المستخدم، يتم جلب من الذاكرة المؤقتة العناصر والموارد المحددة مسبقًا لتجلب منها (مثل الهيكل الذي تحدثنا عنه).
	</li>
	<li>
		بناء المطلوب برمجيًا.
		<p style="text-align: center;">
			<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34047" data-ss1631101939="1" href="https://academy.hsoub.com/uploads/monthly_2020_02/controlling.png.2059d07564de96959dad927cf0f227a6.png" rel=""><img alt="controlling.png" class="ipsImage ipsImage_thumbnailed" data-fileid="34047" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/controlling.png.2059d07564de96959dad927cf0f227a6.png"></a>
		</p>
	</li>
</ul>
<p>
	والرائع هنا أن هذا كله يحدث دون أن يظهر مصدر الإستجابة ولا حتى أن الـ Service Worker قد تدخل.
</p>

<p>
	فلو تتبعنا دورة حياة الـ Service Worker لوجدنا أنه يتم بناءه عند أول دخول ويُحمل بعض الموارد عليه، ثم يُفعل ويَستيقظ عند وجود أي حدث، ويستجيب لهذا الحدث إن لزم الأمر مؤديًا دوره، ثم يُحذف من الذاكرة بمحتواه عند مرور الزمن دون أن ينشط، وتم إنشائه هكذا محدود العمر عن قصد.
</p>

<p>
	ومن الجيد معرفته أن Service Worker يحتوي على <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> محدودة مقارنة بما تحتويه الـ JavaScript في الصفحة العادية، بإمكانك أن تعرف <a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="external nofollow">تفاصيل <abbr title="Application Programming Interface | واجهة برمجية">API</abbr> له هنا</a>. واعلم بأن Service worker لا يمكنه الوصول إلى الـ DOM ولكن يمكنه الوصول إلى <a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Cache" rel="external nofollow">ذاكرة التخزين</a>. ويمكنه أيضًا ارسال <a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="external nofollow">طلبات الشبكة</a>، كذلك يمكنه أن يتواصل وأن يتبادل البيانات مع الصفحة المسؤول عنها عن طريق <a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API" rel="external nofollow">IndexedDB <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a> و <a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage" rel="external nofollow">postMessage</a>.
</p>

<h2>
	لا تفوت ميزاته مع مشاريعك القادمة لكن بحدود
</h2>

<p>
	يتبين مما سبق البون الشاسع الذي يُحدِثه الـ Service Worker في أداء مشاريع الويب معه، لذا يُنصح وبشدة استخدامه في تطبيقات ومواقع الويب، لكن بشكل معقول، فليس من المنطق أن تضيفه إلى مواقع صغيرة الحجم أو لا تقدم خدمة وتفاعل وتميل للمحتوى الثابت الخفيف فلا فائدة أو معنى من إضافته لمثلها.
</p>

<h3>
	تسهيل الحصول على Service Worker مع Workbox
</h3>

<p>
	يعتبر <a data-ss1631101939="1" href="https://developers.google.com/web/tools/workbox?hl=en" rel="external nofollow">Workbox </a> مجموعة من المكتبات والأدوات المستخدمة لإنشاء Service Worker والتخزين المؤقت وغيرها وتسهيل ذلك.
</p>

<h2>
	مراجع
</h2>

<ul>
<li>
		<a data-ss1631101939="1" href="https://addyosmani.com/blog/application-shell/" rel="external nofollow">Instant Loading Web Apps With A Service Worker Application Shell Architecture</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developers.google.com/web/fundamentals/primers/service-workers" rel="external nofollow">Service Workers: an Introduction</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="external nofollow">Using Web Workers</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Cache" rel="external nofollow">Cache</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="external nofollow">Fetch <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API" rel="external nofollow">IndexedDB <abbr title="Application Programming Interface | واجهة برمجية">API</abbr></a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage" rel="external nofollow">Client.postMessage()</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://github.com/GoogleChromeLabs/application-shell" rel="external nofollow">Application Shell Architecture</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://developers.google.com/web/tools/workbox?hl=en" rel="external nofollow">workbox</a>
	</li>
	<li>
		<a data-ss1631101939="1" href="https://www.keycdn.com/blog/service-workers" rel="external nofollow">What Are Service Workers and How They Help Improve Performance</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">833</guid><pubDate>Tue, 10 Mar 2020 18:04:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; &#x62A;&#x637;&#x628;&#x64A;&#x642;&#x627;&#x62A; &#x627;&#x644;&#x648;&#x64A;&#x628; &#x627;&#x644;&#x62A;&#x642;&#x62F;&#x645;&#x64A;&#x629; PWA</title><link>https://academy.hsoub.com/programming/general/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-%D8%A7%D9%84%D8%AA%D9%82%D8%AF%D9%85%D9%8A%D8%A9-pwa-r832/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_02/5e53e13a9c223_---------PWA.jpg.c0b8a68bb9042d43cd4506f52db0a57d.jpg" /></p>
<p>
	صار اليوم من السهل تطبيق فكرة مشروع برمجي ما بطريقة واحدة ليأخذ العديد من الأشكال ويطبق في العديد من المجالات وهي المواقع الإلكترونية وتطبيقات الجوالات وتطبيقات سطح المكتب (مع اختلاف أنظمة التشغيل مثل: Android، IOS، Windows، macOS) وهذا كله بفضل تقنية تطبيقات الويب التقدمية (PWA / progressive web application). حيث كان يصنع كل من الموقع الإلكتروني وتطبيق الجوال وتطبيق الحاسوب على حدة. بل كان يصنع كل تطبيق في نظام تشغيل منفصلًا عن غيره، لنحصل على النتيجة المرجوة من الـ PWA لمشروع واحد.
</p>

<p>
	ألقي نظرة على الموقع <a href="https://abnassar.github.io/expensive-time/#/" rel="external nofollow">expensive-time</a> والذي قمت بإعداده محتويًا على هذه التقنية.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34043" href="https://academy.hsoub.com/uploads/monthly_2020_02/example.jpg.d34a051e1ac754f649dfeac28b4964be.jpg" rel="" data-fileext="jpg"><img alt="example.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="34043" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2020_02/example.thumb.jpg.17a4850076ef8ae9ab047c06861f3d29.jpg"></a>
</p>

<h2>
	مفهوم تطبيقات الويب التقدمية
</h2>

<p>
	تطبيقات الويب التقدمية (progressive web application) تم تطويرها بناءً على علامات تبويب المتصفحات ليتم استخدامها كمواقع وتطبيقات بنفس الوقت، ويتم بنائها كما هو الحال في مشاريع الويب لتعمل على جميع الأجهزة بمختلف مشغلاتها من جوالات وحواسيب مكتبية أو محمولة أو لوحية، دون الحاجة لاختلاف طريقة البناء.
</p>

<h2>
	حاضر مميز ومستقبل متوقع
</h2>

<p>
	لاقت تطبيقات الويب التقدمية إقبالًا كبيرًا وانتشارًا واسعًا خلال فترة قصيرة، حيث حققت نجاحًا باهرًا في عالم المواقع والتطبيقات من فاعلية وسهولة في الصناعة والاستخدام، فهي جمعت بين ميزات التطبيقات والمواقع، ويتوقع لها مستقبل أكبر وأعظم من تطويرٍ ودعمٍ وانتشارٍ أكثر واستغناء أكثر عن الطرق المعروفة في صناعة التطبيقات، لما حققت من الأهداف العظيمة في العديد من المجالات وغيرها من الميزات نتحدث عن بعضها بالتفصيل.
</p>

<h2>
	بعض من خصائص وميزات PWA لها من العظمة بمكان
</h2>

<p>
	جمعت تطبيقات الويب التطورية بين ميزات التطبيقات والمواقع، بل إنها تخلصت من العديد من عيوب التطبيقات والمواقع. فمن ميزات التطبيقات التي حققتها PWA أنها تعطي للمستخدم تجربة وعلاقة أقوى منها في المواقع ومع ذلك فهي حافظت على ميزة السلاسة والسهولة في التعامل كما هو الحال في المواقع من عدم الاضطرار لتحميل ملفات كبيرة وبدون صعوبة وطول التحميل والثقل على الجهاز وغيرها من ميزات في المواقع والتطبيقات. ونجحت من التخلص من عيوب في التطبيقات مثل إجراءات وتقييدات المتاجر المتعبة وبعض العيوب في المواقع مثل عدم الاستقلالية عن المتصفحات في الاستخدام وغيرها من العيوب.
</p>

<p>
	تتميز هذه التطبيقات بأنها تعمل على كل جهاز(جوال، حاسوب لوحي، حاسوب مكتب …)، على كل نظام تشغيل (Android, IOS, Windows …)، على كل متصفح (Google Chrome, Mozilla Firefox, Safari …) باختلاف إصداره. والفضل في ذلك يعود على اعتماد PWA في بنائها على استراتيجية الويب Progressive enhancement فهي عمودها الفقري. (نتحدث عنها أكثر فيما بعد).
</p>

<p>
	وتميزت بالعديد من الخصائص العظيمة مثل السرعة الكبيرة في التحميل حتى مع الشبكات البطيئة بل إنها تعمل بدون اتصال شبكة والفضل في ذلك يعود لتقنية عامل الخدمة Service Worker (نتحدث عنها أكثر فيما بعد)، وهي آمنة ومحمية من خلال بروتوكول <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security" rel="external nofollow">Transport Layer Security-<abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل"><abbr title="Transport Layer Security | بروتوكول أمن طبقة النقل">TLS</abbr></abbr></a> الذي يعمل على منع التطفل والتلاعب بالمحتوى، يقوم المستخدم بتحميل واستخدام هذه التطبيقات بكل سهولة وبساطة دون متاعب وإجراءات متاجر التطبيقات، بل تقوم هذه التطبيقات بتحديث نفسها تلقائيًا دون الحاجة لإعادة تحميل كامل التطبيق، وصنعت لتعمل مع جميع إصدارات المتصفحات ولكن تعطي تجربة أفضل من الدرجة الأولى مع المتصفحات الحديثة التي تدعم التقنيات المتقدمة مثل <a href="https://academy.hsoub.com/programming/general/%D9%85%D9%81%D9%87%D9%88%D9%85-service-worker-%D9%88%D8%AA%D8%A3%D8%AB%D9%8A%D8%B1%D9%87-%D9%81%D9%8A-%D8%A3%D8%AF%D8%A7%D8%A1-%D9%88%D8%A8%D9%86%D9%8A%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r833/" rel="">عامل الخدمة Service Worker</a> والاشعارات وشارة الاضافة إلى الشاشة الرئيسية وغيرها. سهولة مشاركتها من خلال عنوان الموقع سهل النسخ والفتح مما يساعد على انتشارها، تتيح لنا استخدام البرنامج كموقع أو كتطبيق جوال أو كتطبيق سطح مكتب.
</p>

<h3>
	نسخة الموقع الإلكتروني
</h3>

<p>
	يقوم المستخدم بتجربة البرنامج واستخدامه دون تحميله فهو يجربه مباشرة بفتح الموقع الإلكتروني ويقوم بتحميله إن احتاج. بل إن بعض المستخدمين لن يحتاج استخدام البرنامج إلا مرة واحدة وبالتالي يقوم باستخدامه كموقع دون تحميله. والكثير من المستخدمين يميل لاستخدام البرنامج كموقع ولا يفضل تحميله وهنا نترك مساحة للمستخدم للاختيار بين تجربة الموقع والتطبيق.
</p>

<h3>
	نسخة تطبيق الجوال
</h3>

<p>
	يتمكن المستخدم بتحميل التطبيق مباشرة من الموقع واستخدامه بتجربة مستقل عن المتصفحات ومطابقة لتجربة التطبيقات المعتادة ويمتلك أيقونة على الشاشة الرئيسية كما هو الحال بالتطبيقات(يمكنك استخدام هذه الأداة <a href="https://realfavicongenerator.net/" rel="external nofollow">realfavicongenerator</a> لمعرفة شكل أيقونة تطبيقك على مختلف الأجهزة أو إن كان هنالك مشكلة فيها كما تبين الصورة في الأسفل) بل ويتعرف عليه الجهاز على أنه تطبيق مستقل، وهنا يبني المستخدم علاقة مع التطبيق بكثرة الاستخدام وتوافر النسخة على الجهاز بشكل مستقل مما يضفي متعة وراحة وسهولة في تجربة المستخدم.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34044" href="https://academy.hsoub.com/uploads/monthly_2020_02/icon.PNG.b44b7130d9355522adf290bb716d24e6.PNG" rel="" data-fileext="PNG"><img alt="icon.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="34044" data-unique="data-unique" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2020_02/icon.thumb.PNG.cf23a9008add06c06e20ffdf9f8ba693.PNG"></a>
</p>

<h3>
	نسخة تطبيق سطح المكتب PC
</h3>

<p>
	معظم ما ذكرنا في نسخة تطبيقات الجوال تنطبق على نسخة سطح المكتب، حيث يمكن أن تحمل تطبيقات PWA على الجهاز وتعمل بشكل مطابق للتطبيقات الأصلية في الجهاز في نافذة مستقلة بتجربة جذابة للمستخدم، وبالرغم من انتشار تطبيقات الجوال واستخدامها إلا أن ذلك لا يقلل من أهمية وكثرة استخدام أجهزة الحاسوب، لذا جاءت الأهمية بتوفر نسخة لها.
</p>

<p>
	تمثل الصورة في الأسفل توزيع استخدام الأجهزة (جوالات، حواسيب، حواسيب لوحية) في اليوم.
</p>

<p style="text-align: center;">
	<img alt="device-usage.png" class="ipsImage ipsImage_thumbnailed" data-fileid="34919" data-unique="6b2a3q46z" src="https://academy.hsoub.com/uploads/monthly_2020_02/device-usage.png.f5c66510408f160b2a3ca7927583f98b.png">
</p>

<h2>
	عناصر ساهمت بانجاح وتحسين تجربة المستخدم في PWA
</h2>

<h3>
	التحسين التدريجي الاستراتيجية المعروفة بـ Progressive enhancement
</h3>

<p>
	كما ذكرنا <a href="https://alistapart.com/article/understandingprogressiveenhancement/" rel="external nofollow">Progressive enhancement</a> هي أساس PWA والعمود الفقري لها وباختصار فإنها تعتمد على تقسيم البرنامج إلى طبقات يتم عرض كل طبقة حسب دعم المتصفح لها، لذا فإن البرنامج يعمل لدى الجميع إذ يحتوي على طبقة أساسية (المحتوى) تعمل وتعرض على جميع الأجهزة ويتم إضافة الطبقات الأخرى عند دعمها، وطبقات الإضافية والتكميلية تضفي تحسينًا وتجربة أفضل وميزات أعلى.
</p>

<h3>
	تقنية service workers
</h3>

<p>
	الكلام يطول كثيرًا في هذه التقنية المضافة إلى عالم الويب مؤخرًا، لكن نتطرق لبعض ما يهمنا فيها بموضوع PWA. فكما ذكرنا سابقًا أن هذه التقنية مسؤولة عن عمل التطبيق في حالة عدم الاتصال بالشبكة وتلعب دورًا مهما في سرعة أداء البرنامج حتى مع الشبكات البطيئة، فهو يقوم بتخزين الموارد التي ترتبط بالأحداث والتفاعل في البرنامج لاستخدامها بدون اتصال الشبكة أو ببطئها. وأيضًا يقدم تحميل فوري وسريع جدًا للمستخدمين الذين تكرر زيارتهم. ويوفر تجربة للجهاز حقيقية مع التطبيق منفصلة عن المتصفح ولا يشترط أن تكون خلال المتصفح. وإن كانت تعتمد فكرة البرنامج بشكل كامل على اتصال الشبكة فإن المستخدم سيحصل على هيكل وشكل جذاب ومناسب بعدم اتصال الشبكة ويتوافق مع شكل التطبيق الأصلي، وهذه التقنية مسؤولة عن التحديث المستمر للتطبيق. لذا إضافته إلى مشروعك يلعب دورًا هامًا في إنجاحه (راجع مقالي <a href="https://academy.hsoub.com/programming/general/%D9%85%D9%81%D9%87%D9%88%D9%85-service-worker-%D9%88%D8%AA%D8%A3%D8%AB%D9%8A%D8%B1%D9%87-%D9%81%D9%8A-%D8%A3%D8%AF%D8%A7%D8%A1-%D9%88%D8%A8%D9%86%D9%8A%D8%A9-%D9%85%D9%88%D8%A7%D9%82%D8%B9-%D9%88%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%A7%D9%84%D9%88%D9%8A%D8%A8-r833/" rel="">مفهوم Service Worker وتأثيره في أداء وبنية مواقع وتطبيقات الويب</a> لمزيد من التفاصيل).
</p>

<h3>
	ملف manifest لتطبيق الويب
</h3>

<p>
	ملف بسيط بصيغة json متاح لمبرمج التطبيق للتحكم بكيفية ظهور التطبيق على جهاز المستخدم مثل الأيقونة التي تظهر على الشاشة الرئيسية، وعمل التطبيق بشاشة كاملة، مع التحكم في ظهور الشريط الذي يحوي العنوان URL والإعدادات وغيرها كما في علامات التبويب في المتصفحات، ويمكن التحكم باتجاه الشاشة (من الأعلى إلى الأسفل والعكس, أو من اليمين إلى اليسار والعكس) و<a href="https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android?hl=en" rel="external nofollow">لون الشريط العلوي في الشاشة</a>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34045" href="https://academy.hsoub.com/uploads/monthly_2020_02/manifest.PNG.67c4da93efe9d86fdb02287bd93c19ae.PNG" rel="" data-fileext="PNG"><img alt="manifest.PNG" class="ipsImage ipsImage_thumbnailed" data-fileid="34045" data-unique="data-unique" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2020_02/manifest.PNG.67c4da93efe9d86fdb02287bd93c19ae.PNG"></a>
</p>

<h3>
	تطبيقات بشكل رسمي ومعترف
</h3>

<p>
	إذ يتم التعرف عليها من الأجهزة والمتصفحات على أنها تطبيق والفضل بذلك يعود لمنظمة <a href="https://www.w3.org/" rel="external nofollow">w3c</a> من خلال كشوفها المقدمة للمحركات عن الرابط المعني ومن خلال نطاق التسجيل لـservice worker. ويقوم المتصفح بإضافة <a href="https://developers.google.com/web/fundamentals/integration/webapks?hl=en" rel="external nofollow">APK</a> للتطبيق حتى يتعرف عليه الجوال على أنه تطبيق ويسجل في إعدادات التطبيقات في الجهاز، وأما في جهاز الحاسوب PC يتم إضافته إلى نافذة التطبيقات.
</p>

<h3>
	لافتات التحميل
</h3>

<p>
	تظهر لافتة اسفل الشاشة تقترح إضافة البرنامج للشاشة الرئيسية عند فتح الموقع على الجوال، وحتى تظهر هذه اللافتة يجب توفر ما يلي في مشروعك:
</p>

<ul>
	<li>
		ملف Web App manifest
	</li>
	<li>
		أن يكون مخدوم على عناوين HTTPS
	</li>
	<li>
		يحتوي على service worker مسجل وفعال
	</li>
	<li>
		يتم الزيارة من قبل المستخدم مرتين على الأقل يفصل بين كل زيارة خمس دقائق على الأقل
	</li>
</ul>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34040" href="https://academy.hsoub.com/uploads/monthly_2020_02/add.gif.b73eecf18efbc99ec94c607f7521ec54.gif" rel="" data-fileext="gif"><img alt="add.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="34040" data-unique="data-unique" style="width: 260px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2020_02/add.thumb.gif.16cea161d42bb7607bdbfc4237e68e4b.gif"></a>
</p>

<p>
	أما في جهاز الحاسوب تظهر لافتة التحميل أعلى الشاشة بجانب شريط العنوان.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34041" href="https://academy.hsoub.com/uploads/monthly_2020_02/addPC.jpg.a338b26ed6a615698d50ebc12537df3f.jpg" rel="" data-fileext="jpg"><img alt="addPC.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="34041" data-unique="data-unique" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2020_02/addPC.jpg.a338b26ed6a615698d50ebc12537df3f.jpg"></a>
</p>

<h3>
	الإشعارات
</h3>

<p>
	لو سألنا مجموعة مبرمجين سابقًا عن الفرق بين المواقع الإلكترونية والتطبيقات لأجاب معظمهم بالإشعارات، ولكن مع تطور عالم الويب أصبحت تدعم الإشعارات، وهذا عاد بالكمالية لتطبيقات PWA وساهم في إنجاحها. ولكن حتى تتمكن من تفعيل وتمكين الإشعارات لابد أن يحتوي مشروعك على ملف Web App manifest، وأن يحتوي على service worker مسجل وفعال. تعرف على تفاصيل أعمق حول الإشعارات <a href="https://developers.google.com/web/updates/2015/03/push-notifications-on-the-open-web?hl=en" rel="external nofollow">هنا</a>.
</p>

<h3>
	إتاحة التحكم بواجهة برمجة التطبيقات (<abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr>)
</h3>

<p>
	بدأ دخول إمكانيات التحكم بـAPI على الويب منذ فترة ليست بالبعيدة وما زال الدعم والتطوير لها بتزايد كبير في مجال الويب كما يوضح التوزيع في الأسفل. تعرف على تفاصيل أعمق حول <abbr title="Application Programming Interface | واجهة برمجية"><abbr title="Application Programming Interface | واجهة برمجية">API</abbr></abbr> في الويب <a href="https://frontendmasters.com/books/front-end-handbook/2018/learning/web-api.html" rel="external nofollow">هنا</a>.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="34046" href="https://academy.hsoub.com/uploads/monthly_2020_02/web-api.png.fb1ee2888f0e96123a0fee52b8e40ccd.png" rel="" data-fileext="png"><img alt="web-api.png" class="ipsImage ipsImage_thumbnailed" data-fileid="34046" data-unique="data-unique" style="width: 500px; height: auto;" src="https://academy.hsoub.com/uploads/monthly_2020_02/web-api.thumb.png.cbec18130d99f8e16674aa6cf1eb8cb1.png"></a>
</p>

<h3>
	إطارات عمل الجافاسكريبت (frameworks) تنسجم وتساهم في فكرة PWA
</h3>

<p>
	لا يوجد فعليًا قيود تحظر وتمنع إدراج أي تقنيات من مكتبات أو إطارات عمل أو غيرها إلى مشروعك في pwa بالعكس الكثير منها يدعم ويساهم بتحسين نتائجها ويسهل صناعتها من أشهرها VUE و React و svelte. وينصح باستخدامها لما تتيحه من إمكانيات وتسهيلات تدعم المشروع (قمت باستخدام VUE في صناعة تطبيقي المطروح كمثال سابقًا).
</p>

<p>
	لا يعني بأن بناء التطبيق بطريقة Vanilla JS (نسمي عدم استخدام أي من frameworks في الجافاسكربت Vanilla JS) ضعفه وانخفاض مستواه أو سيكون فاشل بل يوجد الكثير منها مبني بهذه الطريقة وقد حقق نجاحًا باهر مثل مشاريع نقاية.
</p>

<h2>
	مثال ناجح
</h2>

<p>
	<a href="https://nuqayah.com/" rel="external nofollow">مشاريع نقاية</a> وهي مجموعة مشاريع PWA تعتبر مثالًا ناجحًا وإبداعيًا جدًا عليها، حققت انتشارًا ونجاحًا باهرًا، تخدم التراث العربي والإسلامي، فأنصحك بالاطلاع عليها وتجريبها على مختلف الأجهزة.
</p>

<h2>
	مراجع
</h2>

<ul>
	<li>
		<p>
			<a href="https://addyosmani.com/blog/getting-started-with-progressive-web-apps/" rel="external nofollow">Getting started with Progressive Web Apps</a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://codelabs.developers.google.com/codelabs/your-first-pwapp/#0" rel="external nofollow">Your First Progressive Web App</a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/progressive-web-apps/desktop#app-window" rel="external nofollow">Progressive Web Apps on Desktop </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://alistapart.com/article/understandingprogressiveenhancement/" rel="external nofollow">Understanding Progressive Enhancement </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://www.w3.org/TR/service-workers/" rel="external nofollow">Push Notifications on the Open Web </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/fundamentals/push-notifications/" rel="external nofollow">Web Push Notifications: Timely, Relevant, and Precise </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://stackoverflow.com/tags/progressive-web-apps/info" rel="external nofollow">progressive-web-apps</a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://www.w3.org/TR/service-workers/" rel="external nofollow">Service Workers </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/fundamentals" rel="external nofollow">The core foundations of a delightful web experience are… </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/fundamentals/app-install-banners" rel="external nofollow">Add to Home Screen </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android?hl=en" rel="external nofollow">Support for theme-color in Chrome 39 for Android </a>
		</p>
	</li>
	<li>
		<p>
			<a href="https://developers.google.com/web/fundamentals/web-app-manifest?hl=en" rel="external nofollow">The Web App Manifest </a>
		</p>
	</li>
	<li>
		<p>
			<a href="http://%5D(https://developers.google.com/web/fundamentals/integration/webapks?hl=en" rel="external nofollow">WebAPKs on Android</a>
		</p>
	</li>
	<li>
		<a href="https://hackernoon.com/progressive-web-apps-apple-app-store-google-play-store-it-was-nice-knowing-you-728a00350e67" rel="external nofollow">Progressive Web Apps: Apple App Store, Google Play Store, It Was Nice Knowing You</a>
	</li>
</ul>

<p>
	 
</p>

<h2>
	اقرأ أيضًا 
</h2>

<p>
	<a href="https://academy.hsoub.com/programming/general/%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-%D8%AA%D8%B7%D8%A8%D9%8A%D9%82%D8%A7%D8%AA-%D8%B3%D8%B7%D8%AD-%D8%A7%D9%84%D9%85%D9%83%D8%AA%D8%A8/" rel="">برمجة تطبيقات سطح المكتب</a>
</p>
]]></description><guid isPermaLink="false">832</guid><pubDate>Tue, 25 Feb 2020 18:05:00 +0000</pubDate></item><item><title>&#x628;&#x646;&#x627;&#x621; &#x62A;&#x644;&#x645;&#x64A;&#x62D; &#x645;&#x633;&#x627;&#x639;&#x62F;&#x629; &#x633;&#x647;&#x644; &#x627;&#x644;&#x648;&#x635;&#x648;&#x644; &#x644;&#x644;&#x62C;&#x645;&#x64A;&#x639;</title><link>https://academy.hsoub.com/programming/general/%D8%A8%D9%86%D8%A7%D8%A1-%D8%AA%D9%84%D9%85%D9%8A%D8%AD-%D9%85%D8%B3%D8%A7%D8%B9%D8%AF%D8%A9-%D8%B3%D9%87%D9%84-%D8%A7%D9%84%D9%88%D8%B5%D9%88%D9%84-%D9%84%D9%84%D8%AC%D9%85%D9%8A%D8%B9-r764/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_11/5ddc15cc146de_-----.jpg.d83a1ec318d927cb26596f7bc03c0435.jpg" /></p>

<p>
	…إنّه أصعب مما ظننت
</p>

<p>
	اليوم هو أحد تلك الأيام التي بدأت مع بحث غوغل عن سؤال/مسألة أخرى تتعلق بسهولة الوصول (accessibility). أنا أعمل على مشروع جديد لعميلتي Provta وجزء من هذا المشروع هو بناء تلميح مساعدة بسيط وجميل يشرح للقارئ/المستخدم عن ماهيّة حاسبة فرامنغهام.
</p>

<p>
	يتم تشغيل التلميح بواسطة أيقونة مساعدة صغيرة مثل تلك التي تظهر في الزاوية اليمنى العليا من لقطة الشاشة هذه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.png.74f85238c0330862c6b90053bb989f01.png" data-fileid="32857" rel=""><img class="ipsImage ipsImage_thumbnailed" data-fileid="32857" data-unique="in3brvrou" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.png.74f85238c0330862c6b90053bb989f01.png" alt="pic01.png"></a>
</p>

<p>
	كما هو الحال مع كل مشروع، فإنّ البدء بالتفكير ما هو عنصر HTML الذي سأستخدمه لترميز المكوّن هو أوّل شيء فعلته. لكن اتّضح أنّه لا يوجد عنصر HTML لترميز تلميح كهذا. وعندما لا يكون لدينا عناصر دلالية لترميز مكوناتنا، فإنّنا نواجه التحدي في التأكّد من أنّ التقنيات المساعدة (ATs)- التي عادةً ما تكون قادرة على فهم ونقل المعنى عن طريق الدلالات - قادرة على فهم ما هي عناصرنا بالفعل وماذا تفعل.
</p>

<h2>
	هل تنقذنا خاصية ARIA؟
</h2>

<p>
	جعل العناصر سهلة القراءة من قِبل التقنيات المساعدة عندما لا يكون HTML كافيًا باستخدام خاصيّات ARIA. مثلًا، يمكنك الحصول على ذلك بإنشاء شريط تقدّم بدون استخدام عنصر <code>&lt;progess&gt;</code> من <code>HTML</code> غير المدعوم جيّدًا. يمكن جعل هذا الشريط يبدو ويتصرّف كأنّه شريطًا باستخدام CSS، لكن إذا كنت تستخدم عناصر <code>div</code> و<code>span</code> لبنائه، فأنت بحاجة لإعطاء التقنيات المساعدة المزيد لصنع شيءٍ ما من تلك العناصر غير الدلالية. هذا هو المكان الذي تصبح فيه خاصيّات ARIA مثل <code>role="progressbar"‎</code> ورفقائها المساعدين <code>aria-valuenow</code>، <code>aria-valuemin</code> و<code>aria-valuemax</code> (من بين أمور أخرى) مفيدةً. يمكنك تحديث القيمة داخل <code>aria-valuenow</code> باستخدام بعض الجافاسكربت كلّما تقدّم المستخدم في الخطوات قدّمتها له وهذا جيّد عمومًا. يمكنك قراءة المزيد حول هذا الموضوع على <a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_progressbar_role" rel="external nofollow">MDN</a> إذا كنت مهتمًا أو غير معتاد على ذلك.
</p>

<p>
	عظيم!
</p>

<p>
	لدينا قيمة الخاصيّة ARIA لمساعدتنا في الإشارة إلى أن عنصرًا معينًا هو تلميح: tooltip. باستخدام <code>role="tooltip"‎</code> فإنّ التقنيات المساعدة تعرف أنّ هذا العنصر هو بالفعل تلميح.
</p>

<p>
	لكن عادةً ما يتم تشغيل التلميحات بواسطة إجراء يتم تنفيذه على عنصر آخر.
</p>

<p>
	دعنا أولًا نعود إلى الأساسيات. حسب ويكيبيديا:
</p>

<p>
	التلميح أو infotip أو النص المُساعد هو عنصر واجهة مستخدم رسومي شائع، يُستخدم جنبًا إلى جنب مع مؤشر، والذي يكون عادةً مؤشر الفأرة. عندما يمرّر المستخدم مؤشر الفأرة على عنصر ما، بدون الضغط عليه، قد يظهر التلميح بشكل مربع صغير يتضمّن معلومات حول العنصر الذي تمّ تمرير المؤشر فوقه. لا تظهر التلميحات عادةً على أنظمة التشغيل في الأجهزة المحمولة، لأنّه لا يوجد مؤشر (على الرغم من أنه قد يتم عرض التلميحات عند استخدام الفأرة).
</p>

<p>
	المشكلة التي أواجهها هي هذا الجزء "لا تظهر التلميحات عادةً على أنظمة التشغيل في الأجهزة المحمولة، لأنّه لا يوجد مؤشر"، لأنّ مستخدمي الهواتف المحمولة لهم الحق أيضًا في الحصول على المعلومات على الصفحة مثل المستخدمين الذين لا يستخدمون الهواتف المحمولة. يجب أن تكون قادرًا على فهم نقاط فرامنغهام سواءً كنت تستخدم فأرة أو إصبعك، لذا فإنّ هذا التلميح يجب أن يكون سهل الوصول في جميع الأحوال، وهنا تبدأ المتعة.
</p>

<h2>
	تشغيل فتح/إغلاق التلميح
</h2>

<p>
	علمتُ أنني لا أستطيع الاعتماد على التمرير وحده (بالرغم من أن العميلة طلبت التمرير فقط) لأنّه إذا لم يكن لديك شاشة تعمل باللمس مع قلم رقمي فاخر يسمح بتشغيل التمرير، فلن تكون قادرًا على رؤية النص المساعد داخل التلميح، وهذا غير مقبول.
</p>

<p>
	بدأت في عرض التلميح عندما يتم التمرير والضغط على أيقونة المساعدة معًا.
</p>

<p>
	من الجدير بالذكر عند هذه النقطة أنّ التلميحات تعمل أحيانًا على شاشة اللمس والمؤشر بدون أن تضطر للقيام بأي عملٍ إضافي، مثل تلك التي تظهر كتسميات مساعدة في حقول الإدخال <code>input</code>، مثل <a href="http://heydonworks.com/practical_aria_examples/#input-tooltip" rel="external nofollow">هذا المثال</a> لـ Heydon Pickering. في سيناريوهات مثل عندما يكون <code>role="tooltip"‎</code> مع <code>aria-describedby</code> فإنّ هذا كافٍ لتعرف التقنيات المساعدة أنّ هذا الجزء من النص يحتاج إلى تلميح يصف محتوى أو وظيفة حقل الإدخال. من السهل جدًا وضع علامة على التلميح في هذه الحالة لأنّه واضح بالفعل بما فيه الكفاية. كل ما تبقى لك هو إظهار/إخفاء النص عندما يتم التركيز على حقل <code>input</code>، وهذا يمكن أن يتم باستخدام سطري CSS فقط. التجربة ممتازة بالنسبة لشاشات اللمس والفأرة، وسيجرّبها الجميع بنفس الطريقة.
</p>

<p>
	ومع ذلك فإنّ الأمور غير واضحة بشكلٍ جيّد عندما يكون لديك مثال كمثالي في المشروع الذي أعمل عليه. ويبدو أنني لست الشخص الوحيد الذي كان هنا وكان مرتبكًا تمامًا في كيفية القيام بهذا الأمر.
</p>

<p>
	إليك بعض الأفكار التي دارت بذهني عندما كنت أفكر في تنفيذ هذا:
</p>

<ul>
<li>
		استخدام عنصر <code>&lt;button&gt;</code> لتشغيل فتح وإغلاق التلميح. سيكون التلميح مخفيًا بالحالة الافتراضية لذا فإنّ التقنيات المساعدة لن تقرأه بصوتٍ عالٍ أثناء تحرّك المستخدم إلى أسفل الصفحة. يقاطع التلميح تدفق المحتويات في حالة مشروعنا لذا يجب عرضه عند الطلب فقط.
	</li>
	<li>
		"عند الطلب" تعني عندما يمرر/يضغط/ينقر/يركّز للتشغيل
	</li>
	<li>
		سيُخفى التلميح في الحالة الافتراضية باستخدام <code>display: none</code> ويُعرض فقط عند الطلب.
	</li>
	<li>
		بما أنّ الدلالات و"كيف ستقرأ الآلات هذا" هي التي ستحدد كيف سأبدأ بكتابة شيفرة HTML، فكرت:
		<ul>
<li>
				إذا استخدمت <code>&lt;button&gt;</code> يجب أن أستخدم <code>aria-controls</code> للإشارة إلى عناصر التحكم للزر والتي ستُظهر/ستخفي بعض العناصر عندما تُضغط. الأمور جيّدة.
			</li>
		</ul>
</li>
	<li>
		عند الحديث عن الدلالات، يمكنني أيضًا استخدام رابط <code>&lt;a&gt;</code> يرتبط بقسم معين في الصفحة، وهو في حالتي العنصر الذي يحتوي على النص المساعد.
	</li>
	<li>
		عند استخدام رابط، سينتقل المستخدم إلى قسم الصفحة الذي يرتبط به هذا الرابط. أنا أكره القفز في الصفحات، أتجنّبه مثل الطاعون إلا إذا كان قرار القفز مقصودًا. (مثلًا، رابط "العودة إلى الأعلى" في كل صفحة طويلة).
	</li>
	<li>
		أحتاج جافاسكربت لتجنب القفز عند استخدام <code>&lt;a&gt;</code>، ولجعل <code>&lt;button&gt;</code> يفتح ويُغلق التلميح.
	</li>
	<li>
		أريد تجنّب جافاسكربت واستخدامه فقط عند الضرورة لسببٍ شاملٍ. ماذا لو كان المستخدم رجلًا كبيرًا ويستخدم جهازًا قديمًا تمّ تعطيل الجافاسكربت به؟
	</li>
</ul>
<p>
	عادةً، أبحث عن آراء ثانية، عندما أحتار بين حلّين وعندما تبدأ الأفكار تدور في ذهني حول استخدام جافاسكربت وعدم استخدامها. مصدري الأول لرأيٍ ثانٍ هو غوغل. فكرت: "يجب أن يكون شخصًا ما قد بنى واحدًا من قبل وكذلك يجب أن يكون شخصًا غيره قد قام بذلك، لذا دعنا نرى كيف تعاملوا معه وحلّوا هذه المشكلة".
</p>

<p>
	عند تلك النقطة كنت مازلت أفكر "أريد القيام بذلك بدون استخدام جافاسكربت إذا كان ذلك ممكنًا"، لكن صدّق أو لا تصدّق أنا أحب جافاسكربت ومنفتحة تمامًا بشأن استخدامها إذا كان الحلّ المعتمد عليها أفضل من غيره من الحلول.
</p>

<p>
	قادني البحث في غوغل إلى سؤال كان بالضبط نفس سؤالي. وجدت الكثير من الأسئلة المتشابهة لكنهم كانوا جميعًا أشبه بمثال تلميح حقل الإدخال. وجدتُ مناقشةً <a href="https://webaim.org/discussion/mail_thread?thread=5041" rel="external nofollow">قديمةً جدًا</a> بدأتها <a href="https://twitter.com/zomigi" rel="external nofollow">Zoe Gillenwater</a> التي كان عندها نفس السؤال الذي لدي الآن في عام 2011. أدرك أنّ بعض التفاصيل التقنية هناك ستكون أو قد تكون غير صالحة اليوم لكن المبادئ العامة تبقى صالحة. أنصح بشدّة بقراءة هذه المناقشة قبل متابعة قراءة هذا المقال لأنّ كل شيء آخر هنا يعتمد على بعض الأفكار التي حصلت عليها من تلك المناقشة. النقاط الرئيسية المذكورة في هذه المقالة:
</p>

<ul>
<li>
		تجنّب استخدام العنصر <code>&lt;button&gt;</code> وتمسّك باستخدام العنصر <code>&lt;a&gt;</code> لأنّه يمكن استخدام الروابط لأي شيء تقريبًا بينما يجب ترك الأزرار للاستخدام في النماذج. يجدر بي القول أنّني لا أتفق مع هذه النقطة، إذا كنت تعرف سببًا جيّدًا لتجنّب استخدام <code>&lt;button&gt;</code> الرجاء <a href="https://twitter.com/SaraSoueidan" rel="external nofollow">إخباري</a>.
	</li>
	<li>
		عند استخدام العنصر <code>&lt;a&gt;</code> يجب أن تأخذ بالحسبان/تتذكر ما يلي:
		<ul>
<li>
				إذا كنت تستخدم <code>&lt;a&gt;</code> وتمّ تضمين النص المساعد بداخله:
			</li>
			<li>
				ستبدو الشيفرة كالتالي:
			</li>
		</ul>
</li>
</ul>
<pre class="ipsCode">
&lt;a href="#" aria-describedby="#tip"&gt; &lt;!-- your icon here, img or svg --&gt; &lt;span id="tip"&gt; Your hint text here &lt;/span&gt; &lt;/a&gt;
</pre>

<ul>
<li>
		<ul>
<li>
				سيكون النص قابلاً للقراءة مع التدفق (وهو غير مناسب في حالتي) لأن محتوى النص المساعد يقاطع تدفق المعلومات والبيانات المعروضة في المحتوى الرئيسي.
			</li>
			<li>
				يمكنك إخفاء وإظهار النص باستخدام CSS فقط مع <code>display: none</code> و<code>display: block</code> على التوالي عندما يتم التمرير فوق الرابط. هذا جيد للمستخدمين المبصرين باستخدام الفأرة. لكن…
			</li>
			<li>
				إذا أخفيت النص باستخدام <code>display: none</code> داخل <code>&lt;a&gt;</code> وعرضته عند التركيز فإنّ التقنيات المساعِدة لن تكون قادرة على قراءة النص المعروض لأنّ محتويات الرابط تُعلن فقط عند <code>focus</code> الأولى ولن يتم إعادة الإعلان عنها عندما يُعرض النص داخل الرابط مع <code>display: block</code>.
			</li>
			<li>
				باختبار ذلك، لاحظتُ أنّه بما أنّ الرابط لا يرتبط فعليًا بأي مكان فإنّ المستخدم سينتقل إلى أعلى الصفحة عندما ينقر الرابط في شاشة تعمل باللمس. هذا أمر فظيع بشكلٍ خاص في حالتنا لأنّه لدينا صفحة طويلة والانتقال إلى الأعلى سيُربك المستخدمين. يمكن حلّ هذا باستخدام جافاسكربت <code>preventDefault</code> لمنع الحدث الإفتراضي عند النقر.
			</li>
			<li>
				(برأيي: أنا لا أحب حقيقة أنّ الرابط لا يرتبط بأيّ مكان. إنّه رابط ذاتي التضمين، برأيي، إذا كان هذا يصنع فرقًا فإنّه ينفي دور الرابط للبدء به. كنت أعلم أنني لا أريد استخدام هذا على الرغم من أنّني اختبرته بدافع الفضول.)
			</li>
			<li>
				إذا كنت تستخدم <code>&lt;a&gt;</code> وجعلته يرتبط بجزء نصي منفصل (ليس من فروع الرابط نفسه):
			</li>
			<li>
				ستكون الشيفرة كالتالي:
			</li>
		</ul>
</li>
</ul>
<pre class="ipsCode">
&lt;a href="#tip"&gt;&lt;!-- icon here --&gt;&lt;/a&gt;&lt;div id="tip"&gt; &lt;!-- tooltip text here --&gt; &lt;/div&gt;
</pre>

<ul>
<li>
		<ul>
<li>
				لا يزال الرابط يسبب انتقالًا في الصفحة ما لم يتم استخدام جافاسكربت.
			</li>
			<li>
				في شاشات اللمس، يؤدي النقر على الرابط إلى التركيز عليه وهذا بدوره يفتح التلميح، لكن تبقى صورة الرابط كما هي ولا توجد طريقة لإغلاق التلميح ما لم ينقر المستخدم أي مكان خارجه لإزالة التركيز عليه، وهذا غير بديهي لأنّ هذا سينطوي على الكثير من الجهد المعرفي والتخمينات والتساؤلات "كيف أغلق هذا" والإحباط، خاصةً أنّ التلميح يغطي المحتوى عندما يفتح.
			</li>
		</ul>
</li>
</ul>
<p>
	يأتي كل حلّ لا يستخدم جافاسكربت بجانب سيء للغاية يؤثّر سلبًا على تجربة المستخدم. جافاسكربت هي الطريقة التي تجعل هذا يعمل مع كل مستخدم بشكلٍ صحيح في جميع الأحوال. إنّها تحلّ كل واحدة من المشكلات المذكورة، باستثناء مشكلة "هذا الرابط لا يرتبط بأي مكان" والتي لا يمكن حلّها إلا بعدم استخدام رابط لا يشير إلى أيّ مكان. D: (قد لا يوافق البعض على أن الرابط الذي لا يرتبط بأيّ مكان ليس خاطئًا أو غير صالح عمليًا، لكن لا أظنّ ذلك شخصيًّا.)، انتهي بي الأمر باختيار حلّ يعمل باستخدام جافاسكربت ولديه آثار غير سيئة للغاية. يغطي هذا الأفكار والاعتبارات الرئيسية التي كانت لدي إلى حدٍّ كبيرٍ.
</p>

<h2>
	خاتمة
</h2>

<p>
	جافاسكربت أمر ضروري لبناء مكونات تفاعلية متاحة بالكامل. يمكنك بالتأكيد الابتعاد عن استخدامها في بعض الحالات، لكن الكثير من قابلية الوصول تتطلّب جافاسكربت. بعض أدوار وخاصيات ARIA ضرورية للغاية لجعل المكونات سهلة للوصول، والكثير منها لن تسلك السلوك الذي تحتاجه ما لم تجعلها تعمل مع جافاسكربت. بما أنّ عميلي هو شركة صحيّة، فمن الممكن أن يكون لدى المستخدمين شكل من أشكال الإعاقة أو غيره لذا يجب أن تكون الجافاسكربت معطّلة لديهم، لذا من الآمن التفكير بعدم استخدام جافاسكربت بدلًا من تعطيلها.
</p>

<p>
	إذا كنت مهتمًا بمعرفة المزيد حول ما تتطلّبه الخاصيّات، أنصح بشدّة بفحص <a href="http://whatsock.com/training/matrices/" rel="external nofollow">مقاييس دور ARIA</a> من WhatSock. فهي توفر نظرة عامة سهلة القراءة.
</p>

<p>
	أيضًا لدى Paul J Adam <a href="http://pauljadam.com/demos/aria-role-tooltip.html" rel="external nofollow">عرض تجريبي</a> يظهر الطرق المختلفة لعرض تلميحات عند التمرير. لا تزال أمثلته تستخدم جافاسكربت لبناء مكونات أكثر قابلية للوصول بتشغيل خاصيات ARIA عندما تفتح/تغلق التلميحات. هذا العرض يستحق تفحّصه بالتأكيد.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.sarasoueidan.com/blog/accessible-tooltips/" rel="external nofollow">Building a fully-accessible help tooltip </a> لصاحبته Sara Soueidan
</p>
]]></description><guid isPermaLink="false">764</guid><pubDate>Mon, 25 Nov 2019 17:57:06 +0000</pubDate></item><item><title>&#x635;&#x648;&#x631; SVG &#x627;&#x644;&#x645;&#x62A;&#x62D;&#x631;&#x643;&#x629; &#x628;&#x627;&#x644;&#x645;&#x648;&#x627;&#x632;&#x646;&#x629; &#x645;&#x639; &#x635;&#x648;&#x631; GIF (&#x648;&#x641;&#x642; CAGEMATCH)</title><link>https://academy.hsoub.com/programming/general/%D8%B5%D9%88%D8%B1-svg-%D8%A7%D9%84%D9%85%D8%AA%D8%AD%D8%B1%D9%83%D8%A9-%D8%A8%D8%A7%D9%84%D9%85%D9%88%D8%A7%D8%B2%D9%86%D8%A9-%D9%85%D8%B9-%D8%B5%D9%88%D8%B1-gif-%D9%88%D9%81%D9%82-cagematch-r763/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_11/5ddbfb63d30fb_-SVG-----GIF-(-CAGEMATCH).jpg.f6d70b261f2a260bd7ea3fc61c66ed20.jpg" /></p>

<p>
	يمكن أن تقوم SVG بأكثر بكثير من مجرد عرض الصور الثابتة، إذ تعد إمكانياتها الحركيّة واحدة من أكثر مميزاتها قوةً، مما يعطيها مزايا فريدة عن صيغ الصور الأخرى، وهي أحد الأسباب العديدة التي تجعل SVG أفضل من الصور النقطية، بما فيها GIF. ولكن هذا، بالطبع، ينطبق فقط على الصور التي تعد مرشحةً جيدةً لتكون SVG، مثل:
</p>
<style type="text/css">
table {
    width: 100%;
}

thead {
    vertical-align: middle;
    text-align: center;
}

td, th {
    border: 1px solid #dddddd;
    text-align: right;
    padding: 8px;
    text-align: inherit;

}
tr:nth-child(even) {
    background-color: #dddddd;
}</style>
<ul>
<li>
		الشعارات،
	</li>
	<li>
		الصور غير المعقدة، المعتمدة على الأشعة،
	</li>
	<li>
		أدوات التحكم بواجهة المستخدم،
	</li>
	<li>
		الرسوم البيانية،
	</li>
	<li>
		والأيقونات.
	</li>
</ul>
<p>
	بالطبع، إذا كان لديك صورة أكثر ملاءمةً للصيغة النقطية – مثل الصور الفوتوغرافية أو الرسومات المعقدة جدًا المعتمدة على الأشعة (والتي من الطبيعي أن تكون كبيرة الحجم جدًا مثل صور SVG)، فعليك استخدام صيغة الصور النقطية بدلاً منها. لا يجب أن تكون الصورة مرشّحاً جيداً لـ SVG فقط، ولكن يجب أن يكون SVG مرشّحاً جيداً للصورة. فمثلًا، إذا كان حجم الصورة صغير جداً كصور PNG، يجب استخدام PNG، وتقديم إصدارات/معاملات دقة مختلفة للصورة باستخدام <code>srcset</code> أو <code>&lt;picture&gt;</code>، بالاعتماد على ما تعمل عليه وتحاول تحقيقه.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		لا ينبغي أن تكون الصورة مرشّحًا جيدًا لـ SVG فقط، ولكن يجب أن تكون SVG مرشّحًا جيدًا للصورة.
	</p>
</blockquote>

<p>
	عمومًا، الصور المذكورة أعلاه هي عادةً مرشّحات مثالية لـ SVG. وإذا كنت ستحرّك أيًا منها، فإنّ الطريقة المعقولة للقيام بذلك هي إنشاء صورك المتحركة عن طريق تحريك شيفرة SVG.
</p>

<p>
	ومع ذلك، في الأسبوع الماضي، ظهر رابطًا منبثقًا في يوميات حسابي على التويتر يشير إلى مجموعة من الأيقونات المتحركة كـ GIF.
</p>

<p>
	إنّ أول ما مرّ في ذهني عندما رأيتهم بأنّهم كانوا مرشحين مثاليين لـ SVG ويجب أن يتم إنشاؤهم كصور SVG، وليس صور GIF.
</p>

<p>
	في العديد من الحالات يمكنك استبدال صور GIF بصور SVG بالفعل، تمامًا كما يمكن أن تستبدلها بتنسيقات الصور النقطية الأخرى لمرشّحين مثل تلك المذكورة أعلاه. إنّ القدرة على تحريك صور SVG هي ما يمنحها هذه الميزة والقدرة. وهذا ينطبق على عناصر أكثر من الأيقونات المتحركة.
</p>

<p>
	لذا، لهذا السبب أعتقد أنّه يجب عليك استخدام SVG بدلًا من صور GIF كلما استطعت.
</p>

<h2>
	جودة الصورة
</h2>

<p>
	الميزة الأولى لاستخدام SVG بدلًا من GIF - أو أية صيغة صورة لهذه المسألة - هي - كما هو متوقع - ميزة SVG الأولى: استقلالية الدقة. ستبدو صورة SVG فائقة الوضوح عند أي دقة للشاشة، بغض النظر عن حجمها. في حين أن صور GIF - صيغة الصورة النقطية - لا تظهر كذلك. حاول تكبير الصفحة التي تحتوي على صورة GIF وشاهد كيف ستبدو صورة الـ GIF منقطة ومحتوياتها غير واضحة.
</p>

<p>
	مثلّا، يبدو تسجيل GIF التالي لحركة صورة SVG جيدًا بهذا الحجم الصغير:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32850" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.gif.2f9a8018f39209ecbee9f6d8ebf78342.gif" rel=""><img alt="pic01.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="32850" data-unique="ci1w63xcx" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic01.gif.2f9a8018f39209ecbee9f6d8ebf78342.gif"></a>
</p>

<p>
	يؤدي تكبير الصفحة عدّة مرات إلى جعل الصورة غيرَ واضحةٍ وتصبح حواف ومنحنيات العناصر الداخلية مسننةً، كما تشاهد في الصورة أدناه:
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32851" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.png.552ac05594bfd10235a8a0239021a59a.png" rel=""><img alt="pic02.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32851" data-unique="1g4vuxhiw" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic02.thumb.png.ce8909f722cf7b739811c46bcfb6ce37.png"></a>
</p>

<p>
	بينما إذا قمت بالتحقق من <a href="https://codepen.io/chrisgannon/pen/myZzJv" rel="external nofollow">عرض SVG التجريبي</a> وتكبير الصفحة، فإن محتوى SVG سيبقى واضحًا وصافيًا بغض النظر عن مقدار التكبير.
</p>

<p>
	لتوفر صورًا واضحةً للشاشات عالية الدقة عند استخدام صيغة صورة نقطية مثل GIF، تحتاج إلى استخدام <code>&lt;picture&gt;</code> أو <code>srcset</code> وتشغيل الصور بسياقات مختلفة.
</p>

<p>
	بالطبع، كلما زادت دقة الصورة، زاد حجم الملف. مع صور GIF، سيصل حجم الملف لحجمٍ كبير بشكلٍ هائل. لكننا سنصل إلى ذلك في غضون دقيقة، كذلك، فإنّ استخدام صور GIF عالي الدقة وعرضها بحجمٍ أصغر للهواتف المحمولة يعد أمرًا سيئًا بالنسبة للأداء، لذا لا تفعل ذلك.
</p>

<p>
	عندما تنشئ أيقونات أو صور GIF متحركة، أبعادها ثابتةٌ. غيّر الأبعاد أو كبّر وصغّر الصفحة، وستحصل على صورة غير واضحة. أمّا مع SVG، ستتخلص من مشكلة الحجم، وستحصل على وضوحٍ دائم. يمكنك إنشاء صور SVG صغيرة وتغيير أبعادها وفق احتياجاتك دون التضحية بوضوح الصورة.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				GIF مثل تنسيقات الصور الأخرى تمامًا، غير مستقلة الدقة، ولذا ستبدو غير واضحة عند تغيير حجمها أو عرضها بدقة أعلى
			</td>
			<td>
				صورة SVG قابلة لتغيير الحجم ومستقلة الدقة، وستبدو واضحةً بأي دقة شاشة
			</td>
		</tr>
</tbody></table>
<h2>
	الألوان والشفافية
</h2>

<p>
	ربما يكون السبب الأول لتبتعد عن التعامل مع صور GIF هو الطريقة التي يتعامل بها مع الشفافية، خاصةً عندما يتم عرض الصورة على خلفية غير الخلفية البيضاء.
</p>

<p>
	هذه مشكلة تظهر غالبًا عند استخدام أيقونات GIF (سواءً كانت متحركة أم لا)، عندما يتم إنشاء الأيقونات عادةً بخلفيات شفافة.
</p>

<p>
	مثلًا، فكر مليّا بالدائرة التالية المحاطة بحدّ، أُنشئت كصورة SVG (يسار) وGIF بخلفية شفافة (يمين). المشكلة واضحة بمجرد النظر إلى الصورتين: تحتوي دائرة GIF على حواف رمادية حول حدّها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32852" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.gif.149350d03bf6930f49c6f205ee8869f5.gif" rel=""><img alt="pic03.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="32852" data-unique="isb4cj4s7" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic03.gif.149350d03bf6930f49c6f205ee8869f5.gif"></a>
</p>

<p>
	إذا كنت لا تعاينها في المتصفح، فقد لا يكون التأثير مرئيًا لك لأنّه من الممكن ألا يتم تطبيق أنماط الشكل. فيما يلي لقطة توضح المشكلة (على اليمين):
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32853" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic04.png.f72051cd63cb6dc6c269a40958bf29f5.png" rel=""><img alt="pic04.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32853" data-unique="21iqyv7fs" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic04.thumb.png.73c8f6dfdcfffbf8f88cba52e91ee54a.png"></a>
</p>

<p>
	يحدث هذا لأن الشفافية في صور GIF ثنائية. هذا يعني أن كل بكسل إما يعمل أو لا يعمل؛ البكسل سيظهر إما شفافًا أو ممتلئًا بشكلٍ كامل. وهذا بدوره يعني أنّ الانتقال بين اللون الأمامي ولون الخلفية ليس سلسًا، والتشوهات الناتجة تظهر بسبب تردد العينات غير المناسب، والمعروفة باسم التعرج.
</p>

<p>
	عندما لا يكون الخط مستقيمًا تمامًا، فإنّه يتسبب بأن تكون بعض البكسلات (حول الحواف) شفافة جزئيًا وممتلئة جزئيًا ، لذلك يحتاج البرنامج إلى معرفة اللون الذي يجب استخدامه لهذه البكسلات. تأثير الهالة "ناتج عن كل البكسلات التي كانت ممتلئة أكثر من 50٪ امتلاءً كاملاً وتحمل لون الخلفية بدلاً من اللون الذي تم تنقيطه" <a href="https://twitter.com/svgeesus/" rel="external nofollow">كريس ليلي</a>. لذلك يكون هذا التأثير عادةً ناتجًا عن تلوث البكسل من لون الخلفية التي تتكون الصورة على أساسه مقارنةً بما هي عليه عند إنشائها/حفظها في محرر الرسومات.
</p>

<p>
	عادةً ما يحاط التعرج بمكافح تعرج، ولكن هذا ليس بالأمر البسيط عندما تكون الشفافية ثنائية:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		هناك تفاعل شديد بين مكافح التعرج والشفافية الثنائية. بما أنّ لون خلفية الصورة مدموج مع الألوان الأمامية، لذا فإنّه ببساطة مجرد استبدال لون خلفية واحد بآخر لا يكفي لمحاكاة الشفافية. سيكون هناك مجموعة كاملة من الظلال التي هي مزيج من ألوان الخلفية والألوان الأمامية […]. التأثير في هذه الحالة هو هالة بيضاء حول العناصر، لأنّ الصورة الأصلية كانت مكافحة لتعرج لون الخلفية البيضاء. — <a href="https://www.w3.org/Conferences/WWW4/Papers/53/gq-trans.html" rel="external nofollow">المصدر</a> <a href="https://twitter.com/svgeesus/" rel="external nofollow">كريس ليلي</a>.
	</p>
</blockquote>

<p>
	حلّ هذه المشكلة هو الشفافية المتغيرة، والمعروفة باسم قناة ألفا، والتي تسمح بدرجات متفاوتة من الشفافية وبالتالي انتقالًا أكثرَ سلاسةٍ بين اللون الأمامي ولون الخلفية، وهذا غير متوفر في GIF؛ وبالتالي، هذا يسبب مشكلة تأثير الهالة. تظهر الصور ذات تأثير الهالة أفضل عادةً عند استخدامها مع خلفيات بيضاء؛ أي لون خلفية آخر عالي التباين سيجعلها تبدو مشوهةً.
</p>

<p>
	لست متأكدةً تمامًا مما إذا كانت هناك طريقة لحل هذه المشكلة، لكنني لم أجد بعد صورة GIF ذات خلفية شفافة وحواف منحنية لم تكن بها هذه المشكلة. لقد رأيت الأشكال المستطيلة تعاني منها أيضًا.
</p>

<p>
	إذا كنت ترغب في استخدام صورتك/أيقونتك على خلفية غير بيضاء - مثلًا، على خلفية تذييل داكنة، قد يكون هذا لوحده يبعدك عن التعامل مع GIF، ولكن هناك أسباب أخرى تجعل استخدام SVG أفضل من GIF أيضًا، والتي سنغطيها في الأقسام التالية.
</p>

<p>
	ملاحظة: إذا كنت تقرأ هذه المقالة باستخدام المتصفح ولكنك لا ترى الحواف في الصورة الأولى على شاشة أصغر، فحاول تكبير الصفحة لترى التأثير.
</p>

<p>
	لماذا من الممكن ألا تكون قادرًا على رؤية الحواف على أحجام أصغر؟ الإجابة هي: ينعّم المتصفح الحواف كجزءٍ من عملية تغيير حجم الصورة. هل هذا يعني أنّه يمكنك استخدام هذا للتخلص من الحواف والاستمرار باستخدام GIF؟ نعم تستطيع. ولكن للقيام بذلك، يجب عليك استخدام صور GIF بحجم أكبر بكثير من الحجم الذي تريد أن تكون الصورة به، ثم تغيير حجمها. هذا يعني أيضًا أنك ستعرض صورًا للمستخدمين أكبر بكثير مما يحتاجون إليه، وبالتالي استهلاك المزيد من النطاق الترددي على الهاتف المحمول، بالإضافة إلى الإضرار بالحجم العام للصفحة وأدائها. رجاءً لا تفعل ذلك.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				صور GIF قادرة على الشفافية الثنائية فقط. يسبب هذا التشوهات، المعروفة باسم تأثير الهالة التي تظهر كلما تمّ استخدام الصورة أو الأيقونة مع خلفية غير بيضاء كلما كان تباين لون الخلفية مع الصورة أعلى، كان تأثير الهالة أكثر وضوحًا مما يجعل الأيقونات غير قابلة للاستخدام عمليًا.
			</td>
			<td>
				تأتي صور SVG مع قناة ألفا ولا تعاني من أيّة مشاكل عند استخدامها مع ألوان خلفية مختلفة.
			</td>
		</tr>
</tbody></table>
<h2>
	تقنيات الصور المتحركة وأداؤها
</h2>

<p>
	يمكنك تحريك صور SVG باستخدام CSS أو جافاسكربت أو SMIL، وتمنحك كلٌّ منها مستوىً مختلفًا من التحكم يمكنك الاستفادة منه لإنشاء جميع أنواع الصور المتحركة على عناصر SVG.
</p>

<p>
	لا توجد "تقنيات" لتحريك صور GIF. يتم تحريكها من خلال عرض سلسلة من الصور - صورة لكل إطار - بشكلٍ تسلسلي، بأسلوبٍ ثابتٍ وسرعةٍ ثابتةٍ. تعلم أنّ هذه الطريقة التي تعمل بها صور GIF فقط. ومن المؤكد أنّه يمكنك الإبداع مع أيقوناتك قبل تحويلها إلى صور GIF ثم "تسجيل" الحركات وتحويلها إلى GIF، ولكن ما مدى جودة مظهرها؟ وما مدى السيطرة على وقت الحركة التي ستحصل عليها بعد ذلك؟ لا شيء.
</p>

<p>
	لن تبدو الحركة سلسةً ما لم تتأكد من أن لديك 60 إطارًا على الأقل - أي 60 صورة - في الثانية لإنشاء صورتك الـ GIF. بينما مع SVG، فإنّ الحصول على صورٍ متحركةٍ سلسةٍ أسهل وأبسط بكثير من خلال الاستفادة من تحسينات المتصفح.
</p>

<p>
	حجم صور GIF أكبر من حجم صور PNG أو JPEG، وكلما طالت مدة حركة صورتك، زاد حجمها. ماذا لو أردت الآن تشغيل صورتك المتحركة لمدة 5 إلى 6 دقائق على الأقل؟ ماذا لو أردت تشغيلها لفترة أطول؟
</p>

<p>
	ستحصل على الصورة.
</p>

<p>
	لنلقِ نظرةً أكثر تحديدًا على مثالٍ بسيط. يوجد أدناه صورتان: صورة SVG متحركة على اليسار وصورة GIF متحركة على اليمين. يتغير لون المستطيل في كلتا الصورتين بفترة ست ثوانٍ.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32854" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic05.gif.802d6091f7045b7d882114e7dc6952be.gif" rel=""><img alt="pic05.gif" class="ipsImage ipsImage_thumbnailed" data-fileid="32854" data-unique="8du24zr1d" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic05.gif.802d6091f7045b7d882114e7dc6952be.gif"></a>
</p>

<p>
	يوجد العديد من الأشياء لملاحظتها هنا:
</p>

<ul>
<li>
		تبدو صور GIF المتحركة سلسةً، لكن إذا ألقيت نظرةً قريبةً ستلاحظ أنّ مستطيل SVG يمر بمجموعة أكبر من الألوان عندما ينتقل من اللون الأولي إلى اللون النهائي. عدد الألوان التي يمر بها GIF محدودًا بعدد الإطارات. في الصورة أعلاه، تمر صورة الـ GIF بـ 60 إطارًا، أي 60 لونًا، بينما يمر SVG عبر الطيف بأكمله بين ظل اللون الوردي المستخدم واللون الأخضر النهائي.
	</li>
	<li>
		بالنسبة لتكرار الصور المتحركة مثل هذه، من الأفضل عمومًا تجنب قفزة اللون الظاهرة في الصورة المتحركة أعلاه، وإنشاء الصورة المتحركة بحيث تنعكس ما إن تصل إلى اللون الأخضر؛ بهذه الطريقة، ستنتقل بسلاسة إلى اللون الوردي ثم تبدأ الجولة الثانية من الصورة المتحركة من هناك أيضًا، مع تجنب قفزة الألوان القبيحة. مع CSS، يمكنك عكس حركة الصورة باستخدام قيمة اتجاه الحركة <code>alternate</code>. ولكن مع GIF، ستحتاج إلى العمل على عدد إطاراتك وربما ينتهي بك الأمر إلى مضاعفتهم لتحقيق ذلك؛ سيؤدي هذا بالطبع إلى زيادة حجم الصورة أيضًا.
	</li>
</ul>
<p>
	أحجام الصورتين الظاهرتين في الأعلى:
</p>

<ul>
<li>
		حجم صورة GIF هو 21.23 كيلوبايت
	</li>
	<li>
		حجم صورة SVG هو 0.355 كيلوبايت
	</li>
</ul>
<p>
	هذا ليس فرقًا بسيطًا. ولكننا نعلم جميعًا أنه يمكننا تحسين صورنا. لذلك دعونا نفعل ذلك.
</p>

<p>
	يؤدي تحسين SVG باستخدام واجهة المستخدم الرسومية SVGO بالسحب والإفلات إلى تقليل حجم ملف الـ SVG إلى 0.249 كيلوبايت.
</p>

<p>
	لتحسين صورة الـ GIF، يمكنك استخدام واحدة من العديد من أدوات تحسين GIF عبر الإنترنت. لقد استخدمت <a href="https://ezgif.com/" rel="external nofollow">ezgif.com</a> لتحسين الصورة أعلاه. (توجد أدوات أخرى أيضًا؛ مثل <a href="http://www.lcdf.org/gifsicle/" rel="external nofollow">gifsicle</a>.) انخفض حجم الملف إلى 19.91 كيلوبايت.
</p>

<p>
	هناك العديد من الخيارات التي يمكنك الاختيار من بينها عند تحسين صور GIF. قمت بتحسين الصورة أعلاه بحيث يبقى عدد الإطارات نفسه، باستخدام ضغط Lossy GIF، الذي "يمكن أن يقلل من حجم ملف GIF المتحرك بنسبة 30 ٪ - 50 ٪ بتكلفة بعض التدرج / التشويش".
</p>

<p>
	يمكنك أيضًا تحسينها عن طريق إزالة كل إطار ذو الرقم n؛ مما يمكن أن يقلل من حجم الملف إلى أبعد حد، ولكن على حساب حركة الصورة التي لم تعد سلسةً بعد الآن. وفي حالة الصور المتحركة مثل الحالة المدروسة الآن، فإن إزالة الإطارات سيجعل التغيير في اللون "سريعًا" وملاحظًا.
</p>

<p>
	تتوفر أيضًا خيارات أخرى للتحسين مثل تقليل الألوان (الذي لن يكون مناسبًا للصور المتحركة المعتمدة على الألوان هنا) وخفض الشفافية. يمكنك معرفة المزيد حول هذه الخيارات في صفحة التحسين في موقع <a href="https://ezgif.com/" rel="external nofollow">ezgif.com</a>.
</p>

<p>
	للتلخيص: إذا كنت أردت أن تكون صورك الـ GIF المتحركة سلسةً، ستحتاج إلى المزيد من الإطارات في الثانية، وسيؤدي ذلك بالتالي إلى زيادة حجم الملف كثيرًا. بينما مع SVG، من المحتمل أن تحتفظ بحجم ملف أصغر بكثير. المثال أعلاه صغيرٌ، وأنا متأكد من وجود أمثلة أفضل، ولكني أردت أن يوضح المثال البسيط الفرق بين الصيغتين.
</p>

<p>
	حتى إذا كنت تحرّك المستطيل أعلاه باستخدام جافاسكربت أو حتى إطار عمل جافاسكربت — نظرًا لأن الصور المتحركة SVG لا تعمل في متصفح IE، مثلًا، من المحتمل أن يكون حجم ملف إطار العمل المقترن بحجم SVG أصغر أو يساوي على الأقل حجم صورة GIF. مثلًا، باستخدام <a href="https://greensock.com/" rel="external nofollow">GreenSock’s TweenLite</a>، سيكون حجم SVG مع المكتبة المدمجة أقل من 13 كيلو بايت (والذي لا يزال أقل من حجم GIF)، إذ انّ حجم TweenLite المصغر هو 12 كيلو بايت. إذا انتهى بك الأمر إلى حجمٍ مساوٍ لحجم GIF، فإن الفوائد الأخرى لـ SVG ستزيد من الحجم وستحصل على المزيد منه.
</p>

<p>
	توجد بعض مكتبات جافاسكربت الأخرى التي تركز على مهام حركة معينة في وقت واحد، وتأتي بأحجام ملفات صغيرة بشكلٍ ممتاز (أصغر من 5 كيلوبايت)، مثل <a href="https://github.com/lmgonzalves/segment/blob/gh-pages/dist/segment.min.js" rel="external nofollow">Segment</a> التي تستخدم لتحريك مسارات SVG لإنشاء تأثيرات رسم خطية. حجم Segment المصغر هو 2.72 كيلو بايت. هذا ليس سيئًا للغاية، أليس كذلك؟
</p>

<p>
	يمكن أن يكون هناك استثناءات، لذلك يجب عليك دائمًا الاختبار. ولكن بالنظر إلى طبيعة صور GIF وكيفية عملها، فمن المحتمل أن تجد أن SVG يُعدُّ خيارًا أفضل في معظم الحالات.
</p>

<p>
	ملاحظة: أداء SVG ليس في أفضل حالاته اليوم، ولكن نأمل أن يتغير هذا في المستقبل. توفر متصفحات IE/MS Edge أفضل أداء لعرض SVG بين جميع المتصفحات اليوم. على الرغم من ذلك، ستظل صور SVG المتحركة تبدو أفضل من صور GIF المتحركة، خاصةً عند التعامل مع الصور ذات الحركة الطويلة، لأنّ حجم ملف GIF - بافتراض تسجيلها بمعدل 60 إطارًا في الثانية - سيكون له تأثيرًا سلبيًا على الأداء العام للصفحة. تقدم المكتبات مثل GreenSock أداءً رائعًا أيضًا.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				- صور GIF أكبر حجمًا عمومًا من صور SVG. حركة الصورة الأكثر تعقيدًا والأطول مدةً، تتطلّب عدد إطارات أكبر لإنشائها ولهذا يكون حجم الملف أكبر ويؤثر سلبًا على الأداء - ما لم تعمل حركة الصورة بمعدل 60 إطارًا في الثانية، فإنّ الحركة ستصبح مسننة وغير سلسة. أيضًا زيادة عدد الإطارات في الثانية سيؤدي إلى زيادة حجم الملف خاصةً للحركات الطويلة نتيجة: سيكون هناك حل بسيط يجب القيام به. إمّا أن تكون حركة صورة GIF ناعمة وسيتأثر الأداء وحجم الملف الكلي وحجم الصفحة بشكلٍ سلبي، أو ستعاني الصورة المتحركة GIF من إطارات أقل. سيتم المخاطرة بأحد أشكال الأداء في كلا الحالتين
			</td>
			<td>
				تستفيد صور SVG من تحسينات المتصفح عند تحريك العناصر. على الرغم من أنّ أداء المتصفح على عناصر SVG لا تزال في أفضل حالاتها، إلا أنّ الصور المتحركة ستبقى تعمل بشكلٍ جيد بدون الحاجة لتقديم تنازلات في أداء الصفحة لا يزال حجم ملف SVG معقولًا جدًا، إن لم يكن صغيرًا جدًا، مقارنةً بـ GIF، حتى عندما قد نحتاج إلى مكتبات معينة للصور المتحركة لإنشاء صور متحركة عابرة للمتصفحات
			</td>
		</tr>
</tbody></table>
<h2>
	إصلاح وتعديل الصور المتحركة
</h2>

<p>
	إنّه من المحزن أن تستخدم صور GIF. ستحتاج إلى استخدام محرر رسومات مثل Photoshop أو Illustrator أو After Effects، على سبيل المثال لا الحصر. وإذا كنت مثلي، فلن يكون محرر الرسومات المكان الذي تصقل فيه مهاراتك، وستشعر أكثر أنّك في مكانك الصحيح أكثر عند إجراء تعديلات في الشيفرة، وليس في برامج تحرير الرسومات.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32855" href="https://academy.hsoub.com/uploads/monthly_2019_11/pic06.png.6a39cf433913d433cddee9d19bc14c83.png" rel=""><img alt="pic06.png" class="ipsImage ipsImage_thumbnailed" data-fileid="32855" data-unique="0ugacpmiu" src="https://academy.hsoub.com/uploads/monthly_2019_11/pic06.thumb.png.a23b935ab0123a48019cfdca761d57a7.png"></a>
</p>

<p>
	ما الذي يحدث إذا كنت ترغب في تغيير توقيت صورتك المتحركة؟ أو إذا كنت تريد تغيير وظائف التوقيت لعنصرٍ واحدٍ أو عدة عناصر داخل صورتك؟ أو إذا كنت ترغب في تغيير الاتجاه الذي يتحرك فيه عنصرٍ ما؟ ماذا لو كنت تريد تغيير التأثير بالكامل وجعل العناصر في صورتك تفعل شيئًا مختلفًا تمامًا؟
</p>

<p>
	ستحتاج إلى إعادة إنشاء الصورة أو الأيقونة مرةً أخرى. يتطلب منك أي تغيير الانتقال إلى محرر الرسومات والعمل مع الإطارات وواجهة المستخدم المعتمدة على الإطار. سيكون ذلك بمثابة تعذيب للمطورين، ومهمةً مستحيلةً لأولئك الذين لا يعرفون طريقتنا بالتعامل مع هذه المحررات بشكلٍ كافٍ لإجراء هذه التغييرات.
</p>

<p>
	مع SVG، فإن إجراء أي نوع من التغيير على الصورة المتحركة (الصور المتحركة) لا يُعدُّ سوى بضعة أسطر من الشيفرة.
</p>

<h3>
	نتيجة (من وجهة نظر المطور)
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				إصلاح وتعديل الصور المتحركة GIF يتطلّب إعادة إنشاء الصورة أو اللجوء إلى واجهة المستخدم في محرر الرسومات المعتمد على الإطارات للقيام بذلك، ويعدّ هذا مشكلة للمطورين في مواجهة التصميم
			</td>
			<td>
				عادةً، يمكن أن تتغير صور SVG ويتم التحكم بها بشكلٍ صحيح داخل شيفرة SVG - أو في أي مكان تم تعريف الصور المتحركة به، باستخدام عدة سطور من الشيفرة.
			</td>
		</tr>
</tbody></table>
<h2>
	حجم الملف، ووقت تحميل الصفحة والأداء
</h2>

<p>
	في القسم السابق، ركزنا على أداء الصور المتحركة نفسها. في هذا المثال، أريد إلقاء بعض الضوء على أداء الصفحة ككل وكيفية تأثرها باختيار صيغة الصورة الذي تقوم به.
</p>

<p>
	في الحقيقة: كلما زاد حجم الملف، زاد التأثير السلبي على وقت تحميل الصفحة والأداء. بأخذ ذلك بالحسبان، لنرى كيف يمكن أن يساعد استخدام SVG بدلاً من GIF في تحسين إجمالي وقت تحميل الصفحة من خلال النظر إلى مثالٍ أكثر واقعيةٍ وعمليةٍ.
</p>

<p>
	في حديثي الأول عن SVG، منذ 18 شهرًا، ذكرت كيف يمكن استخدام SVG لاستبدال صور GIF المتحركة وكيف تؤدي إلى تحسين أداء الصفحة بشكلٍ عام. في ذلك الحديث، قدمت مثالًا واقعيًا لصفحة ويب واقعية استفادت مما توفره SVG وحصلت على الفوائد: الصفحة الرئيسية لـ <a href="sprout.is" rel="">Sprout</a>.
</p>

<p>
	تحتوي صفحة الرئيسية لـ Sprout على صورتين متحركتين تم إنشاؤهما في البداية وعرضهما بشكل صور GIF. قبل عامين، كتب <a href="https://twitter.com/mfortress" rel="external nofollow">Mike Fortress</a> <a href="oak.is/thinking/animated-svgs/" rel="">مقالًا في مدونة Oak</a>، يوضح فيه كيف قاموا بإعادة إنشاء صور GIF متحركة، خاصةً مخطط GIF (انظر الصورة أدناه) كصورة SVG متحركة.
</p>

<div style="text-align: center;">
	<svg enable-background="new 0 0 450 279" height="279px" version="1.1" viewbox="0 0 450 279" width="450px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g id="Layer_1"><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="9" x2="81" y1="208.092" y2="217.046"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="217" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="217" values="217;244;244;208;208;217;217"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="172" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="172" values="172;235;235;217;217;172;172"></animate></line><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="81" x2="153" y1="217.046" y2="143.885"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="172" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="172" values="172;235;235;217;217;172;172"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="153" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="153" values="153;99;99;144;144;153;153"></animate></line><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="153" x2="225" y1="143.885" y2="107.885"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="153" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="153" values="153;99;99;144;144;153;153"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="145" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="145" values="145;63;63;108;108;145;145"></animate></line><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="225" x2="297" y1="107.885" y2="62.954"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="145" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="145" values="145;63;63;108;108;145;145"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="55" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="55" values="55;45;45;63;63;55;55"></animate></line><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="297" x2="369" y1="62.954" y2="98.9081"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="55" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="55" values="55;45;45;63;63;55;55"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="72" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="72" values="72;63;63;99;99;72;72"></animate></line><line fill="none" opacity=".65" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6" x1="369" x2="441" y1="98.9081" y2="53.954"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="72" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="72" values="72;63;63;99;99;72;72"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="45" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="45" values="45;36;36;54;54;45;45"></animate></line><circle cx="9" cy="208.092" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="217" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="217" values="217;244;244;208;208;217;217"></animate></circle><circle cx="81" cy="217.046" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="172" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="172" values="172;235;235;217;217;172;172"></animate></circle><circle cx="153" cy="143.885" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="153" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="153" values="153;99;99;144;144;153;153"></animate></circle><circle cx="225" cy="107.885" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="145" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="145" values="145;63;63;108;108;145;145"></animate></circle><circle cx="297" cy="62.954" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="55" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="55" values="55;45;45;63;63;55;55"></animate></circle><circle cx="369" cy="98.9081" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="72" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="72" values="72;63;63;99;99;72;72"></animate></circle><circle cx="441" cy="53.954" fill="#FFFFFF" r="6" stroke="#6C54C9" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="45" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="45" values="45;36;36;54;54;45;45"></animate></circle></g><g id="Layer_2"><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="9" x2="81" y1="189.951" y2="189.928"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="181" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="181" values="181;171;171;190;190;181;181"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="208" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="208" values="208;162;162;190;190;208;208"></animate></line><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="81" x2="153" y1="189.928" y2="90.069"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="208" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="208" values="208;162;162;190;190;208;208"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="127" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="127" values="127;117;117;90;90;127;127"></animate></line><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="153" x2="225" y1="90.069" y2="144.954"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="127" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="127" values="127;117;117;90;90;127;127"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="82" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="82" values="82;127;127;145;145;82;82"></animate></line><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="225" x2="297" y1="144.954" y2="126.951"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="82" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="82" values="82;127;127;145;145;82;82"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="118" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="118" values="118;108;108;127;127;118;118"></animate></line><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="297" x2="369" y1="126.951" y2="35.977"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="118" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="118" values="118;108;108;127;127;118;118"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="45" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="45" values="45;27;27;36;36;45;45"></animate></line><line fill="none" opacity=".65" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6" x1="369" x2="441" y1="35.977" y2="17.9847"><animate attributename="y1" begin="0s" calcmode="spline" dur="4s" from="45" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="45" values="45;27;27;36;36;45;45"></animate><animate attributename="y2" begin="0s" calcmode="spline" dur="4s" from="36" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="36" values="36;12;12;18;18;36;36"></animate></line><circle cx="9" cy="189.951" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="181" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="181" values="181;171;171;190;190;181;181"></animate></circle><circle cx="81" cy="189.928" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="208" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="208" values="208;162;162;190;190;208;208"></animate></circle><circle cx="153" cy="90.069" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="127" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="127" values="127;117;117;90;90;127;127"></animate></circle><circle cx="225" cy="144.954" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="82" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="82" values="82;127;127;145;145;82;82"></animate></circle><circle cx="297" cy="126.951" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="118" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="118" values="118;108;108;127;127;118;118"></animate></circle><circle cx="369" cy="35.977" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="45" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="45" values="45;27;27;36;36;45;45"></animate></circle><circle cx="441" cy="17.9847" fill="#FFFFFF" r="6" stroke="#B450FF" stroke-miterlimit="10" stroke-width="6"><animate attributename="cy" begin="0s" calcmode="spline" dur="4s" from="36" keysplines="0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1; 0.1 0.8 0.2 1" keytimes="0;0.22;0.33;0.55;0.66;0.88;1" repeatcount="indefinite" to="36" values="36;12;12;18;18;36;36"></animate></circle></g></svg>
</div>

<p>
	يشارك Mike في مقالته بعض الأفكار المثيرة للاهتمام حول أدائهم الجديد للصفحة كنتيجةٍ للتغيير إلى SVG:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		هذا المخطط، والصور المتحركة الأخرى على Sprout، كانت في البداية صور GIF. باستخدام صور SVG المتحركة بدلاً من GIF، تمكنّا من تقليل حجم صفحتنا من 1.6 ميغابايت إلى 389 كيلو بايت، وتقليل وقت تحميل صفحتنا من 8.75 ثانية إلى 412 مللي ثانية. وهذا فرقٌ كبير. — Mike Fortress، <a href="https://oak.is/thinking/animated-svgs/" rel="external nofollow">صور SVG متحركة: سهولة التخصيص والتوقيت</a>
	</p>
</blockquote>

<p>
	إنّه بالفعل فرقٌ كبيرً.
</p>

<p>
	مخطط Sprout هو المرشّح المثالي لـ SVG. لا يوجد سبب لتحريكها عن طريق تحويل الصور المتحركة إلى تسجيل GIF، عندما يمكن لـ SVG أن تحقق الكثير من الفوائد.
</p>

<p>
	يدرك Jake Archibald قوة صور SVG المتحركة أيضًا ، ويستخدمها لإنشاء الرسوم التوضيحية التفاعلية وتحريكها لاستكمال مقالاته. مقاله كتاب الطبخ دون اتصال يعتبر مثالًا ممتازًا (وبالمناسبة مقالًا ممتازًا). هل كان بإمكانه استخدام صور GIF للقيام بذلك؟ بالتأكيد. ولكن بالنظر إلى عدد الصور التي استخدمها، كان من الممكن أن تزيد صور GIF بسهولة الحجم الكلي للصفحة إلى 2 ميغابايت أو أكثر، بحيث يكون حجم كل GIF على الأقل مئات الكيلوبايت؛ في حين أن صفحة الويب بأكملها تبلغ حاليًا 128 كيلو بايت فقط مع جميع صور SVG المضمنة داخليًا، لأنّه يمكنك إعادة استخدام العناصر في SVG، لذا فإن أيّة عناصر متكررة لن تتسبب فقط في أن الصفحة بأكملها ستستعمل برنامج gzip كثيرًا، ولكن لكل صفحة سيصبح الحجم الكلي لصور SVG أصغر.
</p>

<p>
	الآن هذا رائع!
</p>

<p>
	سأبقي حالتي حول تحميل الصفحة والأداء هنا. ولكن لا يزال من المهم الإشارة إلى أنّه يمكن أن يكون هناك استثناءات. مرةً أخرى، في معظم الحالات، من المحتمل أن تجد أن SVG أفضل من GIF، لكنك ستحتاج دائمًا إلى الاختبار على أي حال.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				صور GIF أكبر حجمًا بشكلٍ عامٍ من صور SVG مع الحركات المضافة لهم. وهذا يؤثر سلبًا على حجم الصفحة الكلّي ووقت التحميل والأداء.
			</td>
			<td>
				يمكن أن تُستعمل صور SVG وأن يُعاد استخدامها، مما يجعل حجم الملف أصغر عمومًا من GIF وهذا يحسّن من وقت تحميل الصفحة والأداء
			</td>
		</tr>
</tbody></table>
<h2>
	دعم المتصفح
</h2>

<p>
	ربما تكون الميزة الوحيدة المتفوقة لصور GIF على صور SVG هي دعم المتصفح. تعمل صور GIF إلى حدٍ كبير في كل مكان، في حين أن دعم SVG أقل انتشارًا. على الرغم من أن لدينا العديد من الطرق لتوفير <a href="https://css-tricks.com/a-complete-guide-to-svg-fallbacks/" rel="external nofollow">النسخ الاحتياطية للمتصفحات غير الداعمة</a> - ويجب ألا يعوق دعم المتصفح الحالي أي شخص عن استخدام SVG، إنّ الصور الاحتياطية، إذا تم توفيرها كـ PNG أو JPG، ستكون ثابتة وبدون حركة.
</p>

<p>
	بالطبع ، يمكنك دائمًا تقديم GIF كخطوة احتياطية لـ SVG، ولكن يجب مراعاة الاعتبارات والعيوب المذكورة سابقًا.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				تعمل صور GIF تقريبًا في كل مكان
			</td>
			<td>
				صور SVG يدعمها عدد أقل من المتصفحات، لكنها تأتي مع طرق كثيرة لتوفير صور احتياطية للمتصفحات التي لا تدعمها
			</td>
		</tr>
</tbody></table>
<h2>
	مخاوف سهولة الوصول (a11y#)
</h2>

<p>
	انقل شيئًا ما إلى صفحة، أو أيّ مكان، لهذه القضية، لقد أضفت للتو تسليةً - شيءٌ ما من المؤكد أنّه سيجذب انتباه المستخدم بمجرد أن يبدأ التحرك. هكذا يعمل الدماغ البشري ببساطة. يعدُّ هذا أيضًا أحد الأسباب التي تركز عليها لافتات الإعلانات - وهي مبنية على - تركيزٍ قوي على الصور المتحركة. وهذا هو السبب في أنّ لافتات الإعلانات المتحركة مزعجةٌ للغاية. إنها تشتت الانتباه، خاصةً عندما تحاول أداء مهمة على صفحة تتطلب اهتمامك بالكامل، مثل قراءة مقال.
</p>

<p>
	تخيّل الآن صفحة بها مجموعة من الأيقونات المتحركة (أو الصور) التي لن تتوقف عن الحركة بغض النظر عما تفعله. لم نعد نتحدث عن صورة أو صورتين على الصفحة الرئيسية أو داخل مقالة هنا؛ نحن نتحدث عن متحكمات وعناصر واجهة المستخدم، والأيقونات الأصغر التي من المحتمل أن تكون موجودة في أماكن متعددة على الصفحة، وعلى صفحات متعددة. ما لم يكن من المفترض أن تكون الأيقونة عبارة عن رسوم متحركة بشكلٍ غير محدود - مثلًا، إذا كانت عبارة عن دوران متحرك أثناء مرحلة انتظار غير نشطة للمستخدم، فمن المحتمل أن تسبب مشكلة، وتصبح مصدر إزعاجٍ أكثر من كونها "شيئًا جميلًا".
</p>

<p>
	في الواقع، يمكن أن يصبح الأمر أكثر إزعاجًا لبعض الناس، لأن الحركة المستمرة يمكن أن تجعل بعض الناس حرفيًا يشعرون بالمرض.
</p>

<p>
	تناقش المصممة ومستشارة صور الويب المتحركة Val Head في مقالتها <a href="https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/" rel="external nofollow">"تصميم رسوم متحركة للويب أكثر أمانًا من أجل حساسية الحركة"</a> تأثيرات الصور المتحركة المفرطة الاستخدام في الويب على الأشخاص الذين يعانون من اضطرابات الدهليزية المتسببة بصريًا (منجم التركيز):
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p>
		لا يخفى على أحد أن الكثير من الناس يفكرون في تأثيرات التمرير السريع واختلاف المظهر (parallax) المزعجة والمفرطة في الاستخدام. ولكن ماذا لو كانت الحركة تفعل أكثر من مجرد إزعاجك؟ ماذا لو كانت تجعلك مريضًا أيضًا؟
	</p>

	<p>
		هذه حقيقة يجب أن يتعامل معها الأشخاص الذين يعانون من الاضطرابات الدهليزية المتسببة بصريًا. مع تزايد استخدام الواجهات المتحركة، أصبح المزيد من الناس يلاحظون أنّ الحركة واسعة النطاق على الشاشة يمكن أن تسبب لهم دوارًا أو غثيانًا أو صداعًا أو ما هو أسوأ. بالنسبة للبعض، يمكن أن تستمر الأعراض لفترةٍ طويلةٍ بعد انتهاء الرسوم المتحركة. تضاعفات.
	</p>
</blockquote>

<p>
	تخيّل الآن ما إذا كانت الصور المتحركة لا تنتهي … مضاعفات مزدوجة.
</p>

<p>
	تشرح مقالة Val المشكلة بمزيدٍ من التفصيل، حيث تجمع ردود فعل من شخصين يواجهان هذه المشاكل بالفعل ويشاركان تجربتهما مع الصور المتحركة بأمثلةٍ مختلفةٍ.
</p>

<p>
	أحد الحلول التي يمكن أن تساعد في تجنب هذه المشاكل هو <a href="https://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/#section10" rel="external nofollow">تزويد المستخدم بالقدرة على التحكم في الصور المتحركة</a> حتى يتمكنوا من إيقافها عندما تصبح مزعجةً.
</p>

<p>
	يمكنك القيام بذلك باستخدام SVG. يمكنك التحكم بشكلٍ كاملٍ في الصور المتحركة وتشغيلها مرةً واحدة أو مرتين عند تحميل الصفحة - إذا كنت تحتاج حقًا إلى تشغيلها بمجرد قيام المستخدم "بالدخول" إلى صفحتك، ثم إظهارها عند تمرير مؤشر الفأرة لمرات متتالية، باستخدام سطورٍ قليلةٍ من الـ CSS أو جافاسكربت. لا تحتاج إلى المئات أو الآلاف من أسطر CSS أو جافاسكربت لإنشاء صورةٍ متحركةٍ للأيقونة، إلا إذا كانت أيقونتك مشهدًا معقدًا بالفعل فيها الكثير من المكونات المتحركة. لكنني أعتقد أنّه في هذه الحالة، لم تعد تمثل "أيقونةً" بعد الآن، وأنّها أصبحت عبارةً عن صورةٍ عاديةٍ أكثر.
</p>

<p>
	يمكنك الوصول إلى أقصى قدر من التحكم في إعادة التشغيل، والسرعة لكل تشغيلٍ لاحقٍ، وأكثر من ذلك بكثير، بفرض، بالطبع، أنّك تستخدم جافاسكربت للحصول على هذا المستوى من التحكم.
</p>

<p>
	أو يمكنك إضافة تبديل لمنح المستخدم القدرة على إيقاف تشغيل الصور المتحركة بلا حدود. لا يمكنك فعل ذلك باستخدام GIF … إلا إذا اخترت استبدال GIF بصورة ثابتة عند إجراء تبديلٍ معينٍ.
</p>

<p>
	قد يجادل البعض بأنّه يمكنك عرض نسخة ثابتة من الصورة – مثل صورة PNG مثلًا، ثم توفير إصدار GIF عند تمرير مؤشر الفأرة. ولكن هذا يسبب بعض المشاكل:
</p>

<ul>
<li>
		إذا كانت الصورَ مضمنةٌ، فستحتاج إلى استبدال هذه الصور باستخدام جافاسكربت. هذا الإجراء لا يتطلب أي جافا سكربت إذا كنت تستخدم SVG.
	</li>
	<li>
		إذا كانت الصور عبارة عن صور أمامية (مضمنة في HTML باستخدام <code>&lt;img&gt;</code>)، وتحتاج إلى استبدال هذه الصور، فسينتهي بك الأمر إلى مضاعفة كمية طلبات HTTP لكلّ صورة. وإذا كانت صور الخلفية مضمنة في صفحة الأنماط (هذا غير مستحسن)، فإنّ الصور (خاصةً صور GIF) ستزيد حجم صفحة الأنماط وبالتالي تزيد الوقت الإجمالي لحظر عرض الصفحة.
	</li>
	<li>
		إذا كنت تبدّل/ عندما تبدّل مصادر الصورة عند تمرير مؤشر الفأرة، فهناك وميض ملحوظ بين الصورة الأولى والثانية في الاتصالات البطيئة. اتصالي بطيء؛ أحيانًا اتصال 3G بطيء، ولم أتذكر بعد وقتًا تم فيه استبدال صورة بأخرى عند تمرير مؤشر الفأرة، أو تم تغيير حجم منفذ العرض، أو أي شيء آخر، ولم أشاهد هذا الوميض. يزداد هذا الموقف سوءًا عندما تكون الصورة الثانية (GIF التي تحمّل عند تمرير مؤشر الفأرة) كبيرة الحجم إلى حدٍ ما — سيكون هناك وميض، تتبعه صورةً متحركةٌ بطيئةٌ غير متقنةٍ لـ GIF أثناء تحميلها بالكامل. هذا ليس جذابًا أبدًا.
	</li>
</ul>
<p>
	لذا، نعم، يمكنك تبديل مصادر الصورة للتحكم إذا أو عندما تشتغل الصور المتحركة GIF أو متى يتم ذلك، لكنك تفقد التحكم الدقيق في GIF وتؤثر على تجربة المستخدم مع واجهة المستخدم.
</p>

<p>
	يمكنك أيضًا التحكم في عدد المرات التي يتم فيها تشغيل الصور المتحركة في GIF - وهو أمرٌ رائعٌ، لكن هذا يعني أن الصور المتحركة ستعمل فقط عددًا محددًا من المرات. ثم لإعادة تشغيل الصور المتحركة عند تفاعل المستخدم، ستحتاج إلى اللجوء إلى الأسلوب أعلاه مع صور متعددة.
</p>

<p>
	يمكن تحقيق الصور المتعددة التي تحتاج إلى إصلاح، وطلبات HTTP المتعددة، والحل العام المُستهلَك غير الأمثل بصورة SVG واحدة.
</p>

<ul>
<li>
		ضمّن صورة SVG واحدة على الصفحة.
	</li>
	<li>
		أنشئ الصورة المتحركة بالطريقة التي تريدها/تحتاجها. (أو أنشئ الحركة قبل تضمين الصورة.)
	</li>
	<li>
		شغّل وأوقف وتحكّم بالصورة المتحركة. وأمنح المستخدم القدرة على التحكم فيها أيضًا.
	</li>
</ul>
<p>
	لا توجد طلبات HTTP إضافية لكل صورة، ولا صيانة معقدة للخط الزمني للصورة المتحركة في محرر الرسومات، ولا توجد أي مخاوف تتعلق بسهولة الوصول أو مشاكل لا يمكن تجنبها ببضعة سطور من التعليمات البرمجية.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				صور GIF لا يمكن إيقافها من قبل المستخدم بدون طلب صور إضافية وطلبات HTTP إضافية. لا تتم السيطرة بشكلٍ كاملٍ حتى يتم ذلك
			</td>
			<td>
				يمكن تخصيص صور SVG المتحركة بشكلٍ كامل لذا يمكن تفعيلهم وتعطيلهم والتحكم بهم من قبل المستخدم بدون الحاجة إلى طرق مستهلَكة
			</td>
		</tr>
</tbody></table>
<h2>
	سهولة الوصول إلى المحتوى
</h2>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				صور GIF سهلة الوصول مثل صور PNG وJPEG باستخدام قيمة الخاصية `alt` لوصفهم. لا يمكن تمييز المحتوى الموجود داخل الصورة أو إتاحته مباشرةً لقارئات الشاشة بما يتجاوز الوصف العام للصورة
			</td>
			<td>
				يمكن الوصول إلى صور SVG ودلالتها. يمكن أيضًا وصف المحتوى المتحرك داخل الصورة وجعله قابلًا للقراءة من قِبل قارئات الشاشة باستخدام عناصر سهولة الوصول المدمجة في SVG، كما يمكن تحسينها باستخدام أدوار ARIA وخاصيّاتها أيضًا. (يمكنك أن تقرأ [هنا](https://www.sitepoint.com/tips-accessible-svg/) كل شيء عن جعل SVG قابلة للوصول)
			</td>
		</tr>
</tbody></table>
<h2>
	التفاعل
</h2>

<p>
	لا يوجد الكثير لإضافته هنا، ولكن الحقيقة أنّه يمكنك التفاعل مع العناصر الفردية داخل SVG، أثناء أو قبل أو بعد تحريك الصورة، لكن هذا غير ممكن مع GIF. لذا، إذا كنت تستخدم GIF، فستفقد القدرة على فعل أي شيء يتجاوز تشغيل الصور المتحركة أو إيقافها، وحتى هذا لم يتم تنفيذه فعلاً باستخدام الـ SVG، كما رأينا، ولكن يتم تحقيق ذلك عن طريق مبادلة GIF بالخارج ببديلٍ ثابت. حتى تغيير ألوان العناصر داخل GIF سيتطلب صورًا إضافية للقيام بذلك. هذه ميزة أخرى لاستخدام SVG بدلاً من GIF.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				لا يمكن أن تكون الحركات المحددة في صور GIF تفاعلية، لا يمكنك التفاعل مع العناصر الفردية داخل عنصر GIF، ولا يمكنك إنشاء روابط خارج العناصر الفردية أيضًا.
			</td>
			<td>
				محتوى SVG تفاعلي بالكامل. يمكنك إنشاء التفاعلات مثل تمرير ماوس الفأرة والضغط (والمزيد) التي تستجيب لها العناصر الفردية داخل صورة SVG.
			</td>
		</tr>
</tbody></table>
<h2>
	استجابة وتكيّف الصور المتحركة
</h2>

<p>
	إنّ القدرة على تحريك صورة SVG مباشرةً من الشيفرة، بالإضافة إلى معالجة العديد من خاصياتها، تعطي وتضيف ميزةً أخرى على الصور المتحركة المعتمدة على GIF: القدرة على إنشاء صور متحركة جيدة الأداء، سريعة الاستجابة وقابلة للتكيّف، دون إضافة أي طلبات HTTP إضافية باستخدام بضعة أسطر من الشيفرة وبأحجام ملفات أصغر.
</p>

<p>
	كتبت سارة دراسنر <a href="www.smashingmagazine.com/2015/03/different-ways-to-use-svg-sprites-in-animation/" rel="">مقالةً في مجلة Smashing Magazine</a> تُظهر طرقًا مختلفة لتحريك SVG sprites. تتمثل إحدى هذه الطرق في وجود "مشاهد" متعددة داخل الـ SVG، وتحريكها باستخدام CSS، ثم تغيير "عرض" الـ SVG - عن طريق تغيير قيمة خاصية الـ viewBox - لإظهار مشهدٍ واحدٍ في وقتٍ واحدٍ، اعتمادًا على حجم منفذ العرض الحالي ومساحة الشاشة المتاحة.
</p>

<p>
	إذا كنت ترغب في إنشاء نفس الحركات باستخدام صور GIF، فستفقد إمكانيات التحكم في الصور المتحركة، كما ستحتاج إلى صور متعددة ربما تكون أكبر (في حجم الملف) من صورة الـ SVG الواحدة.
</p>

<p>
	ولكن إذا كنت لا ترغب في استخدام شيفرة SVG المتحركة، فيمكنك دائمًا إنشاء SVG sprite وتحريكه بالطريقة التي يمكنك بها تحريك أي صيغة صورة آخرى - باستخدام <code>()steps</code> وعدة أسطر CSS. تتحدث سارة أيضًا عن هذه التقنية في مقالتها. لا يحتاج تحريك صور SVG أن يكون معقدًا، وهو يقدم أداءً أفضل بشكلٍ عام.
</p>

<h3>
	نتيجة
</h3>

<table><tbody>
<tr>
<td>
				<strong>صورة GIF</strong>
			</td>
			<td>
				<strong>صورة SVG متحركة</strong>
			</td>
		</tr>
<tr>
<td>
				بما أنّه لا يمكن التحكم بالمحتوى داخل صورة GIF بالشيفرة، فلا يمكن جعل الصور المتحركة تتكيف أو تستجيب لتغيّرات منفذ العرض أو السياق بدون اللجوء إلى فصل الصور.
			</td>
			<td>
				بما أنّه يمكن تحريك محتوى SVG بشكلٍ مباشر باستخدام الشيفرة، فإنّه يمكن تعديل المحتوى والحركات بحيث يستجيب و/أو يتكيّف مع سياقات وأحجام منافذ عرض مختلفة، بدون الحاجة إلى اللجوء إلى أي أصول إضافية.
			</td>
		</tr>
</tbody></table>
<h2>
	كلمات أخيرة
</h2>

<p>
	تتمتع صور GIF بدعم جيد جدًا للمتصفح، نعم، ولكن مزايا صور SVG تفوق مزاياها في جميع الجوانب تقريبًا. قد تكون هناك استثناءات، وفي هذه الحالات، تستخدم صور GIF بالتأكيد أو أي صيغة صور آخرى تقدم عملًا أفضل من SVG. قد تستخدم حتى فيديو أو HTML5 Canvas أو أيًا كان.
</p>

<p>
	يمكن أن توفر SVG الكثير من مزايا الأداء إلى القائمة عند موازنتها مع صيغ الصور الأخرى، وخاصةً GIF.
</p>

<p>
	وبالتالي، وبالنظر إلى كل ما سبق، أوصي بأنه في أي مكان يمكن استخدام SVG للصور المتحركة، يجب تجنّب استخدام صور GIF. أنت حر بالطبع في تجاهل توصيتي لكنك ستتخلى عن المزايا الكثيرة التي توفرها صور SVG المتحركة.
</p>

<p>
	ما لم توفر صور GIF الكثير من المزايا على صور SVG التي لا تحقق دعم المتصفح IE8 وأقل منه، فإنني أعتقد أن صور SVG ينبغي أن تكون هي السبيل للانطلاق.
</p>

<p>
	بعض المصادر لمساعدتك على البدء مع صور SVG المتحركة:
</p>

<ul>
<li>
		<a href="http://blogs.adobe.com/dreamweaver/2015/06/the-state-of-svg-animation.html" rel="external nofollow">عالم الصور المتحركة SVG</a>.
	</li>
	<li>
		<a href="https://www.smashingmagazine.com/2015/03/different-ways-to-use-svg-sprites-in-animation/" rel="external nofollow">عدة طرق مختلفة لاستخدام SVG sprites في الصور المتحركة</a>.
	</li>
	<li>
		<a href="https://www.smashingmagazine.com/2015/09/creating-cel-animations-with-svg/" rel="external nofollow">إنشاء الصور المتحركة مع SVG</a>.
	</li>
	<li>
		لدى <a href="greensock.com" rel="">GreenSock</a> مجموعة من المقالات المفيدة حول تحريك SVG.
	</li>
	<li>
		<a href="http://snapsvg.io/start/" rel="external nofollow">Snap.svg</a> ويُعرف أيضًا بأنّه "مكتبة jQuery للـ SVG".
	</li>
	<li>
		<a href="https://davidwalsh.name/svg-animations-snap" rel="external nofollow">الصور المتحركة SVG باستخدام CSS وSnap.SVG</a>.
	</li>
	<li>
		<a href="https://www.smashingmagazine.com/2014/11/styling-and-animating-svgs-with-css/" rel="external nofollow">تصميم وتحريك صور SVG مع CSS</a>.
	</li>
	<li>
		<a href="https://jakearchibald.com/2013/animated-line-drawing-svg/" rel="external nofollow">رسم خط متحرك في SVG</a>.
	</li>
</ul>
<p>
	أرجو أن تكون قد وجدت هذه المقالة مفيدةً. شكرًا للقراءة.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.sarasoueidan.com/blog/svg-vs-gif/" rel="external nofollow">Animated SVG vs GIF [CAGEMATCH]‎</a> لصاحبته Sara Soueidan
</p>

<p>
	 
</p>
]]></description><guid isPermaLink="false">763</guid><pubDate>Tue, 26 Nov 2019 08:06:01 +0000</pubDate></item><item><title>&#x643;&#x64A;&#x641; &#x62A;&#x62A;&#x62C;&#x646;&#x628; &#x643;&#x627;&#x631;&#x62B;&#x629; &#x627;&#x644;&#x627;&#x633;&#x62A;&#x639;&#x627;&#x646;&#x629; &#x628;&#x641;&#x631;&#x64A;&#x642; &#x62E;&#x627;&#x631;&#x62C;&#x64A; &#x641;&#x64A; &#x62A;&#x637;&#x648;&#x64A;&#x631; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x64A;&#x627;&#x62A;</title><link>https://academy.hsoub.com/programming/general/%D9%83%D9%8A%D9%81-%D8%AA%D8%AA%D8%AC%D9%86%D8%A8-%D9%83%D8%A7%D8%B1%D8%AB%D8%A9-%D8%A7%D9%84%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D9%86%D8%A9-%D8%A8%D9%81%D8%B1%D9%8A%D9%82-%D8%AE%D8%A7%D8%B1%D8%AC%D9%8A-%D9%81%D9%8A-%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA-r749/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db014454a871_.jpg.jpg.1b984ec306dd4d01ffa95b438ee30143.jpg" /></p>
<p>
	كلنا نعلم أنّ الاستعانة بفريق خارجي لتطوير البرمجيات هو كارثة على وشك الحدوث. أولًا، تجد شركة تعدك بكل ما ترغب به للمنتج من تسليم في الوقت المحدد، وكلفة ضمن الميزانية، وجودة عالية، وواجهة مستخدم جميلة، وتقنيات متطورة، ودعم طويل الأمد خالٍ من المتاعب، لذا ترسل الدفعة الأولى وتبدأ رحلتك. بالكاد يفهم الفريق احتياجاتك، والجودة سيئة، وتُنتهك كل توقعاتك حول الزمن والميزانية بشدّة، ويرتفع مستوى الإحباط. والجزء "الأفضل" هو أنّه لا يمكنك الابتعاد وإلا ستخسر كل الأموال التي أنفقتها وستضطر أن تبدأ من الصفر. يجب أن تبقى "متزوجًا" من هذا الفريق لأنّه لا يمكنك تحمّل "الطلاق". هل هناك طريقة للاستعانة بفريق خارجي لتطوير البرمجيات بشكلٍ صحيح؟
</p>

<p>
	نعم، من الممكن القيام بذلك بشكلٍ صحيح وخالٍ من المتاعب، ولكن يجب أن تكون مستعدًا لتغيّر فلسفة إدارتك.
</p>

<p>
	المبدأ الأساسي هنا هو:
</p>

<ol>
	<li>
		يجب عليك أن تناقش مخاوفك مع الفريق الخارجي الذي تستعين به بشكلٍ علني ومتكرر، و
	</li>
	<li>
		يجب أن يناقشوا معك المشاكل والمخاطر بشكلٍ علني ومتكرر.
	</li>
</ol>

<p>
	هذان عاملان أساسيان للنجاح في الاستعانة بفريق خارجي ل<a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B7%D9%88%D9%8A%D8%B1-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA/" rel="">تطوير البرمجيات</a> يتم إهمالهما في كثير من الأحيان.
</p>

<p>
	لقد تعلّمت هذا المبدأ من <a href="https://en.wikipedia.org/wiki/Wei_Liaozi" rel="external nofollow">Wei Liao Zi</a>. قال في كتاب <a href="https://www.amazon.com/Military-Strategy-Classics-Ancient-China/dp/1937021033/ref=as_li_ss_tl?s=books&amp;ie=UTF8&amp;qid=1473053807&amp;sr=1-1&amp;keywords=military+strategy+classics&amp;linkCode=sl1&amp;tag=yegor256com-20&amp;linkId=154a4c0f7866c0193b82e0f504b15250" rel="external nofollow">كلاسيكيات الإستراتيجية العسكرية للصين القديمة</a> الصفحة 239:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		عندما تنتقل المعلومات من الأسفل إلى الأعلى، وتنتقل المخاوف من الأعلى إلى الأسفل، فهذا هو الوضع المثالي.
	</p>
</blockquote>

<p>
	دعني أوضّح بعض الأمثلة العملية لكوارث الاستعانة بفريق خارجي لتطوير البرمجيات وشرح كيف يمكن تجنبها باتّباع مبدأ عمره 2500 سنة.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="32141" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db0144765aed_.jpg.jpg.007b7d4051697ec89ce2f8b8516df57e.jpg" rel="" data-fileext="jpg"><img alt="كيف تتجنب كارثة الاستعانة بموارد خارجية.jpg.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32141" data-unique="88s0jr0fd" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db014477aca1_.jpg.thumb.jpg.69d8f0cb02a339035363a0ffc41e4350.jpg"></a>
</p>

<h2>
	يستغرق الأمر إلى الأبد وأنا تجاوزت الميزانية
</h2>

<p>
	دائمًا يكون المنتج جاهزًا بنسبة 95%، ولديك دائمًا شيء ما غير منفَّذ أو معطوب. لقد أنجزوا الكثير من العمل، ودفعت الكثير من المال، ولكن المنتج الجاهز للسوق لم يصل بعد. يستغرق أسبوعًا بعد أسبوع وشهرًا بعد شهر؛ دائمًا هناك أعمال متأخرة، وأنت لا يمكنك إنهاء ذلك ببساطة. لقد بدأت برؤية هذا المشروع في كوابيسك، والفريق لم يعد يساعد بعد ذلك. كيف يبدو هذا؟ مألوفًا؟
</p>

<p>
	أرجو أن تدرك أنّه بغض النظر عن نوع العقد الذي وقّعت عليه مع الفريق الخارجي لتطوير البرمجيات، وعدد الجداول الزمنية التي حددتها، وعدد الوعود التي قطعت لك، يريدون الاحتفاظ بك كعميل إلى الأبد. بالطبع طالما لديك شيء في حسابك المصرفي.
</p>

<p>
	تريد أن ينجح عملك ويزدهر، صحيح؟ إنّهم يريدون نفس ذلك لعملهم. نجاحك يعني منتجًا تم إنهاؤه وإطلاقه للمستخدمين النهائيين. نجاحهم يعني عمليةً لا نهائية من كتابة البرامج لك. هناك القليل جدًا من القواسم المشتركة بين هذين الهدفين. أودّ حتى أن أقول أنّهم متناقضين مع بعضهم بعضًا - عندما تنجح، يفشلون.
</p>

<p>
	سيخبرونك بالطبع أّنهم يريدون إنهاء هذا المنتج لك والحصول على عقود جديدة في المستقبل. سيقولون أنّ الدافع الأساسي هو جعلك سعيدًا والحصول على توصية جيّدة. سيؤكدون لك أنّ رضا العميل أهم من المال، لكن أقترح عليك أن تكون قويّا بما يكفي لتواجه الواقع، كل هذه أكاذيب.
</p>

<p>
	أغلب المشاريع المستعان بها بفريق خارجي لتطوير البرمجيات تفشل. الغالبية العظمى (انظر <a href="https://www.csus.edu/indiv/v/velianitis/161/ChaosReport.pdf" rel="external nofollow">تقرير شاوس</a> الأخير). يدرك مطورو البرمجيات هذا أفضل منك، لأنّهم في معظم الأحيان يشاهدون كيف يحصل هذا كل يوم. ومشروعك ليس استثناءً. لذلك، دعنا ننسى هذه الوعود الجميلة ونركز على الواقع القبيح - اعتمد على نفسك.
</p>

<p>
	بأخذ المبدأ الذي ذكرته في الأعلى بالحسبان، إليك نصيحتي: تأكّد من أنّ الفريق يتفهّم
</p>

<ol>
	<li>
		وقتك الفعلي، وميزانيتك، ومجالك، وقيود مجالك
	</li>
	<li>
		عواقب انتهاكها. يتعلّق هذا بالجزء الأول من المبدأ - يجب عليك أن تناقش مخاوفك بشكلٍ علني ومتكرر -. الذي يحدث عادةً أنّ فريق الخارجي المستعان به يبقى غير مدركًا لوضع العمل الحقيقي ويسمع فقط عبارة "أحتاج إلى هذا في أسرع وقت ممكن" مرّةً كل يومين.
	</li>
</ol>

<p>
	"أسرع وقت ممكن" هو ليس موعدًا نهائيًا. علاوةً على ذلك، إنّه فقط بديل مثبّط للغاية لمرحلة رئيسية حقيقية. عندما لا يعرف الفريق متى تحتاج المنتج بالضبط، ما الذي يجب أن يكون جاهزًا بحلول ذلك التاريخ، ولماذا، فيبدأ العمل ضدك. التركيز هنا على "لماذا". بالنسبة لمعظم أصحاب الأعمال، من الصعب الإجابة على هذا السؤال.
</p>

<p>
	لماذا تحتاج أن يكون المنتج جاهزًا بحلول الأول من حزيران؟ لأنّك سئمت من الانتظار فقط؟ هذه ليست إجابة معقولة. أنت سئمت من ذلك ولكن لا يزال لديك أموالًا في حسابك المصرفي. سيستمرون في إصدار الفواتير لك، ولن يحترمونك. لن يعاملوك كرجل أعمال قوي وموجّه نحو تحقيق الأهداف. إمّا أنّك لست ذكيًا بما يكفي لتحديد القيود الزمنية أو أنّك تخفيها عن الفريق. في كلتا الحالتين لن يقدّروا هذا السلوك.
</p>

<p>
	فيما يلي تحديد قيود الوقت والتكاليف بشكلٍ صحيح:
</p>

<p>
	يجب أن تكون الميزات A و B و D جاهزة قبل الأول من حزيران، لأنّ حملتنا التسويقية تبدأ في الخامس من حزيران. إذا لم يكونوا جاهزين، سأخسر 25000$ من تكاليف التسويق. إذا حدث هذا سأضطر إلى تخفيض ميزانية التطوير الشهرية إلى النصف.
</p>

<p>
	عندما تسمع شركة الاستعانة بفريق خارجي لتطوير البرمجيات، شريكتك، هذا التعريف للموعد النهائي، تصبح شريكًا حقيقيًا لك الآن. الآن أهدافها تتماشى مع أهدافك. إذا تمّ تأخير المرحلة الرئيسية، ستعاني وسيفهمون لماذا بالضبط. إلى جانب ذلك، يرون كيف ستُنقل معاناتك إليهم أيضًا.
</p>

<p>
	توقف عن مطالبتهم بإنهاء كل شيء بأسرع وقت ممكن. توقف عن الاتصال بهم مرتين في اليوم والصراخ لساعة بسبب أدائهم الضعيف. توقف عن استخدام اللغة في رسائل البريد الإلكتروني للعمل. توقف عن القيام بكل هذا الضجيج. إنّه لا يساعدك على أيّ حال. علاوةً على ذلك، لا يؤدي هذا إلا إلى جعل الوضع يزداد سوءًا، لأنّك تفقد احترامك وقد بدأوا في معاملتك كبقرةٍ حلوب - بل بالأحرى شخص غبي وعاطفي.
</p>

<p>
	بدلًا من ذلك، قم بأداء واجبك وحدد مراحلك الرئيسية الواقعية. فكّر بوقتك الحقيقي، ومجالك، وحدود ميزانيتك. دوّنهم بجمل قصيرة ومختصرة جدًا. تأكّد من أنّ قيودك واقعية ووصفها يجيب على السؤال الرئيسي - لماذا -.
</p>

<p>
	لماذا تحتاج هذا بحلول الأول من حزيران؟ لماذا تريد أن تنفق أقل من 50000$؟ لماذا تحتاج أن تكون كل الميزات الخمسة موجودة في النسخة 1.0؟ لماذا تريد لتطبيق الويب الخاص بك أن يكون جاهزًا لمعالجة 1000 جلسة متزامنة؟ لماذا تحتاج إلى تطبيق للهاتف في الإصدار الأول؟
</p>

<p>
	أجب نفسك وتأكّد من أنّ أجوبتك مفهومة من قبل شركة الاستعانة بفريق خارجي. لا تخفي هذه المعلومات.
</p>

<h2>
	المنتج سيء جدًا
</h2>

<p>
	تريد أن يبدو تطبيق الويب الخاص بك مثل Pinterest، يتفاعل سريعًا، ويكون سهل الاستخدام، ويجعلك فخورًا عندما تعرضه على أصدقاءك. لكن المنتج الذي بنوه لك سيء، وبطيء، ولأكون صريحًا، قبيح. تطلب منهم أن يفعلوا شيئًا ما بشأنه، ويستمروا في إعطائك الوعود. يستمر المشروع في استهلاك أموالك وتنمو ميزانيته، لكن المظهر والإحساس لا يتحسّن. إنّه بعيد جدًا عن Pinterest. ينمو الإحباط ولا تشاهد أي طريقة معقولة للخروج من هذا. النصيحة الوحيدة التي تتلقاها من أصدقائك هي أن تعيد تنفيذ كل المشروع من الصفر مع فريق تطوير ويب جديد. كيف يبدو هذا؟ أراهن أنّه مألوفًا.
</p>

<p>
	أعتقد أنّ السبب الرئيسي للطريق المسدود في هذا الموقف هو الخوف من الصراع. تحاول في المراحل الأولى من المشروع أن تفعل كل ما تستطيع للحفاظ على علاقة جيدة مع شركة الاستعانة بفريق خارجي وعدم الإساءة إلى أيّ شخص. لا تريد أن تتحكم في عمل أي شخص لأنّهم قد يعدونها إهانة. لا تريد أن تعبّر عن مخاوفك بشأن الجودة لأنّها قد تثبّط همّة الفريق. أنت فقط تأمل أنّهم سيحسّنون المنتج في المستقبل، لكن عندما يأتي المستقبل، يكون متأخرًا جدًا.
</p>

<p>
	مجددًا، مع أخذ المبدأ القديم بعين الاعتبار، أنصحك بأن تقوم بإجراء روتيني من اليوم الأول للمشروع للتحقق من نتائجهم والتعبير عن مخاوفك. في مشاريعنا في <a href="https://www.zerocracy.com/" rel="external nofollow">Zerocracy</a> نطلب من عملاءنا أن يكونوا موجودين في GitHub، ويراجعوا إصداراتنا بشكلٍ متكرر، ويبلغونا عن أيّة تناقضات موجودة كمشكلات (issues) في GitHub. نشجّع رعاة المشروع أن يكونوا متشائمين وسلبيين بشأن جودتنا منذ بداية المشروع. نحن ندرك أن هذه الطريقة يمكننا بها تقليل خطر "الإحباط المتراكم".
</p>

<p>
	حاول أن تفعل الشيء ذاته في مشروعك الذي تمّ به الاستعانة بفريق خارجي. لا تخف من الإساءة إليهم. النقد التكراري والتدريجي منهجية أكثر صحةً من السلام الخالي من ردود الفعل والذي ينتهي بالحرب. ابحث عن طريقة ليبقى الفريق المستعان على درايةٍ برأيك حول نتائجه بشكلٍ منتظم. لا تحاول أن تكون لطيفًا لتحافظ على مشروعك.أنت تقدّم لنفسك معروفًا سيئًا. بدلًا من ذلك، كن منفتحًا بشأن مخاوفك. تذكر الجزء الأول من المبدأ أعلاه - يجب عليك أن تناقش مخاوفك بشكلٍ علني ومتكرر. هذه هي الطريقة التي سيستقر بها المشروع وتقلّ بها المخاطر.
</p>

<p>
	أيضًا، هناك ممارسة جيّدة جدًا، من وقت لآخر، وهي دعوة المراجعين التقنيين ليعطوا آراءً مستقلة حول المنتج قيد التطوير. اقرأ مشاركتي الأخرى حول هذا الموضوع: <a href="https://academy.hsoub.com/programming/general/%D9%87%D9%84-%D8%AA%D8%AD%D8%AA%D8%A7%D8%AC-%D9%84%D9%85%D8%B1%D8%A7%D8%AC%D8%B9%D8%A7%D8%AA-%D8%AA%D9%82%D9%86%D9%8A%D8%A9-%D9%85%D8%B3%D8%AA%D9%82%D9%84%D8%A9%D8%9F-r736/" rel="">هل تحتاج لمراجعات تقنية مستقلة؟</a>.
</p>

<h2>
	لا يمكنني الاعتماد على وعودهم
</h2>

<p>
	تتصل بهم، وتضعون الخطط، وتوضّحون المراحل الرئيسية، وتعرّفون الميزات، وتحددون الأولويات، وتتفقون على الجودة، ثمّ تنهي الاتصال. خلال أيّام قليلة، تدرك أنّه كان مضيعة للوقت. إنّهم لا يحافظون على وعودهم لأنّ هناك دائمًا شيء ما جديد يحدث. شخصٌ ما مريض، خادمٌ معطل، بعض أجزاء البرنامج غير صالحة للعمل، بعض الشيفرة لم تعد تعمل، وما إلى ذلك. تتصل مجددًا، تعبّر عن إحباطك، وتوجّه اتهامات قوية، وتعيد هيكلة المراحل، وتعيد تعريف الميزات، وتعيد تحديد الأولويات، وخلال عدّة أيّام تبدأ من جديد. كنت هناك، وقمت بذلك؟ هل يبدو هذا مألوفًا؟
</p>

<p>
	من خلال تجربتي، فإنّ سبب عدم القدرة على التنبؤ وعدم موثوقية الفريق الخارجي في معظم الحالات هو راعي المشروع. يحدث هذا عندما لا تستمع إليهم أو يخشون أن يقولوا لك الحقيقة، والذي هو عادةً نفس الشيء. يطلق البعض على هذا "التطوير المُقاد بالخوف". يخاف الفريق منك، ولكي يحتفظ الفريق بك كعميل يدفع له المال، يضطر أن يكذب عليك.
</p>

<p>
	في الأساس، يخبرونك بما تريد أن تسمعه - أنّ نهاية المشروع قريبة، والأخطاء الموجودة حاليًا سهلة الإصلاح، وأنّ مشاكل الأداء بسيطة، وأنّ جودة المعمارية رائعة، وأنّ الفريق متحمس جدًا للعمل معك. عندما تسمع أي مما سبق، اسأل نفسك - هل تشجعهم على قول الحقيقة؟ هل تكافؤهم على إعطائك أخبارًا سيئة لكن صادقة؟
</p>

<p>
	بالإشارة إلى المبدأ الأساسي المذكور أعلاه، مجددًا، أنصحك بالتأكد من أنّ منطقك في المكافآت والعقوبات شفاف لشريكك، الفريق الخارجي، ويستند إلى أهداف المشروع، وفقًا للمبدأ الأساسي وليس لمشاعرك الشخصية.
</p>

<p>
	في إحدى منشوراتي السابقة، كتبت أنّ العميل السعيد هو هدف خاطئ لفريق تطوير البرمجيات. العميل الذي يدعم هذا الهدف هو عميل رهيب محكوم عليه بفشل المشروع. إذا كافأت فريقك عندما يُشعرك بالسعادة بالأخبار الجيّدة، فأنت تدرّبهم على الكذب عليك. إذا كنت تتوقع منهم أخبارًا جيّدة، فأنت لا تشجعهم على إخبارك بالحقيقة وعلى القيام بما هو جيّد للمشروع، ليس لك شخصيًّا.
</p>

<p>
	أنت لا تشجعهم على الجدال معك. بكلماتٍ أخرى، أنت تخنق قناة المعلومات التي من المفترض أن تأتي إليك من الأشخاص الذين يعملون معك. أنت تعزل نفسك، والفريق بدأ بالعمل ضدك، ليس معك.
</p>

<p>
	إليك نصيحةً عمليّةً. أولًا، أعلن عن أهدافك وقيودك المعقولة بانتظام، كما شرحت أعلاه. تأكّد من فهم الفريق لخطط عملك و"لماذا" الأسباب الكامنة وراءها. ثانيًا، اسأل أعضاء الفريق بانتظام عن المخاطر والمشاكل. اسألهم لماذا يعتقدون أن أهداف المشروع قد تتعرض للخطر. ومن الأفضل أن تدعهم يوثّقوا المخاطر بانتظام ويبلغوك بها. كافئهم على صدقهم في قائمة المخاطر هذه.
</p>

<p>
	جرّب ذلك وستُفاجأ بعدد الأشياء المثيرة للاهتمام التي ستتضمنها قائمة المخاطر.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.yegor256.com/2015/05/21/avoid-software-outsourcing-disaster.html" rel="external nofollow">How to Avoid a Software Outsourcing Disaster</a> لصاحبه Yegor Bugayenko
</p>
]]></description><guid isPermaLink="false">749</guid><pubDate>Mon, 11 Nov 2019 14:07:00 +0000</pubDate></item><item><title>&#x62D;&#x644; &#x627;&#x644;&#x645;&#x634;&#x643;&#x644;&#x627;&#x62A; &#x648;&#x623;&#x647;&#x645;&#x64A;&#x62A;&#x647;&#x627; &#x641;&#x64A; &#x627;&#x62D;&#x62A;&#x631;&#x627;&#x641; &#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;</title><link>https://academy.hsoub.com/programming/general/%D8%AD%D9%84-%D8%A7%D9%84%D9%85%D8%B4%D9%83%D9%84%D8%A7%D8%AA-%D9%88%D8%A3%D9%87%D9%85%D9%8A%D8%AA%D9%87%D8%A7-%D9%81%D9%8A-%D8%A7%D8%AD%D8%AA%D8%B1%D8%A7%D9%81-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r760/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_10/5db9938e678ed_.jpg.b71c5e7e3a9e0b631e77458c9bf54cf2.jpg" /></p>
<p>
	إذا كنت مهتما بتعلم البرمجة، فعلى الأرجح أنك رأيت هذا الاقتباس من قبل:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		يجب على كلّ شخص تعلم البرمجة لأنها تُعلمه كيف يفكر - ستيف جوبز
	</p>
</blockquote>

<p>
	في الحقيقة لا أبالغ إن قلت أن البرمجة أصبحت من أهم المهارات في عصرنا الحالي، وذلك لأنها دخلت في جميع مجالات حياتنا سواءً كنا ندرك ذلك أم لا فانطلاقًا من الهواتف المحمولة ومرورًا بالمنازل والشاشات الذكية وانتهاءً بالسيارات ذاتية القيادة. كل شيء من حولنا لم نكن لنراه بهذا الشكل لولا البرمجة، فأنا على سبيل المثال أكتب وأعدل هذا الموضوع من خلال برنامج بُرمج عبر لغة برمجة وأنت تقرأه على الإنترنت باستخدام برنامج (المتصفح) وربما رأيته على مواقع التواصل الاجتماعي وكُلها برامج أيضًا.
</p>

<p>
	ومما لا شك فيه أن تعلم البرمجة أصبح ضرورة مُلحة في هذا العصر بل إن تعلمك لها سيزيد من فرصك بشكل كبير في الحصول على عمل.
</p>

<p>
	ولقد تحدثنا في <a href="https://academy.hsoub.com/programming/general/%D8%AA%D8%B9%D9%84%D9%85-%D8%A7%D9%84%D8%A8%D8%B1%D9%85%D8%AC%D8%A9-r662/" rel="">مقالٍ سابق</a> عن كيفية تعلم البرمجة والدخول إلى هذا المجال من أوسع أبوابه (إن كنت حديث عهدٍ في البرمجة أو تخطط للبدء بها، فننصحك بقراءته قبل إكمال هذا المقال) وسوف نتحدث في هذا المقال عن أكثر المهارات صعوبةً في احتراف البرمجة ألا وهي «حل المشاكل».
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="32231" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db9939370219_.jpg.3d87423d165e3da2cc433fd62fb98462.jpg" rel=""><img alt="حل المشكلات وأهميتها في احتراف البرمجة.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32231" data-unique="84rykuicb" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db993938631a_.thumb.jpg.5dc7d2412ab482c2247bd88c1bb0e7bf.jpg"></a>
</p>

<h2>
	حل المشكلات وارتباطها بالبرمجة
</h2>

<p>
	لطالما وقفنا حائرين أمام مشكلةٍ ما ونسأل أنفسنا ماهي الطريقة الصحيحة للخروج من هذا المأزق؟ هل ستكون طريقة الحلّ التي أتبعها مشابهة للطريقة التي يتبعها المبرمجين المحترفين؟ كيف أستطيع أن أفكر مثلما يفكر المبرمجين المحترفين؟
</p>

<p>
	في البداية وقبل الخوض في التفاصيل دعنا نُعرف البرمجة بحد ذاتها ولنذهب للمقال السابق ونلقي نظرة سريعة عليها:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		البرمجة: هي عملية تقسيم مهمة معينة يُراد تنفيذها عبر الحاسوب إلى أجزاء صغيرة ومترابطة وقابلة للتنفيذ بأوامر بسيطة.
	</p>
</blockquote>

<p>
	نلاحظ أن التعريف السابق صحيح ولكنه مُقْتضَب ولا يقدم لنا المعنى الكامل والدقيق للبرمجة لذا لابدّ لنا من تعريفٍ أكثر دقة وموضوعية يساعدنا في فهم هذا المقال.
</p>

<p>
	يعرف موقع HackerRank في <a href="https://research.hackerrank.com/developer-skills/2018/" rel="external nofollow">تقريره عن مهارات المطورين بعام 2018</a>:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		البرمجة: هي أكثر من مجرد إتقان لغة برمجية أو إصلاح أخطاء شيفرة برمجية معينة وإنما هي إثبات عملي للفكر التحليلي والرياضي والمنطقي والقدرة على تفكيك المشاكل الكبيرة والمعقدة إلى أجزاء صغيرة ومفهومة وقابلة للحلّ.
	</p>
</blockquote>

<p>
	نستنتج مما سبق أن البرمجة تعتمد اعتمادًا أساسيًا على التفكير المنطقي والرياضي والقدرة على حلّ المشاكل وإن لغات البرمجة ما هي إلا وسيلة للتخاطب مع الحاسوب.
</p>

<p>
	إذن الأمر كله يتعلق بتطوير قدرتك في حلّ المشاكل وجعل هذه العملية سهلة وسلسة بنفس الوقت لذا فاسمح لي بأن آخذك معي برحلة صغيرة في هذا المقال نتعرف فيها على أهمية حلّ المشاكل وضرورتها في مشوارك البرمجي.
</p>

<div class="banner-container ipsBox ipsPadding">
	<div class="inner-banner-container">
		<p class="banner-heading">
			دورة علوم الحاسوب
		</p>

		<p class="banner-subtitle">
			دورة تدريبية متكاملة تضعك على بوابة الاحتراف في تعلم أساسيات البرمجة وعلوم الحاسوب
		</p>

		<div>
			<a class="ipsButton ipsButton_large ipsButton_primary ipsButton_important" href="https://academy.hsoub.com/learn/computer-science/" rel="">اشترك الآن</a>
		</div>
	</div>

	<div class="banner-img">
		<img alt="دورة علوم الحاسوب" src="https://academy.hsoub.com/learn/assets/images/courses/computer-science.png">
	</div>
</div>

<h2>
	لماذا حلّ المشاكل مهم؟
</h2>

<p>
	تأتي أهمية حل المشاكل من كونها من أكثر المهارات المطلوبة عالميًا فوفقًا لتقرير أصدره موقع <a href="https://research.hackerrank.com/developer-skills/2018/" rel="external nofollow">HackerRank</a> جاء فيه:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		إن التفكير الرياضي أو القدرة على حلّ المشاكل الكبيرة والمعقدة يعتبر من أفضل المهارات التقنية الأساسية المطلوبة لأي وظيفة.
	</p>
</blockquote>

<p>
	احتلت مهارة حلّ المشاكل<a href="https://research.hackerrank.com/developer-skills/2018/" rel="external nofollow">المرتبة الأولى</a> بنسبة 94.9% لأكثر مهارة مطلوبة لأصحاب الشركات سواء الصغيرة منها أو الكبيرة.
</p>

<p>
	وعلى الصعيد العملي، إن عملية بناء أي شيء من الصفر سواء أكانت آلة معينة أو أي مُنتج جديد ستواجه الكثير من المشاكل في البداية، فعلى سبيل المثال بناء خدمات أمازون السحابية (<a href="https://en.wikipedia.org/wiki/Amazon_Web_Services" rel="external nofollow">AWS</a>)، والّتي جاءت حلًا لمشكلة النفقات العالية للبنية التحتية لتجارتها الإلكترونية بالإضافة إلى الوقت الطويل الّتي تحتاجه في عملية البناء والذي شكل تحدي كبير في إمكانية توسع الشركة، إلى أن جاء آندي جاسي كبير مستشاري جيف بيزوس في ذلك الوقت والذي استطاع إيجاد حلّ لهذه المشكلة ولم يتوقف عند ذلك الحد وإنما أختار تحويل هذا الحلّ إلى خط أعمال جديد تحت أسم خدمات أمازون السحابية والّتي بلغت <a href="https://qz.com/1539546/amazon-web-services-brought-in-more-money-than-mcdonalds-in-2018/" rel="external nofollow">عائداتها السنوية</a> لعام 2018 قيمة تناهز 25 مليار دولار.
</p>

<p>
	نجد من التجربة السابقة أنه حصلت مشكلة فأُوجِد لها حلًا وأثناء خلق حل للمشكلة ظهرت الكثير من المشاكل الأخرى لتقع في سلسلة من المشاكل لا تنتهي. وبعد حلّ جميع المشاكل سيصبح المنتج جاهزًا للعمل، أي أن دورة حياة أي منتج سواءً أكان برمجيًا أو ماديًا ستحتوي على المشاكل، وبناءً على ذلك تكون مهارة حل المشاكل اللَبِنَة الأساسية في بناء مشوارك البرمجي، والّتي يجب علينا الإهتمام بها عند الإقدام على تعلّم البرمجة.
</p>

<p>
	تكون طريقة تعاملنا مع المشاكل غير منظمة وعشوائية في أغلب الأحيان، فمعظمُ المبرمجين الجُدد يَبْدَؤُونَ بحلّ أي مشكلة تُواجهُهُم بالطريقة التالية:
</p>

<ol>
	<li>
		جرّب أي حلّ للمشكلة.
	</li>
	<li>
		إذا لم ينجح الحلّ الأول حاول أن تجرّب أي حلّ آخر.
	</li>
	<li>
		إذا لم يفلح الحلّ كرر الخطوة الثانية إلى أن تصل إلى الحلّ.
	</li>
</ol>

<p>
	لا يحصل هذا الأمر مع المبرمجين فقط، وإنما يحصل مع أي شخص يواجه مشكلة ولا يستعن على حلها بالتحليل والتفكير المنطقي.
</p>

<p>
	في الحقيقة، قد يحالفك الحظ أحيانًا ويتم حلّ المشكلة ولكن كن حذرًا! فهذه هي الطريقة الأسوأ لحلّ المشكلات بل وإنها ستهدر وقتك بشكل كبير لذا من الأفضل استخدام طريقة منظمة توصلنا للحلّ، واسمح لي بأن أشاركك طريقة شاملة توصلك إلى حلّ أي مشكلة قد تواجهك.
</p>

<h2>
	بناء خطة حلّ شاملة
</h2>

<p>
	إن خطة الحلّ الشاملة هي مجموعة من الخطوات الَّتي تتبعها لحلّ أي مشكلة تواجهك، حيث تكون هذه الخطة عامة وتخصص بحسب المشكلة، وهي ليست تعليمات ثابتة وإنما مبادئ ننطلق منها جميعًا، وكلٌ منا يطبقها بأسلوبه الخاص، وفي نهاية المطاف إذا انطلقنا جميعًا من نفس المبادئ، فسنصل حكمًا على نفس جودة الحلّ أيضًا.
</p>

<p>
	إن هذه الخطة مؤلفة من عدة أجزاء ويناقش كلّ جزء فيها جانبًا معينًا من المشكلة إلى أن نصل للحلّ، وهي على الشكل التالي:
</p>

<h3>
	1. فهم المشكلة
</h3>

<p>
	إن فهمنا للمشكلة المطروحة هي الخطوة الأكثر صعوبة في طريقنا لحلّها، بل إن أكثر المشاكل تأتي صعوبتها من عدم تمكننا من فهم عميق لها.
</p>

<p>
	ولكن متى تعلم بأنك استطعت فهم المشكلة؟ إذا كنت قادرًا على شرحها بكلمات واضحة وسهلة بحيث يستطيع أي شخص فهمها عندها تكون بالفعل قد فهمت المشكلة.
</p>

<p>
	هل تذكر عندما كنت عالقًا في مشكلة وبدأت بشرحها فوجدت أخطاء منطقية كثيرة لم تكن قد انتبهت لها من قبل؟ أغلب المبرمجين قد مروا بهذه الحالة من قبل، لذلك من الأفضل دومًا أن تكتب المشكلة الَّتي تواجهك باستخدام مخططات الحالة (State diagram وهي نوع من المخططات الَّتي تستخدم لتوصيف سلوك نظام ما) أو بأن تخبر شخص آخر عن المشكلة سواءً أكان زميل لك في الشركة أو عضو في الفريق أو أي شخص أخر. شاع بين المبرمجين استخدام البطة المطاطية في شرح أجزاء المشكلة لها لفهمها وإيجاد حل لها.
</p>

<p style="text-align: center;">
	<a class="ipsAttachLink ipsAttachLink_image" data-fileext="jpg" data-fileid="32230" href="https://academy.hsoub.com/uploads/monthly_2019_10/5db9928c2ba59_rubberyellowduck.jpg.30d6359fdf4816815153e854e5a1ea5d.jpg" rel=""><img alt="rubber yellow duck.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="32230" data-unique="data-unique" src="https://academy.hsoub.com/uploads/monthly_2019_10/5db9928c2ba59_rubberyellowduck.jpg.30d6359fdf4816815153e854e5a1ea5d.jpg"></a>
</p>

<p>
	يعد أسلوب البطة المطاطية في تنقيح الأخطاء من أكثر الأساليب سهولة وبساطة، إذ يضع المبرمج بطةً بجوار حاسوبه، وعند مواجهته لأي مشكلة يشرع في شرح الشيفرة البرمجية للبطة وما هي النتيجة المرتقبة من الشيفرة وموازنتها مع النتيجة الحالية وغالبًا ما يجد الخطأ أثناء شرحه.
</p>

<p>
	وخلاصة لهذه الخطوة أنقل إليك مقولة ألبرت أينشتاين:
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		إذا لم تستطع شرح فكرتك لطفل عمره 6 أعوام فأنت نفسك لم تفهمها بعد
	</p>
</blockquote>

<h3>
	2. تحليل المشكلة
</h3>

<p>
	إن تقسيم المشكلة يلعب دورًا مهمًا في طريقك لإيجاد الحلّ، لذا حاول أن تقسّمها إلى أجزاء صغيرة ثمّ حُلّ كلَّ جزء منها على حدة ويُنصح في البداية بحلّ أسهل جزء منها ومن ثمّ الأصعب فالأصعب وهكذا إلى أن يتمّ حلّ جميع أجزائها، وبعدها إجمع هذه الأجزاء مع بعضها للحصول على الحلّ النهائي للمشكلة الأصلية (الكبيرة).
</p>

<p>
	منذ فترة كنا بصدد برمجة إضافة لمتصفح غوغل كروم بهدف تسهيل مهمة لموقع ما، فقررنا تجربة هذه الطريقة وبدأنا بتقسّيم المهمة على أجزاء ثم عملنا على حلّ كل جزء منها، وبعدها جمعنا هذه الأجزاء مع بعضها بعضًا لبناء الإضافة، وبالفعل كان العمل بهذه الطريقة سهلًا جدًا ومريحًا كما لم نعهده من قبل.
</p>

<p>
	في بعض الأحيان عندما تواجه شيفرات برمجية كتبها مبرمجون لا يتبعون مبادئ <a href="https://en.wikipedia.org/wiki/SOLID" rel="external nofollow">SOLID</a> (وهي مجموعة من العادات والمبادئ الَّتي يتبعها المبرمجون للحصول على شيفرة برمجية قابلة للصيانة وسهلة التعديل والتكيف مع متطلبات المشروع المتغيرة)، وغالبًا ما تكون شيفرات أولئك المبرمجين غيرمفهمومة ومتشابكة ويطلق عليها اسم <a href="https://en.wikipedia.org/wiki/Spaghetti_code" rel="external nofollow">Spaghetti code</a> (تكون هذه الشيفرات ذات بنية معقدة ومتشابكة وصعبة القراءة وغير مرتبة أي تكون مثل المعكرونة ملتوية ومتشابكة) ولنفرض أنه طُلبَ منك تعديل هذه الشيفرة أو إضافة وظائف جديدة إليها،عندها حتمًا ستواجه العديد من المشاكل في عملية تقسيم المشكلة ومعرفة أي جزء من الشيفرة البرمجية المُسبب للخطأ لذا كان الحصول على شيفرات برمجية مرنة وقابلة للتعديل هي الأرضية المشتركة بين العديد من تقنيات تبسيط الشيفرات البرمجية مثل مبادئ SOLID أو مبدأ MVC والذي ينص على تقسيم الوحدات من حيث طبيعة مهمتها إلى ثلاثة أقسام (Model-View-Controller) والبرمجة كائنية التوجه <abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr> (Object-Oriented Programming)، إذ أن جميعهم يهدفون إلى فصل الأكواد إلى أقسام ليسهل تطويرها وتنقيحها وصيانتها.
</p>

<h3>
	3. إعداد خطة للحل
</h3>

<p>
	بعد أن فهمت وحللت المشكلة، يأتي دور وضع الخطة المناسبة للحلّ بحيث تغطي كافة الجوانب والتفاصيل للمشكلة، ولا تشرع في الحلّ من دون خطة (على أمل أن تجد الحلّ بطريقة ما) لأن المفتاح الرئيسي للوصول للحلّ هي الخطة الواضحة والمنظمة والتي تضمن وصولنا للحلّ النهائي.
</p>

<p>
	أعط لنفسك وقتًا لتحلّيل المشكلة وربط المعلومات المدخلة إلى البرنامج ونوعها والمعلومات الَّتي ستظهر كخرج للبرنامج وفهم سياقها وللحصول على خطة جيدة يجب عليك الإجابة على السؤال التالي:
</p>

<ul>
	<li>
		إذا أُعطي للبرنامج الدخل س، ما هي الخطوات اللازمة للحصول على الخرج ع؟
	</li>
</ul>

<p>
	إن إجابتك على هذا السؤال سوف يحدد ماهي الخطوات اللازمة لحلّ المشكلة ومن ثَمَّ تقوم بترتيبها في خطة واضحة ومنظمة من أجل الحصول على الخرج الذي تريده.
</p>

<h3>
	4. مواجهة حالة السكتة البرمجية
</h3>

<p>
	ماذا لو فرضنا أنك لم تستطع حلّ أي جزء من المشكلة، ولا حتى الأجزاء السهلة منها (وهذا قد يحدث في بعض الأحيان)، إن كثير من المبرمجين يقعون في هذه الحالة فلا يستطيعون أن يُحرزوا أي تقدم يذكر في تطوير الشيفرة البرمجية وهذا أشبه ما يمكن بالسكتة الدماغية (حيث لا يستطيع المريض القيام بأي حركة)، في الحقيقة إن هذه الحالة طبيعية جدًا ومعظمنا قد تعرض لها في بداية مشواره والاختلاف الوحيد هو أن المبرمج المحترف لديه فضول أكثر حول المشكلة ومعرفة سبب حدوثها بدلًا من أن يكون منزعجًا أو غاضبًا منها.
</p>

<p>
	وفي هذه الحالة هنالك حلّين يمكنك تجربتهما للخروج من هذا المأزق:
</p>

<h4>
	1-4. تنقيح الأخطاء (Debug)
</h4>

<p>
	ليس المقصود هنا الأخطاء الكتابية في صياغة اللغة (Syntax errors) مثل نسيان فاصلة منقوطة أو أي خطأ في استخدام المتغيرات أو الدوال أو ما شابه ذلك من أخطاء والَّتي تقوم باكتشافها أي بيئة تطوير متكاملة (IDE وهي عبارة عن محرر شيفرة برمجية مدمج مع نظام ذكي لإكمال الكود ومصحح أخطاء).
</p>

<p>
	وبالطبع ليست أيضًا الأخطاء الّتي تظهر أثناء التنفيذ (Runtime Errors) والّتي تكون عادة نتيجة لفشلٍ في فتح ملف ما أو محاولة القسمة على صفر أو مثل هذه الأخطاء، وإنما المقصود هنا هو أخطاء المنطق البرمجي (Logic errors) الّتي ينفِّذ فيها البرنامج أمرًا غير الَّذي بُرمج من أجله، لذا من الأفضل أن تحاول أن تفحص الشيفرة البرمجية سطرًا سطرًا لعلك تجد هذا الخطأ، أوإذا كنت تعمل على لغاتٍ مثل (C++, C) والّتي تدعم استخدام المُنقِّح Debugger (الذي يراقب عمل البرنامج ويتحكم في تنفيذه بطريقة تستطيع فيها إيقاف تنفيذ البرنامج أو حتى تغييره في أي موضع من الشيفرة وذلك من خلال مجموعة من الأدوات الّتي يقدمها المُنقِّح، مثل: GNU Debugger) فيمكنك استخدامه لإيجاد الخطأ ومن ثَمّ إصلاحه.
</p>

<blockquote class="ipsQuote" data-ipsquote="">
	<div class="ipsQuote_citation">
		اقتباس
	</div>

	<p data-gramm="false">
		إن فنّ تنقيح الأخطاء البرمجية هو اكتشاف العمل الفعلي للبرنامج وموازنته مع التوقع الَّذي كنتَ تنتظره من البرنامج - أندرو سينجر
	</p>
</blockquote>

<p>
	<strong>ملاحظة :</strong> من المنهجيات البرمجية الجيدة هي كتابة تعليقات توضيحية قبل كلّ دالة (Function) أو صنف (Class) برمجي وخُصوصًا تلك الأجزاء المعقدة منها لأن ذلك سوف يساعدك كثيرًا في عملية مراجعة الشيفرة البرمجية وتنقيحها.
</p>

<h4>
	2-4. مراجعة وتقييم الحلّ
</h4>

<p>
	في كثير من الأحيان عند مواجهتنا للمشاكل وخصوصًا للكبيرة منها قد نضيع في التفاصيل الصغيرة للمشكلة الَّتي نواجهها وننسى المشكلة الرئيسية ولذلك من الأفضل دومًا أن نسأل أنفسنا هل هذه هي الطريقة الأفضل للحلّ؟ هل هنالك حلًّا عموميًا أفضل من الموجود؟ هل الشيفرة البرمجية أمثلية؟ هل الحلّ يخرق معايير الجودة المطلوبة؟
</p>

<p>
	ارجع خطوة إلى الوراء وحاول أن تراها من منظور مختلف، وحتمًا ستلاحظ العديد من المشاكل التي غفلت عنها أثناء انشغالك بالتفاصيل الصغيرة.
</p>

<p>
	<strong>ملاحظة :</strong> هنالك طريقة أخرى يتبعها بعض المبرمجين لإعادة تقييم الحلّ وهي حذف الشيفرة البرمجية الخاطئة بالكامل وإعادة كتابتها من جديد فكثير ما يأخذ ذلك وقتًا أقل من تتبع المشكلة ذاتها وحلها.
</p>

<h3>
	5. البحث عن حلول عبر الإنترنت
</h3>

<p>
	إن أغلب المشاريع البرمجية تكون متشابهة بكثيرٍ من الوظائف والخصائص، ونادرًا ما نرى مشروع ذو أفكارٍ جديدة بالكامل لذا فإن أي مشكلة برمجية تواجهها قد واجهها عدد كبير من المبرمجين من قبلك وأوجدوا لها حلولًا وشاركوها مع غيرهم، وكل ما عليك فعله هو أن تتعلم كيف تبحث عن المشكلة. وبالطبع صديقنا <a href="https://stackoverflow.com" rel="external nofollow">stackoverflow</a> والذي يعد من أشهر منصات مشاركة الحلول البرمجية الّذي يقدم لك الحلّ الَّذي أجمع عليه أغلب، المبرمجين، ويوجد العديد من المنصات الأخرى المشابهة مثل <a href="https://askubuntu.com" rel="external nofollow">AskUbuntu</a> وهو النسخة العربية من موقع stackoverflow والكثير غيرهم، وحتى لو أنك قد حللت المشكلة أنصحك بتصفح الحلول الموجودة لأنك سوف تتعلم طرقًا أُخرى لحلّها قد تكون أسهل وأفضل بكثير من الحلّ الَّذي وصلت اليه.
</p>

<p>
	إلى الآن نكون قد ناقشنا الخطوة الأولى من الطريقة الشاملة لحلّ المشاكل والآن لننتقل إلى الخطوة الثانية.
</p>

<h2>
	التدرب على هذه الخطة
</h2>

<p>
	إن أي مهارة جديدة تحتاج إلى تدريبٍ مُمنهجٍ ومستمرٍ حتى تتقنها. لذا لا بدّ لك من وضع خطة واضحة للتدريب وتخصيص زمن محدد وثابت تقضيه في صقل تلك المهارة.يمكنك البدء مثلًا بتخصيص ساعة للتدريب يوميًا لمدة شهر كامل، وبعدها توازن نفسك مع ما كنت عليه في السابق من سرعةٍ في تحديد المشكلة وجودةٍ الحل المطروح والوقت الإجمالي لحل المشكلة وبكل تأكيد ستلاحظ تحسنًا واضحًا في أدائك.
</p>

<p>
	وقد تساءل نفسك كيف يمكنني التدرب على حلّ المشاكل؟ في الحقيقة هنالك طريقة مفيدة جدًا أنصحك بها لتكوين قاعدة صلبة تنطلق منها، وهي على الشكل التالي.
</p>

<h3>
	1. التدرب على المسائل البرمجية
</h3>

<p>
	تعد المسابقات البرمجية سواءً على مستوى الجامعة أو على مستوى القطر أو حتى على مستوى العالم مثل مسابقة <a href="https://icpc.baylor.edu" rel="external nofollow">ACM ICPC</a> من أفضل الفرص للتدريب في مجال البرمجة وصقل هذه المهارة بل وتعتبر دفعة كبيرة لك في رحلتك كمبرمج ولمستقبلك المهني أيضًا، إذ تبادر العديد من الشركات العالمية لِضمّ أولئك المنافسين المتميزين إليها بعد أن أثبتوا بالفعل أنهم النخبة في مجالهم.
</p>

<p>
	فإن كنت تخطط للانضمام إلى هذه المسابقة فلا تتردد وبادر بالتحضير لها من الآن.
</p>

<p>
	ويقدم لنا الكاتب Steven Halim في كتابه Competitive Programming بعض الفوائد الَّتي نجنيها من التدرب على حلّ المشاكل البرمجية في المسابقات.
</p>

<h4>
	السرعة في كتابة الشيفرة البرمجية
</h4>

<p>
	كتابة الشيفرة البرمجية بسرعة في المسابقات يوفر لك الكثير من الوقت للتفكير في بقية المشاكل واختبارها لذلك نرى أغلب المبرمجين يتدربون على سرعة الكتابة على لوحة المفاتيح لينصب تركيزهم على حلّ المشكلة فقط، ولذلك من المنطقي أن تفضل الشركات الموظفين الَّذين سَبق إن شاركوا في المسابقات البرمجية لمعرفتها بسرعة إنتاجيتهم وقدرتهم على تطوير وإيصال منتج برمجي بسرعة عالية بِالْمُوازنة مع أقرانهم ممن لم يشاركوا في المسابقات.
</p>

<h4>
	العصف الذهني وحصر الخوارزميات الممكنة
</h4>

<p>
	لا بدّ من تحسين قدرتك على تحديد نوع المسألة بسرعة وأن تمتلك المعرفة الكافية بالخوارزميات لتتمكن من تطبيقها مباشرة على المسألة المطروحة، لذلك ينبغي على المبرمج الَّذي ينوي الانضمام إلى المسابقة أن يتمكن من جميع الخوارزميات الشائعة في المسائل البرمجية.
</p>

<h4>
	العمل الجماعي وروح الفريق
</h4>

<p>
	تعتمد المسابقة البرمجية على ترتيب الفرق بحسب عدد المسائل الَّتي أجابوا عليها، والوقت الَّذي استهلكوه لحلّ كُلَ مشكلة، وعدد الحلول الخاطئة الَّتي أُرسلت للحكم.
</p>

<p>
	وانطلاقًا من ذلك تكون فوائد العمل كفريق واحد متعددة منها إمكانية توزيع المسائل على كلّ عضو في الفريق بحيث يزداد العدد الكلي للمسائل المحلولة بتوزيعها بين بعضهم بعضًا، ومناقشة حلّ كلّ مسألة وبذلك ينقص عدد الحلول الخاطئة الَّتي قد تُرسل للحكم، وحُكمًا سينقص الوقت المستغرق لحلّ المسائل.
</p>

<p>
	وعلى الصعيد العملي أيضًا نجد أن طبيعة عمل المبرمجين سواءً في الشركات الصغيرة أو الكبيرة، يُطلب منهم العمل كفريق واحد، فعلى سبيل المثال منذ فترة طَلَبَ مني أحد العملاء بناء موقع ويب، وكنت عندها قد أنتهيت من بناء فريقي البرمجي. وبالفعل بدأنا العمل على الموقع و قسّمنا العمل على أجزاء فعكف كلُّ واحد منا على تطوير جزئه الخاص من الموقع، إذ استلمتُ جزء الواجهات الخلفية، وقام أحد أعضاء الفريق باستلام الواجهات الأمامية، والآخَر استلم بناء تطبيق للهواتف الّتي تعمل بنظام أندرويد وفي نهاية الأسبوع جمعنا كل الأجزاء مع بعضها بعضًا وأنهينا المشروع بوقتٍ قياسي لم نكن لنستطيع بلوغهُ لو أننا لم نعمل كفريقٍ واحد، ولذا فإن انضمامك إلى المسابقة البرمجية يجعلك تتدرب على العمل ضمن فريق قبل أن تواجهها في سوق العمل في حال أردت العمل مع أي شركة مستقبلًا.
</p>

<h4>
	المرونة العصبية
</h4>

<p>
	إن تدريبك المستمر على المسائل البرمجية سيؤدي إلى زيادة منطقة الحصين (المنطقة المسؤولة عن الذاكرة والتوجيهات) في الدماغ وهذا ما أثبتته الباحثة <a href="https://www.ucl.ac.uk/cdcn/aboutus/steering/Maguire" rel="external nofollow">اليانور ماجواير</a> من كلية لندن الجامعية عندما <a href="https://www.scientificamerican.com/article/london-taxi-memory/" rel="external nofollow">أجرت دراسة</a> على سائقي الأجرة في مدينة لندن فقاموا بإجراء فحص بالرنين المغناطيسي الوظيفي fMRI لأدمغة السائقين الذين قضوا قرابة عامين من التدريب في سبيل تعلم كيفية التنقل في منعطفات المدينة وذلك من أجل الحصول على رخصة القيادة ومقارنتها بصور لأدمغة رجال أصحاء من نفس العمر ولا يعملون كسائقي أجرة فتبين أن منطقة الحصين أصبحت أكبر لدى السائقين، كما لاحظوا أنه كلما أمضى سائق الأجرة فترة أطول في التدريب، زاد حجم الحصين، وذلك استجابة إلى الخبرة الّتي يكتسبها السائق.
</p>

<p>
	والآن تخيل معي ما سيحدث في حال تدربك على حل المشاكل لمدة عام أو أكثر، سيصبح حلّك للمشاكل البرمجية عادة سهلة ومسلية خلاف ما كانت عليه من صعوبة وتعقيد.
</p>

<p>
	يوجد العديد من المواقع الَّتي تقدم المسائل البرمجية مثل <a href="https://hackerrank.com/" rel="external nofollow">HackerRank</a> أو موقع <a href="https://www.topcoder.com" rel="external nofollow">TopCoder</a> والكثير غيرهم.
</p>

<h3>
	2. التدرب باستخدام الألعاب
</h3>

<p>
	نعم أنت لم تخطئ القراءة إنها الألعاب!
</p>

<p>
	تعد الألعاب أداة قوية جدًا لتنمية المهارات العقلية والقدرات الدماغية على التفكير والتذكر وربط المعلومات ببعضها بعضًا، حيث أن غالبية الألعاب تحتاج لتجميع المعلومات وتنظيمها بحيث تستطيع الاستفادة منها وجعلها مفتاحًا للحلّ، بل إن الركيزة الأساسية الَّتي تشترك بها كافة الألعاب هي حلّ المشاكل!
</p>

<p>
	بالتأكيد نحن لا نقصد هنا ألعاب الفيديو فقط وإنما ألعاب الذكاء أيضًا مثل : لعبة الشطرنج، والألغاز الرياضية، ولعبة سودوكو، ولعبة Go، والكثير من الألعاب الَّتي تندرج تحت هذا السياق تعد ألعاب مفيدة. فعند محاولتك حلّ الألغاز في Saw أنت فعليًا تقوم بحلّ المشاكل (ولكن بإطار مختلف).
</p>

<p>
	وتساعدنا أيضًا في انشاء سيناريوهات للحلّ وهذه المهارة مفيدة في عالم البرمجة في حال تعثرت في أسلوب حلّ معين فتغير سيناريو الحلّ وتبدأ من جديد.
</p>

<p>
	في الحقيقة إن الشيء المشترك بين جميع الناس الناجحين هي اكتسابهم لعادات يومية لحلّ المشاكل الصغيرة على سبيل المثال بيتر تيل (أحد مؤسسي شركة باي بال والمصنف كرابع أغنى شخص على مستوى العالم لعام 2014 بميزانية تفوق $2.2 بليون دولار) <a href="https://www.businessinsider.com/the-chess-concepts-that-taught-peter-thiel-how-to-become-a-billionaire-2012-6?r=US&amp;IR=T" rel="external nofollow">صرح بشكل رسمي</a> أنه يلعب الشطرنج يوميًا بل وشارك في بطولات الشطرنج مرات عديدة، وإيلون ماسك (رائد الأعمال والرئيس التنفيذي لعدة شركات مثل: سبيس إكس لتصنيع مركبات الفضاء وتسلا لصناعة السيارات الكهربائية وغيرها)<a href="https://www.youtube.com/watch?v=8JoTw_JuE78" rel="external nofollow">أكد بأنه يلعب ألعاب الفيديو</a> والكثير غيرهم كرسوا جزءًا من وقتهم اليومي لتنمية مهارة حلّ المشاكل.
</p>

<p>
	ولكن يجب أن تكون حذرًا في إدارة وقت اللعب ويُفضل أن تختار الأوقات المناسبة للعب ووضع مدة زمنية مخصصة لها، وذلك لأن الهدف ليس إضاعة الوقت والتسلية فقط وإنما التدرب على حل المشاكل ولكي لا ينتهِ بك المطاف إلى قضاء اليوم بأكمله على الألعاب.
</p>

<h2>
	الخلاصة
</h2>

<p>
	اعتقد أنك قد كونت فكرة جيدة عن أهمية حلّ المشاكل وضرورتها في مشوارك البرمجي وكيفية بناء خطة حلّ شاملة انطلاقًا من فهم المشكلة وتحليلها ومرورًا بإعداد خطة مخصصة لكلّ مشكلة وتقسيم المشكلة إلى أجزاء ليسهل حلّها ومواجهة حالة السكتة البرمجية وكيفية التغلب عليها من خلال تنقيح الأخطاء أو مراجعة وتقييم الحلّ، وأهمية البحث عن حلول على الإنترنت لنفس المشكلة وانتهاءً بالأسلوب الصحيح للتدرب على حل المشاكل وما هي أفضل الوسائل لتحقيق ذلك سواءً بالانضمام إلى المسابقات البرمجية أو بالتدرب بإستخدام الألعاب.
</p>

<p>
	وختامًا، لا تتوقع أن تصبح مبرمجًا محترفًا في غضون أسبوعٍ أو شهر واحد فهذا ضرب من الخيال بل ستحتاج لحلّ الكثير من المشاكل لبناء قاعدة معرفية صلبة تمكنك من مواجهة أي مشكلة مهما كانت صعوبتها وعندها بالتأكيد سوف تستحق لقب مبرمج محترف.
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
	<li>
		<a href="https://academy.hsoub.com/php/" rel="">تعلم لغة PHP</a>
	</li>
	<li>
		<a href="https://academy.hsoub.com/python/" rel="">تعلم لغة بايثون</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">760</guid><pubDate>Fri, 01 Nov 2019 18:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x623;&#x62E;&#x637;&#x627;&#x621; &#x627;&#x644;&#x633;&#x628;&#x639; &#x627;&#x644;&#x642;&#x627;&#x62A;&#x644;&#x629; &#x644;&#x623;&#x64A;&#x651; &#x645;&#x634;&#x631;&#x648;&#x639; &#x628;&#x631;&#x645;&#x62C;&#x64A;&#x627;&#x62A;</title><link>https://academy.hsoub.com/programming/general/%D8%A7%D9%84%D8%A3%D8%AE%D8%B7%D8%A7%D8%A1-%D8%A7%D9%84%D8%B3%D8%A8%D8%B9-%D8%A7%D9%84%D9%82%D8%A7%D8%AA%D9%84%D8%A9-%D9%84%D8%A3%D9%8A%D9%91-%D9%85%D8%B4%D8%B1%D9%88%D8%B9-%D8%A8%D8%B1%D9%85%D8%AC%D9%8A%D8%A7%D8%AA-r742/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2019_09/5d80888669747_.jpg.bb00817e7db260416a4c274ccd0cb28e.jpg" /></p>
<p>
	تعدّ الصيانة هي الميزة الأكثر قيمةً لتطوير البرمجيات الحديثة. يمكن <a href="https://en.wikipedia.org/wiki/Maintainability" rel="external nofollow">تعريف قابلية الصيانة</a> بشكلٍ أساسيّ بأنّها وقت العمل اللازم لمطور جديد حتى يتعلم البرنامج قبل أن يتمكن من البدء في إجراء تغييرات مهمة فيه. كلما طال الوقت، انخفضت الصيانة. يقترب هذا الشرط الزمني في بعض المشاريع من اللانهاية، مما يعني أنه غير قابل للصيانة حرفيًا. أعتقد أن هناك سبعة أخطاء أساسية وقاتلة تجعل برنامجنا غير قابلٍ للإصلاح وإليك هذه الأخطاء.
</p>

<p>
	<a class="ipsAttachLink ipsAttachLink_image" data-fileid="31631" href="https://academy.hsoub.com/uploads/monthly_2019_09/5d808888ded6c_.jpg.9cb61b2ff0d212b54b616d9a8605acbb.jpg" rel="" data-fileext="jpg"><img alt="الأخطاء السبع القاتلة.jpg" class="ipsImage ipsImage_thumbnailed" data-fileid="31631" data-unique="5p6gv0sre" src="https://academy.hsoub.com/uploads/monthly_2019_09/5d808888f4017_.thumb.jpg.57352c5edf773d0b5f23545f156c6b49.jpg"></a>
</p>

<h2 id="-">
	الأنماط المضادة
</h2>

<p>
	لسوء الحظ، لغات البرمجة التي نستخدمها مرنة جدًا. إنها تسمح بالكثير وتمنع القليل جدًا. مثلًا، لا تعارض لغة جافا وضع التطبيق بالكامل في "صنف" واحد مع عدة آلاف تابع. تقنيًا، سيتم ترجمة التطبيق وتشغيله. ولكن هذا نمط مضاد معروف يدعى <a href="https://en.wikipedia.org/wiki/God_object" rel="external nofollow">God object</a>.
</p>

<p>
	وبالتالي، فإن <a href="https://en.wikipedia.org/wiki/Anti-pattern" rel="external nofollow">النمط المضاد</a> هو طريقة مقبولة تقنيًا لتصميم الأشياء التي يُتفق عليها عمومًا أنها خاطئة. هناك العديد من الأنماط المضادة (anti-pattern) في كل لغة. وجودها في منتجك يشبه وجود الورم في الكائن الحي. بمجرد أن يبدأ في النمو، يصبح من الصعب جدًا إيقافه. وفي النهاية، يموت الجسم بأكمله. في النهاية، يصبح البرنامج بأكمله غير قابلِ للإصلاح ويجب إعادة كتابته.
</p>

<p>
	بمجرد السماح لبعض الأنماط المضادة في المنتج، ستحصل في النهاية على المزيد منها، وسينمو "الورم" فقط.
</p>

<p>
	يعدُّ هذا صحيح خاصةً بالنسبة للغات البرمجية كائنية التوجه (Java، و C ++، و Ruby وPython) ويرجع ذلك غالبًا إلى أنها ترث العديد من اللغات الإجرائية (C، Fortran وCOBOL) ولأن مطوري <a href="https://www.yegor256.com/2016/08/15/what-is-wrong-object-oriented-programming.html" rel="external nofollow"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه"><abbr title="Object-Oriented Programming | البرمجة كائنية التوجه">OOP</abbr></abbr></a> يميلون للتفكير بطريقة إجرائية وضرورية. على كلّ حال، بالإضافة إلى <a href="https://en.wikipedia.org/wiki/Anti-pattern" rel="external nofollow">قائمة الأنماط المضادة المعروفة</a> الموجودة، أنا أعدّ أيضًا أنَّ <a href="https://www.yegor256.com/2014/09/10/anti-patterns-in-oop.html" rel="external nofollow">هذه الأشياء القليلة</a> منهجيات تشفير سيئة. اقتراحي العملي الوحيد هنا هو القراءة والتعلّم. ربما تساعدك <a href="https://www.yegor256.com/2015/04/22/favorite-software-books.html" rel="external nofollow">هذه الكتب</a> أو كتاب <a href="https://www.yegor256.com/elegant-objects.html" rel="external nofollow">"Elegant Objects"</a> في ذلك. حاول دائمًا أن تشك في جودة برنامجك، ولا تكتفي بأن "يعمل فقط". كما هو الحال مع السرطان، كلما تم تشخيصه أبكر، كانت فرصة النجاة أكبر.
</p>

<h2 id="-">
	تغييرات لا يمكن تعقبها
</h2>

<p>
	عندما أنظر إلى سجل الإيداع (commit) يجب أن أكون قادرًا على توضيح كل تغيير، ما الذي تغير، ومن قام بالتغيير، ولماذا تم إجراء التغيير. إضافةً لذلك، يجب قياس الوقت اللازم للحصول على إجابات هذه الأسئلة الثلاثة بالثواني. ولكن في معظم المشاريع لا يتم تطبيق ذلك. إليكم بعض التوصيات العملية:
</p>

<h3 id="-">
	استخدم الملاحظات دائمًا
</h3>

<p>
	بغض النظر عن مدى صغر حجم المشروع أو الفريق، حتى لو كنت فيه لوحدك فقط، أنشئ ملاحظات (مشكلات GitHub) لكل مشكلة تحلّها. اشرح المشكلة باختصار في الملاحظة ووثّق ما تفكر به هناك. استخدم الملاحظة كمخزن مؤقت لجميع المعلومات المتعلقة بالمشكلة. انشر كل شيء يمكن أن يكون له أي فائدة مستقبلًا، عندما يحاول شخص ما فهم ما هي "تلك الالتزامات الغريبة القليلة".
</p>

<h3 id="-">
	أضف مراجعًا للملاحظات في الإيداعات
</h3>

<p>
	لا داعٍ للقول أنّه يجب أن يكون لكل إيداع (commit) رسالة. الالتزامات بدون رسائل تعتبر ممارسة سيئة جداً؛ لن أناقش لماذا. ولكن الرسالة بمفردها لا تعد كافية. يجب أن تبدأ كل رسالة برقم الملاحظة التي تعمل عليها. سيقوم GitHub (أنا متأكد من أنك تستخدمه) بربط الالتزامات والملاحظات تلقائيًا، مما يزيد من إمكانية تتبع التغييرات.
</p>

<h3 id="-">
	لا تحذف أي شيء
</h3>

<p>
	يسمح لنا Git بالقيام برفع (push) "قسري" يقوم بالكتابة فوق كامل الفرع (branch) الذي كان موجودًا سابقًا على الخادم. هذا مجرد مثال واحد على كيفية إتلاف سجل التطوير. شاهدت عدة مرات أشخاصًا يحذفون تعليقاتهم في مناقشات GitHub لجعل الملاحظات تبدو أكثر "نظافة". هذا خطأ، لا تقم أبدًا بحذف أي شيء. حافظ على سجلك بغض النظر عن مدى السوء (أو الفوضوية) التي قد تبدو لك الآن.
</p>

<h2 id="-">
	الإصدارات المخصصة
</h2>

<p>
	يجب أن يُحزَّم كل جزء من البرنامج قبل أن يتم تسليمه إلى المستخدم النهائي. إذا كنت تتعامل مع مكتبة جافا، فيجب أن تُحزَّم كملف ‎.jar ويتم تصديرها إلى مستودع ما؛ إذا كان تطبيق ويب، فيجب نشره على المنصة، وما إلى ذلك. بغض النظر عن صغر حجم المنتج أو كِبره، فهناك دائمًا إجراء معياري يختبر ويُحزِّم وينشر.
</p>

<p>
	سيكون الحل المثالي هو أتمتة هذا الإجراء بحيث يكون من الممكن تنفيذه من سطر الأوامر باستخدام أمر واحد
</p>

<pre class="ipsCode">$ ./release<span class="hljs-selector-class">.sh</span>
...
DONE (took <span class="hljs-number">98.7s</span>)
</pre>

<p>
	معظم المشاريع بعيدة عن ذلك، إذ تتضمن عملية إصدارها دائمًا بعض السحر، فيتعين على الشخص المسؤول عن المشروع (المعروف أيضًا باسم DevOp) النقر فوق بعض الأزرار هنا وهناك، وتسجيل الدخول إلى مكان ما، والتحقق من بعض المقاييس، وما إلى ذلك. لا تزال عملية الإصدار المخصص هذه خطأً نموذجيًا في صناعة الهندسة البرمجية بأكملها.
</p>

<p>
	يمكنني هنا تقديم نصيحة عملية واحدة فقط: "الأتمتة"، أنا أستخدم <a href="http://www.rultor.com/" rel="external nofollow">rultor.com</a> من أجل ذلك، لكن يمكنك استخدام أي أدوات تريدها. المهم أن يكون الإجراء بأكمله مؤتمتًا بالكامل ويمكن تنفيذه من سطر الأوامر.
</p>

<h2 id="-">
	تحليل ثابت طوعي
</h2>

<p>
	<a href="https://en.wikipedia.org/wiki/Static_program_analysis" rel="external nofollow">التحليل الثابت</a> هو ما يجعل شيفرتنا تبدو أفضل. وبجعلها تبدو أفضل، فإننا حتمًا نجعلها تعمل بشكل أفضل. لكن هذا يحدث فقط عندما يضطر الفريق بأكمله إلى اتباع القواعد التي يحددها المحلل (أو المحللون) الثابت (static analyzer). لقد كتبت عن ذلك في <a href="https://www.yegor256.com/2014/08/13/strict-code-quality-control.html" rel="external nofollow">التحكم الصارم لجودة شيفرة الجافا</a>. يمكنني استخدام <a href="http://www.qulice.com/" rel="external nofollow">qulice.com</a> في مشاريع Java و <a href="https://github.com/rubocop-hq/rubocop" rel="external nofollow">rubocop.com</a> في Ruby، وهناك العديد من الأدوات المشابهة لكل لغة تقريبًا.
</p>

<p>
	يمكنك استخدام أيّا منها، ولكن اجعله إلزاميًا، في معظم المشاريع التي يستخدم فيها التحليل الثابت، يبني المطورون تقارير جيدة المظهر ويواصلون كتابة الشيفرة بالطريقة التي استخدموها من قبل. لا يتم بمثل هذه المنهجية "التلقائية" تقديم أيّة إضافات للمشروع. وعلاوة على ذلك، فإنّها تخلق وَهمْ الجودة.
</p>

<p>
	ما أقوله هو أن التحليل الثابت يجب أن يكون خطوة إلزامية عند الإعداد للنشر. لا يمكن أن تتم عملية بناء المشروع في حال انتهاك أي قاعدة من قواعد التحليل الثابت.
</p>

<h2 id="-">
	تغطية اختبار غير معروف
</h2>

<p>
	ببساطة، <a href="https://en.wikipedia.org/wiki/Code_coverage" rel="external nofollow">تغطية الاختبار</a> هي درجة <a href="https://www.yegor256.com/2015/07/16/fools-dont-write-unit-tests.html" rel="external nofollow">اختبار</a> البرنامج من خلال اختبارات الوحدة أو التجميع. كلما زادت التغطية، تم تنفيذ "كمية" أكبر من الشيفرة أثناء إجراء الاختبارات. من الواضح أن التغطية الأعلى أمر جيد.
</p>

<p>
	لكن الكثير من مطوري المشاريع لا يعرفون مقدار تغطية مشاريعهم ولا يعتمدون هذا المقياس. قد يكون لديهم بعض الاختبارات، لكن لا أحد يعرف مدى عمق اختبارهم للبرنامج وماهي الأجزاء التي لم يتم اختبارها منه على الإطلاق. هذه الحالة أسوأ بكثير من تغطية الاختبارات المنخفضة التي يتم قياسها وإبلاغ الجميع بها.
</p>

<p>
	التغطية العالية (High coverage) لا تضمن الجودة العالية لكن التغطية غير المعروفة (unknown coverage) هي مؤشر واضح لمشاكل الصيانة. عندما يدخل مُطور جديد للمشروع، يجب أن يكون قادرًا على إجراء بعض التغييرات ومعرفة مدى تأثر التغطية بها. من الناحية المثالية، يجب فحص تغطية الاختبار بنفس طريقة التحليل الثابت، ويجب أن يفشل البناء إذا كانت أقل من عتبة محددة مسبقًا (عادة ما تكون حوالي 80 بالمائة).
</p>

<h2 id="-">
	تطوير دون توقف
</h2>

<p>
	ما أقصده بدون توقف هو أنه بدون مراحل وإصدارات. بغض النظر عن نوع البرنامج الذي تكتبه، يجب عليك إصداره وتعديله بشكل متكرر. مشروع بدون سجل إصدار واضح هو فوضى يتعذر إصلاحها.
</p>

<p>
	هذا في الغالب لأن الصيانة تدور حول القدرة على الفهم عند قراءة شيفرتك.
</p>

<p>
	عندما أنظر إلى الشيفرة المصدرية وسجل الالتزام والإصدار، يجب أن أكون قادرًا على معرفة ما كان يقصده كاتبها أو كاتبوها، وما الذي كان يفعله المشروع قبل عام، وإلى أين يتوجه الآن، وما هي خريطة التوجه الخاصة به، وغير ذلك. يجب أن تكون كل هذه المعلومات في الشيفرة المصدرية، والأهم من ذلك، في سجل Git.
</p>

<p>
	وسوم <a href="https://git-scm.com/book/en/v2/Git-Basics-Tagging" rel="external nofollow">Git</a> و<a href="https://github.blog/2013-07-02-release-your-software/" rel="external nofollow">ملاحظات إصدار</a> Github هما أداتان قويتان توفران لي هذه المعلومات. استخدمها إلى أقصى حد. ولا تنسَ أن كل إصدار ثنائي للمنتج يجب أن يكون متاحًا للتحميل المباشر. يجب أن أكون قادرًا على تنزيل الإصدار 0.1.3 واختباره مباشرةً، حتى لو كان المشروع يعمل على الإصدار 3.4 في الوقت الحالي.
</p>

<h2 id="-">
	الواجهات غير الموثّقة
</h2>

<p>
	كل جزء من البرنامج لديه واجهات يُفترض أن يُستَخدم من خلالها. إذا كان البرنامج عبارة عن مدير الحزم Ruby gem، فهناك أصناف وطرائق سأستخدمها بوصفي مستخدم نهائي لها. وإذا كان أحد تطبيقات الويب، فهناك صفحات ويب سيراها المستخدم النهائي ويتحكم بها لاستخدام التطبيق. يحتوي كل مشروع برمجي على واجهات، ويجب أن تكون موثّقةً بعناية.
</p>

<p>
	مثل كل شيء سابق، فإنَّ هذا أيضًا له علاقة بالصيانة. بوصفي مبرمجًا جديدًا في مشروع ما، سأبدأ في التعرف عليه من واجهاته. ويجب أن أكون قادرًا على فهم ما يفعله ومحاولة استخدامه بنفسي.
</p>

<p>
	أنا أتحدث هنا عن التوثيق للمستخدمين، وليس للمطورين. بشكلٍ عام، أنا ضد التوثيق داخل البرنامج. وأتفق تمامًا مع <a href="http://agilemanifesto.org/" rel="external nofollow">Agile Manifesto</a>- بأن عمل البرنامج أهم بكثير من الوثائق الشاملة. لكن هذا لا يشير إلى التوثيق "الخارجي"، التي يفترض أن يقرأه المستخدمون، وليس المطورون. لذلك يجب توثيق تفاعل المستخدم النهائي مع البرنامج بشكل واضح.
</p>

<p>
	إذا كان برنامجك عبارة عن مكتبة، فإن مستخدميها النهائيين الذين سيستخدمونها هم من مطوري البرامج - لا يساهمون فيها ولكن يستخدمونها ببساطة كـ"الصندوق الأسود".
</p>

<p>
	هذه هي المعايير المستخدمة لتقييم المشاريع المفتوحة المصدر التي دخلت المنافسة على <a href="https://www.yegor256.com/2015/04/16/award.html" rel="external nofollow">الجائزة</a> لدينا.
</p>

<p>
	ترجمة -وبتصرف- للمقال <a href="https://www.yegor256.com/2015/06/08/deadly-sins-software-project.html" rel="external nofollow">Seven Deadly Sins of a Software Project</a> لصاحبه Yegor Bugayenko.
</p>
]]></description><guid isPermaLink="false">742</guid><pubDate>Mon, 28 Oct 2019 14:02:00 +0000</pubDate></item></channel></rss>
