A couple of working diagrams. Here’s why I think rough diagrams are quite often good enough.

Here we are, around 0850 on Friday. I’m running at maybe 75 or 80 percent of nominal, and my nominal is pretty low at the best of times. Still good to be above the ground, though. So there’s that.

I’ve mentioned class diagrams and sequence diagrams from time to time. If we were working as a team, I’d think that maintaining a few rough diagrams would be worthwhile, and I think that maintaining detailed high resolution diagrams would probably be too much. But you do you.

I rarely draw diagrams, because I want to explore what happens when we work primarily with the code before us, a situation that seems to me to be more common in the world. But sometimes I do draw a diagram, and there are two reasons why I might do it.

One reason would be to communicate with my readers. Even in that case, I would go with a hand-drawn diagram in most cases, because I think the benefit of visualization comes from the drawing itself, and from there being anything to visualize, and I think that very little additional benefit comes from making the diagram all rectangular and nicey-nice. But you do you.

That being said, I have drawn a couple of diagrams over the past little while, and I’ll share them with you now.

Classes and Relationships

classes diagram

I drew the class diagram above while balancing the iPad on my keyboard tray, swiping back and forth between Codea and Paper, reading a bit of code and drawing something to represent what I wanted to represent.

What we mostly see in the diagram is a picture of classes and what they know–what they have a member variable pointing to. GameRunner has-a Dungeon and Dungeon has-a GameRunner. Dungeon also has-a Tiles, which has-a a Map. Dungeon also has-a Map, and the red X is there as an indication that I think it shouldn’t. The Map has all the Tiles: its job is to hold them and index them. It doesn’t really know what they are: that is the job of other classes. Finally, Dungeon has the Rooms.

The above paragraph should tell us why sometimes a picture is better. As I drew the thing, I learned or relearned what is in the system, and in some cases I didn’t like what I learned, such as that the Dungeon still has the Map. Whatever Dungeon wants should be entirely moderated by the Tiles class that we wrote yesterday.

Down in the lower right, we see the lovely DungeonObject, which is the abstract superclass for Entity, NPC, and a plethora of other things that can be in the Dungeon. Looking at that bunch of items on the far right makes one wonder whether more of the objects might be represented by a single class driven by data. We have accomplished that with the Monster class, a subclass of Entity. Monsters are built from a table that describes their appearance and behavior. We might imagine benefit from doing that for items discovered in the Dungeon.

In a real game development, we’d absolutely want to do that. We’d have a Treasures Team and a Traps Team and an Encounters Team, and we’d want them to provide us with configuration files that would set up whatever was needed to make a box of potions or a pile of bones containing an Amazin Gift Card.

Three other things of note are on the diagram, the DungeonBuilder, DungeonAnalyzer, and DungeonContentsCollection.

The latter is a single global instance that is used to find out where things are. Tiles used to each have their own contents, and now the mapping between an object and its location is in the DungeonContentsCollection. This saves a member variable in every Tile, which is not a big deal in my view, and centralizes a bit of dungeon searching. Anyway, it is what it is.

DungeonBuilder, of course, is the thing we’ve been working on for a while now, moving all the dungeon construction that we can over to it. DungeonAnalyzer is a class for determining positions in the dungeon and (probably) other dungeon-searching requirements. It implements methods like randomRoomTileAvoidingRoom(room).

Thinking about it now, I can imagine that a combination of DungeonAnalyzer and DungeonContentsCollection might be useful. I’ll try to keep that in mind as we progress.

That Diagram is UGLY, Ron!

Never come near me and my baby ever again! No, really, yes, it is. Partly that is an artifact of the poor setup I had for drawing it, part is due to my generally weak drawing ability, and most of it is due to the fact that I just wanted to visualize my system, not to document it for posterity. I needed a diagram that I could understand.

That said, even I would prefer that it was a bit more neat, but I doubt that I’ll look at it very often, if ever, in the future.

Let’s look at another.

Sequence Diagram

sequence diagram

I drew the diagram above while thinking, and communicating with some folks on a Slack that I attend, about an idea I had. It seems to me that I could eliminate some of the coupling between my classes using the EventBus’s publish-subscribe capability. Instead of an object calling some method on a known object to express some important fact, it would just publish the fact, and whoever wanted to know that would subscribe, and the information would arrive.

That got me thinking about requesting and receiving information using the Bus. In a distributed system, or even a multi-threaded one, we might post a request to some address, and at some later time, a response might come back to us. If that were practical, then maybe I could decouple even more of my objects.

However, my Codea app isn’t, and really can’t be multi-threaded. When an object publishes an event, all the subscribers are informed, and return from being informed, before the publisher proceeds.

I wanted to visualize that for myself and those on the Slack, so I drew the diagram above. There we can see that after A and B subscribe to X, when C publishes X, the Bus runs, then A runs, then A returns and the Bus runs, then B runs, then B returns, the Bus runs, and returns to C.

We may come back and do something with this idea: I still think it has merit. But if we really wanted A and B to “respond” to the X message with a result, we need to be aware that their responses would be created, and would be provided, before the request function had even completed. So that’s interesting.

It does offer some interesting possibilities, however. You could imagine requestor code like this:

    self.result = {}
    Bus:publish("requestX", self)
    for k,v in self.result do
        print("Here is response ", k, v)

In fact … we might even be able to do something like this:

    local result = {}
    Bus:publish("tellMeYourName", self, result)
    -- voila, the names are in result

I can’t decide whether that is really nice, or too cool to live. It’s near trivial to implement, and the code should be easy to understand. Knowing me, I’m very likely to try it in the near future.

We’ll see.

So. Those are some diagrams, what they mean to me, and a bit about how I find a rough diagram to be just about the right level of completeness. No one is likely to mistake either of those diagrams as containing the exact truth of the situation, and that’s a good thing.

I draw diagrams to inform myself, or a few other people. As such, they can be pretty rudimentary, and in my view should be as rudimentary as possible within the purpose. Of course, your purpose may be different, and your preferences may differ. You do you. I’ll do me. That’ll do, Ron, that’ll do.