Model-View-Command?

It’s sunday, and as I sit here waiting for IntelliJ to update, I figured I’d write a little discussion thread about plugin writing. Specifically, why I think the MVC pattern fits so well.

Model-View-Controller Command?

It has been a long standing convention in enterprise development to split up all the different parts of a UI application into 3 distinct and decoupled from eachother parts, also known as Model-View-Controller. However, what I want to talk about in this case is the similary between Sponge plugins, and web applications specifically.

Now, I know how this sounds, and before you take up those burning pitch forks, let me makes my case here.

Model

The models are what contain the so-called “business”, or logical, components of the system. That’s really the most basic definition I can think to give, though I’m sure for those who have never heard of this before, it might sound confusing.

Talking in examples, the Player class might be located here. Along with World, Entity, GameProfile, BlockState, and any other part of the server you might want to modify.

Controller

Now, here’s what’s interesting. In web applications, the Controller is understood to be a class which intercepts incoming HTTP requests ( maybe transforms them in some useful way ), and triggers some code on the backend.

What is the difference, I ask then, between a Controller and a Command?

For brevity’s sake, let’s take a look at an HTTP request. Very simplified, it looks a little something like this:

GET https://forums.spongepowered.org/c/plugins/plugin-development

Yep, that’s about it. You’ll notice it looks a lot like a url, and you’re right, because it is. What you see in the URL bar on your browser is usually a GET request to some sort of URL. The HTTP standard defines 9 types of requests, where 4 are most commonly used in practice. These are:

  • GET - Retrieve something
  • POST - Create something
  • PUT - Update something
  • DELETE - Delete something

To extend upon this, the reason only these 4 get the most use is because of CRUD. CRUD is an abbreviation meaning Create, Read, Update, Delete. And these 4 methods map exactly to the 4 most-used HTTP request types.

They also map nicely to actual real-world use-cases. Say you have some sort of model, a Player for example. What do you want to be able to do with a Player?

Well, I would like to be able to Create one to start with. But then, what if I have to change what I created? Ok, so I’d need to be able to Update that Player now. Oh but darn, they’ve left the server, I guess that means I have to Delete them now. Oh, but they’re back now again. Well, if I stored them in a database, now I’d be able to Get them, instead of having to create a whole new Player.

Ok, so how is all of this relevant to Commands, you ask?

Well, think about the use-cases we face when creating a plugin. I often need to be able to do CRUD operations on the models I define in my code. Obviously though, players need an interface for this. In web applications, the interfaces are Controllers managing HTTP requests, in Sponge, it’s Commands.

And in fact, a Command is not much different than an HTTP request. See the similarities below:

POST https://some.website/towns/createTown?name=My+Town
/createtown "My Town"

There are differences in syntax, of course, but the point is that they transmit exactly the same information, in a very similar way, from the client, to the server.

From there, it is the plugin’s job to intercept this request, and do something with it. Presumably, the above example will create a new model of type Town, and store it in a database or something.

View

This is what the end user sees when they interact with the whole system. Obviously, when you write out a command, what you get in return is not Java code. It’s some sort of nicely written and informative message, designed to help usability of your whole plugin.

And the key word there really is design. Views are suppose to be pretty, informative and ultimately as useful as possible to the user.

These are the chat messages you send, the particles you push to the client, the book views, and any other part of the UI you change only for that specific player because they did a command. Here are also included player-specific BlockState changes, and anything really which is contextual in nature ( See: Viewer class ).

A player will only see the View in question, because they did an action ( via a controller ), which resulted in modifying some sort of backend element ( a model ), which in turn then pushed some sort of change to their view, which is what the player finally got to see.

Diagram

I love me a good diagram. Here, have this one:

mvcommand

Yes, it’s the same as the MVC one you’d get from Wikipedia, because after all that’s the entire point of this thread :stuck_out_tongue:

Post below what you think about my ravings. Oh, and on that note, IntelliJ managed to update while writing this, and I now see it has new icons. I’m going to head off and re-learn the UI then.

2 Likes