Scope of Variables

Started by
4 comments, last by cemedias 16 years, 8 months ago
Good evening, (A little background info) Language: CPP Project Type: Text RPG I am eager to understand the design and structure of an exemplary program, and there is a lingering problem whose answer has been eluding me for ages. How should I hide variables from functions which don't require their use? I understand how to pass variables as pointers and create local copies of variables. However, a problem arises when I have a variable that is used in many functions. For instance, when I create a player object or an item object, it needs to be passed from battle to battle, room to room, function to function, etcetera. Is it necessary to pass each object to each function, or should I create one giant object which holds every other object (this idea sounds ludicrous)...? Allow me to restate my question: How should I manage the scope of variables? And what about constants and enumerations? Should they ever be global? Thank you in advance, - John P.S. I don't mind doing some reading and refactoring :) EDIT: I wrote about a similar problem in a previous post, which I had forgotten about. Even so, I would like more information, even an exhaustive discussion on the topic, if possible.
--------------------Enigmatic Coding
Advertisement
Quote:I am eager to understand the design and structure of an exemplary program, and there is a lingering problem whose answer has been eluding me for ages. How should I hide variables from functions which don't require their use? I understand how to pass variables as pointers and create local copies of variables. However, a problem arises when I have a variable that is used in many functions. For instance, when I create a player object or an item object, it needs to be passed from battle to battle, room to room, function to function, etcetera. Is it necessary to pass each object to each function, or should I create one giant object which holds every other object (this idea sounds ludicrous)...?


In general, yes, it is best to pass anything that a function/object needs to it as a parameter. If you structure things in a modular way then there really shouldn't be many things that each function needs to know about. In fact that is one of the ways you can judge how good your design is. If you find your self needing to access something from lots of places then that object is probably doing to much and should be refactored. IMO having one giant object is one of the worst ideas possible as it violates the Single Responsibility Principle (SRP) and creates unnecessary dependencies.

Some Related Reading's.
Performant Singletons (Relevant to the "Giant Object")
Single Responsibility Principle
Open-Closed Principle
Liskov Substitution Principle
Dependency Inversion Principle
Interface Segregation Principle
Thanks for the reply.

I've read SRP and the Open-Close principle -- good reads. I especially enjoyed the idea about opening modules for extension yet closing them for modification. And this makes sense because it is important to create an interface which is flexible and allows expansion while guarding the programmer from certain data. The hard part is putting it into practice. I wonder if there are any exercises I could do to increase my understanding of the concept. I might as well try it in my game (after rereading the excerpt, of course).

Speaking of my game, it would only be logical to pass player objects to battles and rooms, and there would be no need to pass a sound object to a battle. I should just create it inside the battle itself, right?

A couple of questions:

Should I avoid 'nesting' functions deeply? (C++ doesn't allow the nesting of functions inside of parent functions. What I really mean is having one function call another function which calls another function, etc.)
Because the player carries items in my game, should the items be passed to each function that the player is passed?
Can enumerations be global, and how do you pass enumerations?

Regards,
- John

EDIT: I forgot to mention that I store my players in a vector, and I will do the same for items. I think that would be ok, but correct me if I'm wrong.
--------------------Enigmatic Coding
Quote:Original post by anothrguitarist
The hard part is putting it into practice. I wonder if there are any exercises I could do to increase my understanding of the concept. I might as well try it in my game (after rereading the excerpt, of course).


Try here?

Quote:
Speaking of my game, it would only be logical to pass player objects to battles and rooms, and there would be no need to pass a sound object to a battle. I should just create it inside the battle itself, right?


Right. Keep in mind that the idea in OOP is for Sound objects to represent *the sounds to be played*, rather than the interface to the hardware. Although I guess if your sound system required a really high level of control, you might end up with global Speaker objects or something o_O

Quote:
Should I avoid 'nesting' functions deeply? (C++ doesn't allow the nesting of functions inside of parent functions. What I really mean is having one function call another function which calls another function, etc.)


There are still at least two separate concepts here.

In terms of the code structure, just do what makes sense. But remember what makes sense: functions aren't intended as places to go next, but as components that can do useful work for you.

In terms of what happens at run-time, you do need to avoid nesting things too deeply. But it's very hard to cause a problem except by using recursion (and even then, the problem is usually an unbounded recursion due to forgetting or improperly handling the base case) or by using huge local arrays.

Quote:Because the player carries items in my game, should the items be passed to each function that the player is passed?


Generally, no: instead, have the function ask the player about those items. Be sure it really needs to know, though.

Quote:Can enumerations be global, and how do you pass enumerations?


Enumerations are *data types*, so they are *normally* global. :) You pass them just like you would pass ints.

Quote:EDIT: I forgot to mention that I store my players in a vector, and I will do the same for items. I think that would be ok, but correct me if I'm wrong.


Without knowing any more, it should be just fine.
Thank you, Zahlman.

Quote:Right. Keep in mind that the idea in OOP is for Sound objects to represent *the sounds to be played*, rather than the interface to the hardware. Although I guess if your sound system required a really high level of control, you might end up with global Speaker objects or something o_O


Lol. Actually I'm using fmod, so I don't have to worry about controlling the hardware. However, I do initialize fmod in my soundManager class and close it in the same class. Now that I think of it, that is clunky. Do you think I should have a separate class for initializing fmod, or should I initialize fmod in an init function?

Quote:There are still at least two separate concepts here.

In terms of the code structure, just do what makes sense. But remember what makes sense: functions aren't intended as places to go next, but as components that can do useful work for you.

In terms of what happens at run-time, you do need to avoid nesting things too deeply. But it's very hard to cause a problem except by using recursion (and even then, the problem is usually an unbounded recursion due to forgetting or improperly handling the base case) or by using huge local arrays.


In other words, functions are supposed to do a specific task, rather than being used as a goto statement... am I on track?

Also, I find that I can do most tasks with a loop rather than recursion, but I'm sure I'll have to use it someday.

Quote:Generally, no: instead, have the function ask the player about those items. Be sure it really needs to know, though.


So the player's inventory is stored in the player object, and I should only pass the player object to the battlefield... that makes much more sense (at least I think that is what your saying).

Quote:Enumerations are *data types*, so they are *normally* global. :) You pass them just like you would pass ints.


Should I store them in the same file that I store my typedefs? Or should I make a new file?

Regards,
- John
--------------------Enigmatic Coding
Quote:In other words, functions are supposed to do a specific task, rather than being used as a goto statement... am I on track?


Yes, functions are meant to perform a specific task, hence the name "function" :P
"If I were a philosopher, I might argue that an array name's type is not equivalent to its equivalent. But I'm not a philosopher, so when I suggest something like that, I'm not a philosopher; I'm only being equivalent to a philosopher.""Saturn ascends, choose one or ten. hang on or be humbled again." - Tool

This topic is closed to new replies.

Advertisement