You’re over-complicating it
First off, why do you have these capital letter nouns? Like Customer, Table, Restaurant?
This is OOP mindset. In Clojure, you need to think in terms of data-structure. You don’t need protocol, you don’t need objects, just plain data.
The first question is, where is your data stored? I am going to assume it is stored in some relational database for now. With the following table schemas:
table: table-id, chair-count
customer: customer-id, phone-number
restaurant: restaurant-id, restaurant-name, table-ids, waiter-ids
waiter: waiter-id, waiter-name
bookings: restaurant-id, customer-id, table-id, waiter-id
That’s your data model. Once you’ve figured that out, in Clojure, you just use it directly, no extra ORM layer or anything like that.
(defn book!
[db restaurant-id customer-id]
(let [available-tables (get-available-table db restaurant-id)]
(when available-tables
(let [new-booking (make-new-booking restaurant-id, customer-id, available-tables)]
(save-booking! db new-booking)))))
This is really simplified to give you an idea, you’d want a transaction, you’d want to factor out some of this logic into multiple function, you need to make the queries to the DB, you’d need logic to know how many chairs for the booking, and find a table that best fits, etc.
But its to show you the idea, you just query the DB, get the data back, in the shape of your data model, and you just perform the necessary verification and modification on it. Done.
You don’t need to create any more abstraction in your code.
This does not matter, shove it all in one giant namespace called: my-cool-booking-app.core
. I am not sarcastic I’m serious. Let me explain.
In Clojure, the structure of the code into namespaces is only for code readability and discoverability. It is why you would maybe want to store your music collection into folders. The structures that matters in Clojure are the functions and the data-structures.
You asking this question is because of your OOP background. In OOP, classes are a unit of abstraction, they are a structural unit, and sometimes they map with files. What you are asking is how to structure your classes, but there are no classes in Clojure, so this is the mental blocker you are facing.
Namespaces in Clojure are best compared to packages in Java. Why do you have packages in Java? They don’t really matter, you could shove all your classes under one package, or choose to split it up, its purely organizational.
Structurally, what you want to do in Clojure is define what are the functions you want, and the data-structures they’re going to work with. The answer to this is often, well, what is my DB, and what is my DB data model? Whatever your DB is and its data-model, those are the data-structures you work on directly. Now just go and write functions that thus query and manipulate the result-set directly.