COMP2511

25T1 Week 9

Thursday 9am-12pm (H09B)

 

Slides by Sam Zheng (z5418112)

Original slides by Alvin Cherk

This week

  • Finding Patterns
  • Code and Design Smells
  • Visitor Pattern

Admin

  • Assignment-ii: No blogs, no marks
  • Assignment-iii: Please fill out the form provided on Teams, even if you are not doing the assignment
  • Week 10 Tute: Kahoot & Revision
    • Any particular topics to go over message me on Teams and we'll try slot it in :)
  • Week 10 Lab: Sample Exam dry-run using exam environment
  • MyExperience

Group Task

Finding patterns

Finding Patterns

In groups, determine a possible pattern that could be used to solve each of the following problems:

 

  1. Sorting collections of records in different orders
  2. Listing the contents of a file system
  3. Traversing through a linked list without knowing the underlying representation
  4. Updating a UI component when the state of a program changes
  5. Allowing users to remap their movement controls to different buttons on a game controller
  6. Creating a skeleton implementation for a payment processing algorithm that changes based on type (e.g. credit card, PayPal)
  7. A frozen yogurt shop model which changes cost and weight of a bowl of frozen yogurt based on the toppings that customers choose

Strategy

Composite

Iterator

Observer

Command

Decorator

Template

Group Task

Code and Design Smells

Code and Design Smells

Mark, Bill and Jeff are working on a PetShop application. The PetShop has functionality to feed, clean and exercise different types of animals.

Mark notices that each time he adds a new species of animal to his system, he also has to rewrite all the methods in the PetShop so it can take care of the new animal.

What code or design smell is present here?

  • Code smell - Divergent change
  • Design problem - Open Closed Principle, high coupling

Code and Design Smells

public class Person {
    private String firstName;
    private String lastName;
    private int age;
    private int birthDay;
    private int birthMonth;
    private int birthYear;
    private String streetAddress;
    private String suburb;
    private String city;
    private String country;
    private int postcode;
    public Person(String firstName, String lastName, 
    			  int age, int birthDay, int birthMonth,
                  int birthYear, String streetAddress,
                  String suburb, String city, String country,
                  int postcode) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.birthDay = birthDay;
        this.birthMonth = birthMonth;
        this.birthYear = birthYear;
        this.streetAddress = streetAddress;
        this.suburb = suburb;
        this.city = city;
        this.country = country;
        this.postcode = postcode;
    }
    // Some various methods below...
}

What code or design smell is present here?

Data clumps & long parameter list

How would you refactor to fix this?

  • Refactor by making more classes for birthday and address (Extract Class / Introduce Parameter Object)
  • Design problem - DRY and KISS

 

If some of the input was "optional" builder pattern may be useful here

Code and Design Smells

public class MathLibrary {
    List<Book> books;

    int sumTitles {
        int total = 0
        for (Book b : books) {
            total += b.title.titleLength;
        }
        return total;
    }
}

public class Book {
    Title title; // Our system just models books
                 // as titles (content doesn't matter)
}

public class Title {
    int titleLength;

    int getTitleLength() {
        return titleLength;
    }

    void setTitleLength(int tL) {
        titleLength = tL;
    }
}

What code or design smell is present here?

  • Inappropriate intimacy (accessing public fields)
  • Message chains/Law of Demeter
  • Data classes/Lazy classes Design smell - High coupling, from encapsulation being broken

How would you refactor to fix this?

  • Make things private
  • Delete the classes and represent titles as strings

Code and Design Smells

How do these code smells cause problems when developing code?

  • Reusability
  • Maintainability
  • Extensibility

How fast does it take for a new developer to understand what is happening? Is behaviour predictable, reasonable and uniform?

Is a code smell always emblematic of a design problem?

No

  • Switch statements & comments are often listed as code smells, but are aren't always 'a problem'

Visitor Pattern

Visitor Pattern

What kind of design pattern is it?

Behavioural

  • Allows you to separate algorithms from the objects they work on
  • Adds functionality to an object structure without changing its classes - abides by Open-Closed principle

Visitor Pattern

  • When to use?
    • When you have a complex object structure and need to apply various operations
  • Advantages
    • Centralising operations logic
    • Easier to add new operations
    • Enhance code readability and maintainability
    • Helps to adhere to SRP
  • Drawbacks
    • Difficult to add new element types
    • Can become verbose with many element types
    • Visitors may lack access to private fields/methods

Visitor Pattern

// Base class for shapes
abstract class Shape {
    abstract void draw();
    abstract double calculateArea();
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    void draw() {
        System.out.println("Drawing a circle with radius " + radius);
    }

    @Override
    double calculateArea() {
        return Math.PI * radius * radius;
    }
}
class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    void draw() {
        System.out.println("Drawing rectangle, w:" + width + " h: " + height);
    }

    @Override
    double calculateArea() {
        return width * height;
    }
}

// Client code
public class Main {
    public static void main(String[] args) {
        Shape[] shapes = {new Circle(5), new Rectangle(4, 6)};
        for (Shape shape : shapes) {
            shape.draw();
            System.out.println("Area: " + shape.calculateArea());
        }
    }
}
interface Shape {
    void accept(ShapeVisitor visitor);
}

class Circle implements Shape {
    double radius;
    Circle(double radius) { this.radius = radius; }
    @Override
    public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}

class Rectangle implements Shape {
    double width, height;
    Rectangle(double w, double h) { this.width = w; this.height = h; }
    @Override
    public void accept(ShapeVisitor visitor) { visitor.visit(this); }
}

interface ShapeVisitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}

class DrawVisitor implements ShapeVisitor {
    @Override public void visit(Circle c) { System.out.println("Draw Circle: " + c.radius); }
    @Override public void visit(Rectangle r) { System.out.println("Draw Rect: " + r.width + "x" + r.height); }
}

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = {new Circle(5), new Rectangle(4, 6)};
        ShapeVisitor draw = new DrawVisitor();
        for (Shape shape : shapes) shape.accept(draw);
    }
}

Code Demo

Computers

Visitor Pattern Demo

In this scenario we have Computers, Keyboards and Mouses which all are of type ComputerComponent. We want to be able to 'visit' different types of Computer components by logging the following messages:

Looking at computer Corelli with memory 500 GB.
Looking at keyboard Mechanical keyboard which has 36 keys.
Looking at mouse Bluetooth mouse.

In particular though, anyone which is visiting a Computer must be validated prior to being able to visit.

Extend/modify the starter code to use the Visitor Pattern to allow different computer components to be visited.

Made with Slides.com