العنصر الأكثر استخدامًا في برمجيات المؤسسات
“إذا كسرت LOV، كسرت العمل. لا يهمنا ما يفعله البديل غير ذلك — يجب أن تبدو القائمة المنسدلة متطابقة في اليوم الأول”، هذا ما قاله لنا رئيس العمليات في بنك أوروبي إقليمي خلال بدء المشروع العام الماضي. عدّ فريقه لاحقًا استدعاءات LOV عبر المنظومة لأسبوع واحد: 11.4 مليون، عبر 238 شاشة و1,700 مستخدم يوميًا. تقريبًا LOV واحد كل ثانيتَين. لم يقترب أي عنصر آخر من ذلك.
ذلك التردد مهم. عندما تتدهور LOVs أثناء الترحيل، يلاحظ المستخدمون خلال ساعة. عندما تتحسن، يظهر مكسب الإنتاجية في اليوم الأول من التشغيل المتوازي.
عميل في 2008 كان لديه LOV متتالي ثلاثي المستويات على شاشة طلب المبيعات — العميل، والشحن إلى، وجهة الاتصال — وذات ظهيرة توقف مركز الاتصال بأكمله في Poznan عن العمل لأن LOV جهة الاتصال كان يُعيد قائمة فارغة. أقسم DBA أن شيئًا لم يتغير. اتضح أن مطوّرًا مبتدئًا قد أعاد ترتيب الأعمدة في مجموعة السجلات الأساسية الليلة السابقة، مما كسر بصمت تعيين موضع متغير الربط. لم يُقدّم المستخدمون تذكرة؛ توقفوا ببساطة عن أخذ الطلبات وذهبوا للقهوة. كان ذلك اليوم الذي تعلمت فيه كم من الإنتاجية تعتمد على قائمة منسدلة واحدة تتصرف تمامًا بالطريقة التي تصرفت بها بالأمس.
ما يفعله LOV في Oracle Forms فعليًا
LOV هو منتقي modal مدعوم بمجموعة سجلات. مجموعة السجلات عادةً بيان SELECT، أحيانًا قائمة ثابتة، أحيانًا مؤشر برمجي. يدعم التقليل التلقائي (اكتب أحرفًا للتصفية)، وتعيين الأعمدة (الصف المنتقى يملأ عناصر متعددة)، والتحقق (يمكن رفض القيم غير الموجودة في LOV).
تحتوي .fmb النموذجية على 18 LOV. حوالي 60% بحث عمود واحد. الـ 40% المتبقية تفعل شيئًا أكثر إثارة للاهتمام: معاملات متتالية، مرشحات معتمدة، أو ملء متعدد الأعمدة.
-- مجموعة سجلات LOV تمثيلية
SELECT customer_id, customer_name, credit_limit, region_code
FROM customers
WHERE status = 'A'
AND region_code = :ORDERS.REGION
ORDER BY customer_name;
متغير الربط :ORDERS.REGION هو السبب في فشل الترحيلات الساذجة. LOV ليس مستقلًا — إنه مُعلَّم على حالة النموذج الحية.
المكافئ الحديث ليس قائمة منسدلة
عنصر HTML <select> الأصلي يتعامل ربما مع 10% من حالات LOV. كل شيء آخر يحتاج إلى مكون type-ahead مع تصفية من جانب الخادم، واستعلامات مُؤجَّلة، وتنقل بلوحة المفاتيح، والقدرة على ملء حقول مربوطة متعددة من اختيار واحد. استقرينا على مكون React واحد يقبل نقطة نهاية بحث مُوصَّفة بـ OpenAPI وتعيين أعمدة.
توقيع نقطة النهاية الذي نُولّده لكل LOV يبدو هكذا:
GET /api/lov/customers?q=acm®ion=EU&limit=25
// الاستجابة
{
items: [
{ customer_id: 4821, customer_name: "Acme Industrial",
credit_limit: 250000, region_code: "EU" }
],
total: 1
}
كل LOV في .fmb المصدر يصبح نقطة نهاية واحدة زائد نسخة مكون واحدة. SQL مجموعة السجلات يصبح جسم الاستعلام. متغيرات الربط تصبح معاملات استعلام موصولة بحالة النموذج.
التقليل التلقائي، والتأجيل، وقاعدة الـ 150ms
تبدو LOVs في Forms فورية لأنها تعمل مقابل مؤشر محلي. رحلات الشبكة ذهابًا وإيابًا لا. لمطابقة الإحساس الأصلي، يجب على type-ahead إعادة النتائج في أقل من 150 مللي ثانية لحالة p95. نصل إلى هذا الرقم بتوليد نقاط نهاية بحث مُفهرسة مباشرة من SQL LOV، وتخزين الصفحة الأولى مؤقتًا لكل جلسة مستخدم، وتأجيل الإدخال عند 80 مللي ثانية.
عبر 14 نشرة قِسنا فيها أوقات استجابة LOV المتوسطة بين 38 مللي ثانية و110 مللي ثانية. يُبلغ المستخدمون أن المنتقيات الجديدة تبدو أسرع من الأصلية — ليس لأن الشبكة أسرع، بل لأن التعامل مع لوحة المفاتيح أفضل.
LOVs المتتالية وحالة النموذج
النمط الأصعب هو التتالي: اختيار عميل يُصفّي LOV الشحن إلى، الذي يُصفّي LOV جهة الاتصال، الذي يُصفّي LOV المنتج. في Forms، هذه العلاقات ضمنية — متغيرات الربط تقرأ قيم الحقول الحالية عند وقت الفتح. في منصة حديثة، يجب أن تكون العلاقات صريحة.
نُرمّزها في JSON descriptor كمصفوفة dependsOn. يُعيد المكون الجلب عندما تتغير أي تبعية ويمسح الاختيارات التالية. يُنتج المُولِّد الأسلاك تلقائيًا من تحليل متغير الربط الأصلي.
تكافؤ التحقق
يمكن لـ LOVs في Forms أن تكون صارمة (يجب أن توجد القيمة في القائمة) أو استشارية (يُقترح القيمة لكن النص الحر مسموح). حوالي 70% من LOVs التي رحّلناها صارمة. يفرض مكون type-ahead هذا بفحص نهائي من جانب الخادم عند الإرسال — ليس فقط من جانب العميل — لأن سلوك Forms الأصلي كان يُتحقق مقابل بيانات حية، لا قائمة مُخزَّنة.
الخلاصة
LOVs ليست قوائم منسدلة. إنها منتقيات مُعلَّمة، متتالية، متعددة الأعمدة قادت 30 عامًا من تجربة مستخدم المؤسسات. استبدالها جيدًا يتطلب مكونًا يفهم حالة النموذج، ونقطة نهاية مُولَّدة من SQL الأصلي، وميزانيات تأخر مُقاسة بالمللي ثانية. مُنفَّذ بشكل صحيح، يجعل الترحيل العنصر الأكثر استخدامًا في التطبيق أسرع مما كان من قبل.