Java – Proper Way to Model Real-World Activity with Circular References in OOP

circular-dependencygame developmentjavaobject-oriented

I've been wrestling with a problem in a Java project about circular references. I'm trying to model a real-world situation in which it seems the objects in question are interdependent and need to know about each other.

The project is a generic model of playing a board game. The basic classes are non-specific, but are extended to deal with specifics of chess, backgammon and other games. I coded this up as an applet 11 years ago with half a dozen different games, but the problem is that it's full of circular references. I implemented it back then by stuffing all the intertwined classes in a single source file, but I get the idea that that's bad form in Java. Now I want to implement a similar thing as an Android app, and I want to do things properly.

The classes are:

  • RuleBook: an object that can be interrogated for such things as the
    initial layout of the Board, other initial game State information
    like who moves first, the Moves that are available, what happens to
    the game State after a proposed Move, and an evaluation of a current
    or proposed board position.

  • Board: a simple representation of a game board, which can be
    instructed to reflect a Move.

  • MoveList: a list of Moves. This is dual-purpose: a choice of moves
    available at a given point, or a list of moves that have been made in
    the game. It could be split into two near-identical classes, but
    that's not relevant to the question I'm asking and may complicate it
    further.

  • Move: a single move. It includes everything about the move as a list
    of atoms: pick up a piece from here, put it down there, remove a
    captured piece from there.

  • State: the full state information of a game in progress. Not only
    the Board position, but a MoveList, and other state information such
    as who is to move now. In chess one would record whether the king
    and rooks of each player have been moved.

Circular references abound, for example: the RuleBook needs to know about the game State to determine what moves are available at a given time, but the game State needs to query the RuleBook for the initial starting layout and for what side effects accompany a move once it is made (e.g. who moves next).

I tried organising the new set of classes hierarchically, with RuleBook at the top as it needs to know about everything. But this results in having to move lots of methods into the RuleBook class (such as making a move) making it monolithic and not particularly representative of what a RuleBook should be.

So what's the proper way to organise this? Should I turn RuleBook into BigClassThatDoesAlmostEverythingInTheGame to avoid circular references, abandoning the attempt to model the real-world game accurately? Or should I stick with the interdependent classes and coax the compiler into compiling them somehow, retaining my real-world model? Or is there some obvious valid structure I'm missing?

Thanks for any help you can give!

Best Answer

I've been wrestling with a problem in a Java project about circular references.

Java's garbage collector doesn't rely on reference counting techniques. Circular references do not cause any kind of problem in Java. Time spent eliminating perfectly natural circular references in Java is time wasted.

I coded this up [...] but the problem is that it's full of circular references. I implemented it back then by stuffing all the intertwined classes in a single source file, [...]

Not necessary. If you just compile all the source files at once (e.g., javac *.java), the compiler will resolve all forward references without problems.

Or should I stick with the interdependent classes and coax the compiler into compiling them somehow, [...]

Yes. Application classes are expected to be interdependent. Compiling all Java source files that belong to the same package at once isn't a clever hack, it's precisely the way Java is supposed to work.

Related Topic