"Principle of least knowledge"
What is it?
A method in an object should only call methods of:
Only talk to your immediate friends
Avoid doing method chaining! (You will lose marks)
o.get(name).get(thing).remove(node)Purpose?
Achieve loose coupling in code
Cohesion refers to what a class / module can do.
Low cohesion means class has a great variety of actions (broad, unfocused)
High cohesion means a class is focused on what it should be doing
Coupling refers to how dependent classes are toward each other.
High coupling makes it difficult to change your code as classes are so knit together.
Good software design is
high cohesion
and
low coupling
In the unsw.training package there is some code for a training system.
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;
}In violating this principle, what other properties of this design is not desirable?
TrainingSystem is needlessly tightly coupled with Trainer and Seminar
TrainingSystem has low cohesion as it relies on classes that are not its closest friends to achieve its purposeSeminar has no control over the number of attendees. It relies on TrainingSystem to restrict number of attendees. This makes Seminar hard to re-use in the future (poor encapsulation)
In violating this principle, what other properties of this design is not desirable?
TrainingSystem no longer has any knowledge of Seminar. Seminar class is responsible for ensuring number of attendees do no exceed 10.In refactoring the principle is no longer violated, how has this affected other properties of the design?
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;
}
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
SRP
OCP
ISP
DIP
A pipeline contains:
What is a stream?
A sequence of elements which runs through the pipeline that transforms from intermediate operations.
map(): Applies a given function to elements in the stream
filter(): Selects specific elements as per the Predicate (boolean function)
sorted(): Used to sort the stream
Intermediate Operations
collect(): Collects the result of a stream into a list, set, etc.
forEach(): Iterate through every element of the stream
reduce(): Reduce the elements of a stream into a single value
Terminal Operations
Behavioural design pattern that lets you define a family of methods that are interchangeable at runtime
What problem does it solve?
Introducing new behaviours without modifying existing code, adhering to the Open-Closed Principle. Avoids conditional statements to select algorithms.
When should we use this pattern?
When we need multiple ways of achieving the same task
Different transport behaviours (strategies) that can be interchangeable
Currently, the code uses switch statements to handle each of the different cases.
How does the code violate the open/closed principle?
Currently, the code uses switch statements to handle each of the different cases.
How does the code violate the open/closed principle?
switch statement.
How does this make the code brittle?
Currently, the code uses switch statements to handle each of the different cases.
How does the code violate the open/closed principle?
switch statement.
How does this make the code brittle?
Let's refactor it!
Now that we have refactored, how about we want to add a new pricing strategy?
Notice how after refactoring, it is a lot easier to add additional functionality and we are no longer breaking the Open-Closed Principle.
Find out more at Strategy (refactoring.guru)
What is it?
Behavioural pattern which defines a subscription mechanism that notifies observers about any event that happens to the subject that they are observing
What problem does it solve?
Modelling a n-to-many relationship may be difficult. If
not done well, it typically leads to tight coupling
When should we use this pattern?
When changing the state of one object requires changing other objects in turn
Subject
Maintains a list of observers and notifies them of state changes. During this notification, they are passing data (push/pull)
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers(data); // Calls update() of observersObserver
Register (and unregister) themselves on a subject and to update their state when they are notified.
// Two possible options for update()
public void update(Subject obj); // PULL data from subject
public void update(data); // PUSH data to observersModel the system in Java!
Which design pattern should we use for each of the following?
Represent tasks with subtasks, all supporting markComplete()
Which design pattern should we use for each of the following?
Represent tasks with subtasks, all supporting markComplete()
Composite Pattern
Which design pattern should we use for each of the following?
Represent tasks with subtasks, all supporting markComplete()
Composite Pattern
In a data analysis tool, switch between different sorting algorithms depending on the dataset needs
Which design pattern should we use for each of the following?
Represent tasks with subtasks, all supporting markComplete()
Composite Pattern
Strategy Pattern
In a data analysis tool, switch between different sorting algorithms depending on the dataset needs
Which design pattern should we use for each of the following?
News app (e.g., email alerts, mobile notifications) notifies when a new article is published
Represent tasks with subtasks, all supporting markComplete()
Composite Pattern
Strategy Pattern
In a data analysis tool, switch between different sorting algorithms depending on the dataset needs
Which design pattern should we use for each of the following?
In a data analysis tool, switch between different sorting algorithms depending on the dataset needs
News app (e.g., email alerts, mobile notifications) notifies when a new article is published
Represent tasks with subtasks, all supporting markComplete()
Composite Pattern
Strategy Pattern
Observer Pattern