Real Programming S01E09: Making A Start, Starting A Make?
This time, we’re going to start our making app. What’s a making app?
Come and see!
If you want to follow along in the code, the project is at github.
Hey. Welcome to Real Programming. The show where even after taking many months of break time, we still don’t have a slogan. My people are getting with the slogan team. We’re going to try to figure out what’s going on with that crew. I’ll get back to you. I’m your host GeePaw.
And today what I want to do is get my game on. We want to get our game on. What do I mean? Well, if you take a look on what we’ve got right now, you know what? This is what we got. This dumb thing. It’s got a Start button, a Roll button, it does some cool stuff. We’re happy with how it’s going, but there’s no game there. See real games have a beginning and an ending, and they have players, and they have turns, and they have scoring, and we got nothing, nada, bupkis, zip, zilch. That’s where I want to start, and where I want to start is with the start.
So let’s start by thinking about our current model what we’ve got going on right here. We’ve broken it up into pieces. We have a game, which actually knows everything there is to know about Yahtzee. Then we have a bus, and the bus serves as a kind of channel for events. When you change things in the game, it sends events out on the bus.
Now, we have a model, which is actually watching the bus– watching events coming from the bus and doing things. And occasionally sending commands into the game. And then we have our proper view. The line that we’ve drawn here is between UI on the left side, and the actual game of Yahtzee on the right hand side. So when I say I want to start games have a start. Take a look for just a split second at the score card or a Yahtzee game.
Now, in real face to face Yahtzee, what happens is everybody gets a copy of this sheet of paper. And then if we play five games you just keep your own scores all through the game in these columns. And these give you the reminders of the rule over on the left, and then the score goes here, and you add all the numbers up and that’s how we decide what happens. Now, we want exactly that kind of thing except we’re not going to be handing out sheets of paper. We’re going to be showing this on the screen. And instead of having one player with five games on the scoreboard we want all the players to be on the scoreboard. We might start by just playing the game hot seat with two other humans, or even playing against yourself where you are all five games going on at once.
But I can imagine a time in which we have bots that actually can play the game with you, and give you some competition that’s lively. In which case, each one of these columns that right now says game turns into a particular player for the current game. And that’s where we want to go.
Now, given how we have laid out our code. We aren’t going to have an event that will start a new game, and we’ll call it game start. And it’s going to have a single member that is just a list of the different players. In this case GeePaw, Molly, and Wally. What’s going to happen is when that event arrives at the model, we want the model to change its internal list of players. And that’s what this test is trying to accomplish. Now, when we try to run this test, you’ll see well that’s not terribly good that’s just because we haven’t done the invention of the game start or this player thing in here.
So let’s do that now. It’s really very simple. I’m just going to summarize how it goes. The games start object is just trivial. Game start takes about players. We want all of our events to have that. We made it a data class, so that it can be easy to literally compare them, and move them around. That’s all we did with game start. Now, over in the model we’ve added a players object.
Now, this players thing is an observable list of player models. So first of all, what’s an observable list? Do you remember the way JavaFX works is that a control is almost always in an observer relationship to some subject, and that subject has to be observable as what JavaFX calls a property. An observable list of is just a list that fires events into JavaFX as it changes.
Now, let’s look at player model. It’s going to be super simple. Player models got one value, and that is the name that just got passed into it. Model himself has to handle the game start. Should probably change that name to match the others. And what does he do? He clears the players list then for each player that is in the list that we got in our game start event, well, we just make a new player model out of that player string, and we add it to our list.
So what this is going to do in theory is it’s going to make this test pass. Let’s give it a run. Works like a charm. We have our start. But now believe it or not I’m going to completely change direction, and head in a different direction entirely. See the part of this whole app right now that’s making me nervous is not actually the part where I have a game object. And we tell the game to do things, and it sends events out the bus. That part seems pretty straightforward to me partly because it’s 100% my own code. But the part that’s bugging me is connecting up the JavaFX parts, the UI.
I’m more interested right now in figuring out whether I can make this UI do the things I want it to do. Now, you might think that I’m just going to rush right in, and start doing that, but actually I’m not. I want to introduce to this application what we call a making app. What on earth is a making app?
Well, in fact, we have actually been running a making app the entire time. See, we’ve been doing a shipping application, our lousy Yahtzee game all this time. But we’ve also been running our microtests all the time. The microtests are an example of a making app. Let’s take a look.
It starts just as we started with a shipping application. That’s the application that the user actually experiences when they run the program. The shipping app depends on the shipping source. That’s our YzGame, and our model, and our UI all of that stuff is here. But secretly, all along, we have been doing something additional. See we’ve been running a testing app. And every time we run a JUnit in this particular case, we’re running a completely different main than the main that is in the shipping app.
We’re not running the program and then writing tests for it. These tests are actually based on a combination of the shipping source same source code that the shipping app uses and the testing source. The source code for the actual tests that we wrote. Now, the testing app is an example of a particular kind of making app. But I’m actually going to want another kind of making app.
Now, this making app is just like the testing app in that it depends on the one hand on the shipping source, and then on the other hand, it also depends on some additional making source. So what’s this arrangement for? What’s it about? Well, I should say I don’t desperately need a making app at this point in the history of the Yahtzee application. But I want to show you the concept, and I want to get it started, so that we can feel free to use it to do whatever it is that we want to do.
The things that I have in mind doing with it is– remember I’m interested in the model UI connection. If I want to play around with that a lot, I have two choices. I can change the game, and drive the game in various ways, so that the game creates the events that I’m interested in. Or I can sidestep all that and give myself some handy buttons, and displays, and anything else that send just the messages I want on that event bus just when I want them. In this case, we’ll make it slightly faster for me to be able to establish are the various pieces of my UI actually behaving correctly.
Now, as I say, in real life it’s a little early, but you know what? You might as well get your head around it, and start doing it fairly early in your real grown up applications. A making app can save us so much time and energy. And it can even add really cool features. Imagine though if we were shipping Yahtzee we would not want to populate the Yahtzee screen with all this developer crap. That’s the crux of the problem. I want my developer crap to be available to me as a developer, but I do not want it to be available to the customer. How are we going to do that?
Well, it starts with us creating a version of the program, a version of main possibly a different main or the same main. It starts in any case with us invoking it from Gradle. So let me show you the Gradle configurations. This is the run configuration that we’ve been using the entire time. And what it does is it simply calls the target run for Gradle. And that’s going to actually invoke run, and we get our Yahtzee screen whenever that runs.
Now, this guy though is our new making version of the program. And notice the invocation is different. Instead of calling just plain run, it calls run and it uses the Gradle dash dash args thing to supply an additional argument to the command line. So it turns into run dash dash args making, and that is this secondary Gradle configuration.
Now, I actually have a main here that says something stupid print line called. This is because in the beginning when I first tried to do this, I realized that all along we have been running our application not using the main that I supplied, but using JavaFX’s built in Maine. So I actually had to tweak this a little bit to get it to actually run. And you’ll see that it does actually say yeah, yeah you called me, and that is also true.
Now, when I do the making run. Yeah, yeah you called me. The difference being here that I now have some args let’s print them out. In the making run I now find that I have this successful argument dash making. Whereas in the regular run, no particular arguments are printed out at all. So big deal. We passed ourselves an argument to get to one Gradle configuration runs with the argument the other one doesn’t. Whoop-de-do what’s next?
What we want to do is if we have that making, we want to launch a different app. Instead of launching the regular shipping game, we’re going to launch our making application. Let me show you how that looks. Here it is. If the args contains dash making, this weird looking thing, Launch making args is going to fire up this particular app class. This one on the other hand, if that isn’t true, is going to fire up the other class.
Let’s see if that actually works. We’re going to just look at the print lines again. This is a regular run, and sure enough I am starting main down here. And in this making run, when he comes up he’s starting the making application. Now, you look at these two guys, and they’re identical except for the fact that this guy says I’m starting main, and this guy says I’m starting making. Well, what do we do?
Let’s do something different. Ah yes here’s the trick. The trick is here. This guy right now is showing the game’s main view. And so is this guy when he runs. But we want this guy to be showing a different view. Well, first let’s add a different view. It doesn’t have to do anything clever but let’s take a look. What we did here was added change this from being a YzView to being a making view.
Now, to be honest with you, it would be much preferable for me to use the same view and pass an arg. Here’s the thing though, we don’t really have time for me to launch into a rant about this trade’s current fascination with creating singletons that require no argument constructors. Instead of putting construction directly into my control, we’ll invent a brilliant dependency injection framework that keeps me from being able to make what I want, when I want, how I want it.
But we’re not going to do that rant. Instead, we’re going to go take a look at the making view, and see what’s different about it. Here it is it’s a view just like the other F For his route he’s doing something a little different though. He’s giving ourselves a BorderPane. That’s a pane where you can put things on the top, or the left, or the center, or the right. And he’s setting the top to be a new toolbar with a cool button. He’s setting the center on the other hand, to be– what the other view, the game view. Let’s look at the straight run again. Let’s look at it this time on the UI. Looks exactly like it looked before. But now let’s try the making run. Oh, look there. I’ve got a cool new tool button there. That’s my visual indication– that Tool button doesn’t do anything yet. That I am in the making mode of running this particular application.
Now, quick like a bunny I want to do a couple of renames. It seems weird to have that guy called YzView. I now want to call him game view. So I’m just going to make a couple of quick renames. Right now for the moment the problem with this button is it doesn’t do anything. Let’s make it do something. Let’s make it post an arbitrary event to the bus. Let’s make it change one of the dice’s pips. That’s a pip change event.
The trick is that somewhere in here, I’m going to want to give this guy an action. And in that action I’m going to want to take the bus. What bus you ask? Well, that’s a problem. And post a pip change. That will accomplish what we want. So where does that bus come from? Well, the bus is kind of buried, which I don’t like. We’ll get back to that. The bus is kind of buried in game view.
So let’s smooch things around again. The bus is inside not game view directly, but inside the game model, but not directly but inside the game that’s where the bus is. Yeah, I mean, reaching into some gross stuff. Nevertheless, I’m going to do it because I want to get that tool button to do its thing, and here’s the transformation, It’s kind of unattractive.
First, instead of making the game view on the fly down here I made it up earlier. Now, I reached in and got the game model out of the game view. And then I reached further and got the bus out of the game model dot game dot bus, and now I have the bus. Not thrilling me in any way at all. We’re going to have to do something about that. But for the moment, now I have my button. My button says, hey, post a pip change when you press me. Let’s see what happens. [LAUGHS]
He posted a change to die number two of pips value 3, and it worked. So OK I gave myself a button. What did I give myself buttons FOR? What did I even want these buttons for? Well, what I want to do is make various messages come out of this thing as if the game had played them. Just like I just did just now only with different messages like that start message.
But again, I’m going to take even a little more detour here. When you actually start the game, there’s going to be a flow of events. Wouldn’t it be cool if our making app could show us that flow of events as they happen? Again, I don’t need that desperately right now. The Yahtzee application is very simple right now, and in the end, it’s probably going to remain fairly simple in terms of its event flow. But what I want to do is I just want to show you the power of the concept of a making app.
Well, I’ve got this making view here. What if– in addition to the game model, what if the making view had a making model? And that making model could listen to every conceivable event. And as soon as it hears one add them to a visible list somewhere inside the making view. So I wrote us a little test here. Give me a bus, give me a model. In the case of the making model we’re actually going to pass the bus indirectly.
So we just have bus and model. Catches the pip change events. I just want to say to myself, you know what? If I send a pip change event, then the list of events that’s inside the making model should contain that pip change event. Now, the making model itself– clever. All it is a list of events. An observable list of– an observable list of any. That’s not going to work, but let’s run the tests, and see that nothing works actually.
Yeah, sure enough. Because it isn’t a– we haven’t actually implemented anything. So no problem, but the part that’s bothering me here is this any. This should be an event that actually would come out of the event bus. The trick is right now when you go look at can role change in game start, and there’s another one the pip change itself, they don’t have any common base. Because they don’t have a common base I’m not actually going to be able to subscribe to the bus to catch all the events.
In fact, when I look at this, I’m a little annoyed that I’ve got these events all over the place. I’m thinking what I want to do is rederive them all from some common interface, and put them all in a central location or someplace where I know for sure where the events are. And here’s what that looks like. I just added a new package. And I moved these guys over one at a time. You can extract this as a simple refactoring you don’t have to do this using any brain cells. You simply right click, and, say put this in a new file. Then I pick it up, and drag it, and drop it over into this package.
So I’ve got [INAUDIBLE] GeePaw. I’ve got a yz dot event. It’s got four things in it. It’s the three events we’ve already seen can roll change game start and pip change. But they have been changed. Now, they are game events. What’s a game event? Nothing. It’s really just– we call this kind of interface a marker interface. It says, listen I’m not promising anything really about anybody derived from me except if you ask them whether they are a game event, they will know. And that’s matters because that is how the bus that we’re using actually works. You need to have– in order to subscribe to a particular event you need to have a marker that lets you say, oh, yeah it’s one of those events.
Now, over here in the making model look at the change. The events is now an observable list of game event. And we got our bus, and we register, and now we have a subscribed value, and it is just dead simple. It says, hey, listen if you happen to see a game event come over the bus, then add it to my list of events. And now we need to make our clever making view have something that’ll do that.
My theory is we’ve got something at the top that’s our toolbar. We’ve got something in the center that’s our game view. Let’s put something over on the right. We can just make it a list view. It would be a list view of a game event. Oh, cool. So that’s our list over here. There haven’t been any events. If I fire an individual event using the Tool button, it should pop up there. Oh, it doesn’t. Oh, you’re breaking my heart.
Well, I’ve said this as a list view of game event, but I didn’t tell it what he should be watching. And now you can watch the making models events. Let’s try this bad boy again. It’s a pip change event dice 2 pips3. What if we actually try to play the game? Well, it doesn’t play very well, but if we press the Start, we should get– I don’t know what we’ll get. We will get another pip change as we change each one of these pips to zero.
So that’s five of those followed by– because I press the Start button. Remember there was a can roll change event. And the can roll change event is true. Now, we could play, we can roll, which gives us more and more events as we go. All of this was not horrendously necessary today. But I wanted to show you the concept of changing an application so that– creating an application so that you get what you need.
See the problem with the shipping application. Imagine that the Yahtzee game was in the field. We would not want to be doing any of this crazy stuff. And we would not want it to be accessible. That’s possible. But another way to do it in a way that actually gives you even more freedom is to simply write a very different kind of app and a very different kind of display. Out there in the trade, developers spend all day long using the shipping app as their primary tool for working with the changes in the shipping app, but you don’t have to. You can actually write a making app. And when you do write a making app, several things are going to happen.
First of all, it isn’t very hard. The bulk of the source is actually still over there in the shipping app. It’s just a few things as we saw today. But secondly, you get ideas, you get capabilities that you cannot possibly put into the shipping app. In fact, when I say cannot possibly, I don’t mean just that. They might be uncomfortable for the user if you did that that’s not the issue. You can do things in a making app that cannot be done through the production surface, right? They cannot be done ever. You can cheat in various ways, you can use passwords that are hardwired, you can send 1,000, 1,000 runs through the system simultaneously to test its performance. You can do all of this, but first you have to build a making application.
So that’s it for today, I did get a start because I got a start message. But I didn’t get very far, did I? We went off on a track. I don’t care. It’s a good track, and we’re going to take advantage of that track next time when we actually start using this thing to drive our development of the scorecard. I’m GeePaw. Thanks for coming. We’ll see you next time.