كيف يعمل التطبيق فعلا
التطبيق برنامج يُثبَّت على الجهاز نفسه، تعمل واجهته ومنطقه داخل ذلك الجهاز، ويحادث خادما من أجل كل بيانات جديدة. وأغلب ما يسميه المستخدم بطء التطبيق يجري داخل تلك المحادثة مع الخادم، لا في الشفرة القابعة على الهاتف.
- الدرس 1 من 8
- مبتدئ
- مجاني، دون تسجيل
طبقات التطبيق الخمس، والحد الذي تُتخذ عليه كل القرارات
- واجهة المستخدمالطبقة الوحيدة التي يراها المستخدم، والوحيدة التي يخبرك أحد بها حين تتعطل.
- منطق التطبيقيقرر ما تفعله كل لمسة وهل البيانات اللازمة على الجهاز أم يجب طلبها.
- عقد واجهة البرمجةالحد الحقيقي. ما فوقه يخص جهازا واحدا وما تحته مشترك بين المستخدمين جميعا.
- الواجهة الخلفيةموضع المنطق الذي يجب ألا يكون على جهاز المستخدم: الأسعار والمخزون والصلاحيات والدفع.
- قاعدة البياناتتحفظ الأشياء. ولا يحادثها المستخدم مباشرة أبدا ولا ينبغي أن يقدر على ذلك.
هذا الترتيب الطبقي ترتيب تعلّم لا معيار، والأسماء تختلف من فريق إلى فريق. الطبقتان العلويتان على الهاتف والثلاث السفلى على الخادم.
آخر مراجعة: تُراجع الحقائق وأسماء الأدوات في هذا الدرس مقابل مصادرها في هذا التاريخ.
ماذا يحدث حين تضغط زرا؟
نقرة واحدة تشغّل أربعة أعمال متتابعة. أولا تعرف شفرة الواجهة أين لُمست الشاشة وإلى أي زر تعود تلك اللمسة. ثم يقرر منطق التطبيق ما البيانات التي يحتاجها هذا الزر وهل هي موجودة على الجهاز أصلا. فإن لم تكن، ذهب طلب HTTPS إلى خادم. وأخيرا يتحول ما يعود إلى شاشة.
ثلاثة من هذه الأربعة تنتهي في أجزاء من الألف من الثانية. أما الثالث فلا. فالذهاب والإياب إلى الخادم هو الجزء الأطول دائما تقريبا، وإن قِسته مرة بنفسك لم تنسه بعدها. يرسل هذا الأمر طلبا واحدا إلى واجهة هذا الموقع نفسه ويطبع مراحله منفصلة:
curl -s -o /dev/null -w 'dns=%{time_namelookup} tls=%{time_appconnect} first_byte=%{time_starttransfer} bytes=%{size_download}\n' "https://rgb.ir/wp-json/wp/v2/posts?per_page=1&_fields=id,title,link,date"شغّلناه ثلاث مرات متتابعة. استغرق حل اسم النطاق بين ١٫٤ و٤٫٢ من الألف من الثانية، وانتهت مصافحة TLS الآمنة عند ٣١ إلى ٤٩ من الألف، ووصل أول بايت من الجواب بين ١٦٧ و١٩٤ من الألف. وكل ما عاد كان ٣٥٣ بايت. وبعد ساعات أخذنا الأمر نفسه مرة أخرى فجاء أول بايت هذه المرة بين ١٨٠ و٢٥١ من الألف، بينما بقي حجم الجواب ٣٥٣ بايت بالضبط. والرقم الجدير بالحفظ هو ٣٥٣ لا الأزمنة.
انظر إلى النسب. أخذ إنشاء الاتصال الآمن نحو ربع الزمن، والباقي هو ما احتاجه الخادم ليبني الجواب. وطوال ذلك لم يفعل التطبيق شيئا سوى الانتظار. وهنا بالضبط يقول المستخدم إن البرنامج بطيء ويذهب المبرمج يبحث عن تحسينات في الواجهة.

