Law of Demeter | slide # 2 |
...Benefits | slide # 6 |
...Law of Demeter and God Classes | slide # 7 |
...Law of Demeter and Container Classes | slide # 10 |
Lieberherr, Holland, Riel, Object-Oriented Programming: An Objective Sense of Style, OOPSLA 1988 Proceedings
Lieberherr, Adaptive Object-Oriented Software: The Demeter
Method with Propagation Patterns, PWS Publishing Company,
1996
class Course { Instructor boring = new Instructor(); int pay = 5; public Instructor getInstructor() { return boring; } public Instructor getNewInstructor() {return new Instructor(); } public int getPay() {return pay; } } class C { Course test = new Course(); public void badM() { test.getInstructor().fired(); } public void goodM() { test.getNewInstructor().hired(); } public int goodOrBadM?() { return getpay() + 10; } }
class Course { Instructor boring = new Instructor(); int pay = 5; public Instructor fireInstructor() { boring.fired(); } public Instructor getNewInstructor() { return new Instructor();} public int getPay() { return pay ; } } class C { Course test = new Course(); public void reformedBadM() { test.fireInstructor(); } public void goodM() { test.getNewInstructor().hired(); } public int goodOrBadM() { return getpay() + 10; } }
class Course { Instructor boring = new Instructor(); int pay = 5; public Instructor fireInstructor() { boring.fired(); } public Instructor hireNewInstructor() { boring = new Instructor();} public int getPay() { return pay ; } } class C { Course test = new Course(); public void reformedBadM() { test.fireInstructor(); } public void goodMImproved() { test.hireNewInstructor();} public int goodOrBadM() { return getpay() + 10; } }
Assume that Student and Scores are basicly structs with lots of get/set methods and Course does all the work
class Student { Scores exams = new Scores(); public Scores getExamScores() { return exams; } public Scores setExamScores( Scores newScores) { exams = newScores;} // stuff missing } class Course { Student[] enrolled = new Student[ 40 ]; public void computeAverage( int studentIndex ) { Scores toCompute = enrolled[ studentIndex].getExamScores(); float sum = 0; for ( int k = 0; k < toCompute.length(); k ++ ) sum += toCompute.gradeAt( k ); } }Law of Demeter and God Classes
Compare coupling in two examples
class StudentImproved { Scores exams = new Scores(); public int computeAverage() { // compute average here; } public Scores setExamScores( Scores newScores) { exams = newScores; } } class Course { StudentImproved[] enrolled = new StudentImproved[ 40 ]; public void computeAverage( int studentIndex ) { int average = enrolled[ studentIndex].computeAverage(); } }
class Student { Scores exams = new Scores(); public Scores getExamScores() { return exams; } public Scores setExamScores( Scores newScores) { exams = newScores;} // stuff missing } class Course { Student[] enrolled = new Student[ 40 ]; public void computeAverage( int studentIndex ) { computeStudentAverage( Student[ studentIndex].getExamScores()); } public void computeStudentAverage( Score exams ) { float sum = 0; for ( int k = 0; k < exams.length(); k ++ ) sum += exams.gradeAt( k ); } }
class Test { public void ok( Scores exam, Scores homework ) { exam.hereIsAMethodCall(); homework.hereIsAMethodCall(); } public void seemsOK( Scores[2] gradeEvents ) { gradeEvents[0].hereIsAMethodCall(); gradeEvents[1].hereIsAMethodCall(); } public void seemsNotOK( Vector gradeEvents ) { gradeEvents.at(0).hereIsAMethodCall(); gradeEvents.at(1).hereIsAMethodCall(); } }