Skip to main content

Section 12.14 Step 3: Crafting Examples

Having understood the specification (Step 0), defined our internal data representation (Step 1), and established the class structure (Step 2), we now arrive at Design Recipe Step 3: Examples & Tests. The core idea of this step is to solidify our understanding of exactly how each method should behave by creating concrete examples before we write the implementation code. These examples serve multiple purposes:
  • They force us to think through specific scenarios, including typical usage, edge cases, and error conditions.
  • They clarify any remaining ambiguities in the specification.
  • They provide precise targets for our implementation logic (Step 5).
  • They form the basis for the automated unit tests (discussed in the next section) that verify our code.
As recommended in the Design Recipe guide (See Section 1.7), using a structured format helps ensure thoroughness. For each key operation, we should consider: Case Type, State Before, Action, and Expected Result (State After / Return Value / Exception), based on the ListADT Javadoc. We’ll structure each example clearly below using lists and paragraphs for readability.

Note 12.14.1. State Representation.

We’ll represent the conceptual list state like this: [A, B, C] (size=3). When thinking about the internal array, we might visualize it as array=[A|B|C|null] (size=3, cap=4).

Subsection 12.14.1 1. Examples for Adding Elements

Subsubsection 12.14.1.1 add(int index, T item)

  • Case: Add to Empty List
    State Before: [] (size=0)
    Action: add(0, "A")
    Expected Result: State After: ["A"] (size=1)
  • Case: Add at Beginning (size > 0)
    State Before: ["A", "B"] (size=2)
    Action: add(0, "X")
    Expected Result: State After: ["X", "A", "B"] (size=3)
  • Case: Add in Middle
    State Before: ["A", "B", "C"] (size=3)
    Action: add(1, "X")
    Expected Result: State After: ["A", "X", "B", "C"] (size=4)
  • Case: Add at End (index == size)
    State Before: ["A", "B"] (size=2)
    Action: add(2, "C")
    Expected Result: State After: ["A", "B", "C"] (size=3)
  • Case: Error - Invalid Index (Negative)
    State Before: ["A"] (size=1)
    Action: add(-1, "X")
    Expected Result: Throws IndexOutOfBoundsException
  • Case: Error - Invalid Index (Too Large)
    State Before: ["A"] (size=1)
    Action: add(2, "X")
    Expected Result: Throws IndexOutOfBoundsException
  • Case: Error - Null Item
    State Before: ["A"] (size=1)
    Action: add(0, null)
    Expected Result: Throws IllegalArgumentException
  • Case: Add causing Resize (Conceptual)
    State Before: List [A, B, C] (size=3), internal array capacity is 3.
    Action: add(3, "D") (or addLast("D"))
    Expected Result: State After: [A, B, C, D] (size=4), internal capacity has increased.
Examples for addFirst and addLast follow directly from the index 0 and index size cases above.

Subsection 12.14.2 2. Examples for Removing Elements

Subsubsection 12.14.2.1 remove(int index)

  • Case: Remove Only Element
    State Before: ["A"] (size=1)
    Action: remove(0)
    Expected Result: Returns "A", State After: [] (size=0)
  • Case: Remove First Element (size > 1)
    State Before: ["A", "B", "C"] (size=3)
    Action: remove(0)
    Expected Result: Returns "A", State After: ["B", "C"] (size=2)
  • Case: Remove Middle Element
    State Before: ["A", "B", "C"] (size=3)
    Action: remove(1)
    Expected Result: Returns "B", State After: ["A", "C"] (size=2)
  • Case: Remove Last Element
    State Before: ["A", "B", "C"] (size=3)
    Action: remove(2)
    Expected Result: Returns "C", State After: ["A", "B"] (size=2)
  • Case: Error - Invalid Index (Negative)
    State Before: ["A"] (size=1)
    Action: remove(-1)
    Expected Result: Throws IndexOutOfBoundsException
  • Case: Error - Invalid Index (>= size)
    State Before: ["A"] (size=1)
    Action: remove(1)
    Expected Result: Throws IndexOutOfBoundsException
  • Case: Error - Remove from Empty List
    State Before: [] (size=0)
    Action: remove(0)
    Expected Result: Throws IndexOutOfBoundsException

Subsubsection 12.14.2.2 removeFirst() / removeLast()

  • Case: Remove First (size=1)
    State Before: ["A"] (size=1)
    Action: removeFirst()
    Expected Result: Returns "A", State After: [] (size=0)
  • Case: Remove Last (size > 1)
    State Before: ["A", "B", "C"] (size=3)
    Action: removeLast()
    Expected Result: Returns "C", State After: ["A", "B"] (size=2)
  • Case: Error - removeFirst from Empty List
    State Before: [] (size=0)
    Action: removeFirst()
    Expected Result: Throws NoSuchElementException
  • Case: Error - removeLast from Empty List
    State Before: [] (size=0)
    Action: removeLast()
    Expected Result: Throws NoSuchElementException

Subsubsection 12.14.2.3 remove(T item)

  • Case: Item Present (First)
    State Before: ["A", "B", "C"] (size=3)
    Action: remove("A")
    Expected Result: Returns true, State After: ["B", "C"] (size=2)
  • Case: Item Present (Middle/Duplicate)
    State Before: ["A", "B", "A", "C"] (size=4)
    Action: remove("A")
    Expected Result: Returns true, State After: ["B", "A", "C"] (size=3)
  • Case: Item Not Present
    State Before: ["A", "B", "C"] (size=3)
    Action: remove("X")
    Expected Result: Returns false, State After: ["A", "B", "C"] (size=3)
  • Case: Remove from Empty List
    State Before: [] (size=0)
    Action: remove("A")
    Expected Result: Returns false, State After: [] (size=0)

Subsubsection 12.14.2.4 clear()

  • Case: Clear non-empty list
    State Before: ["A", "B"] (size=2)
    Action: clear()
    Expected Result: State After: [] (size=0)
  • Case: Clear empty list
    State Before: [] (size=0)
    Action: clear()
    Expected Result: State After: [] (size=0)

Subsection 12.14.3 3. Examples for Other Operations

We must create similar detailed examples for the remaining methods (get, set, first, last, indexOf, contains, isEmpty, size), always considering:
  • Empty list cases
  • Single-element list cases
  • Multi-element list cases (typical usage)
  • Boundary indices (0 and size()-1)
  • Error conditions specified in the Javadoc (invalid indices, empty lists, null arguments).
  • Specific scenarios for search methods (item present, absent, null).
Thinking through these examples systematically is crucial for ensuring our implementation will be correct and robust.
Example for first() Error Case:
  • Case: Error - first() on Empty List
    State Before: [] (size=0)
    Action: first()
    Expected Result: Throws NoSuchElementException
Example for get() Error Case:
  • Case: Error - get() Invalid Index
    State Before: ["A"] (size=1)
    Action: get(1)
    Expected Result: Throws IndexOutOfBoundsException
These concrete examples define the target behavior for our ArrayList<T>. They specify precisely what should happen for various inputs and states. In the next section, we’ll discuss how the provided unit tests automate the process of checking whether our eventual implementation meets these behavioral examples.
You have attempted of activities on this page.