هندسة
إضافة عميل موبايل لمنتج له تطبيق ويب بالفعل
By Clasify Team · · 5 min read
إضافة عميل موبايل إلى منتج له تطبيق ويب بالفعل تبدو تمرينًا في النقل. وهي ليست كذلك. فتطبيق الويب راكم سنوات من السلوك، والعمل المثير هو تقرير أي جزء منه ينتمي إلى الهاتف، ثم منع الاثنين من التباعد بعد أن يصيرا حيّين معًا.
بنينا عميل Flutter لـ Clasify، منصتنا للأكاديميات، بقاعدة كود واحدة تخدم iOS وأندرويد. وهذه المشكلات الثلاث هي ما كلّفنا وقتًا فعليًا — ولا واحدة منها كانت في التخطيط البصري.
التكافؤ هدف متحرك، فاختبره بوصفه سلوكًا
الخطة الساذجة قائمة مراجعة: هذه شاشات الويب، أعد بناءها. وتبدأ هذه الخطة في التعفّن يوم يغيّر أحدهم شاشة ويب، لأن لا شيء يخبر تطبيق الموبايل أنه تخلّف.
والأسوأ أن اختبارات الموبايل المعتادة لا تلتقط ذلك. اختبار الـ widget يثبت أن مكوّنًا يُرسم بمعزل. واختبار لقطة الشاشة يثبت تطابق البكسلات مع مرجع، ويثبت غالبًا أن المرجع قديم. ولا واحد منهما يلاحظ أن شاشة صارت ترمي استثناءً حين تحمّل بيانات حقيقية لدور حقيقي.
ما نشغّله بدلًا من ذلك اختبار تكافؤ يقود التطبيق الفعلي: يسجّل الدخول بوصفه معلمًا، ويمشي في كل شاشة مسّها عمل التكافؤ — الجدول، والحضور والتحليلات، والطلاب، والملخصات، والواجبات، والرئيسية — ثم يسجّل الدخول بوصفه طالبًا ويكرّر. ويفشل الاختبار إذا رمت أي شاشة استثناءً أثناء بنائها.
وهذا سقف منخفض عن قصد. فهو لا يتحقق من صحة الشاشة، بل يتحقق من أنها **موجودة وتنجو من ملامسة بيانات حقيقية لذلك الدور** — وهذا هو الفشل الذي يُشحن فعلًا. فمعظم انحدارات الموبايل التي كنا سنشحنها لم تكن بكسلات خاطئة، بل شاشة افترضت حقلًا توقفت الواجهة عن إرساله، لدور واحد فقط.
وتشغيله لكل دور أهم من تشغيله لكل شاشة. فالمعلم والطالب يريان أشكالًا مختلفة من البيانات نفسها، والخلل يكون دائمًا تقريبًا في الدور الذي اختبرته أقل.
قرار النطاق ميزة، ويحتاج اختبارًا هو أيضًا
ليس كل ما في الويب ينتمي إلى الهاتف. بعضه أسوأ فعليًا هناك، وبعضه من الخطورة بحيث يكون صِغَر السطح هو المقصد نفسه.
تغيير كلمة المرور واحد مما تركناه عمدًا خارج شاشة الملف الشخصي في الموبايل. وهذا قرار حقيقي بسبب حقيقي — لكن القرارات من هذا النوع هي بالضبط ما يُنقض بهدوء بعد ستة أشهر على يد من يضيف "الزر الناقص" بحسن نية.
لذلك للغياب اختبار. هناك اختبار تكامل مهمته كلها التأكيد على أن زر تغيير كلمة المرور الاختياري **ليس** على شاشة الملف الشخصي، للمعلم وللطالب الذي يشاركه الشاشة نفسها.
وكتابة اختبارات لأشياء يجب ألا توجد تبدو غريبة في المرة الأولى. وهي أرخص طريقة لجعل قرار النطاق مُعمِّرًا — المنطق نفسه في تعليق يشرح لماذا سطرٌ غائب، إلا أن الاختبار لا يمكن تخطّيه بالقراءة السريعة.
الجهاز ليس مستخدمًا، وفي نظام متعدد المستأجرين ليس مستأجرًا أيضًا
الإشعارات هي حيث يكفّ الموبايل عن كونه عميلًا ويبدأ في كونه مشكلة أنظمة موزّعة بذاته.
النموذج يبدو بسيطًا. يسجَّل جهاز، فتخزّن الـ token الخاص به، ثم ترسل إليه. وفي مخططنا يحمل الجهاز المسجَّل المنصة والـ token والمستخدم الذي يخصّه والمستأجر. والخطوة التالية البديهية أن تعامل هذا الـ token كأي صف آخر مملوك لمستأجر فتحصر البحث بالمستأجر.
وهذا خطأ، ولزم خللٌ حقيقي كي نرى لماذا.
مفتاح التسجيل هو الـ token، والـ token يخصّ **الهاتف** لا شخصًا ولا أكاديمية. فالجهاز نفسه قد يكون جهاز معلم في أكاديمية، ثم يُسجَّل خروجه ويدخل بحساب شخص في أكاديمية أخرى على التطبيق ذاته. وإن بحث التسجيل عن الجهاز محصورًا بمستأجر المُستدعي، فلن يجد الصف القائم — ثم يحاول إدخال token موجود سلفًا، فيصطدم بقيد التفرّد الذي كان يُفترض به ترتيب الأمور.
لذلك فالبحث عن الـ token أثناء التسجيل عام عن قصد، وكل عملية أخرى على الأجهزة — سرد أجهزة مستخدم، أو حذف واحد — محصورة صراحةً بدلًا من ذلك. والاستثناء مكتوب وسببه بجانبه، لأن بحثًا عامًا بلا تفسير في نظام متعدد المستأجرين يبدو تمامًا كخلل وسيُصلَح في النهاية.
والدرس العام: الهاتف يعمّر أطول من أي جلسة وأي مستأجر. فامذجه بوصفه شيئًا طويل العمر بذاته يرتبط به مستخدم حاليًا، لا بوصفه مِلكًا للمستخدم.
ما سنقوله لفريق آخر
- قرّر ما **ليس** تطبيق الموبايل قبل أن تقرّر ما هو، وضع المحذوفات تحت الاختبار.
- اختبر التكافؤ بوصفه سلوكًا زمن التشغيل لكل دور، لا بوصفه لقطات شاشة. سؤال "هل تنجو هذه الشاشة من بيانات حقيقية لهذا المستخدم؟" يلتقط ما ينكسر فعلًا.
- عامل هوية الجهاز منفصلةً عن هوية المستخدم وهوية المستأجر. عمرها مختلف عنهما.
- اكتب السبب بجانب كل استثناء مقصود. ففي قاعدة كود متعددة المستأجرين، يُقرأ الاستعلام غير المحصور بلا تفسير على أنه عيب.
قاعدة كود واحدة للمنصتين كانت القرار الصحيح لنا، ولم يكن إطار العمل يومًا هو الجزء الصعب. الجزء الصعب كان الحدّ: ما الذي ينتمي إلى هنا، وكيف نعرف أنه انحرف؟
نبني عملاء موبايل لفرق أخرى ضمن تطوير تطبيقات الجوال، وكيف بنينا Clasify يغطي الواجهة الخلفية التي يخاطبونها.
كل المقالات