However, I've already made a fair number of "working" programs. But
does this mean it is OK to use these "bad" things so long as you can
make it work? But what would _maintaining_ that program be like?
You have to find this out by yourself ;-). Seriously, doing "good"
things means understanding why they are good. One of best ways to find
out why is to do bad things and hopefully learn from mistakes.
However, the thing is, the display may be accessed by a great variety
of different functions and objects, especially to print messages. What
should be done? Is it OK to have a "display" parameter to all those
different diverse things?
Passing a parameter normally beats having a global (sometimes not by
much, though, see below). If nothing else, you can track where things
are used by looking at function signatures (as opposed to chasing down
their uses by reading everything).
About "especially to print messages" part: you should probably think
about that in a more abstract way. Program elements that want to
"print messages" don't really want to print messages. What they really
want is for their messages to go somewhere, and where that is, they
don't really care. They don't care about message window. So you should
probably do exactly that: pass, to those program elements, a facility
that they can use to "send" their messages. E.g.
file: messageReceiver.h
struct IMessageReceiver
{
virtual void Receive(const Message& m) = 0;
};
file: MessageDisplay.h
class MessageDisplay : public DisplayWindow, IMessageReceiver
{
// ...
virtual void Receive(const Message& m)
{
show message...
}
};
file: gameDisplay.h
class GameDisplay
{
MessageDisplay messageWnd;
DisplayWindow gameWindow;
// ...
};
file: partOfTheGame.cpp
void randomFunction(IMessageReceiver& r)
{
workworkwork;
r.Receive(Message("some text", Important));
workworkwork;
}
What I am talking about here is also known as "interface segregation
principle": for a given part of your code, you want to pass in things
it needs to do the work. To do that in a clean way, a good way is to
create the interface (from the rest of your code) to another part, and
pass that interface in. You don't want one big great massive thing
that can do everything, and then cherry-pick what you need from that
great big thing. That's akin to a global variable, except that you
avoided having it as one, by passing it -everywhere- through a
parameter.
Goran.