4

次のコードは、デメテルの法則に違反しています。

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. LoDはどのように壊れていますか?
  2. LoDを破るコードはどこにありますか?
  3. LoDを維持するためにコードをどのように書く必要がありますか?
4

5 に答える 5

3

ここに2つの問題があると思います。

  1. Gradesロジックが。と混ざりすぎていStudentます。Gradesそれはクラスで行われるべきです
  2. Teacherのロジックはに配置されStudentます。

結論:生徒は教師と学年の内部構造と論理についてよく知っているので、LoDを壊します

于 2010-04-09T16:51:08.943 に答える
2

このようなほとんどの問題は、ドメインモデルを再検討することで解決できます。

学生には本来よりもはるかに多くの責任があるようです。変更する理由は1つだけです。

ReportCardオブジェクトを追加して、これをリファクタリングします。

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...
}
于 2010-04-09T19:44:33.020 に答える
1

Person.isTeacherあなたが言及したウィキペディアの記事によると、「到達」します。

学生の所有物である成績のリストを見つけて驚いた。それは学校が知っていて管理しているものではないでしょうか?どの先生がどの年に生徒を採点したかを学校に聞いてみます...

于 2010-04-09T16:50:30.187 に答える
1

デメテルの法則を破るクラスStudentのメソッドは

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

これらはドメインオブジェクトの成績と教師をアプリケーションに公開するためです。

Student内のGradesとGrades内のTeacherを引き続き非表示にする場合、この問題を解決する1つの方法は、クラスStudentで、内部のGradesオブジェクトとTeacherオブジェクトに代わって動作するプロキシメソッド(デリゲートメソッドとも呼ばれる)を定義することです。アプリケーションの、メソッドと同様Student.isTeacher(int, String)です。このソリューションは、LofDを尊重するクラス設計の欠点である、成績と生徒の教師のメソッドの重複につながる可能性があります。

より良い解決策は、生徒から成績と教師を削除し、それらをすべて別のクラスに配置することです。

class Transcript {
  Student student;
  Teacher teacher;
  Grades grades;
  Integer year;
}  
于 2010-04-09T20:23:51.867 に答える
0

これらの2つのプライベート関数を使用すると、LoDが壊れます。

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

学生は、そのようなタスクを実行するためのロジックを必要とすべきではありません。

これを再設計する方法は、データをロジックから分離することです。学生は純粋にデータのみである必要があります。学生と学生に関する情報のみを含める必要があります。したがって、その概念には科目や教師などの他の人が必要であるため、これには成績は含まれません。

同じことが先生にも当てはまります。次に、成績情報を保存する場所と、科目情報を保存する場所を作成します。

同様のタスクを実行するには、次のようにします。

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

件名もデータのみのオブジェクトです。

于 2010-04-09T16:58:09.367 に答える