CSE 331: Software Design and Implementation, Autumn 2026
Your job is to deliver code that you know works.
P, through the code, to QOne method reads the numbers:
13static List<Integer> readList() {
14 Scanner in = new Scanner(System.in);
15 List<Integer> list = new ArrayList<>();
16 while (in.hasNextInt()) {
17 list.add(in.nextInt());
18 }
19 return list;
20}And another adds them up:
22static int sumList(List<Integer> list) {
23 int sum = 0;
24 for (int i = 0; i < list.size(); i++) {
25 sum += list.get(i);
26 }
27 return sum;
28}Then main calls them both:
6public static void main(String[] args) {
7 System.out.println("Enter some numbers.");
8 List<Integer> list = readList();
9 System.out.println("Got " + list);
10 System.out.println("The sum: " + sumList(list));
11}Sum, on every inputmain work?7System.out.println("Enter some numbers.");
8List<Integer> list = readList();
9System.out.println("Got " + list);
10System.out.println("The sum: " + sumList(list));Sum meets its specification, we need:readList returnssumList returns for that listmain does not saymain may rely on how sumList happens to be writtensumList can break mainmain is a client of sumListHomework 1 says satisfies where we say meets; the two mean the same.
readList promisessum: what sumList promisesreadList asks nothing of its clientsumList asks only for a list that is not null/**
* Returns the element in the middle of a list.
*
* @param list the list to look in; must be non-null
* @requires list has an odd number of elements
* @return the element with as many elements before it as after it
*/
static int middle(List<Integer> list) {
return list.get(list.size() / 2);
}/**@javadoc: turns these comments into web pagesArrayList and Scanner| Tag | Says | Part of the |
|---|---|---|
@param |
what a parameter is for | precondition |
@requires |
a precondition too long for one @param |
precondition |
@return |
what the method returns | postcondition |
@throws |
which exception it throws, and when | postcondition |
@modifies |
the parameters the method may change | postcondition |
@effects |
how those parameters change | postcondition |
@requires, @modifies, and @effects are this course's, from Liskov and Guttag.
First, readList:
/**
* Reads whole numbers typed by the user.
*
* @return a list holding, in order, every number the user typed
* before the input ended or something that was not an int appeared
*/
static List<Integer> readList()Then sumList:
/**
* Adds up a list of numbers.
*
* @param list the numbers to add; must be non-null
* @return the sum of the elements of list, wrapped into the int range
* if the true sum falls outside it
*/
static int sumList(List<Integer> list)Scanner, loops, indices: a client does not need them@modifies: sumList has nonelist/**
* Reads whole numbers typed by the user into a list.
*
* @param list the list to add to; must be non-null
* @modifies list
* @effects adds to the end of list, in order, every number the user
* typed before the input ended or something that was not an int
* appeared
*/
static void readInto(List<Integer> list)The parameters it may change: here, list
How list changes: the new list in terms of the old
7System.out.println("Enter some numbers.");
8List<Integer> list = readList();
{{ list holds, in order, every number the user typed before
the input ended or something that was not an int appeared }}
9System.out.println("Got " + list);
10System.out.println("The sum: " + sumList(list));readList: no precondition, and a promise about the list it returns
Line 8 stores that list in list, so the claim holds
{{ P }}
a call
{{ Q }}P state to a Q state, as the specification promisesreadList promised a list, so list is not nullsumList requireslistsumList promises not to change listSum's specification saysHalf sheet, question 2
main relies on the promises and nothing elsesumList may add up the list from the endmain needs no change and no new argument/**
* Searches for a value in part of an array.
*
* @param a the array to search; must be non-null
* @param lo the index where the range to search begins
* @param hi the index just past where the range to search ends
* @param x the value to search for
* ... and one of the specifications below ...
*/
static int indexOf(int[] a, int lo, int hi, int x)| Spec | Requires | Returns | If there is no match |
|---|---|---|---|
| A | a match | a match | no promise |
| B | the smallest match | -1 | |
| C | the largest match | -1 | |
| D | some match | -1 | |
| E | the smallest match | NoSuchElementException |
i with lo <= i < hi and a[i] == x0 <= lo <= hi <= a.length// Implementation 1
for (int i = lo; i < hi; i++) {
if (a[i] == x) {
return i;
}
}
return -1;// Implementation 2
for (int i = lo; i < hi; i++) {
if (a[i] == x) {
return i;
}
}
throw new NoSuchElementException();// Implementation 3
int i = lo;
while (a[i] != x) {
i++;
}
return i;// Implementation 4
for (int i = hi - 1; i >= lo; i--) {
if (a[i] == x) {
return i;
}
}
return -1;Half sheet, question 1
| Spec A | Spec B | Spec C | Spec D | Spec E | |
|---|---|---|---|---|---|
| Implementation 1 | yes | yes | no | yes | no |
| Implementation 2 | yes | no | no | no | yes |
| Implementation 3 | yes | no | no | no | no |
| Implementation 4 | yes | no | yes | yes | no |
Implementation 1: the first match, or -1
Implementation 2: the first match, or an exception
Implementation 3: never looks at hi
Implementation 4: the last match, or -1
| Spec A | Spec B | Spec C | Spec D | Spec E | |
|---|---|---|---|---|---|
| Implementation 1 | yes | yes | no | yes | no |
| Implementation 2 | yes | no | no | no | yes |
| Implementation 3 | yes | no | no | no | no |
| Implementation 4 | yes | no | yes | yes | no |
| Met by | 4 | 1 | 1 | 2 | 1 |
P is stronger than QQ is true whenever P isS1 is stronger than S2S1 also meets S2Q is weaker than P, S2 than S1B, C, D, and E share one, so we compare only their postconditions:
S1 is stronger than S2 when
S1's precondition is weaker than or the same as S2's,
and, on every call where S2's precondition is true,
S1's postcondition is stronger than or the same as S2's.
| A | B | C | D | E | |
|---|---|---|---|---|---|
| A | X | W | W | W | W |
| B | S | X | --- | S | --- |
| C | S | --- | X | S | --- |
| D | S | W | W | X | --- |
| E | S | --- | --- | --- | X |
The row against the column: S stronger, W weaker, --- incomparable.
indexOf to find the first matchindexOf search from either end| Change | Cannot break | Can break |
|---|---|---|
| Strengthening | a client | the implementation |
| Weakening | the implementation | a client |
count correct?static int count(int[] a, int x) {
int c = 0;
int i = indexOf(a, 0, a.length, x);
while (i != -1) {
c++;
i = indexOf(a, i + 1, a.length, x);
}
return c;
}The first search starts at 0; each later one, just past the last match
Against B: correct, since no search skips a match
Against D: a search may skip matches, so count is wrong
count on [5, 1, 5, 2, 5]Implementations 1 and 4 both meet D.
// With implementation 1
indexOf(a, 0, 5, 5) // 0
indexOf(a, 1, 5, 5) // 2
indexOf(a, 3, 5, 5) // 4
indexOf(a, 5, 5, 5) // -1
count(a, 5) // 3// With implementation 4
indexOf(a, 0, 5, 5) // 4
indexOf(a, 5, 5, 5) // -1
count(a, 5) // 1Against D, count is wrong, though it may pass every test you give it
indexOf(a, 0, a.length, x) != -1indexOf returns or throws@effects: how the parameters in @modifies change@modifies: any parameter it does not list stays unchanged@effectsTwo versions of sort's @effects, both with @modifies list:
Original @effects rearranges the elements of list into ascending order
New @effects after the call, list is in ascending order@modifies: compare only @effectsThe original @effects follows Liskov and Guttag's sort.
@effects promise as much?Try an implementation that throws the elements away:
list.clear();[3, 1, 2], it leaves []; the original asks for [1, 2, 3][], in ascending order@modifiessumList has no @modifies, so it promises not to change list.
Suppose its specification added two lines:
@modifies list
@effects rearranges the elements of list into some order@return: compare promises about list@modifies promise as much?Try an implementation that sorts list and then adds it up.
list, so it meets the new specification[3, 1, 2], it leaves [1, 2, 3], so it fails the originallist in @modifies drops the promise not to change it