CPSC 210

Design Review

(last lecture 😢👋)

We have a guest today...

The maker of Lab4 has a new lab to present...

More workspace practice for the final exam!

Mazen

And now...

Teaching

Evaluations

Please

Design Review

From high-level design principles to a sample of concrete design patterns

  • Well-designed software has high cohesion and low coupling
  • Most design patterns improve on cohesion and coupling

Cohesion

Every class should have a
single responsibility

Coupling

Measure how system components depend on each other

Liskov Substitution Principle

  • Design principle that states:
    • when a subtype is substituted for its super type:
      • the subtype must provide the expected behaviours of the super type

Refactoring

  • We refactor our code to improve on:
    • the design of our codebase
    • coupling by abstracting duplicated code
    • cohesion by splitting up classes

Design Patterns

We make mistakes

We identify our mistakes

We learn from our mistakes

We prevent mistakes

We Evolve Design Patterns

Lessons Learned!

Composite

I have a tree structure and I don't know all the types of objects in the tree

Run operations recursively through my tree without knowing the types in my tree

Observer

I want objects to know about a state but I don't know what these objects are

Objects can be added and removed as they desire

Singleton

I want to coordinate a state across my system

There is always exactly one instance of this state in my system

Iterator

I have a collection of elements and there should always be a "next" element

Traverse elements without exposing its implementation

ArrayListIterator<E>
LinkedListIterator<E>
HashSetIterator<E>

Iterable<E>

Iterator<E> iterator()

<<interface>>

Iterator<E>

boolean hasNext()
E next()
void remove()

<<interface>>

Collection

<<interface>>

Design patterns help us with the design of our code base

  • But language design also improves over time
  • Some examples...
Iterator<Item> itr = collection.iterator();
while (itr.hasNext()) {
  Item nextItem = itr.next();
  // do something with nextItem
}

Before Java 5

Since Java 5 (2004)

for (Item next : collection) {
    // do something with next
}
button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent evt) {
    System.out.println("Do something");
  }
});

Before Java 8

button.addActionListener(e -> {
  System.out.println("Do something");
});

Since Java 8 (2014)

List<String> list = new ArrayList<>();
list.add("dog");
list.add("cat");
list.add("hamster");

Before Java 9

List<String> list = List.of(
  "dog", "cat", "hamster");

Since Java 9 (2017)

Map<String, Integer> map = new HashMap<>();
map.put("dog", 1);
map.put("cat", 5);
map.put("hamster", 7);

Before Java 9

Map<String, Integer> map = Map.of(
  "dog", 1, "Cat", 5, "Hamster", 7);

Since Java 9 (2017)

Libraries and Frameworks also help us with design

  • Sometimes it's a good idea to look what's out there to help us write good code!
  • One example... you may want to update your projects... 😉

Lombok

public class User {
  private String firstName;
  private String lastName;
  private int age;
  private String email;

  public User(String firstName, String lastName, 
              int age, String email) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = age;
    this.email = email;
  }
  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }
  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public void setAge(int age) {
    this.age = age;
  }
  public void setEmail(String email) {
    this.email = email;
  }
  public String getFirstName() {
    return firstName;
  }
  public String getLastName() {
    return lastName;
  }
  public int getAge() {
    return age;
  }
  public String getEmail() {
    return email;
  }
}
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class User {
  private String firstName;
  private String lastName;
  private int age;
  private String email;
}

Where to next?

  • Now that you have taken CPSC 210, you should be more than capable to build fairly sophisticated software in most other modern programming languages!
     
  • Let's look at the same code in a couple of different languages just to see...
     
  • Note: this is just for fun and the comparison is definitely not examinable!

Syntax is the easy part!

public class Test {
    public static void main(String args[]) {
        String array[] = {"Hello, World", "Hi there, Everyone", "6"};
        for (String i : array) {
          System.out.println(i);
        }
    }
}

Java

stuff = ["Hello, World!", "Hi there, Everyone!", 6]
for i in stuff:
    print(i)

Python

fn main() {
    let stuff = vec!["Hello, World!", "Hi there, Everyone!", 6];
    for i in stuff.iter() {
        println!("{}", i);
    }
}

Rust

Error messages

public class NullPointerExample {
    public static void main(String[] args) {
        String someVariable = null;
        someVariable.length();
    }
}

Java

# Attempting to call a method on a None object
some_variable = None
some_variable()

Python

fn main() {
    let some_variable: Option<&str> = None;
    some_variable.unwrap();
}

Rust

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "someVariable" is null
        at NullPointerExample.main(NullPointerExample.java:4)
TypeError: 'NoneType' object is not callable
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:3:5

Inheritance in Java and Python

... and more!

Hope you had a good time!
We certainly did!

 

Good luck on the Final Exam!

This was CPSC 210!

Design Review (Firas)

By Felix Grund

Design Review (Firas)

  • 269