حين نتولّى نظاماً قائماً في الكويت — نظام ERP أو CRM أو منصّة حجوزات — توجد قائمة قصيرة من الأعطال نتوقّع إيجادها قبل أن نفتح الشيفرة. وهي ليست نتيجة هندسة سيئة. بل نتيجة برمجيات كُتبت واختُبرت بالإنجليزية، ثم مُلئت بأسماء عربية ودنانير كويتية. وكلٌّ منها غير مرئي في العرض التقديمي وواضح لقسم الحسابات في الشهر التاسع. وهذه هي، مع الآلية خلف كلٍّ منها وإصلاحه.
لماذا لا يُرجع البحث عن اسم عربي شيئاً؟
لأن أ وإ وآ وا أربعة أحرف مختلفة، لا أربع صور لحرف واحد. لها نقاط ترميز يونيكود منفصلة، وقاعدة البيانات تقارنها كما تقارن «a» و«b».
وعملياً يكتب موظف الاستقبال «احمد» في خانة البحث فيُبلّغ النظام بعدم وجود هذا العميل، بينما «أحمد» جالس في الجدول. والأمر نفسه ينطبق على ه وة في آخر الكلمة، وعلى ى وي. فيتعلّم المستخدمون تجربة هجاءين أو ثلاثة، ثم يستنتجون أن البحث غير موثوق ويبدأون بتمرير القائمة بدلاً منه. ولا يُبلِّغ أحد عن خلل، لأن الأمر يبدو من الخارج يوماً هادئاً.
هذا أكثر عطل في البيانات العربية نجده في الأنظمة القائمة، وأكثر ما يُحتمل أن يكون المستخدمون قد تحايلوا عليه بصمت.
والإصلاح هو التطبيع عند الكتابة: خزّنوا نسخة مُسطَّحة من الاسم إلى جانب الأصل — بتوحيد صور الألف إلى ا، وة إلى ه، وى إلى ي، وإزالة التشكيل — وابحثوا في العمود المُسطَّح مع عرض الأصل. أمّا القيام بذلك عند القراءة فيعني أن كل استعلام يحوّل كل صفّ، وهذا بالضبط النمط الذي يمنع الفهرس من أن يكون قابلاً للاستخدام.
ولماذا يُعطّل التشكيل المطابقة أيضاً؟
علامات التشكيل أحرف تركيبية منفصلة لا جزء من الحرف الذي تجلس عليه. والنص المخزَّن بها لن يُطابق استعلاماً يُكتب دونها، ولا أحد تقريباً يكتبها. والبيانات المنسوخة من مستند رسمي أو نموذج حكومي أو نصّ قرآني تحملها كثيراً دون أن تُرى.
أزيلوها في جولة التطبيع نفسها التي تعالج صور الألف. فنسخة العرض تحتفظ بها؛ ونسخة البحث لا.
لماذا تُرتَّب الأسماء العربية ترتيباً خاطئاً؟
الترتيب المقارن. فـutf8mb4_general_ci وutf8mb4_unicode_ci في MySQL ترتّبان العربية وتقارنانها بشكل مختلف إحداهما عن الأخرى، وليست أيٌّ منهما افتراضاً آمناً يُختار بالمصادفة. وPostgreSQL يحتاج ترتيب ICU للتعامل مع العربية بشكل صحيح.
والعَرَض قائمة عملاء مرتَّبة أبجدياً بطريقة لا يعرفها أي متحدّث بالعربية، وبحث يُفوّت سجلات كان عليه إرجاعها — لأن الترتيب المقارن يحكم المقارنة كما يحكم الترتيب. ويستحق الأمر التحقّق من الترتيب على العمود لا على قاعدة البيانات فقط: فالجدول المُنشأ قبل تغيير الإعدادات يحتفظ بالقديم، فيمكن لعمود واحد أن يخالف كل ما حوله.
لماذا تنزلق المجاميع بعدة فلوس؟
الدينار الكويتي ذو ثلاث خانات عشرية، وfloat وdouble لا يستطيعان تمثيل 0.001 بدقة. فهما تقريبان ثنائيان، فكل مبلغ مخزَّن خاطئ بقدر ضئيل جداً، والأخطاء تتراكم عبر الصفوف.
وعلى مئة فاتورة يكون هذا غير مرئي. وعلى سنة من المعاملات يتوقّف إجمالي التقرير ومجموع بنوده نفسها عن التوافق، ويجد قسم المالية ذلك في نهاية السنة — يدوياً عادةً، وأثناء إقفال الدفاتر عادةً، وبافتراض أن أحداً أدخل شيئاً خطأً عادةً.
استخدموا numeric(12,3) أو DECIMAL(12,3) للمال. وعمود عملة من نوع float خلل مؤجَّل.
والتصحيح على نظام قائم هو ترحيل لنوع العمود إضافةً إلى جولة تسوية، ويصبح أغلى كلّما طال تراكم الصفوف بالنوع الخاطئ. ويستحق التحقّق منه مبكراً ولو لم يبدُ شيء خاطئاً.
كيف ينبغي تخزين التواريخ الهجرية وتوقيت الكويت؟
خزّنوا الطوابع الزمنية كـtimestamptz بتوقيت UTC وحوّلوا عند الحدّ، لحظة عرض القيمة. فالكويت على UTC+3 دون توقيت صيفي، وهذا يجعل تخزين التوقيت المحلي يبدو غير ضارّ لسنوات — حتى يُنقل خادم، أو يأتي تكامل من منطقة زمنية أخرى، أو يحتاج تقرير إلى المقارنة بأي شيء خارجي.
وأبقوا الهجري قيمة عرض مُستمدّة، لا مفتاحاً مخزَّناً أبداً. فالتواريخ الهجرية تعتمد على الرؤية والتحويل غير ثابت، فالتاريخ الهجري المخزَّن سجلّ لتحويل واحد بعينه جرى في يوم واحد بعينه. واستمدّوه عند عرضه فيبقى السجل الأساسي غير ملتبس.
كيف تتحقّقون من وجود هذه الأعطال في نظامكم؟
لا شيء من هذا يحتاج وصولاً إلى الشيفرة المصدرية. خمسة تحقّقات، كلٌّ منها دقائق:
- 1
ابحثوا عن عميل دون الهمزة
اعثروا على سجل مخزَّن كـ«أحمد» وابحثوا عن «احمد». فإن لم يرجع شيء، فالتطبيع غائب.
- 2
رتّبوا قائمة العملاء بالاسم العربي
اعرضوها على متحدّث بالعربية واسألوه هل الترتيب صحيح. والترتيب الخاطئ يعني ترتيباً مقارناً خاطئاً.
- 3
اجمعوا بنود تقرير يدوياً
خذوا تقريراً بعدة مئات من الصفوف وقارنوا إجماليه بمجموع البنود المعروضة. والفرق بعدة فلوس عمود float.
- 4
قارنوا طابعاً زمنياً بمصدر ثانٍ
قارنوا وقتاً مسجَّلاً ببريد إلكتروني أو سجلّ بوابة دفع للحادثة نفسها. وفرق ثلاث ساعات ثابت يعني أن التوقيت المحلي يُخزَّن كأنه UTC.
- 5
الصقوا اسماً من نموذج حكومي
انسخوا اسماً من ملف PDF رسمي إلى خانة البحث. فإن فشل بينما تنجح كتابة الاسم نفسه، فالتشكيل يُخزَّن ولا يُزال.
فإن نجحت الخمسة كلها، فالنظام بناه من رأى بيانات عربية من قبل. وهذا أندر مما ينبغي، ويستحق معرفته عمّن بناه.