محتويات الدورة
Dart
الأساسيات: القيم والغياب والمجموعات والكائنات الصالحة
العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة
التكامل: الأهداف والموارد والتحقق والأدلة

Dart / العقود: الأنماط والواجهات العامة والنتائج غير المتزامنة / الدرس 8

نمذجة البدائل بنتائج مغلقة وتعدادات

مثّل نتيجة صالحة واحدة في كل مرة، وافصل المعالجة الداخلية الشاملة عن توافق الرموز الخارجية.

وقت القراءة التقريبي: 4 دقيقةتاريخ مراجعة المحتوى
في هذه الصفحة

أهداف الدرس

  • اختر بيانات مناسبة لكل نتيجة بدلا من حقول خالية تسمح بالتناقض.
  • استخدم رموز تعداد مستقرة وراجع عواقب إضافة بدائل جديدة.

اجعل إنشاء التراكيب غير الصالحة أصعب

قد تسمح استجابة بحقول ok وcount وjobId وerror بنجاح مصحوب بخطأ أو انتظار بلا هوية مهمة. يمنح التسلسل المغلق كل بديل بياناته المطلوبة: عدد للقبول وسبب للرفض ومرجع مهمة للانتظار. لا يتحقق التسلسل وحده من صيغ النص أو المجالات العددية؛ بل يثبتها المنشئ أو المحول. ابدأ بسرد حالات العمل المسموحة، لا بنسخ حمولة نقل تجعل كل حقل قابلا للخلو. تفيد الأنواع عندما تحافظ على المعنى عند الحد.

استخدم حد المكتبة لضبط البدائل المباشرة

تقيّد sealed في Dart الامتداد أو التنفيذ المباشر بالمكتبة نفسها وتدعم تحليل الشمول. تكون مجردة ضمنيا، فيستخدم المستدعي بدائل ملموسة. يعرّف المثال أصنافا فرعية final وأنماط كائنات داخل switch لاستخراج البيانات. جميع التعريفات في مكتبة توضيحية واحدة وتحتاج Dart 3. لا يوجد نمط شامل لأن معالجة كل بديل معروف مفيدة هنا. قد تكشف إضافة بديل معالجات مصدر تحتاج تعديلا، وهو دليل مفيد لا سبب لإخفاء الحالات المقبلة كلها وراء بديل عام.

dart بيانات نتائج مختلفة مع معالجة شاملة
sealed class BatchOutcome {}
final class Accepted extends BatchOutcome {
  final int count;
  Accepted(this.count);
}
final class Rejected extends BatchOutcome {
  final String reason;
  Rejected(this.reason);
}
String describe(BatchOutcome value) => switch (value) {
  Accepted(count: final count) => 'accepted:$count',
  Rejected(reason: final reason) => 'rejected:$reason',
};
void main() {
  print(describe(Accepted(2)));
  print(describe(Rejected('invalid-input')));
}
الناتج المتوقع
accepted:2
rejected:invalid-input

المخرج المتوقع accepted:2 ثم rejected:invalid-input. يحذف النموذج الصغير تحقق المنشئات وحالة الانتظار عمدا؛ وتكتمل بدائله المعلنة لهذا المثال فقط. لم تُجر ترجمة Dart.

استخدم تعدادا محسنا للاختيارات المحدودة المتجانسة

يحدد enum مجموعة ثابتة من مثيلات نوع واحد. تستطيع التعدادات المحسنة إرفاق حقول final وسلوك بهذه المثيلات وفق قواعد منشئات ثوابت التعداد. يناسب ذلك اختيارات متجانسة كأنماط المعالجة، وأقل ملاءمة لبدائل تحتاج بيانات مختلفة جذريا. لا تحفظ index رمزا تجاريا غير مفسر؛ فتغيير الترتيب يغير الموضع. فضّل رمزا مستقرا صريحا وافصل تسميات العرض حتى لا تكسر الترجمة والتحرير البيانات المخزنة. يسمي التعداد الحالات، ولا يفرض تلقائيا الانتقالات القانونية بينها.

ترجم الرموز الخارجية المجهولة بقصد

