LESSON 1.1
Classes and objects
Identity, state and behavior, using a parking ticket whose time cannot run backwards.
6 min read
A parking-lot program starts with two arrays: ticket ids in one, arrival times in another. A third function calculates a fee by looking up matching positions. It works until somebody sorts one array and forgets the other. The data belongs together, and so do the rules that make it meaningful.
The problem
const ids = ["T1"];
const enteredAt = [10];
// Sorting ids alone would detach each arrival time from its ticket.
console.log(ids[0], enteredAt[0]);The object boundary
A class describes the state and operations its instances support. An object is one instance with its own identity and state. Two tickets can have the same arrival time without being the same ticket. A class is not the collection of every parking-related operation: payment, space allocation and notification each have a different reason to change. Start with the thing whose rule you can state precisely.
Here the ticket owns its id and arrival time. Its invariant is small: an id is required, and a duration cannot be measured before arrival. Putting the check inside the operation means the command-line interface and a future HTTP endpoint cannot accidentally calculate different answers. A constructor should either create a usable object or reject the input; requiring callers to remember a separate initialization call leaves an invalid intermediate state.
A method receives the current object as its receiver. Each ticket shares the method implementation, but the method reads that ticket's fields. Keeping time as an argument makes the example deterministic: a test can ask for the duration at minute 25 without sleeping or changing the machine clock. The clock is an input to the calculation, not a hidden global dependency.
In code
Both versions run the same small example. Java uses a single Example class; save it as Example.java.
When the boundary earns its place
Use an object when several operations share state and must preserve a rule. A plain record is enough for an immutable message that only moves between layers; a function is enough for a calculation with no owned state. Creating a class for every noun adds names and indirection without adding protection. In an interview, explain which invalid state the class prevents before drawing the next box.
JavaScript and Java
Java variables hold references to objects, and JavaScript object variables do too. Assigning the same ticket to another variable does not copy it. Java classes declare field types; JavaScript validates values at runtime. JavaScript class methods live on a prototype rather than being copied into every instance. Do not confuse object identity with value equality: Java records and a deliberate equals implementation have different semantics from comparing two ordinary object references.
An assignment preserves identity. Run this separately: both names refer to the same ticket, while constructing another ticket creates another object even when its fields match.
Java's record also defines value equality: the final line is true. JavaScript's reference equality does not compare fields automatically. Choose which meaning your domain operation needs rather than treating every comparison as an identity check.
Try it
Parking Lot LLD
Identify the objects and state the rule each one owns before adding a pattern.