Additional TutA tutorial slots have been opened in MyTimeTable
Action: enroll as soon as possible
Class representatives
Applications close Friday COB (close-of-business)
Assignment A1
Specification released — recommended to start immediately
Web form (released later this week) will let you …
register for mandatory code-walks
optionally state date/time preferences for the walk
optionally request extension tokens
Form can be edited/resubmitted any number of times before the deadline
Warning: do not procrastinate, otherwise you may forget to register
Administrative footers on every slide (TEQSA provider, CRICOS code, etc.)
Implication: ANU compliance & accreditation context
Problem Statement Introduced in This Lecture
Design a program that handles geometric shapes of three kinds:
Circle
Rectangle
Right Triangle (right-angled triangle)
Provide two general-purpose functions that accept any shape instance and compute
its area
its perimeter (a.k.a. circumference for circles)
The Design Recipe (6-Step Methodology)
Step 1 — Problem Analysis & Data Design
Step 2 — Function Signature & Purpose Statement
Step 3 — Examples / Tests-as-specification
Step 4 — Design Strategy (how will we actually solve it?)
Step 5 — Implementation (coding phase)
Step 6 — Tests (turn examples into automated checks)
Key pedagogical motto: “The shape of the data determines the shape of the code.”
Step 1 • Data Design — Review of Data Modelling Tools
Basic data types (primitives such as int, double, boolean, String)
Enumerations (enum) for finite sets of distinct values without associated data
Records (record) for compound data with fixed fields
NEW: General Itemizations
Use when there are multiple distinct variantseach with their own payload
(a.k.a. algebraic data type / tagged union / sum type)
Java 21+ mechanism: sealed interface + one record per case
General Itemization Pattern (Shapes Case Study)
Declare a sealed interface to name the whole family and to enumerate all legal variants
/** A Shape represents a geometric shape and is one of:
* - Circle
* - Rectangle
* - RightTriangle
*/
sealed interface Shape permits Circle, Rectangle, RightTriangle {}
Supply one record for each variant (must implements Shape)
/** A Circle is a Shape characterized by its radius */
record Circle(double radius) implements Shape {}
/** A Rectangle is a Shape characterized by width & height */
record Rectangle(double width, double height) implements Shape {}
/** A RightTriangle is a Shape characterized by its two legs */
record RightTriangle(double leftLeg, double rightLeg) implements Shape {}
Documentation block should mention examples (e.g. “circle of radius 1.0”).
Radius, width, height, leg lengths expected to be non-negative (domain constraint).
double area(Shape s) {
return switch(s) {
case Circle(var r) -> Math.PI * r * r;
case Rectangle(var w, var h) -> w * h;
case RightTriangle(var a,var b)-> 0.5 * a * b; // right-triangle area formula
};
}
double perimeter(Shape s) {
return switch(s) {
case Circle(var r) -> 2 * Math.PI * r;
case Rectangle(var w, var h) -> 2 * (w + h);
case RightTriangle(var a,var b)-> a + b + Math.hypot(a,b);
};
}
Note: Math.hypot(a,b) computes a2+b2 robustly.
Ensure input validation if negative parameters are disallowed (either throw or require pre-condition).
Step 6 • Tests — Motivation & Mechanics
Why test?
Confidence that code meets specification.
Safety net against future refactors (regression testing).
What to test? ➔ Everything! (except outputs too complex, e.g. raw Image).
In COMP1110/1140/6710: all functions mandated by Design Recipe whose result is notImage.
Test Coverage considerations
Start by converting examples into test cases.
Ensure every code path, branch, and helper is executed at least once.
Testing hierarchy (3-levels)
test() function — orchestrator.
Test case functions — one per scenario, preceded by comment explaining intent.
Assertions inside test case — testEqual, testNotEqual, testTrue, testFalse.
Example from slides:
/** Tests that the sum of 5 and 2 is 7 */
void testSumExample1() {
testEqual(7, sum(5,2), "5 + 2 should be 7");
}
void test() {
runAsTest(this::testSumExample1);
}