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 with Trainer and Seminar
  • 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 with Trainer and Seminar
  • 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:

  1. Pre-condition - what inputs does it expect?
  2. Post-condition - what outputs does it guarantee?
  3. 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