Suppose, we have the following Boy
class that tries to arrange a date with a Girl
by analyzing her schedule (example in Java):
public class Boy {
public boolean tryArrangeDate(Girl girl, Date time) {
boolean success = true;
for (GirlRoutine routine : girl.getSchedule()) {
if (routine.happensAt(time)) {
success = false;
break;
}
}
return success;
}
}
Boy.tryArrangeDate()
method clearly violates Law of Demeter because of routine.happensAt()
call. One of the ways to resolve this is to move schedule analysis directly to Girl
and avoid having a dependency on GirlRoutine
. That would probably be one the best decisions in this case. RFC for Boy
class will be reduced.
But suppose we choose a different direction for resolving violations of Law of Demeter and change the code in this way:
public class Boy {
public boolean tryArrangeDate(Girl girl, Date time) {
return isFree(girl.getSchedule(), time);
}
private boolean isFree(List<GirlRoutine> schedule, Date time) {
boolean free = true;
for (GirlRoutine routine : schedule) {
if (happensAt(routine, time)) {
free = false;
break;
}
}
return free;
}
private boolean happensAt(GirlRoutine routine, Date time) {
return routine.happensAt(time);
}
}
There are two private methods added that just delegate calls down to the Girl
and her schedule / routines.
Each method taken individually does not seem to violate Law of Demeter (for simplicity reasons let us treat retrieval of item from collection as a primitive no-method-call operation). But overall we have not reduced RFC for this class, did not improve the cohesion, and actually increased WMC. Tell, don't ask principle is not preserved. So, Law of Demeter is satisfied but design is still flaky.
Question: Is it true that (formally) second code snippet does not violate Law of Demeter?
NOTE: Purpose of the question is NOT to find alternative solutions, but to confirm / refute that the solution adheres to the Law of Demeter