Sunday, March 24, 2013

Teaching Kids Clean Code

‹prev | My Chain | next›

As I finish the last chapter in 3D Game Programming for Kids (there still a few earlier chapters and appendices), I begin to ask myself how much about coding I really ought to be teaching kids. This is the last chapter in the book, so I feel like I ought to send them off with a few organization pointers, but it is hard to stop at a few organization pointers.

Without saying so, I am suggesting that kids might think about Clean Code organization for code. Specifically, I tell them to define functions after they are called and to keep the same abstraction layer grouped together (yeah, I'm definitely not using the term abstraction layer). For instance, in the river rafting game in this chapter, I first call all of the functions that add the components:
  addScoreboard();
  addSunlight(scene);
  addRiver(scene);
  // add raft ???
Then I have the kids define those functions below.

The functions that take scene as an argument are a little awkward. By this time in the book, I have already introduced objects and the importance of never access external "things" from objects or methods. It is nearly impossible to anticipate how much will sink in for the majority of readers, but I feel better for having done it. So passing what amounts to a global variable, scene into these functions will not be completely foreign to most readers.

The question becomes a little more difficult for the raft that will be navigating the wild river rapids in the game:



I almost feel as though I need to give the add function a signature of addRaft(scene, river, scoreboard). The raft needs to be added to the scene like the other game objects. The raft needs to have access to the river to know where the start point is in world coordinates. Finally the raft needs to be able to communicate scoring events to the scoreboard.

I could move addRaft() to be part of addRiver(). I could then rename it as addGamePieces() or something like that. The river probably needs to know about the scoreboard anyway—it probably works better for obstacles in the river to know how to add or subtract points from the current score.

The problem with this is twofold. First it is the wrong clean code abstraction. The addSunlight() method adds a single object to the scene. The proposed addGamePieces() function would be responsible for adding a myriad of things to the gameboard. The second problem is that it disrupts my narrative. I am mostly trying to hold up clean code style as analogous to writing an outline, followed by the actual essay. I do not know what kind of teachers you had in school, but mine would not have been pleased with an outline comprised of two parts: add light and then add everything else. Then again, if my teachers were Erlang aficionados maybe I would have gotten a pass.

Anyhow... I do not think that is the way to go.

This, of course, comes does to communicating state. And unfortunately, communicating state would also be ugly-ish:
  var scoreboard = addScoreboard();
  addSunlight(scene);
  var river = addRiver(scene);
  addRaft(scene, river, scoreboard);
This just looks awkward. Keeping a reference to scoreboard and to river interrupt the more obvious outline analogy that I was hoping to use.

In the end, I fall back on another lesson from Clean Code. Functions should do one thing. My proposed addRaft() would need access to three variables because it was doing too much. It was creating the raft, positioning in the right place relative to the river, and attaching events to the scoreboard. And really, positioning the raft in the right starting point is something that I might want to re-use to enable game resetting. Which gives me this idea:
  addSunlight(scene);
  var scoreboard = addScoreboard();
  var river = addRiver(scene);
  var raft = addRaft(scene);
  resetGame(raft, river, scoreboard);
Sure, I traded one function that took three arguments for another that takes three arguments, but I think I have the abstraction levels right (or closer to right) with this approach. The raft, like all of the other game objects, is created and added to the scene with the new addRaft() function. Adding the raft is the only purpose of addRaft(). It is then the job of resetGame() to position all of the game objects properly (the raft include) for the start of a game.

This may not be perfect Clean Code, but it is clean enough as a send-off for kids. I only want new programmers to start thinking about these things. Hopefully this will suffice.


Day #700

No comments:

Post a Comment