CPSC 210
D8 Cont'd & Design Review
(last lecture 😢👋)
Lecture Lab
More (fun with) Iterators
More (fun with) Iterators
OneThenTwo
Alternating
Cartesian
More (fun with) Iterators
OneThenTwo
Alternating
Cartesian
More (fun with) Iterators
OneThenTwo
Alternating
Cartesian
More (fun with) Iterators
Strategy
Reminder
Teaching
Evaluations
Please
Reminder
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
-
when a subtype is substituted for its 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!
Last Class !
By firas_moosvi
Last Class !
- 59