محتويات الدورة
Kotlin
أسس اللغة والحالة الصريحة
السلوك القابل للاستخدام والحدود المنمطة
التزامن والتكامل والتصميم المترابط

Kotlin / السلوك القابل للاستخدام والحدود المنمطة / الدرس 12

تنظيم الوحدات وبناء فحوص حتمية

استخدم الحزم ومعدلات الرؤية بقصد، وافصل القواعد الصرفة عن الساعات والإدخال والإخراج وإعداد إطار الاختبار.

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

أهداف الدرس

  • ميّز فضاء أسماء الحزمة عن وحدة ترجمة Kotlin.
  • صمّم فحوصا ذات معنى بمدخلات ثابتة ونتائج متوقعة محددة صراحة.

تنظم الحزمة الأسماء ولا تمنح الوصول بذاتها

يسند عنوان package أسماء مؤهلة بالكامل إلى تصريحات ملف المصدر. تتيح imports استخدام التصريحات بأسماء قصيرة؛ ولا تنسخ الشيفرة أو تتجاوز قيود الرؤية. تساعد أعراف مواضع الملفات القائمين بالصيانة وأدوات البناء، لكن تصريح package هو الذي يحدد فضاء الأسماء. لا تفترض أن تصريحين في الحزمة نفسها يتشاركان تلقائيا وصولا مميزا. تشير internal في Kotlin إلى وحدة ترجمة يحددها ترتيب البناء، لا إلى مجلد اعتباطي أو حزمة. يجب أن تتبع حدود الوحدات احتياجات البناء والملكية الفعلية، لا تسمية مجلد مضللة.

اعرض أصغر عقد مفيد للمستدعي

تظهر تصريحات private العليا داخل ملفها، وتقيّد private لأعضاء الصنف الوصول داخله، بينما تدعم protected وصول الأصناف الفرعية المعني. وتكون public افتراضية عندما لا يغيرها معدل آخر. تفيد internal لواجهة تنفيذ داخل وحدة، لكنها ليست حدا أمنيا ضد شيفرة تشغيل غير موثوقة. أبق المساعد خاصا عندما ينبغي للمستدعي الاعتماد على عملية أعلى مستوى. وإذا احتاجت الاختبارات إلى كل مساعد خاص، فأعد النظر هل تختبر تفاصيل التنفيذ بدلا من السلوك المقصود. لا توسّع واجهة الإنتاج لمجرد تسهيل توكيدات بسيطة على الدوال المساعدة.

kotlin قاعدة عامة ومساعد خاص بالملف
package lab.booking

private fun normalized(text: String): String = text.trim()
fun validWorkshopCode(text: String): Boolean {
    val value = normalized(text)
    return value.startsWith("ws-") && value.length > 3
}
fun main() {
    println(validWorkshopCode(" ws-7 "))
    println(validWorkshopCode("ws-"))
}
الناتج المتوقع
true
false

المخرج المتوقع true ثم false. يتحقق المثال من صيغة معرف اصطناعية صغيرة مقصودة، لا من معيار هوية إنتاجي. هذا ملف مصدر كامل بعنوان package، لكنه لم يُترجم.

مرّر السياق المتغير إلى القاعدة

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

افحص حد العمل بدلا من تكرار التنفيذ

يستخدم المثال check للتحقق من نتائج منطقية متوقعة قبل الموعد النهائي وعنده. بخلاف assert على JVM، التي يعتمد تنفيذها على تفعيل التوكيدات، تكون check دالة عادية وقت التشغيل ترمي عندما يكون الشرط false. هذا فاحص تعليمي مستقل صغير، وليس بديلا عن إطار اختبارات المشروع. يجب أن يستخدم الجناح الحقيقي توكيدات إطاره المعد ودورة حياته، ويسجل نسخ الأدوات، ويتجنب اختراع نجاح إذا لم يعمل اختبار. المخرج أدناه هو النتيجة المتوقعة فقط عند ترجمة البرنامج وتنفيذه بنجاح.

kotlin فاحص حتمي لحالات حدود قاعدة الإلغاء
fun mayCancel(nowMinute: Int, deadlineMinute: Int): Boolean =
    nowMinute < deadlineMinute
fun main() {
    val cases = listOf(9 to true, 10 to false, 11 to false)
    for ((now, expected) in cases) {
        check(mayCancel(now, 10) == expected) { "boundary mismatch at $now" }
    }
    println("3 declared boundary cases passed")
}
الناتج المتوقع
3 declared boundary cases passed

السطر المتوقع 3 declared boundary cases passed. تُرفض المساواة عمدا. هذا مخرج متوقع بالتحليل فقط؛ فلم يُنفّذ مترجم Kotlin أو مشغّل اختبار في بيئة التأليف.

اجعل توافق البناء وادعاءات الاختبار صريحة

يجب أن تتوافق نسخ مصدر Kotlin وإضافة المترجم والمكتبة القياسية وهدف JVM وأدوات Java وإطار الاختبار مع بناء المشروع المعلن. لا تنسخ رقما يبدو أحدث إلى بناء قائم دون مراجعة سياسة توافقه. ترتبط kotlin.test وJUnit بتكامل خاص بالمنصة؛ وليستا اسمَي حزم قابلين للتبادل يعملان دون إعداد. لا تثبّت هذه الدورة اعتماديات ولا تقدم نص بناء غير متحقق. وعندما يتوفر اختبار حقيقي معزول، احفظ الأوامر كاملة وبيئة التنفيذ والنتائج المرصودة، وأبق الأمثلة غير المنفذة موسومة بوضوح.

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

يُتوقع أن تقصر internal الوصول على حزمة واحدة.

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

يفشل اختبار الموعد بحسب الوقت الحالي عند تشغيله.

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

يدعي تقرير اختبار النجاح رغم عدم تشغيل مترجم.

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

اختبر فهمك

1. هل ينبغي جعل مساعد تطبيع خاص عاما لمجرد اختبار trim؟

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

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

2. ماذا ينبغي أن يقول تقرير صادق عن الفاحص المقدم في هذه الدورة؟

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

هو مصدر Kotlin كامل ذو مخرج متوقع بالتحليل وثلاث حالات حدود معلنة، لكنه لم يُترجم أو يُنفّذ لأن أدوات Kotlin لم تتوفر. إنها مادة تعليمية مفيدة، وليست نجاح اختبار مسجلا. يجب أن يوثق تنفيذ المشروع الفعلي أدواته المتوافقة ونتيجته الخاصة.

أهم ما تعلمته

  • تعبّر الحزم والوحدات ومعدلات الرؤية عن حدود مختلفة.
  • تجعل الفحوص الحتمية وسجلات التنفيذ الصادقة الأدلة قابلة للاستفادة.

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