C++ Abuse

08 May 2006

I’m reading through MUD Game Programming by Ron Penton. I found it at Fry’s for $16.99, so I’m hoping it will be worth it at least for the discussions on network code (he only covers Telnet, as it’s for MUDs, but adapting to other protocols isn’t hard) and the fact that this book actually goes into management of the actual game, rather than just backend stuff.

Most of the books I’ve bought cover all kinds of info about how to write the various bits of a game engine, but they leave you with bits and not all that clear of an idea how they all get put together. Couple that with me being unable to ignore perfectionist tendencies and you’ll have a good idea of why I take awhile to get very far in my personal projects. :) This book is cool because it focuses on something so simple: your average MUD is text based; the most complicated part is handling the bits that go over the network. That leaves Mr. Penton plenty of time to discuss how it all works together.

He has enough room that he writes two full MUD engines; the first very simple and similiar to older-style game. It’s mostly hard-coded so any real changes require access to the codebase. His second engine is a great deal more flexible, and includes Python bindings and all that jazz.

So for $16.99, I’m stoked. It’s a good book. However, I would ask anyone who might be interested in reading it to have a firm grasp of how C++ works and what you can, can’t, should, or should not do in it, because Mr. Penton abuses the language in a number of ways.

First up, can anyone explain why you would do this:

class MyClass {
    int& MyVariable() { return m_myVariable; }

    int m_myVariable;

Rather than just:

class MyClass {
	int m_myVariable;

With the first variant, you have to call MyClass::MyVariable() to get access to the variable, but it returns a reference, so you can do things like:

MyClass m;
m.MyVariable() = 14;

What is the point in having the variable private in the first place? It is no longer protected from getting modified in bad ways, and you’re still exposing that implementation detail to the world. If you want a variable to be accessible to everyone, just make the darn thing public. If you don’t want it to be, use get/set functions. It’s much clearer what you’re trying to do, and you have more flexibility down the line to evolve the interface further.

Along the lines of accessor functions, Jonathan Blow makes some very good points in his “Implicit vs Explicit Software Engineering Costs” rant here: http://number-none.com/blow/rants.html. I personally tend to use accessor functions when I want to either 1) validate things before I set them, or 2) allow read-only access to variables. If it doesn’t fit in either category, it goes public.

Second nitpick on MUD Game Programming is C pre-processor abuse. Mr. Penton defines a couple macros that look like this:

#ifdef WIN32
WSADATA g_wsadata;
#define StartSocketLib WSAStartup( MAKEWORD(2, 2), &g_wsadata);
#define CloseSocketLib WSACleanup();
#define StartSocketLib {}
#define CloseSocketLib {}

And then uses them in the code lookin’ something like this:

void main() {
	// do networky stuff

I’m reading through the example code and see something like “StartSocketLib;” on it’s own in a line of C++ and my brain halts. It’s not immediately obvious what that statement does: it should do absolutely nothing. Any variable or function placed like that evaluates to a NOP. I understand completely hiding OS-dependant details behind some pre-processor magic, but if you’re going to do that at least make the macro look like valid code.

Anyway, I bought the book for the ideas within it, and they’re worth what I spent on it, but the code drives me nuts, so it’s been slower going than I’d like it to be.