سؤال

الكود التالي يكسر قانون ديميتر:

public class Student extends Person {
  private Grades grades;

  public Student() {
  }

  /** Must never return null; throw an appropriately named exception, instead. */
  private synchronized Grades getGrades() throws GradesException {
    if( this.grades == null ) {
      this.grades = createGrades();
    }

    return this.grades;
  }

  /** Create a new instance of grades for this student. */
  protected Grades createGrades() throws GradesException {
    // Reads the grades from the database, if needed.
    //
    return new Grades();
  }

  /** Answers if this student was graded by a teacher with the given name. */
  public boolean isTeacher( int year, String name ) throws GradesException, TeacherException {
    // The method only knows about Teacher instances.
    //
    return getTeacher( year ).nameEquals( name );
  }

  private Grades getGradesForYear( int year ) throws GradesException {
    // The method only knows about Grades instances.
    //
    return getGrades().getForYear( year );
  }

  private Teacher getTeacher( int year ) throws GradesException, TeacherException {
    // This method knows about Grades and Teacher instances. A mistake?
    //
    return getGradesForYear( year ).getTeacher();
  }
}

public class Teacher extends Person {
  public Teacher() {
  }

  /**
   * This method will take into consideration first name,
   * last name, middle initial, case sensitivity, and
   * eventually it could answer true to wild cards and
   * regular expressions.
   */
  public boolean nameEquals( String name ) {
    return getName().equalsIgnoreCase( name );
  }

  /** Never returns null. */
  private synchronized String getName() {
    if( this.name == null ) {
      this.name == "";
    }

    return this.name;
  }
}

أسئلة

  1. كيف يتم كسر لود؟
  2. أين هو الكود الذي يكسر لود؟
  3. كيف يجب أن تتم كتابة الرمز لدعم LOD؟
هل كانت مفيدة؟

المحلول

الأساليب في طالب الفصل الذي يكسر قانون ديميتر

private Grades getGradesForYear( int year )
private Teacher getTeacher( int year )

لأن هذه تعرض درجات الكائنات المجال والمعلم للتطبيق.

على افتراض أنك ترغب في مواصلة إخفاء الدرجات داخل طالب ومعلم داخل الدرجات ، فإن إحدى الطرق لعلاج هذه المشكلة هي تحديد أساليب الوكيل (تسمى أيضًا أساليب المندوب) في طالب الفصل الذي يعمل على الدرجات الداخلية وأشياء المعلم نيابة من التطبيق ، على غرار الطريقة Student.isTeacher(int, String). قد يؤدي هذا الحل إلى ازدواج الأساليب في الدرجات والمعلم في الطالب وهو أ عيب من تصميم الفصل الذي يحترم LOFD.

سيكون الحل الأفضل هو إزالة الدرجات والمعلم من الطالب ووضعها جميعًا في فصل آخر ، على سبيل المثال:

class Transcript {
  Student student;
  Teacher teacher;
  Grades grades;
  Integer year;
}  

نصائح أخرى

أعتقد أن هنا مشكلتان:

  1. Grades المنطق مختلط كثيرا مع Student. يجب أن يتم في Grades صف دراسي
  2. Teacherيتم وضع منطق Student.

الخلاصة: الطالب يعرف الكثير عن الهيكل الداخلي ومنطق المعلم والدرجات والذي يكسر لود

يمكن حل معظم المشكلات مثل هذا عن طريق إعادة النظر في نموذج المجال الخاص بك.

يبدو أن الطالب يتحمل مسؤولية أكثر مما ينبغي. يجب أن يكون لها سبب واحد فقط للتغيير.

أود أن أشد هذا عن طريق إضافة كائن بطاقة تقرير.

public class ReportCard
{
  public Student Student...
  public int Year...
  public ReportCardItem[] ReportCardItems...

  getGrades()...
  createGrades()...
}

public class ReportCardItem
{
  public Grade Grade...
  public string Subject...
  public Teacher Teacher...
}

Person.isTeacher "تصل إلى" وفقًا لمقال ويكيبيديا الذي ذكرته.

لقد فوجئت بالعثور على قائمة الدرجات من ممتلكات الطالب. ألا ينبغي أن يكون هذا شيئًا تعرفه المدرسة وتديره؟ سأطلب من المدرسة ، أي معلم قام بتقدير طالب في أي عام ...

من خلال وجود هاتين وظيفتين خاصتين استراحة لود.

private Grades getGradesForYear( int year )
private Teacher getTeacher( int year )

يجب ألا يحتاج الطلاب إلى المنطق لأداء مثل هذه المهام.

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

الشيء نفسه ينطبق على المعلم. أود بعد ذلك إنشاء مكان لتخزين المعلومات ومكان آخر لمعلومات الموضوع.

لأداء مهام مماثلة سأفعل ذلك:

gradesDatabase.getGrade(subject, student);
subjectDatabase.getTeacher(subject, student);

حيث يكون الموضوع أيضًا كائن بيانات فقط.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top