Search code examples
oopcoupling

low coupling vs intuitive object design


I'm about to start making a video game and I have a design dilemma.

I have a main class called GameWorld, and a small class called Missile. When an instance of Missile explodes, it should damage all ships around it.

I have come up with two approaches to doing that:

// APPROACH A:
// in class Missile
explode()
{
    for each (ship in GameWorld.getShips()) {
        if (distanceTo(ship)) <= BLAST_RADIUS) {    
            ship.dealDamage(DAMAGE);
        }
    }
}

/* creates coupling that allows Missile to call GameWorld and all of 
* it's methods, which is bad. but also keeps the entire explosion 
* process within Missile which is intuitive object design.
*/


// APPROACH B:
// in class GameWorld
update()
{
    .
    .
    .
    if (missile.position.equals(missile.destination)) {
        for each (ship in shipsArray)   {
            if (distanceTo(ship)) <= missile.BLAST_RADIUS) {    
                ship.dealDamage(missile.DAMAGE);
            }
        }
    }
    .
    .
    .
}

/* no two-way coupling from GameWorld to Missile since Missile has no 
* reference to GameWorld which is good. 
* but explosion is now something being done by the GameWorld and not 
* Missile, which is an unintuitive design. also when expanding this design 
* approach to the rest of the objects and interactions
* GameWorld can become sort of a "god class" with all smaller objects being very thin
*/

so which approach is better? is it worth coupling the classes by giving Missile reference to GameWorld so it can use it's getters in order make the entire explosion process within Missile.explode() or should the 2nd less intuitive and less-coupled approach better?

thanks in advance.


Solution

  • Approach 1 has definitely advantages over option 2.

    You see, GameWorld is probably some really central element in your game; and you can't do without it. And of course, you want to make sure that this central class ... still manages as few things as possible (you want to avoid that this class ... in the end, does everything).

    In that sense, it seems very reasonable, that the GameWorld has methods to query for elements (ships) of that world. And that other classes, such as Missile can call such methods to gather that information that is required to do "their" work.

    Whereas with option 2, you more or less give up the need for a Missile class. As the GameWorld class is actually doing most/all of the crucial work itself.

    You see, the model that you choose seems to distinguish between elements (such as ships or missiles); and the "world" those elements exist in. In that sense: it is the responsibility of GameWorld to keep track of all the elements in your world. But the then each element is responsible for "doing its thing" in the end.