Implement a bounded counter whose invariant is always 0 <= current <= maximum. A private field can hide representation, but only validation and update logic can preserve this rule. Decide what construction and failed updates do before coding.
The maximum must be a nonnegative integer. Construction with an invalid maximum throws RangeError. increment returns false at the limit and otherwise increments and returns true. Two instances must remain independent. The getter returns a number, not a mutable reference to internal state.
Budget twenty minutes: write the contract, implement the class, then test zero capacity, normal increments and independence. This prepares you to review library invariants later; it is not a reason to put every function into a class.
Predict, run, and explain
Write the output and trace the important state changes before checking it. Then run the program. Each editor is independent. Async examples end with main() so this editor waits for their work.
const max = 0;
console.log(Number.isInteger(max) && max >= 0);
console.log(0 < max);Check your prediction
true
false Acceptance cases before you code
Write a small test plan before implementing bounded counter rules. These cases extend the brief; they are not a second worked solution. Predict the expected behavior independently, then test through the public function. A good ordinary example and a good boundary example should catch different possible mistakes.
| Case to try | What your result should demonstrate |
|---|---|
| Maximum zero | Never increment and keep current at zero |
| Reach exact maximum | Next increment reports false without changing state |
| Separate instances | Do not share private counts |
After the core task passes, deliberately break one rule and identify the case that notices it. Restore the implementation and explain the failure in terms of the contract, not the number of assertions. If a case requires a concept you have not recalled, revisit the relevant lesson before opening the solution.
Your turn
Checkpoint: Bounded Counter: practise
Write BoundedCounter(maximum) with private state, getter current and increment() as specified. A maximum of 1 should produce true, false and 1. A separate maximum-zero instance must stay at 0.
// Test the invariant at construction and before each state change.Hint 1: the idea
An unsuccessful operation must leave state unchanged.
Hint 2: a first step
Validate maximum before storing it, then compare current with maximum.
Show one solution
class BoundedCounter {
#current = 0;
#maximum;
constructor(maximum) {
if (!Number.isInteger(maximum) || maximum < 0) {
throw new RangeError("Invalid maximum");
}
this.#maximum = maximum;
}
increment() {
if (this.#current >= this.#maximum) {
return false;
}
this.#current += 1;
return true;
}
get current() {
return this.#current;
}
}
const counter = new BoundedCounter(1);
console.log(counter.increment());
console.log(counter.increment());
console.log(counter.current);
console.log(new BoundedCounter(0).current);true
false
1
0Explain why the implementation meets the stated contract. Which part is enforced by the language or checker, and which part needs behavioral evidence?
Change it and test it
Assert that -1 and 1.5 are rejected. Borrow increment onto an unrelated object and observe the private-field failure. Explain which rule privacy enforces and which rule your conditions enforce. Redo this API tomorrow with a closure instead of a class.
Completion is saved in this browser only. It does not measure mastery.