Real Programming S01E01: Getting Started
Hi Folks! In this first episode we lay the groundwork for a simple desktop Yahtzee application.
If you want to follow along in the code, the project is https://github.com/geepawhill/yz
Hey, folks. It’s GeePaw sitting out here on my deck, where I do most of my work in the summer months. And today is the first episode of my new series called real programming, the show where we don’t have a cool slogan yet.
Anyway, my friends, Bill and Ted, had been working on Yahtzee programs. Yahtzee, the kids game with the dice, and I really liked the idea of doing it. And that’s what we’re going to do today is start the series based around that.
Now, if you take a look at Yahtzee, it’s a pretty straightforward game. I’ve looked at a lot of different rule sites. They are all identical. There aren’t a lot of special variant rules for Yahtzee. I’m using the one at ultra board games. And this is what a sample score sheet looks like. I’m not going to go very deep into the rules except operationally as we go. But the bottom line is you got five dice, you roll them a lot, and you fill out one of the score sheets. The person with the max score wins the game.
Now, there are just three rules to the series. Rule number one is I have to call my shot, OK? I have to tell you what I’m going to do before I do it every single time because if I don’t, we won’t keep ourselves honest. Rule number two, I have to show you the screw-ups too. We’re going to jump from chunk to chunk of code.
Essentially, every time I do a micro-step, we’ll take a look at the difference that’s been added to the code. But some of those aren’t going to work, and I gotta show them. And the third rule, super important, no obsessing over production values because when I start obsessing over production values, that’s when I stop producing. So instead, I’m just going to focus on churning out a series of very short videos that get us somewhere, and maybe give you some insight and some ideas into how I actually do my work.
OK, so let me show you the starting base. This is my git commit. It’s a running program with one worthless test. We’ll take a look at that. There’s 19 files, and I’m not going to look at 19 files. Much of it is the stuff that goes with the intelligence. What’s left is the Gradle. Not going to show you the individual Gradle files. The gist of them is that they’re what makes it. It’s boring, stupid work. And what I do is I have an unusual set up here.
I start from a project called base and it’s one that I keep up in my GitHub account. And I check it out, I change about four things and then I have my starter program. So let’s take a look at the starter program, you’ll see just how sophisticated I can really be.
Oh, here it is. It’s a program. Oh, it’s a Windows program. It’s got a window. It has a button. A button doesn’t do anything, and you can minimize it and maximize it, and you can close it, which we’re going to do right now and take a look at the underlying base code. There’s not very much to it. In fact, the entire expression of that code is right in here. I got a package name org.geepawhill.yz, I’m using tornadoFX, which is a JavaFX, Kotlin wrapper around JavaFX.
And in this environment, what you have is you have an application class that’s derived from the app. It tells us what class to use as the main view. And there’s the MainView::class, and there’s my main view. This is tornadoFX we’re looking at.
The gist of it, though, is this, when we looked at the running program, we actually were looking at a view, which is that center inside a frame of some kind that’s got a BorderPanes. BorderPanes have top, center, or bottom, but all I have in mine is a top. And I put it in a toolbar, and the toolbar has got a button, and the button says button. And that’s it. That’s the whole starting point of our program. The source code is all up on GitHub, and you can go check out that start and poke around and see how I set up my Gradle and all that, anytime you want.
So it’s time to get to work, and the work that I’m going to do first is very straightforward. I’m going to gut this. I’m going to gut it, and I’m going to replace it with something that looks well, not so much like what exactly I want as something that looks at least a little more like the Yahtzee that I have in mind.
We’ll do that now for the very first tiny step. And here it is, as you can see, it’s absolutely a no brainer of a step. That’s how I like it. Remember, mama didn’t raised no thinkers. The small steps I take, the less I have to think to make things happen. So let’s take a look at our new exciting running program.
Well, there’s not much more to it than there was before, is there? What I’ve got here is I’ve got a start button. I’ve got a roll button, and I got a bunch of labels with hard-wired values in two, three, four, five, and six. And I’m imagining that those are going to be the dice. And we’ll get further along as we go, but that’s good enough for just this very first tiny step.
So what’s my next shot? Well, let’s make those labels instead of having the labels down here hard-wired. Let’s make them actually attached to something that can change. And first, I’ll do the attaching and then we’ll do the changing after that. OK, then let’s take a look.
First, let’s run it. Now, you notice I changed the numbering instead of being two, three, four, five, six, is now one, two, three, four, five. That’s just so I could get a visual to determine whether I had really changed anything and hooked it up correctly.
So what did I change? Well, these labels used to have hardwired literals, and now they refer to something called model dice. What’s this model thing? Well, the model thing is a guy I made called a YzModel. And what’s he got in him, just a list of dice. What’s a list of dice? OK, this is JavaFX stuff. Essentially, what’s going on here is that a simple integer property is the subject role inside a subject observer arrangement that comes with JavaFX.
Now, you might feel he’s already starting to over-engineer this. But in this particular case, I have a very strong reason. But it’s good that you wondered, why did you go so quickly to extracting model and view? Because it’s a very good question and we’ll answer it at the end.
Anyway, the gist of it is this the simple integer properties are now initialized one, two, three, four, five, instead of two, three, four, five, six. And they’re mapped with model dot dice. And that’s all there is to it. That is what makes it possible for me to run the program and see one, two, three, four, five. That’s just one more itty-bitty teeny tiny step.
So what’s my next shot? Well, let’s change it. Let’s make these guys change their value. We’ll do it in response to somebody clicking the roll button. OK, let’s see what we got at this point? If I hit the roll button, these numbers over here one, two, three, four, five should change. Fingers crossed. Bam, they do. And I’m going to hit that roll button as many times as I want. You can think of me as sitting around with the dice before we start the game, rolling the dice over and over again.
So how do we do that? Again, really straightforward code and tornadoFX. This may look weird to you, this tree-shaped data that’s happening here. But in fact, windowing system, everything is always tree-shaped. There’s always– This is a child window of this, child window of this, child window of that, right? And this just makes that explicit.
But here for the first time, instead of essentially laying out data, we’re actually giving instruction. What we’re saying is if somebody clicks the roll button or activates it in any way, this is the action I want you to do. Do a model dot roll. And what has model dot roll do? Well, pretty much about what you would think it does. It goes through this list of dice. And for every die inside the list of dice, change its value to a random value between 1 and 6.
This may look unusual to you, but it’s how we always do it. I also added a Java util random object to be the random object. So that’s the end result of that step. I can now roll the dice as many times as I want. So that’s pretty cool.
What’s our next shot? Well, I don’t want to roll the dice as many times as I want. I want to roll the dice three times. You can roll the dice three times, which is cool. But you can’t roll’em four times unless you start over again because, in real Yahtzee, the rules say, each pass through the dices is essentially set up that way.
And again, I’m not really programming Yahtzee per se today. My meta step that I’m aiming at is something a lot smaller than Yahtzee, but this will help. So for my next shot, what I’m going to do is make it impossible to roll the dice until you’ve hit start at once, and then only possible to roll the dice three times.
OK, let’s take a look. Oh cool. First little bug. That’s a little tiny thing, but I set it up. I’ll show you how I set it up here in a minute. But I didn’t get it. You can roll. You can start by rolling three times. Now, this part doesn’t work either. What is going on? My start button’s action isn’t taking place.
All right, can you see why it isn’t taking place? Bonehead. It isn’t taking place because I didn’t say, dude, here’s your action. Instead, I just used the command as if it weren’t a command. In fact, what happened is when you first instantiated this whole window, that model dot start got called, which is what messed me up.
Let’s try it again, real quick. Now, we’re cooking with gas. The roll button is disabled. If I hit start, roll button is now enabled, and I can roll up to three times once, twice, three times. And then it’s disabled again until I hit start.
How do we do that? Again, pretty straightforward. I added a new property to the model. A private one called rolls left, and a public one called can roll. So can roll is true, if you’re allowed to roll, and it’s false if you’re not. This is all built-in JavaFX stuff. There’s nothing terribly clever about it. It’s essentially saying if the roles left property is not equal to zero, then you can roll.
There are other brilliant things you can do to assign bindings like this. But this is a very easy one, and I know it very well, so I went with that. What about roles left property himself? He’s just a simple integer with a value of zero to start with, so he starts disabled.
And now, start’s action resets the rollsleft property value to three. Whereas roll’s action adds a line the decrements that value. So you’re getting a sense here of the flow. It’s a little messy, and the code is not very tight, but you get a sense of where I’m headed with this. And it is, in fact, working correctly. One trick: enableWhen.
How did I make it so that the roll button is only turned on under certain circumstances? Well, by that clause right there. So now, I have enabled when model can roll, and the action is model dot roll. And that’s what gives this a result.
OK, so then, what about the next shot that we’re going to take? Well, I’m actually going to wrap it up pretty quick. I want these videos to be pretty short and pretty precise. But what I’m going to do is this, you notice that I really have three things going on here. I have the main class, even though it doesn’t have much in it. I have this yz model class, and it does have some stuff in it. And I have this view class. I’m going to split them up into three separate classes and put them three separate places. When I come back, I am going to tell you why I did all of this.
OK, once again, a very tiny step. I now have a main view that’s its own thing. I have a model that’s its own thing, and I have a main that is back to being just its own little tiny thing. So let’s talk about this other issue.
Let’s try it on a picture. Right now, the circumstance that we have is kind of interesting because, man, GeePaw just jumped in, and he start crapping code quick like a bunny, and it was zip, zip, zip. And you notice two things about it if you’re paying really very much attention. You’ll have noticed one, that I did this whole view and model thing even though really there wasn’t very much complexity going on in the view. And there’s no reason I couldn’t put all of that code into the view. So I over-engineered it.
And then the second thing is, here’s this guy who is supposedly this test-driven development guy that’s always talking about TDD. And I just did this whole little sequence without writing a single test. Here’s the thing, those two things are the same thing. And that is the actual step whose shot I wanted to call at the very beginning, which is to get myself to being able to test.
So here’s what’s going on in this picture. Over here, I have a bunch of untestable JavaFX. And over here, I have a bunch of testable model. And that is the basic model view split. It is to say, we put windowing stuff on one side, and we put the actual guts of the game or the application on the other side. But in my particular case, that isn’t just a vague theoretical concern.
JavaFX is like all GUI systems, is a multi-threaded beast that is difficult as hell to test. It’s not impossible to test. It’s just a pain in the ass to test. By rushing into this over-engineering of splitting view and model, what I’m actually doing is I’m getting all of the untestable parts of JavaFX on one side of this line and using only testable parts over on the other side of this line.
So with that in mind, let’s take one more look specifically at the model class and see what we have here. This class certainly uses JavaFX-ism’s. That’s what simple integer properties. It’s a JavaFX-ism, that what’s bindings is. But the interesting part of this is that these are not the parts of JavaFX that can’t be tested without firing up the windowing system.
In other words, I can test these guys in a regular old JUnit style test with no special preparation. If you go back and you look at main view, there is essentially no way to reliably test this guy without invoking the entire JavaFX framework. And I don’t want to do that. It’s not that it’s undoable, it’s that it’s painful. And anything that’s painful to test, I know myself really well, I will test it.
So there you go. Here’s Wally’s butt and me. And we wrote a very small amount of code, but we had a very focused idea in mind, which was let’s get to a place where GeePaw can actually use its test-driven capability to test-drive us some code and get us something cool. The final running program doesn’t do much, and it doesn’t even do what real Yahtzee does. I don’t care.
This whole thing took us, beginning to end, maybe 45 minutes. And it was worth it for me to essentially work up the code to a shape that I would then have it available for the kind of methodology that I use, the test-driven development methodology. So in our next episode, I can pretty much guarantee you, we’re going to spend a lot of time working on that yz model and getting it to go. OK, it’s GeePaw. Thanks, it’s GeePaw and Wally’s butt. And thanks for watching. Bye-bye.