Code Better: Headers without Hidden Dependencies

When you work on a larger project, you cannot easily keep track of which header depends on which other header. You can (and should) do your best to keep the number of other headers referenced inside your headers low (to speed up compilation) and move as many header dependencies as you can into your source files, but this still doesn’t prevent you from building headers that implicitly depend on another header being included before them.

Take this example:

#ifndef MAP_H
#define MAP_H

/// <summary>Stores the tiles of a 2D map<summary>
struct Map {};

#endif // MAP_H
#ifndef WORLD_H
#define WORLD_H

#include "Actor.h"
#include <vector>
// Oops, forgot Map.h, but won't notice since World.cpp includes Map.h before World.h

/// <summary>Maintains the state of the entire world<summary>
struct World {
  /// <summary>Stores the map as a grid of 2D tiles</summary>
  public: Map Map;
  /// <summary>Actors (player, monsters, etc.) currently active in the world</summary>
  public: std::vector<Actor *> Actors;

#endif // WORLD_H

Throughout your project, map.h might always end up being included before world.h and you might never notice that if someone included world.h on its own, a nasty compilation error would be the result.

So what can you do ensure this situation never happens?

Read More

Code Better: Reference Containers for Change-Resistant Constructors

Proponents of dependency injection try to design classes so they can either work autonomously or get all services they rely on handed to them through their constructor. But even without dependency injection, the situation often arises where certain classes need to interact with a lot of other objects.

In these cases, you often end up with very complicated constructors and a lot of duplicate code:

public class RadarBuildingRenderer {
  public RadarBuildingRenderer(
    ISceneGraph sceneGraph,
    IContentManager contentManager,
    IAudioManager audioManager,
    RadarBuilding building
  ) {
    this.sceneGraph = sceneGraph;
    this.contentManager = contentManager;
    this.audioManager = audioManager;
    this.building = building;
  private ISceneGraph sceneGraph;
  private IContentManager contentManager;
  private IAudioManager audioManager;
  private RadarBuilding building;

Above class takes care of rendering the visual and audible representations of a RadarBuilding in a computer game. As you can imagine, the same references will be required by other buildings, think TankFactoryBuilding, CommandCenterBuilding and so on – all duplicating the fields, their assignment and the complex constructor.

Read More

Code Better: Booleans instead of Comments

There are lots of small tricks a programmer learns over time. With this post, I’m starting a little column called Code Better in which I’ll share some of my own tricks! If you want to show off some useful tricks of your own, I’d be happy to publish them here, too :)

The first trick is a simple technique to make complicated if statements more readable. Let’s take a look at this beast:

// Only access the height field if the position is within
  (x >= 0) && (y >= 0) &&
  (x < this.heightField.Width) &&
  (y < this.heightField.Length)
) {
  return this.heightField[x, y];
} else { // Position is outside the height field
  return 0.0f;

The code isn’t unreadable per se, but it takes more than a glance to understand what’s going on. The comments help, but there’s a more elegant way that makes those comments entirely redundant:

bool isInsideHeightField =
  (x >= 0) &&
  (y >= 0) &&
  (x < this.heightField.Width) &&
  (y < this.heightField.Length);

if(isInsideHeightField) {
  return this.heightField[x, y];
} else {
  return 0.0f;

The beauty in this is that the first thing you see is bool isInsideHeightField, prominently positioned at one indent less than the conditions. Your brain registers the purpose of that block of code before it encounters the actual code.

The if below is also much more obvious. If the position is inside the height field, look up the value in the height field, otherwise return zero. Almost like reading english.

Finally, this level of obviousness eliminates the need for any additional comments in the code!