Modeling: From Structured Data Representation to Problem Domain

Recently, I was discussing adding a feature to an application which is about event creation and booking. The project manager has a strong database background and works on the schema himself. The schema is also his go-to tool to express changes in the features. But thinking about the real Domain in terms of objects revealed much, much more.

Imagine a schema which kind of looks like the following diagram:

Event schema
A schema showing the details of events in the database

Events have a limited number of seats. Users can book seats at events. Once the user pays, his order is added to the database and the remaining number of seats should decrease. – This was the new feature, expressed through the seatsLeft row in the Event schema.

We don’t have performance problems, so I didn’t see why we should mutate an existing event in the database when a booking takes place to decrease the number of seatsLeft. Also, I figured that concurrent access could cause problems – problems which the DBMS will probably take care of in transactions.

clay
Photo credit: Blob o' clay by Martin Cathrae. License: CC BY-SA 2.0

I’m a developer, and I’m an object thinker, it seems. Capturing the problem domain by the means of a database schema (solution space/implementation concern) is a bad idea because lots of information get lost.

In the discussion, I proposed a different kind of representation. In essence, it boiled down to this:

PM: “When ordering, you can choose how many seats you want”

Me: “Didn’t know that. Could cause trouble faster. The checkout process may take some time. If seatsLeft is checked by the client before ordering and by the server before accepting an order, this number may have changed in the meantime.”

“Yes. We definitely need to check twice before accepting.”

“We could also async check for seatsLeft during order process and see if the current booking settings still work to make UX better.”

“Good point.”

“Seems unfair if looking for a password for too long will ruin the order though. What about a Reservation for an Event which expires after a given Timeout? The server prunes reservations automatically.”

“So the actual number of seats left = total seats - bookings - reservations. Sounds good!”

I created this initial model sketch from that discussion, shown here:

Domain model
Sketch of objects with real behavior in the problem space

Up next came concerns about representing this in the schema and server logic:

“So when a user completes an order with all details, do we need to create a new row in Reservation or Booking?”

Well, this depends on the context: the server will not have the exact same problem and solution space as the client apps. In fact, a client will not even know about a Reservation because it’s just the server’s way to capture an active session.

The actual relation of objects in the server’s code could be different. Instead of a Booking replacing a Reservation once the order is complete, it could be better to keep a reservation around next to a booking and simply remove the timeout. So there are temporary reservations and final reservations. A final reservation is one which is booked: the customer has paid and completed the process.

2nd domain model diagram
Another model where Reservations are not temporary. Captures how we use the term better: a reservation at a restaurant doesn't go away when we arrive.

Of course, TemporaryReservation is just an object waiting to see the light. So is the BookingRequest on the client side. These things are details of both contexts.

In the database, a Booking table could suffice to capture both concepts. Reducing JOIN operations without violating normalization too much can be an objective of the backend guys:

schema variants
Three alternative schema representations

Variant “C” makes a lot less of the business rules explicit. A temporary reservation is saved as a Booking with a timeout; a final reservation will need the timeout to be removed, or let the server not remove rows with full details, or whatever.

This discussion was very fun and revealed a lot of the application of object thinking to me. This stuff works, makes talking about problems easier – and thanks to the “object as person” metaphor reveals a lot of user stories in the meantime.