كيفية التعامل مع حالات البرمجة الدفاعية المختلفة؟

StackOverflow https://stackoverflow.com//questions/21014651

سؤال

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

public Period(Date start, Date end) {
    this.start = new Date(start.getTime());
    this.end = new Date(end.getTime());
}

أسئلة:

  1. ماذا تفعل إذا Date لم يكن لدي منشئ ليأخذ نفسه فيه، لأجعل نفسي أكثر عمومية، يتم تمرير كائن بدون آلية لتكرار نفسه، وهذا الكائن لا ينتمي إلينا، أي لا يمكننا تغييره بأي شكل من الأشكال؟

  2. ماذا لو أخذ المنشئ معلمة النوع كوسيطة، على سبيل المثال Period(T object) ويمكن أن يكون T قابلاً للتغيير لذا يحتاج إلى نسخة دفاعية.ليس لدينا أي فكرة عما هو T.كيفية عمل نسخة دفاعية في هذه الحالة؟

  3. يتم تمرير ما هي الواجهة حيث تحتوي بعض فئاتها الفرعية على مُنشئ مثل Date لإنشاء كائن من تلقاء نفسه وبعض فئاته الفرعية ليس لديها أي آلية للقيام بذلك؟

  4. ما مدى العمق الذي يجب أن ننسخه بشكل دفاعي؟لنفترض أننا نسخنا مصفوفة، لكن عناصر المصفوفة كانت قابلة للتغيير؟

هل كانت مفيدة؟

المحلول

  1. إذا كانت كل حالته متاحة، فيمكنك استخراج حالته وإنشاء كائن جديد بنفسك.بخلاف ذلك، لا يمكنك فعل أي شيء حيال ذلك باستثناء استخدام حيل الانعكاس أو التسلسل السيئة.
  2. إذا لم يكن T مثيلًا لفئة تسمح بنسخ نفسها، فلا يمكنك فعل أي شيء.
  3. لا يمكنك فعل أي شيء حيال ذلك.
  4. هذا يعتمد.

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

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

نصائح أخرى

  1. إذا لم تتمكن من تغيير حالة الكائن على أي حال، فلن تحتاج إلى نسخة دفاعية.
  2. الشيء الوحيد الذي يمكنك فعله هو افتراض التنفيذ المحتمل لـ T والتحقق منه حالة.
  3. نفس 2.
  4. حسب تقديرك.إذا كنت تفترض أن تعديل عناصر المصفوفة قد يؤدي إلى تعطيل برنامجك في أماكن أخرى، فيجب عليك نسخها جميعًا أيضًا.

البرمجة الدفاعية مهمة عندما تكون الكائنات التي تمررها إلى إحدى الطرق قابلة للتغيير.من الممارسات الجيدة (الموصوفة أيضًا في كتاب Java الفعال) جعلها غير قابلة للتغيير.

  1. إذا لم تكن فئة التاريخ نهائية، فيمكنك كتابة فئة مجمعة لها، وهي فئة فرعية من التاريخ.
  2. هذا يعتمد.ربما لن تكون هناك حاجة لاستنساخه.
  3. لا ينبغي أن يزعجك.ينبغي لمنفذ الواجهة الاهتمام بقضايا المزامنة.بشكل عام، من الممارسات الجيدة تمرير الواجهات بدلاً من تطبيقاتها.
  4. بالنسبة لمجموعات Java القياسية، هناك الكثير من الأساليب المساعدة في فئة java.util.Collections، مثل unmodifiableList وunmodifiableMap، المخصصة للاستخدام في البرمجة الدفاعية.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top