Contact us for your own Poker & Casino license now!

info@cubeia.com
Stora Nygatan 44, 111 27 Stockholm
  • No products in the cart.

Cubeia Poker, Casino & White Label

How I Learned to Stop Worrying about Serialization and Love the Wrapper

Background
One of the great benefits with Firebase is the support for transparent failover. All you as a game developer have to do is to make sure that your game state is serializable.

The Problem
One common pattern that follows from this approach is that non-serializable classes (such as the Notifier or the Scheduler) tend to get passed around a whole lot, because they can’t be stored as instance variables. If you want to do Domain Driven Development, this is a bad pattern.

Half of the Solution
Storing those instances as “transient” is always an option, but only solves half of the problem. On deserialization, those values will be null and there’s no way to recreate them in readObject().

The Solution
Instead of referring to the Scheduler and Notifier directly, create a wrapper class which holds them as transient members. Then, pass that into all your collaborating classes. The parent class will hold a reference to this same wrapper and on each call from Firebase, it will inject the live versions of the Notifier and Scheduler and since all collaborating classes refer to the same instance of the wrapper, we’re now all set!

An Example
I find that a concrete example always makes things clearer. Here’s some code for a poker game. First, here’s the game state class.

public class Poker implements Serializable {
    private Wrapper wrapper = new Wrapper();

    public void addPlayer() {
        Player player = new Player(wrapper);
        ...
    }

    public void handle(GameDataAction action, Table table) {
        injectCallbacks(table.getNotifier(), table.getScheduler());
        ...
    }

    private void injectCallbacks(GameNotifier notifier, Scheduler scheduler) { 
        wrapper.setNotifier(notifier);
        wrapper.setScheduler(scheduler);
    }
}

And here’s the wrapper.

public class Wrapper implements Serializable {
    private transient GameNotifer notifier;
    private transient Scheduler scheduler;
    
    ... getters and setters ...
}

Which means that from any any place in the code, we can do something like player.updateBalance(newBalance), which would look like:

public class Player {

  private final transient Wrapper wrapper;

  public Player(Wrapper wrapper) {
    this.wrapper = wrapper;
  }
  
  public void updateBalance(int newBalance) {
    balance = newBalance;
    notifier().notifyAllPlayers(createGameDataAction(newBalance));
  }

  private Notifier notifier() {
    return wrapper.getNotifier();
  }
}

So, time for you to fire up your refactoring tool and put some candy in that wrapper!

Comments
  • August 11, 2011

    How does the class that has the updateBalance method get hold of the wrapper?
    I assume that the method getNotifier needs to access the wrapper, so then you need to pass the wrapper around. Do you use IOC for this? If so, how?

    Stupid question: Wouldn’t it be more prudent to have the wrapper field declared transient instead of having each field within the wrapper transient?

  • August 11, 2011

    The updateBalance is in the Player class, and the Player class gets the wrapper in the constructor. The “mother game class” creates the player and has the wrapper.

    Warning: do NOT use Guice to inject this, as serializing instances created by Guice creates a bad mess!

    If you make the wrapper transient, you will have to deal with the possibility of it being null if the game state has been deserialized. Since I know that the transient memebers of the wrapper will be injected into the on each action, I know neither the wrapper or its members will be null when I handle an action. Does that make sense?

Post a Comment