5

Backstory:

Currently I have a series of three classes related to a game. I've previously made games using Unity where you access components such as the camera using functions accessible throughout all code. My current setup, however, relies on instances of each class being sent across the other classes. See the following outtake:

class World{

};
class Game{
     Camera* camera;
     World* world;
};
class Camera{
     Game* game;
     World* world;
};

Questions:

  • Is this a result of bad design or are there times when a setup like this is justified?

  • Should I rather use static classes over my current setup since it would clarify the code and no more than one instance of each class is ever used?

  • What are the possible downsides of using static classes over instances?

Edit: Why they need to access each other.

Why Camera needs World: The camera needs access to the world since the world need to be rendered from the perspective of the camera. The camera triggers a render of the world depending on what it sees. Rendering is triggered from various methods in the camera such as when it moves.

When the camera is drawn it draws what it sees, such as the world. To draw the world the camera needs access to the world.

Why Camera needs Game: Game has values such as FPS which Camera use to display an overlay of debugging information.

Alex
  • 606
  • 11
  • 23
  • 3
    Does each class need access to the whole other concrete class? Would an abstract class be wiser? This looks like "everything relies on everything else" rather than SOLID/fluid/... usual design ideas – doctorlove Feb 28 '17 at 11:21
  • I would definitely look at any scaling/cardinality issues. Does your World truly only have 1 Camera (or possibly even 1 Game?). Answering questions like this help to shape your design. If your World has more than 1 Camera, how is your World (and Game) able to distinguish between the various Cameras? – franji1 Feb 28 '17 at 13:47
  • @franji1 good point. But in this case I for an absolute know that there will be only one of each. – Alex Feb 28 '17 at 15:21
  • @doctorlove Could you clarify what you mean by using an abstract class? They do depend on each other, but there are no inheritance. – Alex Feb 28 '17 at 15:33
  • SOmething with a pure virtual function - then you can just expose the exact parts you want to use from each. – doctorlove Feb 28 '17 at 15:35

2 Answers2

5

Three classes which are that tightly coupled does suggest some questionable design choices. Try to change your code so that, for example, the Camera gets a pointer or reference to World passed in only the methods where it actually needs to deal with World. Also consider whether Camera and World actually need a pointer to Game. Conceptually it would make more sense if Game has a World and has a Camera, instead of all three objects being owned by someone else (who)?

The relationship between Game and Camera still only suggest that you should pass Game, or even better, relevant data FROM Game as method arguments to the Camera draw method.

Anonymous Entity
  • 3,254
  • 3
  • 27
  • 41
  • I clarified the need for the Camera to access both of the other classes, take a look in the updated question. You're right about it making more sense that Game should carry both World and Camera. – Alex Feb 28 '17 at 15:35
  • I don't quite understand your design, are you rendering the world whenever camera moves, or are you rendering once per frame? Your edit seems to suggest both. – Anonymous Entity Feb 28 '17 at 17:41
1

If you have static (global) instance(s) of any class(es) it can be accessed from anywhere and might end up with a "big ball of mud" making it hard to track what uses or needs what.

One idea from the so-called "SOLID" principles is that

"Details should depend upon abstractions"

Now introducing extra abstract base classes (or interfaces in languages that support them) might seem extra complicated, but it might help you find which parts of each object you rally need from where, and allow you say to introduce another Game in the future.

One approach might go as follows:

#include <iostream>

class World {
public:
    int Info() { return 0; }
};
//An abstract base class
class IGame {
public:
    virtual ~IGame() = 0 {}
    virtual int FPS() = 0;
};

//One specific type of game
class Game : public IGame {
public:
    int FPS() { return 0; }
};


class Camera {
public:
    Camera(Game * game, World * world) : game(game), world(world) {
    }

    void Move() {
        //actually move first then ...
        Draw();
    }

    void Draw() {
        //This will show us what needs to be public in the other classes
        std::cout << world->Info() << '\n';
        if (game)
            std::cout << game->FPS() << '\n';

    }

private:
    IGame* game;
    World* world;
};

int main() {
    World world;
    Game game;
    Camera camera(&game, &world);
    camera.Move();
}

(to the Dependency Inversion Principle) as discussed in this question

This might seem like overkill for what you are doing, but takes you nearer "everything relies on something abstract" rather than "everything conrete relies on everything else".

Community
  • 1
  • 1
doctorlove
  • 18,872
  • 2
  • 46
  • 62