طريق نقرة واحدة، والموضع الذي يذهب إليه الوقت
-
1
لمس الشاشة
تعرف الواجهة أين وقعت اللمسة وإلى أي زر تعود.
-
2
المنطق يقرر
أهي البيانات على الجهاز أصلا؟ إن كانت، انتهى العمل هنا.
-
3
طلب HTTPS
هنا يُنفَق الوقت فعلا. والمصافحة الآمنة جزء من هذه الخطوة أيضا.
-
4
الخادم يبني الجواب
ردود الواجهة لا تُخزَّن مؤقتا، فكل نقرة تنفيذ كامل على الخادم.
-
5
إعادة رسم الشاشة
كلما خف الجواب قصرت هذه الخطوة، حتى على هاتف رخيص.
على هذا الموقع نفسه أعادت الخطوة الثالثة أول بايت بين ١٦٧ و١٩٤ من الألف من الثانية. والخطوات الثلاث الأخرى مجتمعة لا تبلغ ذلك، وإن كانت الخطوة الأخيرة تظهر أيضا على هاتف ضعيف.
من أي طبقات يُبنى التطبيق؟
خمس طبقات، والحد الواقع بين اثنتين منها أهم من الطبقات نفسها. واجهة المستخدم هي ما يُرى ويُلمس: الأزرار والقوائم والنماذج. ومنطق التطبيق يقرر ما ينبغي أن تفعله كل لمسة وما يُعرض. وكلاهما يعمل على الهاتف نفسه.
الطبقة الثالثة هي واجهة البرمجة، أي العقد الذي يحدد بأي عنوان وبأي شكل يطلب التطبيق البيانات من الخادم، وبأي شكل يجيب الخادم. وعلى الجانب الآخر من ذلك العقد تجلس الواجهة الخلفية على خادم تنفّذ المنطق الذي يجب ألا يكون على جهاز المستخدم: الأسعار والمخزون والصلاحيات والدفع. وتحتها قاعدة بيانات تحفظ الأشياء.
الحد الحقيقي بين الطبقة الثانية والثالثة. فكل ما فوقه يخص هذا الجهاز وحده، وكل ما تحته مشترك بين المستخدمين جميعا. وكل سؤال صعب يظهر في مشروع تطبيق ينتهي إلى هذا السؤال الواحد: أيجري هذا العمل فوق الحد أم تحته. وإن أخطأت الجواب عدّل العميل السعر على هاتفه.
الترتيب الطبقي أعلاه ترتيب تعلّم لا معيار، والأسماء تختلف من فريق إلى فريق. أما ما لا يختلف فهو ذلك الحد.
الأصلي والوب والهجين ثلاثة أشياء مختلفة
حين يقول العميل إنه يريد تطبيقا، فهو يعني في الغالب أيقونة على شاشة الهاتف. وثلاث تقنيات مختلفة تماما تمنحك تلك الأيقونة، ولا يظهر الفرق بينها إلا حين ينقطع الاتصال أو حين تريد إيصال نسخة جديدة.
الأصلي يعني برنامجا يُترجَم لذلك النظام ويُثبَّت بوصفه حزمة. وتوثيق أندرويد نفسه يقول ذلك بدقة: تطبيقات أندرويد تُكتب بكوتلن وجافا وسي بلس بلس، وأدوات SDK تجمع الشفرة والموارد في ملف APK أو App Bundle؛ وملف APK هو ما يستعمله الجهاز للتثبيت، أما App Bundle فلا يُثبَّت على جهاز البتة لأنه صيغة نشر لا صيغة تثبيت. وهذه الجملة وحدها تنفعك لاحقا عند النشر.
الوب يعني ما يُفتح في المتصفح. لا يُثبَّت شيء، ويصل التحديث إلى الجميع لحظة إطلاقه، والوصول إلى عتاد الهاتف محدود. وPWA صورة من ذلك، وهي بتعريف MDN مبنية بتقنيات الوب لكنها تقدم تجربة أشبه ببرنامج خاص بالمنصة: كالموقع تعمل على منصات عدة من قاعدة شفرة واحدة، وكالبرنامج المثبت يمكن تثبيتها على الجهاز والعمل دون اتصال وفي الخلفية والاندماج مع الجهاز.
الهجين يعني تطبيق وب مغلَّفا داخل قشرة أصلية. يبدو من الخارج أصليا وهو من الداخل وب. يعمل جيدا مع النماذج والمحتوى، ويُظهر سقفه حيثما كان هناك رسم متحرك ثقيل أو عمل متصل بالكاميرا والحساسات.
وموقفنا بسيط: الاختيار بين هذه الثلاثة ليس قرارا في التقنية، بل قرار في الحال التي يكون فيها مستخدمك حين يستعمل البرنامج. فمن يعمل في مستودع بلا تغطية ومن يجلس في مكتب على واي فاي يحصلان على جوابين مختلفين.
المواضع الأربعة التي يفترق فيها الأصلي والوب فعلا
-
تثبيت أم فتح
الأصلي حزمة تُثبَّت وتصنع أيقونة. والوب يُفتح بعنوان فحسب، وهذا أقل احتكاك ممكن عند الدخول.
-
ماذا يحدث بلا اتصال
الأصلي يستطيع حفظ نسخة من البيانات وعرض شيء. والوب البسيط يعرض صفحة خطأ، إلا أن يكون PWA مبنيا لهذه الحال بعينها.
-
من أين تصل النسخة الجديدة
الوب يصل إلى الجميع في اللحظة نفسها. والأصلي عليه المرور بمتجر، ويبقى دائما مستخدمون على نسخة قديمة.
-
الوصول إلى العتاد
للأصلي وصول كامل إلى الكاميرا والحساسات والعمل في الخلفية. وللوب جزء من ذلك، وحده يحدده المتصفح لا أنت.
الهجين لا موضع له عمدا في هذه الخانات الأربع، لأنه يختار في كل واحدة جهة: يُثبَّت كالأصلي وهو من الداخل وب.
ما الذي يبقى على الهاتف وما الذي يعيش على الخادم؟
قاعدتان تنهيان الأمر. كل ما يجب أن يراه شخصان على صورة واحدة يبقى على الخادم: الأسعار والمخزون والطلبات والرسائل. وكل ما يجب أن يراه المستخدم بلا اتصال يحتاج إلى نسخة على الجهاز: الإعدادات والمسودات وآخر قائمة نظر إليها، وعلامة الدخول التي تعفيه من كتابة كلمة السر كل مرة.
وعلامة الدخول تلك، وتسمى الرمز المميز، هي الموضع الحساس. فما دامت على الجهاز بقي المستخدم داخلا، وهذه هي الراحة. وإن ضاع الهاتف ضاع الرمز معه، فوجب أن يكون قابلا للإبطال من جهة الخادم. وهذا ما لا تقدر عليه إلا الواجهة الخلفية ولا يعوّضه أي قدر من الشفرة على الهاتف.
وثمة كلام غير محبوب عن العمل دون اتصال أيضا. فأغلب المشاريع التي تطلب وضعا دون اتصال تريد في الحقيقة ألا يرى المستخدم شاشة خطأ وهو بلا تغطية داخل مصعد. وما تحتاجه هو ذاكرة قراءة مؤقتة، وهي رخيصة. أما العمل الحقيقي دون اتصال فيعني أن يستطيع المستخدم تغيير شيء بلا اتصال، وعندها عليك أن تقرر من يفوز إذا غيّر شخصان الشيء نفسه في وقت واحد. وهذا القرار مكلف، والمشروع الذي لا يحتاجه ينبغي ألا يشتريه.
لماذا يكون تطبيقك بسرعة واجهته البرمجية بالضبط
شاشة قائمة عادية تعرض عشرة صفوف. طلبنا من واجهة هذا الموقع عشر مقالات، مرة بالشكل الافتراضي ومرة بقولنا إننا نحتاج أربعة حقول فقط:
curl -s -o /dev/null -w '%{size_download}\n' "https://rgb.ir/wp-json/wp/v2/posts?per_page=10"
curl -s -o /dev/null -w '%{size_download}\n' "https://rgb.ir/wp-json/wp/v2/posts?per_page=10&_fields=id,title,link,date"كان الجواب الأول ٤٠٣٬١٥٢ بايت والثاني ٣٬٧٨٠ بايت. وللمقالة الواحدة يصير الزوج نفسه ٣٧٬٣٤١ بايت مقابل ٣٥٣ بايت. أخذنا خمس عينات متتابعة فبقيت الأحجام متطابقة؛ أما الأزمنة فلا، وقد استغرقت واحدة من تلك الخمس ٥٫٣ ثانية على هذا الخادم الحي. وهذا الفارق درس بذاته: الحجم متوقع والزمن ليس كذلك.
لم يتغير شيء في جهة التطبيق. صارت شاشة القائمة أخف مئة مرة لأن الطلب قال ما يحتاجه. وبقية تلك الـ٤٠٣ كيلوبايت كانت النص الكامل المعروض للمقالات، وهو ما لا تعرضه شاشة قائمة أبدا.
وحمل القياس نفسه شيئا آخر. جاءت ردود الواجهة بترويسة x-flying-press-cache: MISS وcf-cache-status: DYNAMIC، أي أنه خلافا لصفحات HTML في هذا الموقع لا يُخزَّن أي من هذه الردود مؤقتا، وكل نقرة تنفيذ كامل لـPHP. فالخادم الذي يجيب زائر الوب بأريحية يؤدي عملا من نوع آخر تحت تطبيق.
فالترتيب الصحيح للعمل هو هذا: قبل اختيار إطار العمل، انظر إلى ما تعيده واجهتك. والدرس التالي في هذا المسار يتناول ذلك الاختيار بعينه، أصلي أم متعدد المنصات، وهو متاح من قائمة الدروس في صفحة مسار تطوير التطبيقات. وإن أردت أن ترى شكل العقد نفسه من جهة الوب، فإن درس ما هي واجهة البرمجة يفتحه من الأساس.
الشاشة نفسها، قبل أن يقول الطلب ما يريد وبعده
- مقالة واحدة ٣٧٬٣٤١ بايت٣٥٣ بايت
-
قائمة عشر مقالات
٤٠٣٬١٥٢ بايت٣٬٧٨٠ بايت
شاشة القائمة هي موضع الفرق، لأنها تطلب عشرة أضعاف البيانات.
هذه الأرقام حجم لا زمن. بقي الحجم ثابتا تماما في خمس عينات، بينما بلغ الزمن ٥٫٣ ثانية مرة؛ وعلى بيانات الهاتف الحجم هو الذي يظهر أثره.
المسار السريع مع الذكاء الاصطناعي
أسرع ما يمكن أن يفعله النموذج لك هنا ليس كتابة الشفرة. بل استخراج عقد البيانات للتطبيق قبل وجود سطر واحد: ماذا تعرض كل شاشة، ومن أي عنوان يأتي ذلك، وأي الحقول تلزم بالضبط. وهي الحركة نفسها التي خففت شاشة القائمة مئة مرة في القسم الأخير.
- اكتب شاشات التطبيق بأسمائها كما تصفها لإنسان: تسجيل الدخول، قائمة الطلبات، تفاصيل الطلب، الملف الشخصي. بلا تقنية وبلا إطار عمل.
- اكتب لكل شاشة ما يراه المستخدم عليها فعلا فقط. فإن كانت شاشة القائمة تعرض عنوانا وتاريخا، فاكتب هذين الاثنين ولا شيء غيرهما.
- سلّم تلك القائمة إلى نموذج قوي مع الوصفة أدناه ليبني عقد الواجهة. واختر نموذجا من فئة الحكم لا الأسرع والأرخص، فالعمل هنا قرار لا ترجمة.
- الخطوة الأخيرة هي ما لا يفعله غيرك: اطلب من النموذج حذف كل حقل لا تستهلكه أي شاشة، وأن يقول أي الحقول خمّنه. وهذا السطر وحده يحوّل القائمة من شيء يبدو حسنا إلى شيء خفيف.
وصفة جاهزة للنسخ
الدور: مهندس واجهة برمجة لتطبيق موبايل.
شاشات التطبيق وما تعرضه كل واحدة:
{الشاشة ١}: {الحقول التي يراها المستخدم عليها}
{الشاشة ٢}: {الحقول التي يراها المستخدم عليها}
{الشاشة ٣}: {الحقول التي يراها المستخدم عليها}
ما ينبغي فعله، بهذا الترتيب:
١. اكتب لكل شاشة طلبا واحدا: الطريقة والعنوان والمعاملات ونموذج رد JSON.
٢. أبقِ في نموذج الرد الحقول التي تعرضها تلك الشاشة فقط. واحذف كل حقل زائد.
٣. أعطِ جدولا بالحقول التي حذفتها والشاشة التي قد تُعيد كلا منها عند الحاجة.
٤. اذكر منفصلا أي الأسماء أو البنى خمّنتها، وأين ينبغي أن أتحقق منها.
٥. إن كانت بيانات مشتركة بين شاشتين، فقل أي شاشة ينبغي أن تخزنها مؤقتا وكم مدة.
لا تكتب أي رقم عن السرعة أو الحجم. سأقيس ذلك بنفسي.
قبل أن تثق بالناتج: مخرج هذه الوصفة اقتراح لا وثيقة. فالنموذج يخترع أسماء الحقول بل والعناوين، ولذلك يجب أن يُقارَن كل سطر منه بما تعيده الواجهة الخلفية فعلا؛ وطلب curl واحد على العنوان الحقيقي ينهي ذلك. وإن لم يكن للمشروع واجهة خلفية بعد، فهذا العقد مدخل لبنائها لا بديل عنها.
الذكاء الاصطناعي في هذا العمل
في هذا الموضوع تُحسن النماذج أمرين حقا وتسيء في أمر. تُحسن قراءة وثيقة منصة طويلة، واستخراج عقد بيانات من وصف شاشة. وتسيء في كل جملة تمس رقما أو سياسة متجر. وموقفنا أن تضع النموذج في جهة تصميم العقد وتبقيه خارج جهة إطلاق الادعاءات.
أدوات تساعد فعلا
- Claude مناسب لما تطلبه الوصفة أعلاه بالضبط: تحويل وصف الشاشات إلى عقد بيانات، والأهم حذف ما لا تحتاجه أي شاشة. وإيران ليست في أي من قائمتَي الدول المدعومة لدى أنثروبيك؛ قرأنا ذلك على صفحتهم لا من قياس شبكي.
- Gemini جيد في قراءة وثائق المنصات الطويلة، وهذا الدرس نفسه أخذ عدة جمل من توثيق أندرويد الرسمي. وتقول صفحة غوغل نفسها إن تطبيق جيميناي على الوب يعمل في أكثر من مئتين وثلاثين دولة وإقليما، وإيران ليست في تلك القائمة.
- NotebookLM حين يكون السؤال ما الذي تقوله وثيقة SDK بالضبط، فهذه الأداة أصوب من محادثة عادية، لأنها تجيب من المصدر الذي أعطيتها إياه فقط. وتقول مساعدة غوغل نفسها إنها تعمل في المناطق ذاتها التي يعمل فيها تطبيق جيميناي، وإيران ليست في تلك القائمة.
- GitHub Copilot يعمل داخل المحرر، وقصة الوصول إليه هي الأكثر مفاجأة للقارئ الإيراني: تقول صفحة ضوابط التجارة في جيتهاب نفسها إن ترخيصا من الخزانة الأمريكية يغطي خدماتها السحابية للمطورين المقيمين في إيران، المجانية والمدفوعة. ننقل هذا ولا ندّعي شيئا عن الدفع.
اين ينقلب ضدك
الخطر الأول هنا خاص بالتطبيقات ومتصل بالنموذج مباشرة. فالتطبيق يذهب إلى هاتف المستخدم، وكل ما في الحزمة يصير في يد من يملك ذلك الهاتف. والنماذج تكتب عادة شفرة مثال ومفتاح الواجهة في وسطها، لأن هذه هي الطريقة الوحيدة ليعمل المثال؛ ثم يُنسخ ذلك المثال ويُرسل إلى متجر. وقائمة OWASP Mobile Top 10 في إصدار ٢٠٢٤ تضع سوء استعمال بيانات الاعتماد في المرتبة الأولى وضعف حماية الملف النهائي في السابعة. والقاعدة التي تخرج من هذا الدرس بسيطة: المفتاح الذي يجب أن يبقى سرا لا موضع له فوق الحد وينتمي إلى الواجهة الخلفية.
والخطر الثاني أكثر اعتيادا. فالنموذج الذي يكتب عن حزم تطوير الموبايل أو قواعد المتاجر يخترع اسم دالة أو شرط نشر باللهجة الواثقة نفسها. وكل جملة من هذا النوع يجب أن تُقارن بتوثيق الصانع نفسه. وسبيل الدفع من إيران لهذه الأدوات في دليل الشراء.
المصادر: OWASP Mobile Top 10 (2024) Anthropic: supported countries GitHub and Trade Controls Google: where the Gemini web app is available
حدود هذه النصيحة
يشرح هذا الدرس الشكل الشائع: تطبيق له شاشات يحادث واجهة برمجة عبر HTTP. والألعاب ليست هنا، وكذلك التطبيقات التي تُبنى قيمتها على الجهاز نفسه، كمعالجة صور الكاميرا أو نموذج يعمل على الهاتف؛ ففيها يقع الحد الذي يقف عليه هذا الدرس في موضع آخر تماما. ولا بد من ملاحظة عنا أيضا: عمق خبرتنا المباشرة هو جهة الخادم من ذلك الحد، أي الاستضافة والواجهة، وكل رقم في هذه الصفحة رقم خادم لا رقم تطبيق موبايل منشور.
من عملنا نحن
على هذا الخادم نفسه نحتفظ بإضافة صغيرة إلزامية اسمها rgb-rest-raw.php وُجدت لسبب واحد لا غير. فالإضافة الأمنية Really Simple SSL تفتح ذاكرة إخراج مؤقتة وتحوّل كل https://rgb.ir إلى https://rgb.ir في بدن الرد كله. وهذا صحيح مع HTML. أما على رد JSON فهو إفساد صامت: فأداة فحص إعادة التوجيه عندنا وُجدت لتُظهر أن عنوان http يُعاد توجيهه إلى https، وتلك الكتابة جعلت الحلقة الأولى من السلسلة تُقرأ https إلى https، أي أن ما بُنيت الأداة لاكتشافه صار غير مرئي. وكانت القيمة المحفوظة في قاعدة البيانات صحيحة، ولم يُعدَّل إلا بدن المخرج. ولم يكن أي متصفح ليلاحظ ذلك. أما برنامج يقرأ العنوان بايتا بايتا فيلاحظ. والأمر الثاني من نوع آخر: واجهتنا العامة خلف كابتشا، وأعاد طلب بسيط إلى /wp-json/rgb/v1/domain اليوم الرمز ٤٢٢ ورسالة تطلب انتظار اكتمال التحقق الأمني. وهذا صحيح على نموذج في موقع، وهو بعينه سبب أن التطبيق لا يستطيع استهلاك واجهة موقع كما هي ويحتاج إلى مسار مصادقة خاص به.
اسئلة متابعة حقيقية
هل أحتاج حتما إلى خادم لبناء تطبيق؟
لا، إن بقي كل شيء على الجهاز نفسه: حاسبة، ملاحظات دون اتصال، أداة قياس. أما لحظة أن يلزم أن يرى جهازان الشيء نفسه على صورة واحدة، أو أن يسجل مستخدم دخوله إلى حساب، فيصير الخادم لازما لا اختياريا. والقاعدة في القسم الرابع تحدد ذلك الحد.
ما الفرق بين التطبيق وموقع الموبايل؟
أربعة أمور: التطبيق يُثبَّت ويصنع أيقونة، ويستطيع عرض شيء بلا اتصال، وله وصول كامل إلى الكاميرا والحساسات والعمل في الخلفية، ونسخته الجديدة عليها المرور بمتجر. والموقع لا شيء من ذلك عنده، وفي المقابل لا احتكاك عنده عند الدخول ويصل تحديثه إلى الجميع في اللحظة نفسها.
لماذا يكون تطبيقي سريعا على الواي فاي وبطيئا على بيانات الهاتف؟
لأنها مشكلة حجم دائما تقريبا لا مشكلة شفرة. فالواي فاي يخفي الحمل الكبير وبيانات الهاتف لا تخفيه. والقياس في القسم الأخير يبين ذلك بالضبط: كانت شاشة قائمة من عشرة صفوف في هذا الموقع ٤٠٣٬١٥٢ بايت بشكلها الافتراضي وصارت ٣٬٧٨٠ بايت حين سمّى الطلب الحقول الأربعة التي يحتاجها، دون أي تغيير في جهة التطبيق.