Kotlin / دليل حلول تحريري

تشخيص النسخ السطحي والمساواة غير المستقرة

افحص اللقطات المتغيرة والمراجع القابلة للتعديل وخصائص منشئ data class وإخفاقات البحث في حاويات التجزئة.

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

قاعدة معرفة للقراءة فقط · بلا تعليقات عامة

تعرّف على الأعراض

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

افهم الأسباب المحتملة

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

ارسم المراجع قبل تغيير النموذج

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

kotlin مثال مقصود لمشاركة ناتجة عن نسخ سطحي
data class Draft(val labels: MutableList<String>)
fun main() {
    val original = Draft(mutableListOf("basic"))
    val copied = original.copy()
    copied.labels.add("extra")
    println(original.labels.joinToString("|"))
    println(original.labels === copied.labels)
}
الناتج المتوقع
basic|extra
true

السطران المتوقعان هما basic|extra ثم true. يختلف مثيلا Draft، لكن خاصية labels فيهما تشير إلى القائمة القابلة للتعديل نفسها. هذا ليس نمطا آمنا للقطة مستقلة، ولم يُترجم.

حدّد بدقة الحقول التي تعرّف القيمة

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

اختر سياسة نسخ وملكية تطابق الوعد

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

kotlin لقطة لقائمة نصوص ونسخة معدلة بصورة صريحة
data class Snapshot(val labels: List<String>)
fun main() {
    val source = mutableListOf("basic")
    val first = Snapshot(source.toList())
    source.add("extra")
    val second = first.copy(labels = first.labels + "reviewed")
    println(first.labels.joinToString("|"))
    println(second.labels.joinToString("|"))
}
الناتج المتوقع
basic
basic|reviewed

المخرج المتوقع basic ثم basic|reviewed. لا يغير تعديل المصدر first لأن بنية قائمتها نُسخت. تمنع العناصر النصية تعقيد تعديل كائنات العناصر بعمق في هذا المثال. المصدر غير منفذ.

تحقق من عزل المحتوى ومن سلوك القيمة معا

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

تحقق من نجاح الإصلاح

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

امنع تكرار المشكلة

  • استخدم أنواع قيم مستقرة للمفاتيح، وأبعد المراجع القابلة للتعديل عن واجهات اللقطات، وراجع عمليات data class المولدة كلما تغيرت حقول المنشئ. وثّق سلوك النسخ السطحي واختبر حالة داخلية ممثلة، بدلا من افتراض أن val أو copy تحقق الثبات العميق.

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