يعيد المحلل أدناه null للنمط غير المدعوم عبر حلقة، بدلا من رمي ناتج بحث مطابق للاسم. ينفصل الرمز عن اسم ثابت المصدر وقد يبقى مستقرا عند تغيير التسمية الداخلية. إرجاع null سياسة واحدة؛ وقد يحفظ تطبيق آخر الرمز الخام المجهول في نتيجة حد مخصصة. لا تختَر نمطا ذا صلاحيات واسعة بصمت كافتراضي لقيمة غير مدعومة. ينبغي أن يظهر قرار التوافق، لا أن يُدّعى أن المستدعي اختار صراحة قيمة لم يفهمها النظام.

dart رموز مستقرة ونتيجة صريحة لغير المدعوم
enum ProcessingMode {
  preview('preview'), commit('commit');
  const ProcessingMode(this.code);
  final String code;
}
ProcessingMode? parseMode(String code) {
  for (final mode in ProcessingMode.values) {
    if (mode.code == code) return mode;
  }
  return null;
}
void main() {
  print(parseMode('preview')?.name);
  print(parseMode('future-mode')?.code ?? 'unsupported');
}
الناتج المتوقع
preview
unsupported

المخرج المتوقع preview ثم unsupported. يستخدم البرنامج تعدادا محسنا وبحثا قابلا للخلو، ولا ينفذ نمط معالجة أو عملية خارجية. لم يُترجم.

افصل شمول المصدر عن توافق النقل

لا تتحقق معرفة المترجم بالأصناف المحلية من بايتات قادمة من منتج بعيد أحدث. قد تتطلب قيمة تعداد أو نتيجة مغلقة جديدة تعديلات مستهلك، وتكوّن الأسماء والحقول المسلسلة عقدا عاما مستقلا. راجع النسخ المختلطة عند الإصدار المستقل. قد يصح نمط شامل عند حد غير موثوق لكنه يخفي معالجة داخلية ناقصة عند تعميمه. حدّد نتائج المنتج وإخفاقات التكامل ومدة دعم العملاء القدماء. لا تدّع توافقا ثنائيا أو في التسلسل لمجرد ترجمة switch محلية.

الأخطاء الشائعة وإصلاحها

تحمل نتيجة نجاح بلا بيانات مطلوبة ولا سبب.

لماذا يحدث؟
أتاحت الحقول الخالية المستقلة تراكيب متناقضة.
كيف تصلحه؟
امنح كل بديل بياناته المطلوبة وتحقق منها.
كيف تتجنب تكراره؟
راجع كل حالة يسمح ببنائها النوع، لا الأمثلة المقصودة فقط.

يتغير معنى فهارس التعداد المخزنة بعد إعادة الترتيب.

لماذا يحدث؟
عومل ترتيب التصريح كمعرف خارجي دائم.
كيف تصلحه؟
قدّم رموزا مستقرة وانقل التمثيلات المخزنة عمدا.
كيف تتجنب تكراره؟
افصل الهوية ونص العرض وترتيب التقديم.

يبتلع نمط شامل نتيجة داخلية أضيفت حديثا بصمت.

لماذا يحدث؟
تُجاوز فحص الشمول دون سبب توافق.
كيف تصلحه؟
عالج البدائل الداخلية صراحة حيث يلزم الاكتمال.
كيف تتجنب تكراره؟
راجع مستهلكي النتائج عند تطور التسلسل.

اختبر فهمك

1. هل يكفي التسلسل المغلق لضمان أن Accepted يحمل عددا موجبا دائما؟

اعرض الحل المشروح

لا. يقيّد الإغلاق البدائل ويدعم الشمول، لكن منشئ المثال يقبل أي int. أضف حد بناء متحققا أو حارس منشئ إذا كانت الإيجابية قيدا. افصل الرفض الخارجي المتوقع عن إساءة المبرمج، واختبر الصفر والسالب والموجب. يظل شكل النوع وصحة بياناته ادعاءين مختلفين.

2. لماذا لا ينبغي أن تتحول رموز معالجة مجهولة تلقائيا إلى commit؟

اعرض الحل المشروح

يسند ذلك فعلا مؤثرا لم يحدده المستدعي بنجاح، وقد يخفي اختلاف نسخة أو مدخلا مشوها. ارفض المجهول أو احفظه لمسار توافق صريح. وقد لا يصح حتى افتراضي المعاينة إذا أوحى بإنجاز فعل. اختر السياسة من عقد المنتج، لا لتسهيل التخلص من null.

أهم ما تعلمته

  • تصف البدائل المغلقة والتعدادات نوعين مختلفين من الاختيار المحدود.
  • تحتاج الرموز الخارجية المستقرة والبيانات المتحققة عقودا صريحة.

المراجع الرسمية