Objects and responsibilities
Picture
A room has two available seats. Booking one should leave one; booking three should fail and leave two. The useful object is not merely a “room” noun—it owns the rule that availability never becomes negative.
Predict
Why place book next to the availability it changes?
Walk through the small example
So every caller uses the same validation boundary. Separate objects still have separate state, allowing two rooms to behave independently.
Mental model and complete Python solution
A class describes how an object is constructed and what operations it offers. init sets up one instance; self refers to that instance. Methods are functions operating on its state. A read-only property exposes availability without offering a public setter. The underscore is a Python convention, not a security boundary. Invalid requests raise; valid requests that cannot fit return False. This distinction is part of the public contract.
What the function promises: Room(capacity) accepts a nonnegative integer capacity. book(count) accepts a positive integer and returns whether the entire booking succeeds. No partial booking, cancellation, concurrency, or persistence is included.
class Room:
def __init__(self, capacity):
if type(capacity) is not int or capacity < 0:
raise ValueError("Capacity must be a nonnegative integer")
self._available = capacity
@property
def available(self):
return self._available
def book(self, count):
if type(count) is not int or count <= 0:
raise ValueError("Booking count must be a positive integer")
if count > self._available:
return False
self._available -= count
return True
a, b = Room(2), Room(2)
assert not a.book(3) and a.available == 2
assert a.book(1) and a.available == 1
assert b.available == 2
assert not Room(0).book(1)
Work and storage: Each operation is O(1) in the usual integer model. The design cost being controlled is duplicated validation, not algorithmic speed.
When to recognize it: Keep the data and the operations protecting its rules together.
Check before applying it: A class is not useful just because a noun exists. Start with an actual responsibility and a rule that must stay true.
Change one rule
Two threads call book at the same time. Does grouping code into a class make it atomic?
See what changes
No. Encapsulation organizes responsibility but does not synchronize execution. A lock or transactional storage boundary must protect check-and-update if concurrent callers are allowed.
Connect
functions: A method is a function attached to an object’s responsibility.
Design a parking lot: A parking spot also owns limited availability.