Sequential user stories, one at a time, each finished with tests before the next. Budget 30 minutes for tasks 1 to 4, task 5 if time remains.
Story: A load balancer holds up to N instance addresses. register(address) adds one and
returns true; it returns false when the address is already present or the balancer is full.
Acceptance Criteria:
- Capacity of 0 or less is rejected in the constructor
- Duplicates return
falseand do not change the size nullis rejected
Hints:
- Ask: "Is an address a
String, or should I model it?" AStringis fine; say why - A
Setgives uniqueness for free; whichSet, and why, is the follow-up
Story: unregister(address) removes one and returns whether it was present.
Acceptance Criteria:
- Removing an unknown address returns
false - Removing frees capacity for a new registration
Story: get() returns one registered address at random. With none registered it throws.
Acceptance Criteria:
- Empty balancer throws a specific exception
- Only registered addresses are ever returned
- Over many calls every address is eventually returned
Hints:
- Ask: "Equal probability?" and "Does the caller need to know which one?"
ThreadLocalRandomrather than a sharedRandom
Story: Make the selection algorithm pluggable: random and round robin. Round robin must cycle through all addresses in registration order and wrap around.
Acceptance Criteria:
- A
SelectionStrategyinterface with two implementations - Round robin over
a, b, cyieldsa, b, c, a, b - Round robin adapts when an address is unregistered mid-cycle
Hints:
- Registration order means an ordered set:
LinkedHashSet Math.floorModkeeps the counter correct after it wraps
Story: Threads register, unregister and get at the same time. Nothing may throw a
ConcurrentModificationException, and round robin must stay correct.
Acceptance Criteria:
- A test with 10 threads hammering all three operations completes without exceptions
- Round robin over three addresses under 6 concurrent threads distributes exactly evenly
Hints:
- The critical sections are tiny and contention is low:
synchronizedis the right tool, and saying when you would switch to aReadWriteLockorCopyOnWriteArraySetis the point
- What is the time complexity of your duplicate check? How does
HashSet.containswork? (The word they want is buckets, thenequalsinside the bucket. Candidates have been rejected for saying "memory addresses".) - What do
equalsandhashCodehave to do with each other? - Why
LinkedHashSetand notHashSetorArrayList? - When is
synchronizednot enough?
- This round is about code quality and communication. A candidate who writes a perfect algorithm silently scores lower than one who narrates a simple one.
- Ask for the tests before the next story, every time.