COMP2511

25T2 Week 3

Friday 9AM - 12PM (F09A)

 

Slides by Christian Tolentino (z5420628)

Today

  • Design By Contract
  • Domain Modelling / UML
  • IDE Programming / Debugging
  • JUnit Testing
  • Exceptions

Important Notice

  • Assignment-i is out, please start early
  • Go to help sessions if you need help (they get busier towards the due date)
  • No auto generated UMLs and no UMLs generated based of code/text. You will get 0. 
  • Assignment-ii pair preferences will be out soon. I will be posting a preference link on Teams.

Design By Contract

Design By Contract

At the design time, responsibilities are clearly assigned to different software elements, clearly documented and enforced during the development and using unit testing and/or language support.

  • Clear demarcation of responsibilities helps prevent redundant checks, resulting in simpler code and easier maintenance
  • Crashes if the required conditions are not satisfied. May not be suitable for highly availability applications

Design By Contract

Every software element should define a specification (or a contract) that govern its transaction with the rest of the software components.

A contract should address the following 3 conditions:

  1. Pre-condition - what does the contract expect?
  2. Post-condition - what does that contract guarantee?
  3. Invariant - What does the contract maintain?

Subclass Conditions

  • An implementation or redefinition (method overriding) of an inherited method must comply with the inherited contract for the method
  • Preconditions may be weakened (relaxed) in a subclass, but it must comply with the inherited contract
  • An implementation or redefinition may lesson the obligation of the client, but not increase it.
  • Similarly, an implementation can output more than whats required to a client, but not less i.e. strengthening postconditions
  • Discuss why strengthening preconditions and weakening postconditions violates good inheritance design.
    • ​You can't treat a subclass as if it was the parent class (you can't treat a Penguin as a Bird even though a Penguin is a bird).

​​

Liskov Substitution Principle (LSP) answers, in a program can you substitute every subclass with its parent class and nothing goes wrong?

  1. In the people package, there are a few classes which represent the people at a university
    • Briefly discuss the preconditions and postconditions of the constructors, getters and setters in Person.java
    • Fill in the preconditions and postconditions for setSalary in Person.java
    • Discuss the validity of the subclasses of Person, and why they are/aren't valid subclasses
    • Fix any issues you identified before
  2. Will you need write unit tests for something that doesn't meet the preconditions?
    • No, input that does not satisfy the preconditions is undefined behaviour and is assumed to be adhered to.
  3. If we were to try make our code more defensive, we could throw an exception on any inputs not satisfying the preconditions. Discuss whether these exceptions are now considered defined behaviour or not, and whether you now need to account for it in your postconditions.
    • Yes!

Domain Modelling

UML

UML

UML

UML

Composition is a specialized form of aggregation. In composition, if the parent object is destroyed, then the child objects also cease to exist e.g. what are the legs of a chair, if the chair didn't exist?

Cardinalities

Domain Modelling

Create an OO domain model for a system with the following requirements.

A Car has one or more engines and a producer. The producer is a manufacturing company who has a brand name. Engines are produced by a manufacturer and have a speed. There are only two types of engines within UNSW's cars:

  • Thermal Engines, which have a default max speed of 114, although they can be produced with a different max speed, and the max speed can change to any value between 100 and 250.
  • Electrical Engines, which have a default max speed of 180. This is the speed at which they are produced, and the max speed can change to any value that is divisible by 6.

Cars are able to drive to a particular location x, y.

Since UNSW is a world-leader in technology innovation, they want you to be able to model the behaviour of Time Travelling for any vehicle, and to model a time travelling car. A vehicle that travels in time stays in the same location but travels to a LocalDateTime.


Domain Modelling

Create an OO domain model for a system with the following requirements.

A Car has one or more engines and a producer. The producer is a manufacturing company who has a brand name. Engines are produced by a manufacturer and have a speed. There are only two types of engines within UNSW's cars:

  • Thermal Engines: which have a default max speed of 114, although they can be produced with a different max speed, and the max speed can change to any value between 100 and 250.
  • Electrical Engines: which have a default max speed of 180. This is the speed at which they are produced, and the max speed can change to any value that is divisible by 6.

Cars are able to drive to a particular location x, y.

Since UNSW is a world-leader in technology innovation, they want you to be able to model the behaviour of Time Travelling for any vehicle, and to model a time travelling car. A vehicle that travels in time stays in the same location but travels to a LocalDateTime.

 

LucidCharts

A generally good diagram maker software that is free*

 

*if you sign up with an .edu account

