COMP2511 Week 4
Agenda
- Admin Stuff
- Law of Demeter
- Liskov Substitution Principle
- Streams and Lambda
- Design by Contract
Admin Stuff
-
Assignment 1 is due next Friday
- Get started please 😫
- Get feedback on assignment UML,
- Feel free to come to me or the LA during the lab
-
Assignment 2 pair
- Tell us your preference during the lab
Law of Demeter
"Principle of least knowledge"
Law of Demeter
What is it?
A method in an object should only call methods of:
- The object itself
- Attributes of the object
- Object passed in as a parameter to a method
- Objects instantiated within the method
Only talk to your immediate friends
Law of Demeter
Avoid doing this! (You will lose marks)
o.get(name).get(thing).remove(node)
Purpose?
Achieve loose coupling in code

Law of Demeter
In the unsw.training
package there is some code for a training system.
- Every employee must attend a whole day training seminar run by a qualified trainer
- Each trainer is running multiple seminars with no more than 10 attendees per seminar
In the TrainingSystem
class, there is a method to book a seminar for an employee given the dates on which they are available.
This method violates the principle of least knowledge (Law of Demeter).
Where and how is the Law of Demeter being violated?
TrainingSystem
is getting instances of Seminar
from instances of Trainer
and calling its methods
Interacting with classes beyond its friends
public LocalDate bookTraining(String employee, List<LocalDate> availability) {
for (Trainer trainer : trainers) {
for (Seminar seminar : trainer.getSeminars()) {
for (LocalDate available : availability) {
if (seminar.getStart().equals(available) &&
seminar.getAttendees().size() < 10) {
seminar.getAttendees().add(employee);
return available;
}
}
}
}
return null;
}
Law of Demeter
What other properties of this design are not desirable?
Law of Demeter
What other properties of this design are not desirable?
-
TrainingSystem
is needlessly tightly coupled withTrainer
andSeminar
-
TrainingSystem
has low cohesion as it relies on classes that are not its closest friends to achieve its purpose - Seminar does not enforce the capacity requirement. So, it makes the class more difficult to be re-used. (Poorly encapsulated)
Law of Demeter
What other properties of this design are not desirable?
-
TrainingSystem
is needlessly tightly coupled withTrainer
andSeminar
-
TrainingSystem
has low cohesion as it relies on classes that are not its closest friends to achieve its purpose - Seminar does not enforce the capacity requirement. So, it makes the class more difficult to be re-used. (Poorly encapsulated)
Let's refactor it together!
Law of Demeter
Liskov Substitution Principle (LSP)
Liskov Substitution Principle
What is it?
Design principle that states instances of the superclass must be replaceable by instances of the subclasses without breaking changes.

Liskov Substitution Principle
How does OnlineSeminar
violate LSP?
/**
* An online seminar is a video that can
* be viewed at any time by employees.
* A record is kept of which employees
* have watched the seminar.
*/
public class OnlineSeminar extends Seminar {
private String videoURL;
private List<String> watched;
}
Liskov Substitution Principle
How does OnlineSeminar
violate LSP?
/**
* An online seminar is a video that can
* be viewed at any time by employees.
* A record is kept of which employees
* have watched the seminar.
*/
public class OnlineSeminar extends Seminar {
private String videoURL;
private List<String> watched;
}
Does not have a list of attendees, so clients won't be able to use it in the same way as Seminar
.
i.e making a booking
Streams and Lambda
Streams and Lambda
What it is?
Java's way of enabling functional programming
Common stream methods:
forEach, filter, map, reduce
Why bother?
- reduce bugs by writing code on a more abstract level
- often lead to more compact and readable code
Design by Contract
What is it?
Software design approach that specifies how a component
should interact with other components
A contract should address the following 3 conditions:
- Pre-condition - what inputs does it expect?
- Post-condition - what outputs does it guarantee?
- Invariant - What does not change?
Design by Contract
Design by Contract
public class Calculator {
public static Double add(Double a, Double b) {
return a + b;
}
public static Double divide(Double a, Double b) {
return a / b;
}
public static Double sin(Double angle) {
return Math.sin(angle);
}
public static Double tan(Double angle) {
return Math.tan(angle);
}
}
Specify a contract for each function
i.e. preconditions & postconditions
public class Calculator {
/**
* @preconditions a, b != null
* @postconditions a + b
*/
public static Double add(Double a, Double b) {
return a + b;
}
/**
* @preconditions a, b != null, b != 0
* @postconditions a / b
*/
public static Double divide(Double a, Double b) {
return a / b;
}
/**
* @preconditions angle != null
* @postconditions sin(angle)
*/
public static Double sin(Double angle) {
return Math.sin(angle);
}
/**
* @preconditions angle != null, angle != Math.PI / 2
* @postconditions tan(angle)
*/
public static Double tan(Double angle) {
return Math.tan(angle);
}
}
Design by Contract
Design by Contract
COMP2511 Tutorial 4
By Matthew Liu
COMP2511 Tutorial 4
- 130