No, that’s not a typo and I’m not talking about the alien species, either. Ha Ha… I’m sorry – it had to be done. So yeah, object-oriented design. One example of it. Here we go 🙂
A little context up front
This is from a different side-project of mine: A turn-based game where you answer questions. Like a quiz. The questions are grouped into levels. The levels also have some sort of metadata, probably (I’m not done yet).
Either way, the actual content of the game does not matter. This post is about modeling the internals.
The easiest entities to model are typically actual things from the real world. Creating a CMS? You might model pages and authors and comments. A ticketing-service? You got events and artists and tickets. These are all kind of like nouns.
Then you might model some actions. The stuff you do with your entities. The verbs: create a page, list all events, delete a comment, and all the CRUD you can imagine.
And in the game
For this project, I started by modeling the questions and the levels. Easy peasy. Then, I thought about how the actual game would play. Coming in from the outside with my user-hat on, I ended up with the following “flow”:
- A question is posed
- I submit my answer
- An indication of whether the answer was correct or not is shown
- Goto 1
Here, we see a little speciality in comparison to your garden-variety CRUD-web-app: Not all actions are initiated by the user directly. The transition from step 3 to step 4 happens automatically, but only after some time has passed. No big deal, we’ll probably just have some sort of timeout trigger the action. But interesting nonetheless.
How would playing the game be implemented, though? You might use variables for state somewhere. Hopefully not global state, but yeah. And then, possibly a loop that runs until some end-condition is met?
This all feels somewhat dirty. Which is excellent news – with a real problem at hand (and this being just a side-project), I could try out different approaches and see how they can help solve it. And it’s more interesting than following an arranged tutorial or implementing “the Todo-App”.
Give it a REST
By day, I do a lot of web-development. So somehow, I got the idea of making the whole thing RESTful into my head. I’m not sure how; it seemed like a good idea at the time. Must have been something about best-practices. Anyway, I started to think about how to implement the game in a restful manner.
CRUDding levels and questions: no problemo.
But actually playing the game… Which endpoints to use? Which HTTP-verbs? What resource am I even interacting with? What REST-call would I make, when the user gives an answer? It did not come naturally to me, because it did not align neatly with the verbs and nouns I already had.
Modeling Pt. II
And then it hit me: What if I were to model the state of the game as it is being played?
In the analogy of nouns and verbs, this would be a nominalization: Taking a verb and turning it into a noun: In our case, taking “play” and turning it into something like “the act of playing”.
For me, this is interesting, as it departs from modeling actual (tangible, even) things from the real world. What is being modeled now is not something that actually “exists”.
It shows, that there is more to object-oriented design than just CRUD web-apps. And although I already knew that, I always enjoy finding practical applications. It helps me better grok the theory and gives me concrete examples to use when discussing with colleagues.
The act of playing
So this new entity knows about the current state of the game (what question is currently being asked; how many wrong answers have already been given) and it is updated whenever the player makes a move. Modeling the act of playing as an entity has other benefits too (apart from, you know, being able to actually play the game): Because it is now its own entity that can be persisted, we can save a running game and let the player resume at some later time.
REST-wise, that means creating (aka starting) a new game via POST. And then updating the resource while playing the game via PATCH. We would need some patch-format of course, to send along with with request. After the PATCH, the client can GET the new state of the current “act of playing the game” and display it to the player.
No REST for the… app
I intentionally did not say “single-page-app” above, because I feel like that would imply the existence of some sort of backend. Of some communication necessarily going on behind the scenes. And in that case, REST surely does bring advantages: meaningful URLs, Deeplinking, the ability to share a URL with someone.
But these are all not needed in an app that runs only locally, without a server, without data to be shared among users. It would just add more complexity.
So I ditched it.
I’m still glad I had the idea in the first place and tried to run with it. Because it made me model the right entities. And because pursuing the rest-approach in the context of this “real” problem made me think about the why and when of using it.
Because I wanted an application to be restful, I did some non-trivial object oriented design. Later, I realized the rest-aspect was overkill and cut it out. But I kept the newly modeled entities.