From-Scratch Build · Programming · Java 17

Valinor

A restaurant reservation system sounds mundane until two parties try to book the same table at the same time. Valinor is that system, built in real Java — tables, time slots, parties and bookings, modelled with clean object-oriented design and one ironclad invariant: a table can never hold two overlapping reservations. This page explains the design; the engine itself is a Maven project with a JUnit 5 suite that lives in this repo.

Java 17MavenJUnit 5 OOPDomain modelling26 tests passing

What it is

Reservations, modelled correctly

The domain is small but unforgiving. A restaurant has tables of different sizes; the evening is divided into time slots; a party of a given size wants a booking. The system has to match parties to suitable tables, hold the booking, and — above all — never let the same table be reserved twice for the same slot. That last rule is an invariant: a truth the system must protect no matter what.

Java makes it a clean object-oriented exercise. Tables, slots, parties and bookings become classes with clear responsibilities; the booking logic lives where the rules can be enforced. Done well, the design makes an invalid state — a double booking — simply impossible to represent.

no double
-booking, ever — the one invariant the whole design exists to protect, and the test of whether the model is right.

The trick is that a time slot is half-open: [start, end) covers the instant at start but not at end. Two windows overlap only when each starts strictly before the other ends — so a table freed at 22:00 can be re-booked from 22:00. Edge-touching is allowed; any genuine overlap is rejected.

The domain model

Five small classes, one invariant

Each type has one responsibility; the booking rules live where they can be enforced.

TimeSlot

Half-open window

An immutable [start, end) interval that knows how to test overlap — the key to handling clashes correctly.

Table

Id + capacity

Immutable; identity is the id alone, so a table is a safe map key. Knows whether it can seat a party.

Reservation

One party, one slot

Immutable booking of a party at a table for a window. Validates that the party fits on construction.

Restaurant

Table inventory

Lists the tables that can seat a party, smallest capacity first — the basis for allocation.

ReservationService

The booking engine

Holds the reservations and enforces the no-overlap invariant. Books, cancels, and answers availability.

exceptions

Loud failures

DoubleBookingException and NoTableAvailableException make rejected bookings explicit.

Architecture

How a reservation is made

Every booking request runs through the same guarded flow:

  1. Request

    A party of a given size asks for a table at a time slot.

  2. Search

    Find tables large enough and free for that slot.

  3. Check

    Confirm the booking won't violate the no-clash invariant.

  4. Commit

    Hold the table and record the reservation.

  5. Reflect

    Update availability so the slot can't be booked again.

Try it

A booking grid you can clash

Pick a party size, click two cells on a row to set a window, and book. The grid mirrors Valinor's real rules — smallest suitable table, capacity limits, and the half-open overlap check. This widget is a small JavaScript re-implementation of the same logic for the page; the engine itself is the Java/Maven project in this repo.

Rows = tables · columns = 30-min slots (18:00–23:30) · click a start cell then an end cell on the same row

Pick a party size and a window, then book.

Reflection

What rebuilding it taught me