SQLite مقابل Realm للتخزين غير المتصل في تطبيقات الميدان
مقارنة بين SQLite وRealm للتخزين غير المتصل لتطبيقات الميدان: الترحيلات، خيارات الاستعلام، معالجة التعارضات، أدوات التصحيح، ونصائح عملية للاختيار.

ما الذي تحتاجه تطبيقات الميدان ذات النهج غير المتصل فعلاً؟
النهج غير المتصل لا يعني فقط “يعمل بدون إنترنت”. يعني أن التطبيق يمكنه تحميل بيانات مفيدة، قبول مدخلات جديدة، والحفاظ على كل تعديل آمنًا حتى يمكن مزامنته.
العمل الميداني يضيف مجموعة محددة من القيود: انقطاع الإشارة وعودتها، الجلسات الطويلة، الأجهزة القديمة الممكنة، ووضعيات حفظ البطارية الشائعة. الناس يتحركون بسرعة. يفتحون مهمة، يتصفحون قوائم طويلة، يلتقطون صورًا، يملؤون استمارات، وينتقلون للمهمة التالية دون التفكير في التخزين.
ما يلاحظه المستخدمون بسيط. يفقدون الثقة عندما تختفي التعديلات، عندما تتباطأ القوائم والبحث أثناء عدم الاتصال، عندما لا يستطيع التطبيق أن يجيب بوضوح على “هل عملي محفوظ؟”، عندما تتكرر السجلات أو تختفي بعد إعادة الاتصال، أو عندما يسبب تحديث سلوكًا غريبًا.
لهذا اختيارك بين SQLite وRealm يتعلق في الغالب بسلوك اليومي، لا بالمعايير التقنية فقط.
قبل أن تختار قاعدة بيانات محلية، حدد أربعة مجالات بوضوح: نموذج البيانات سيتغير، استعلاماتك يجب أن تطابق سير العمل الحقيقي، المزامنة دون اتصال ستخلق صراعات، والأدوات ستحدد مدى سرعة تشخيص مشكلات الميدان.
1) بياناتك ستتغير
حتى التطبيقات المستقرة تتطور: حقول جديدة، حالات معاد تسميتها، شاشات جديدة. إذا كانت الترحيلات مؤلمة، فإما أنك تطلق تحسينات أقل أو تخاطر بكسر أجهزة حقيقية ببيانات حقيقية.
2) الاستعلامات يجب أن تطابق سير العمل الحقيقي
تطبيقات الميدان تحتاج فلاتر سريعة مثل “مهام اليوم”، “المواقع القريبة”، “النماذج غير المتزامنة”، و“العناصر المحررة خلال الساعتين الماضيتين”. إذا جعلت قاعدة البيانات هذه الاستعلامات محرجة، تصبح واجهة المستخدم بطيئة أو يتحول الكود إلى متاهة.
3) المزامنة دون اتصال تخلق صراعات
قد يقوم شخصان بتحرير نفس السجل، أو يعِدّل جهاز واحد بيانات قديمة لأيام. تحتاج خطة واضحة لما يفوز، ما يُدمج، وما يتطلب قرارًا بشريًا.
4) الأدوات مهمة
عندما يحدث خطأ في الميدان، تحتاج إلى فحص البيانات، إعادة إنتاج المشكلة، وفهم ما حدث دون تكهنات.
الترحيلات: تغيير نموذج البيانات دون كسر المستخدمين
نادراً ما تبقى تطبيقات الميدان ثابتة. بعد أسابيع قليلة، تضيف خانة اختيار، تعيد تسمية حالة، أو تفصل حقل “الملاحظات” إلى حقول مهيكلة. الترحيلات هي المكان الذي تفشل فيه التطبيقات دون اتصال غالبًا، لأن الهاتف يحمل بيانات حقيقية بالفعل.
SQLite يخزن البيانات في جداول وأعمدة. Realm يخزن البيانات ككائنات بخصائص. يظهر هذا الاختلاف بسرعة:
- مع SQLite، عادةً تكتب تغييرات مخطط صريحة (ALTER TABLE، جداول جديدة، نسخ بيانات).
- مع Realm، عادةً ترفع رقم إصدار المخطط وتنفذ دالة ترحيل تحدث الكائنات عند الوصول إليها.
إضافة حقل سهلة في كلا النظامين: أضف عمودًا في SQLite، وأضف خاصية مع قيمة افتراضية في Realm. إعادة التسمية والانقسام هما المؤلمتان. في SQLite، قد تكون إعادة التسمية محدودة حسب إعدادك، لذا غالبًا ما تنشئ الفرق جداول جديدة وتنسخ البيانات عبرها. في Realm، يمكنك قراءة الخاصية القديمة وكتابتها في جديدة أثناء الترحيل، لكن عليك أن تكون حذرًا من الأنواع، القيم الافتراضية، والقيم الخالية.
التحديثات الكبيرة مع بيانات على الجهاز تحتاج حذرًا إضافيًا. ترحيل يعيد كتابة كل سجل يمكن أن يكون بطيئًا على أجهزة قديمة، ولا ينبغي أن يبقى فني يراقب مؤشر تحميل في موقف سيارات. خطط لوقت الترحيل، وفكر في توزيع التحويلات الثقيلة على عدة إصدارات.
لاختبار الترحيلات بعدالة، عاملها كما لو كانت مزامنة:
- ثبّت إصدارًا قديمًا، أنشئ بيانات واقعية، ثم قم بالترقية.
- اختبر مجموعات بيانات صغيرة وكبيرة.
- أعد تشغيل التطبيق أثناء الترحيل وأعد تشغيله.
- اختبر سيناريوهات المساحة المنخفضة.
- افترض أنه يمكنك التقدم للأمام حتى لو لم تستطع الرجوع للخلف.
مثال: إذا أصبح “equipmentId” هو “assetId” ثم انقسم لاحقًا إلى “assetType” و“assetNumber”، يجب أن تجعل الترحيل الاحتفاظ بالتفتيشات القديمة قابلة للاستخدام، لا يجبر على تسجيل الخروج أو المسح.
مرونة الاستعلام: ماذا يمكنك أن تستعلم من بياناتك
تطبيقات الميدان تعتمد على شاشات القوائم: مهام اليوم، الأصول القريبة، العملاء ذوو التذاكر المفتوحة، الأجزاء المستخدمة هذا الأسبوع. اختيار التخزين يجب أن يجعل تلك الأسئلة سهلة التعبير، سريعة التنفيذ، وصعبة الفهم الخاطئ بعد ستة أشهر.
SQLite يمنحك SQL، وهي لا تزال أكثر الطرق مرونة لتصفية وترتيب مجموعات بيانات كبيرة. يمكنك دمج شروط، الانضمام بين الجداول، تجميع النتائج، وإضافة فهارس عندما تبطئ الشاشة. إذا كان تطبيقك يحتاج “كل التفتيشات للأصول في المنطقة أ، المخصصة للفريق 3، وبها أي عنصر فشل في قائمة التحقق”، فعادة ما يعبر SQL عن ذلك بوضوح.
Realm يعتمد على الكائنات وواجهة استعلام عالية المستوى. بالنسبة للعديد من التطبيقات هذا شعور طبيعي: استعلم عن كائنات Job، صفِّ حسب الحالة، رتب حسب تاريخ الاستحقاق، وتابع العلاقات لكائنات مرتبطة. المقايضة هي أن بعض الأسئلة التي تكون بسيطة في SQL (خاصة استعلامات تقارير عبر علاقات متعددة) قد تكون أصعب للتعبير عنها، أو قد تضطر إلى إعادة تشكيل البيانات لتناسب الاستعلامات المطلوبة.
البحث والعلاقات
للبحث الجزئي في نص عبر حقول متعددة (عنوان المهمة، اسم العميل، العنوان)، غالبًا ما يدفعك SQLite للتفكير في فهرسة دقيقة أو نهج نص كامل مخصص. يمكن لـRealm أيضًا تصفية النص، لكن عليك التفكير في الأداء ومعنى “يحتوي” عند النطاق الكبير.
العلاقات نقطة ألم عملية أخرى. يتعامل SQLite مع واحد إلى متعدد وكثير إلى كثير بواسطة جداول الربط، مما يجعل أنماط مثل “الأصول الموسومة بهذين الوسمين” مباشرة. روابط Realm سهلة التصفح في الكود، لكن الكثير إلى الكثير وأنماط “الاستعلام عبر” تتطلب تخطيطًا أكثر للحفاظ على سرعة القراءة.
الاستعلامات الخام مقابل سهولة الصيانة
نمط سهل الصيانة هو الاحتفاظ بمجموعة صغيرة من الاستعلامات المسماة التي تطابق الشاشات والتقارير: مرشحات القائمة الرئيسية والفرز، استعلام عرض التفاصيل (سجل واحد وسجلات مرتبطة)، تعريف البحث، بعض العدادات (شارات ومجاميع دون اتصال)، وأي استعلامات تصدير/تقرير.
إذا كنت تتوقع أسئلة ad hoc متكررة من العمل، فإن قوة استعلامات SQLite الخام صعب التفوق عليها. إذا أردت أن يقرأ معظم الوصول إلى البيانات كعمل مع كائنات عادية، فـRealm قد يكون أسرع في البناء، طالما أنه يجيب على أصعب الشاشات بدون حلول ملتوية.
حل التعارض والمزامنة: أي دعم تحصل عليه
تطبيقات الميدان ذات النهج دون اتصال عادةً تدعم نفس الأفعال الأساسية أثناء عدم الاتصال: إنشاء سجل، تحديث سجل، حذف شيء غير صالح. الجزء الصعب ليس الحفظ المحلي. إنه قرار ما يحدث عندما يغير جهازان نفس السجل قبل أن يتم التزامن.
تظهر التعارضات في مواقف بسيطة. يقوم فني بتحديث تفتيش على جهاز لوحي في قبو بدون إشارة. لاحقًا، يقوم مشرف بتعديل نفس التفتيش من حاسوب محمول. عندما يعيد كلاهما الاتصال، يتلقى الخادم نسختين مختلفتين.
تتبع معظم الفرق أحد هذه النهج:
- آخر كتابة تفوز (سريع، لكنه قد يكتب فوق بيانات جيدة بصمت)
- الدمج حسب الحقل (أكثر أمانًا عندما تتغير حقول مختلفة، لكنه يحتاج قواعد واضحة)
- قائمة مراجعة يدوية (الأبطأ، الأفضل للتغييرات عالية المخاطر)
SQLite يعطيك قاعدة محلية موثوقة، لكنه لا يوفر المزامنة بنفسه. عادةً تبني الباقي: تتبع العمليات المعلقة، إرسالها إلى واجهة برمجة تطبيقات، إعادة المحاولة بأمان، وفرض قواعد تعارض على الخادم.
Realm يمكن أن يقلل بعض الأعمال البنية التحتية إذا استخدمت ميزات المزامنة الخاصة به، لأنه مصمم حول الكائنات وتتبع التغييرات. لكن “المزامنة المدمجة” لا تختار قواعد عملك. أنت تقرر ما الذي يعد تعارضًا وما الذي يُسمح له بالفوز.
خطط لسجل تدقيقي من اليوم الأول. فرق الميدان غالبًا تحتاج إجابات واضحة عن “من غيّر ماذا، متى، ومن أي جهاز”. حتى لو اخترت أن آخر كتابة تفوز، احفظ بيانات وصفية مثل معرف المستخدم، معرف الجهاز، الطوابع الزمنية، وعند الإمكان سبب التغيير. إذا كان خلفيتك تُولد بسرعة، مثل منصة بدون كود مثل AppMaster (appmaster.io)، فستكون قادرًا على تكرار قواعد هذه القواعد مبكرًا قبل أن يكون لديك مئات الأجهزة غير المتصلة في الميدان.
التصحيح والفحص: التقاط المشكلات قبل أن يراها الميدان
أخطاء دون الاتصال صعبة لأنها تحدث عندما لا يمكنك مراقبة التطبيق وهو يتحدث إلى خادم. تجربتك في التصحيح غالبًا تتلخص في سؤال واحد: ما مدى سهولة رؤية ما على الجهاز وكيف تغير مع الوقت؟
SQLite سهل الفحص لأنه ملف. في التطوير أو الاختبار يمكنك سحب قاعدة البيانات من جهاز اختبار، فتحها بأدوات SQLite الشائعة، تشغيل استعلامات ad hoc، وتصدير الجداول إلى CSV أو JSON. هذا يساعدك على تأكيد “ما الصفوف الموجودة” مقابل “ما تُظهره الواجهة”. العيب أن عليك فهم مخططك والانضمامات وأي سقالات ترحيل أنشأتها.
Realm قد يشعر بأنه أكثر “تشابهًا مع التطبيق” للفحص. تُخزن البيانات ككائنات، وأدوات Realm غالبًا هي أسهل وسيلة لتصفح الفئات، الخصائص، والعلاقات. ممتاز لكشف مشاكل رسم كائنات (روابط مفقودة، قيم فارغة غير متوقعة)، لكن التحليل ad hoc أقل مرونة إذا كان فريقك معتادًا على فحص قائم على SQL.
تسجيل وإعادة إنتاج مشكلات دون الاتصال
معظم فشل الميدان يعود إلى أخطاء كتابة صامتة، دفعات مزامنة جزئية، أو ترحيل لم يكتمل نصفه. استثمر في بعض الأساسيات: طوابع زمنية “آخر تغيير” لكل سجل، سجل عمليات على الجهاز، سجلات مهيكلة حول الترحيلات والكتابات الخلفية، طريقة لتمكين تسجيل واسع النطاق في إصدارات الاختبار، وإجراء “تفريغ ومشاركة” يصدر لقطة مُنقّحة.
مثال: يبلغ فني أن التفتيشات المكتملة تختفي بعد نفاد البطارية. لقطة مشتركة تساعدك على التأكد مما إذا كانت السجلات لم تُكتب أبدًا، كُتبت لكن لم تُستعلم، أو تم التراجع عنها عند بدء التشغيل.
مشاركة لقطة فاشلة
مع SQLite، المشاركة غالبًا بسيطة بمشاركة ملف .db (مع أي ملفات WAL). مع Realm، عادةً ما تشارك ملف Realm مع ملفاته الجانبية. في كلتا الحالتين، عرّف عملية قابلة للتكرار لإزالة البيانات الحساسة قبل خروج أي شيء من الجهاز.
الموثوقية في العالم الحقيقي: الأخطاء، إعادة التهيئة، والترقيات
تطبيقات الميدان تفشل بطرق مملة: تموت البطارية أثناء الحفظ، يقتل نظام التشغيل التطبيق في الخلفية، أو تمتلئ المساحة بعد أسابيع من الصور والسجلات. اختيار قاعدة البيانات المحلية يؤثر على عدد المرات التي تتحول فيها تلك الأخطاء إلى فقدان عمل.
عندما يحدث تعطل أثناء الكتابة، يمكن أن تكون كلتا SQLite وRealm آمنتين عند الاستخدام الصحيح. SQLite يكون موثوقًا عندما تغلف التغييرات بمعاملات (ويمكن أن يساعد وضع WAL في المرونة والأداء). كتابات Realm تكون معاملة افتراضيًا، لذا عادةً تحصل على حفظ “الكل أو لا شيء” بدون عمل إضافي. الخطر الشائع ليس محرك القاعدة. إنه كود التطبيق الذي يكتب في خطوات متعددة بدون نقطة التزام واضحة.
الفساد نادر، لكنك ما زلت بحاجة إلى خطة استرداد. مع SQLite، يمكنك تشغيل فحوصات التكامل، الاستعادة من نسخة احتياطية معروفة جيدة، أو إعادة البناء من إعادة مزامنة الخادم. مع Realm، غالبًا ما يعني الفساد أن ملف Realm بأكمله مشكوك فيه، لذا تكون مسارات الاسترداد العملية غالبًا “حذف المحلي وإعادة المزامنة” (جيد إذا كان الخادم مصدر الحقيقة، مؤلم إذا كان الجهاز يحمل بيانات فريدة).
نمو قاعدة البيانات مفاجأة أخرى. يمكن أن يتضخم ملف SQLite بعد الحذف ما لم تقم بتفريغ المساحة (VACUUM) دوريًا. قد ينمو ملف Realm أيضًا ويحتاج إلى سياسات ضغط، بالإضافة إلى تقليم الكائنات القديمة (مثل الوظائف المكتملة) حتى لا يتوسع الملف إلى الأبد.
الترقيات والعودة للخلف فخ آخر. إذا غيّر تحديث المخطط أو تنسيق التخزين، قد يعلق المستخدمون في إصدار أحدث لا يمكنهم قراءته عند الرجوع. خطط للترقيات كاتجاه واحد، مع ترحيلات آمنة وخيار “إعادة تعيين البيانات المحلية” لا يكسر التطبيق.
عادات الموثوقية التي تجني ثمارها:
- تعامل مع “القرص ممتلئ” وفشل الكتابة برسالة واضحة ومسار لإعادة المحاولة.
- احفظ مدخلات المستخدم في نقاط تفتيش، ليس فقط في نهاية استمارة طويلة.
- احتفظ بسجل تدقيق محلي خفيف للاسترداد والدعم.
- قم بتقليم وأرشفة السجلات القديمة قبل أن تكبر قاعدة البيانات كثيرًا.
- اختبر ترقيات نظام التشغيل وقتل الخلفية على أجهزة من الفئة المتوسطة.
مثال: تطبيق تفتيش يخزن قوائم وفوتوغرافيا قد يصل إلى مساحة منخفضة خلال شهر. إذا اكتشف التطبيق نفاد المساحة مبكرًا، يمكنه إيقاف التقاط الصور مؤقتًا، التحميل عند الإمكان، والحفاظ على حفظ القوائم بأمان، بغض النظر عن قاعدة البيانات المحلية المستخدمة.
خطوة بخطوة: كيفية اختيار وإعداد نهج التخزين
عامل التخزين كجزء من المنتج، لا كقرار مكتبة فقط. الخيار الأفضل هو الذي يحافظ على قابلية استخدام التطبيق عند انقطاع الإشارة، ومتوقعًا عند عودتها.
مسار قرار بسيط
اكتب أولاً تدفقات المستخدم دون اتصال. كن محددًا: “افتح مهام اليوم، أضف ملاحظات، أرفق صورًا، علم بالمكتملة، التقط توقيعًا.” كل ما في هذه القائمة يجب أن يعمل بدون شبكة، في كل مرة.
ثم اعمل عبر تسلسل قصير: قوائم الشاشات الحرجة دون اتصال وكمية البيانات التي يحتاجها كل منها (مهام اليوم مقابل السجل الكامل)، ارسم نموذج بيانات أدنى والعلاقات التي لا يمكنك تزويرها (Job -> ChecklistItems -> Answers)، اختر قاعدة تعارض لكل كيان (ليس قاعدة واحدة لكل شيء)، قرر كيف ستختبر الفشل (ترحيلات على أجهزة حقيقية، إعادة المحاولة للمزامنة، سلوك تسجيل الخروج/إعادة التثبيت القسرية)، وابن نموذجًا أوليًا صغيرًا ببيانات واقعية تستطيع قياسه (تحميل، بحث، حفظ، مزامنة بعد يوم دون اتصال).
هذه العملية تكشف عادة القيد الحقيقي: هل تحتاج استعلامات ad hoc مرنة وفحص سهل، أم تفضل وصولًا قائمًا على الكائنات وإنفاذ نموذج أكثر تشددًا؟
ما الذي يجب التحقق منه في النموذج الأولي
استخدم سيناريو واقعي واحد، مثل فني يكمل 30 تفتيشًا دون اتصال ثم يقود إلى التغطية. قِس وقت التحميل الأول مع 5,000 سجل، ما إذا كانت تغييرات المخطط تتحمل التحديث، كم عدد التعارضات التي تظهر بعد إعادة الاتصال وهل يمكنك تفسير كل واحد، ومدى سرعة فحص “سجل سيئ” عندما يتصل الدعم.
إذا أردت التحقق بسرعة قبل الالتزام، نموذج بدون كود في AppMaster يمكن أن يساعدك على تثبيت سير العمل ونموذج البيانات مبكرًا، حتى قبل أن تختار قاعدة البيانات على الجهاز نهائيًا.
أخطاء شائعة تضر بالتطبيقات غير المتصلة
معظم فشل النهج غير المتصل لا يأتي من محرك القاعدة. يأتي من تخطي الأشياء المملة: الترقيات، قواعد التعارض، والتعامل الواضح مع الأخطاء.
فخ واحد هو افتراض أن التعارضات نادرة. في العمل الميداني هي طبيعية: يقوم فنيان بتحرير نفس الأصل، أو يغير مشرف قائمة تحقق أثناء بقاء جهاز دون اتصال. إذا لم تعرف قاعدة (آخر كتابة تفوز، الدمج حسب الحقل، أو الاحتفاظ بالإصدارات)، ستكتب عملًا حقيقيًا فوقه في النهاية.
فشل هادئ آخر هو التعامل مع نموذج البيانات كأنه “منتهٍ” وعدم ممارسة الترقيات. التغييرات في المخطط تحدث حتى في التطبيقات الصغيرة. إذا لم تقم بترقيم مخططك واختبار الترقيات من الإصدارات الأقدم، قد يبقى المستخدمون عالقين بعد تحديث بترحيلات فاشلة أو شاشات فارغة.
مشكلات الأداء تظهر متأخرًا أيضًا. أحيانًا تقوم الفرق بتحميل كل شيء “للالحاق بالأمر”، ثم تتساءل لماذا يشعر البحث بالبطء ويستغرق فتح التطبيق دقائق على هاتف متوسط.
أنماط يجب مراقبتها:
- عدم وجود سياسة تعارض مكتوبة، فتُكتب التعديلات فوق بعضها بصمت.
- ترحيلات تعمل على تثبيت جديد لكن تفشل في الترقيات الحقيقية.
- التخزين المؤقت دون اتصال الذي يكبر بلا حدود، مما يجعل الاستعلامات بطيئة.
- فشل المزامنة مخفي وراء مؤشر تحميل، فيظن المستخدم أن البيانات أُرسلت.
- التصحيح بالتخمين بدلًا من وجود نص لإعادة إنتاج المشكلة وبيانات نموذجية.
مثال: يكمل فني تفتيشًا دون اتصال، يضغط مزامنة، ولا يحصل على تأكيد. التحميل فشل فعليًا بسبب مشكلة رمز المصادقة. إذا أخفى التطبيق الخطأ، يغادر المكان معتقدًا أن المهمة مكتملة، وتضيع الثقة.
أيًا كانت قاعدة التخزين التي تختارها، شغّل اختبار “وضع الميدان” الأساسي: وضع الطائرة، بطارية منخفضة، تحديث التطبيق، وجهازيْن يعدلان نفس السجل. إذا كنت تبني بسرعة بمنصة بدون كود مثل AppMaster، أدمج هذه الاختبارات في النموذج الأولي قبل أن يصل سير العمل إلى فريق أكبر لا يستطيع تحمل التوقف.
قائمة تحقق سريعة قبل الالتزام
قبل اختيار محرك تخزين، حدد ما يعنيه “جيد” لتطبيقك الميداني، ثم اختبره ببيانات وأجهزة حقيقية. الفرق تجادل حول الميزات، لكن معظم الفشل يأتي من الأساسيات: الترقيات، الشاشات البطيئة، قواعد التعارض غير الواضحة، وعدم وجود طريقة لفحص الحالة المحلية.
استخدم هذا كباب قبول/رفض:
- إثبات الترقيات: خذ على الأقل إصدارين أقدماً، قم بالترقية إلى إصدار اليوم، وتأكد أن البيانات تفتح وتعدل وتزامن.
- اجعل الشاشات الأساسية سريعة في الحجم الحقيقي: حمّل بيانات واقعية وقس أبطأ الشاشات على هاتف متوسط.
- اكتب سياسة تعارض لكل نوع سجل: تفتيشات، توقيعات، أجزاء مستخدمة، تعليقات.
- اجعل البيانات المحلية قابلة للفحص والسجلات قابلة للجمع: عرف كيف يلتقط الدعم والاختبار الحالة عند عدم الاتصال.
- اجعل الاسترداد متوقعًا: قرر متى تُعيد بناء الكاش، إعادة التحميل، أو متى تطلب تسجيل دخول مرة أخرى. لا تجعل "إعادة تثبيت التطبيق" هي الخطة.
إذا كنت تنشئ نموذجًا أوليًا في AppMaster، طبِّق نفس الانضباط. اختبر الترقيات، حدد التعارضات، وتدرب على الاسترداد قبل أن تسلم إلى فريق لا يمكنه تحمل التوقف.
سيناريو نموذجي: تطبيق تفتيش فني مع إشارة متقطعة
فني ميداني يبدأ اليوم بتحميل 50 أمر عمل إلى هاتفه. كل مهمة تتضمن العنوان، عناصر قائمة التحقق المطلوبة، وبعض الصور المرجعية. بعد ذلك، تتقطع الإشارة طوال اليوم.
خلال كل زيارة، يقوم الفني بتعديل نفس السجلات مرارًا: حالة المهمة (وصل، قيد التنفيذ، منجز)، الأجزاء المستخدمة، توقيع العميل، وصور جديدة. بعض التعديلات صغيرة ومتكررة (الحالة). أخرى كبيرة (الصور) ويجب ألا تُفقد.
لحظة المزامنة: لمسها شخصان
عند 11:10، يعلّم الفني المهمة #18 كمُنتهية ويضيف توقيعًا دون اتصال. عند 11:40، يعيد المرسل تعيين المهمة #18 لأنها لا تزال تبدو مفتوحة في المكتب. عندما يعود الفني إلى التغطية عند 12:05، يرفع التطبيق التغييرات.
تدفق تعارض جيد لا يخفي ذلك. يُظهره. يجب أن يرى المشرف رسالة بسيطة: “توجد نسختان من المهمة #18”، مع الحقول الرئيسية جنبًا إلى جنب (الحالة، الفني المخصص، الطابع الزمني، وجود/عدم وجود توقيع) وخيارات واضحة: احتفظ بتحديث الحقل، احتفظ بتحديث المكتب، أو دمج حسب الحقل.
هنا يظهر قرارك في التخزين والمزامنة في الحياة الواقعية: هل يمكنك تتبع سجل نظيف من التغييرات، وهل يمكنك إعادة تشغيلها بأمان بعد ساعات من العمل دون اتصال؟
عندما “تختفي” مهمة، يكون التصحيح غالبًا عن إثبات ما حدث. سجِّل ما يكفي للإجابة: معرف السجل المحلي ومعرف الخادم (بما في ذلك وقت الإنشاء)، كل كتابة مع الطابع الزمني/المستخدم/الجهاز، محاولات المزامنة ورسائل الخطأ، قرارات التعارض ومن فاز، وحالة رفع الصور المتتبعة منفصلة عن سجل المهمة.
مع هذه السجلات، يمكنك إعادة إنتاج المشكلة بدلًا من التكهن من شكوى.
الخطوات التالية: تحقق بسرعة، ثم ابنِ الحل الميداني الكامل
قبل الانخراط في جدالات SQLite مقابل Realm، اكتب مواصفة صفحة واحدة لتدفقات العمل دون اتصال: الشاشات التي يراها الفني، ما البيانات التي تعيش على الجهاز، وما الذي يجب أن يعمل بلا إشارة (إنشاء، تعديل، صور، توقيعات، تحميلات مؤجلة).
ثم اصنع نموذجًا أوليًا للنظام بأكمله مبكرًا، ليس قاعدة البيانات فقط. تفشل تطبيقات الميدان عند الحواف: حفظ استمارة محلية لا يفيد إذا لم يستطع فريق الإدارة مراجعة وإصلاح السجلات، أو إذا رفض الخلفية التحديثات لاحقًا.
خطة تحقق عملية:
- اصنع شريحة نهاية إلى نهاية رقيقة: استمارة واحدة دون اتصال، عرض قائمة واحد، محاولة مزامنة واحدة، وشاشة إدارة واحدة.
- نفّذ اختبار تغيير: أعد تسمية حقل، قسم حقلًا إلى اثنين، أطلق إصدار اختبار، وراقب سلوك الترقية.
- حاكِ تعارضات: عدِّل نفس السجل على جهازين، مزامنة بترتيب مختلف، وسجل ما ينهار.
- تمرن على تصحيح الميدان: قرر كيف ستفحص الحالة المحلية، السجلات، وحمولات المزامنة الفاشلة على جهاز حقيقي.
- اكتب سياسة إعادة التعيين: متى تمسح الكاش المحلي، وكيف يتعافى المستخدمون دون فقدان العمل.
إذا كانت السرعة مهمة، تمريرة بدون كود أولية يمكن أن تساعدك على التحقق من سير العمل بسرعة. AppMaster (appmaster.io) خيار واحد لبناء الحل الكامل مبكرًا (خدمات خلفية، لوحة إدارة ويب، وتطبيقات محمولة)، ثم تجديد كود نظيف مع تغير المتطلبات.
اختر الخطوة التالية للتحقق بناءً على الخطر. إذا كانت النماذج تتغير أسبوعيًا، اختبر الترحيالات أولاً. إذا كان عدة أشخاص يلمسون نفس المهمة، اختبر التعارضات. إذا تخشى “عمل في المكتب فقط”، أولِ أولوية لتدفق تصحيح الميدان.
الأسئلة الشائعة
Offline-first يعني أن التطبيق يبقى مفيدًا بدون اتصال: يمكنه تحميل البيانات المطلوبة، قبول إدخالات جديدة، وحفظ كل تغيير بأمان حتى يصبح التزامن ممكنًا. الوعد الأساسي هنا أن المستخدمين لا يفقدون عملهم أو ثقتهم عندما تنقطع الشبكة أو يقتل نظام التشغيل التطبيق أو تنفد البطارية أثناء المهمة.
SQLite خيار آمن عادةً عندما تحتاج إلى فلاتر معقدة، استعلامات تقريرية، علاقات كثير إلى كثير، وفحص ad hoc سهل بأدوات معروفة. Realm مناسب عندما تريد الوصول إلى البيانات ككائنات، وتقدّر أن الكتابات تكون معاملة افتراضيًا، ويمكنك أن تبقي احتياجات الاستعلام متوافقة مع نقاط قوة Realm.
عامِل الترحيلات كمِيزة أساسية، لا كمهمة لمرة واحدة. ثبت إصدارًا قديمًا، أنشئ بيانات واقعية على الجهاز، ثم حدث وحقق أن التطبيق لا يزال يفتح ويعدل ويتزامن؛ واختبر كذلك مجموعات بيانات كبيرة، مساحة تخزين منخفضة، وإيقاف التطبيق في منتصف الترحيل.
إضافة حقل تكون عادةً بسيطة في كلا النظامين، لكن إعادة التسمية والانقسام هما الذي يسببان المشاكل. خطط لهذه التغييرات بعناية، ضع قيمًا افتراضية معقولة، تعامل مع القيم الفارغة بعناية، وتجنّب ترحيلات تعيد كتابة كل السجلات دفعة واحدة على أجهزة قديمة.
الشاشات والقوائم والمرشحات التي تعكس العمل الفعلي هي المعيار: “وظائف اليوم”، “نماذج غير متزامنة”، “محررة خلال الساعتين الماضيتين”، وبحث سريع. إذا كان التعبير عن هذه الاستعلامات مُحرجًا، سيصبح واجهة المستخدم بطيئة أو الكود صعب الصيانة.
لا يحل أي من SQLite أو Realm مشكلة التعارضات بنفسه؛ أنت تحتاج قواعد أعمال واضحة. اختر قاعدة لكل نوع كيان (آخر كتابة تفوز، الدمج حسب الحقل، أو صف مراجعة يدوي) واجعل التطبيق قادرًا على شرح ما حدث عندما يغيّر جهازان نفس السجل.
سجّل ما يكفي من البيانات الوصفية لتفسير وإعادة تشغيل التغييرات: معرف المستخدم، معرف الجهاز، الطوابع الزمنية، وعلامة “آخر تغيير” لكل سجل. احتفظ بسجل عمليات محلي لترى ما تم وضعه في الطابور، ما أُرسل، ما فشل، وما قبله الخادم.
SQLite سهل الفحص لأنه ملف يمكنك سحبه من الجهاز واستعلامه مباشرة، مما يساعد في التحليل ad hoc والتصدير. فحص Realm غالبًا ما يكون أكثر طبيعية بالنسبة لرسوميات الكائنات والعلاقات، لكن الفرق قد يجعل التحليل العميق أقل مرونة إذا كانت الفريق معتادًا على SQL.
المخاطر الكبرى عادةً تكون في منطق التطبيق: كتابات متعددة الخطوات بدون نقطة التزام واضحة، أخطاء مزامنة مخفية، وعدم وجود مسار استرداد عند امتلاء القرص أو الفساد. استخدم معاملات/نقاط حفظ، أظهر حالة الحفظ والمزامنة بوضوح، وضع خيار “إعادة التهيئة وإعادة المزامنة” متوقعًا.
ابنِ سيناريو حقيقي واحد نهاية إلى نهاية وقِسَه: التحميل الأول مع آلاف السجلات، البحث، الحفظ في استمارة طويلة، واختبار “يوم دون اتصال ثم إعادة الاتصال”. تحقق من الترقيات من إصدارات سابقة، قم بمحاكاة التعارضات على جهازين، وتأكد من أنك تستطيع فحص الحالة المحلية والسجلات عند حدوث خلل.