Common mistakes

  • Wrong types of arrows and lines used.
  • Missing cardinalities and/or no aggregation/composition relationship identified
  • No way to differentiate between abstract classes, interfaces and a regular class - you can either use different font, italicise, bold or even just labelling it.
  • Not using + to indicate public and - to indicate private

 

When I mark, these sort of mistakes lose 0.5 - 1 mark each.

 

Try making a draft one before you start coding your assignments

Code Demo

Wonderous.java

package wondrous;

import java.util.ArrayList;
import java.util.List;

public class Wondrous {
    private final int MY_MAGIC_NUMBER = 42;

    public List<Integer> wondrous(int start) {
        int current = start;
        List<Integer> sequence = new ArrayList<Integer>();

        while (current != 1) {
            sequence.add(current);
            if (current % 2 == 0) {
                current /= 2;
            } else {
                current = (current * 3) + 1;
            }
        }

        return sequence;
    }
}

The Wondrous Sequence is generated by the simple rule:

  • If the current term is even, the next term is half the current term.
  • If the current term is odd, the next term is three times the current term, plus 1

Debug Mode

  • Set a breakpoint, run the test in debug mode
  • Stops at a breakpoint it encounters
  • See variable values, call stack, debug console, debug actions (step through, step in)

JUnit Testing

JUnit Testing

Make sure your VSCode is open in the correct folder, otherwise, these buttons wont appear

JUnit Testing

Make sure your VSCode is open in the correct folder, otherwise, these buttons won't appear

JUnit Testing

  • Failed test output
  • See past history

Now lets fix it

package wondrous;

import java.util.ArrayList;
import java.util.List;

// If the current term is even, the next term is half the current term.
// If the current term is odd, the next term is three times the current term, plus 1.
public class Wondrous {
    public List<Integer> wondrous(int start) {
        int current = start;
        List<Integer> sequence = new ArrayList<Integer>();

        while (true) {
            sequence.add(current);
            if (current == 1) {
                break;
            } else if (current % 2 == 0) {
                // Even
                current /= 2;
            } else {
                // odd
                current = (current * 3) + 1;
            }
        }
        return sequence;
    }
}

Exceptions

Exceptions

What are they?

  • An exception is an event, which occurs during the execution of a problem, that disrupt the normal flow of the program's instructions
  • When error occurs, an exception object is created and given to the runtime system. This is called throwing an exception
  • The runtime system searches the call stack for a method that contains a block of code that can handle the exception
  • The exception handler chosen is said to catch the exception

Exceptions

Checked vs Unchecked

  • Checked: Must be checked, will result in compilation error if not handled
    • Any class that inherits from `Exception` is a checked exception.
    • E.g., IOException, SQLException
  • Unchecked: Genuine errors that occur at run time
    • Any class that inherits from `RuntimeException` is unchecked
    • E.g., ArrayIndexOutOfBoundsExceptions, ArithmeticException

Exceptions - Wonderous

How can we use it in Wonderous to make the code better?
Checked or Unchecked?

Exceptions - Wonderous

How can we use it in Wonderous to make the code better?

package wondrous;

import java.util.ArrayList;
import java.util.List;

// If the current term is even, the next term is half the current term.
// If the current term is odd, the next term is three times the current term, plus 1.
public class Wondrous {
    public List<Integer> wondrous(int start) {
        int current = start;
        List<Integer> sequence = new ArrayList<Integer>();

        if (start < 1) {
            throw new IllegalArgumentException("wondrous start must be >= 1");
        }

        while (true) {
            sequence.add(current);
            if (current == 1) {
                break;
            } else if (current % 2 == 0) {
                // Even
                current /= 2;
            } else {
                // odd
                current = (current * 3) + 1;
            }
        }
        return sequence;
    }
}

JUnit Testing

Let's write a test for this exception

package wondrous.test;

import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;

import wondrous.Wondrous;

public class WondrousTest {
    @Test
    public void testBasic() {
        Wondrous w = new Wondrous();
        List<Integer> expected = new ArrayList<Integer>(Arrays.asList(3, 10, 5, 16, 8, 4, 2, 1));

        assertEquals(expected, w.wondrous(3));
    }

    @Test
    public void testOne() {
        Wondrous w = new Wondrous();
        List<Integer> expected = new ArrayList<Integer>(Arrays.asList(1));
        assertEquals(expected, w.wondrous(1));
    }

    @Test
    public void testInvalid() {
        Wondrous w = new Wondrous();

        assertThrows(IllegalArgumentException.class, () -> {
            w.wondrous(0);
        });
    }
}

COMP2511 Week 3 25T2

By Christian Tolentino

COMP2511 Week 3 25T2

  • 109