Quote:
Originally Posted by Validius
Very true. Keeping scope small also leads to much more readable code. For example, lets assume you are debugging a function that was written with no global variables. In this case you know that all function input MUST be passed through the arguments given to the function at the time the function was called. Once you verify the integrity of the paramaters passed the scope of your debugging is entirely within that function because it is impossible that any data besides the originally passed paramaters had made its way into that function.
|
Another good practice is to indentify pointer parameters that won't change with the keyword
const. This allows the user of a function to know what is passed won't be changed by the function. If const is absent from the function declaration, the user can assume the data does in fact change inside the function. It also helps the function author in that the compiler can help enforce the constness in case the author accidentally tries to modify the data or forgets during changes to the function. Of course, this only applies to data passed via pointers since simple arguments are stack copies and it's only that copy the function changes.
Quote:
Originally Posted by Validius
On the other had if you have use of global variables then you have no conrtol over the data that the function is using. Vars could be changing mid-function making debugging work very hard.
Example: Your using variable x which is global. You call function process_x() passing it no args since x is global and you dont need to. At some point within function process_x you call another function process_y. Since its been a while since you wrote process_y you forgot that it tweaks the value of x. Because of this process_x starts screwing up and you spend WAY to long debugging it.
|
This is a good example. Using globals this way is a good way to not be able to see and understand what happens to the data. It also leads to a coupling the code to specific data and keeps the code from being as generically reusable as possible. A better way even if the data is global is to pass it as a parameter. A pointer to struct in the case of structures.
Another example, although this one there's not a lot that can be done about it and it is relative rare but does occur, is variables associated with interrupts. They need to be clearly identified with the
volatile keyword so everyone knows the value can change at any instant and if they're working directly on the variable, they need to protect it for the duration of use.
Yet another example which doesn't apply to RC code is multithreaded code or shared variables in multiple processes. All of what applies to your example applies to these types of applications in spades. You don't get a nice linear debug path to find where the data is changing.