Clean Coding and Arduino, Global Variables and constants

Just a question on best practice when writing an arduino program.

As my program gets larger i am beginning to find that i am getting a long list of global vars at the beginning of my program.

My question is, for readability, and portability, would it be better practice for me to place global vars and constants that are only used in one function, next to the function that they are used in?

From what i have read it is best practice to keep variable declarations close to where they are used.

I would still keep variables and constants that are used throughout at the start of the program, before setup() but after includes.

What are your thoughts on the matter?
What would be the clean code standard?

Ben.

The question you should be asking is “Why have I got so many globals?”

Benny_H88:
My question is, for readability, and portability, would it be better practice for me to place global vars and constants that are only used in one function, next to the function that they are used in?

From what i have read it is best practice to keep variable declarations close to where they are used.

Not just next to the function they're used in. Inside the functions they're used in. It makes them non-global, but that is usually a good thing.

There is more benefit to it with large programs than small ones. I follow the practice of placing all globals at the beginning. Just so you don't have to hunt for them. The reasoning behind that is, a global is global because it's used in many places. So there is no other placement in the code that should have any particular significance.

When a variable can be declared inside a function, that is where i put it.

Thing is every time the function is exited the local variables are disposed of. So if i need to keep it, then it gets removed from the function.

but should i put these variables near the function, or should i leave it at the start??

Thing is every time the function is exited the local variables are disposed of.

The statics aren't

should i put these variables near the function, or should i leave it at the start??

Either way will work but as has been suggested it is more convenient to group all global variables at the start of the program. Equally important is to give all variables meaningful names.

Almost all of us agree than minimizing the number of global variables is a good idea. I also agree that, when you do use them, place them and any symbolic constants (e.g., #define's or const's) near the top of the source file.

Globals make debugging harder because every element of the program has access to your data. It's like putting a prostitute at the top of your source file and then handing out $50 bills to every assignment operator in that file. It makes it very difficult to know who the father of the error is. By encapsulating the data definition inside a function (or smaller scope) block, at least you have some idea of where the data gets changed. After all, the hardest part about debugging is isolating the error. Correcting it is usually pretty simple.

Lol, thats quite the analogy!

I had wondered the purpose of the "static". I'll go put it to use.

I'm definitely all for descriptive variable names.

Thank you all for your input.

I’ve been teaching for over 40 years and have found that, the more outrageous the example, the more the students remember it. Hope I didn’t offend anyone…

Another option that you may want to consider is to create a structure with all the global variables in it and then declaring a variable 'G' of that type. It takes a bit more setting up but it helps make all global data explicit as it is in the structure and is referenced as 'G.variablename'. Where you put the definition is then a moot point as the variables are clearly segregated.

This is a variation on the the old Fortran 'COMMON' block for those that remember that far back.

Interesting how a question about WHERE to put global variables got answered “global variables are bad karma”.

I have not teach for many years, but know something about staying on topic.

I’ll give you “F”.

Who got the F for being off topic?

Here is an interesting document to read: http://www.atmel.com/images/doc8453.pdf#page=5

Vaclav:
I have not teach for many years, but know something about staying on topic.

I have never taught (apart from specialised training courses), but I've noticed that those who I consider to be good at teaching know how far "off-topic" to allow a discussion to go, because they always manage to use the "off-topic" to illustrate the "on-topic", before steering the discourse back on-topic.

It's a programming question, Vaclav, in the programming section of the forum, which has, as part of its header "Understanding the language"

If you have many global’s, that you do not think will be useful as local variables, you can still keep them from cluttering the global namespace.

This will make it less likely that in the future, you’ll declare a local variable of the same name, and confuse yourself as to which you are using.

namespace sensorData{
  long lastReadingMillis = 0;
  int sensorTimeout;
  int temperature = 0;
};

namespace appData{
  bool loaded = false;
  //...
};


void loop(){

  if( !appData::loaded ){

    Serial.begin(9600);
    sensorData::sensorTimeout = 1000;
    !appData::loaded =true;
  }

  // You can also use a namespace in a function which needs it.
  // This means you can keep the variables out of the global namespace
  // and still access them easily where needed.

  using namespace sensorData;

  if( millis() > (lastReadingMillis +sensorTimeout)  ){
    
    temperature = readTemp();
    lastReadingMillis = millis();
  }
}

But if its easier, you can still write you code so you can tell local and global apart. This is not recommended (see below this example).

int foo;

void bar( int foo ){

  foo = 1;    //Function parameter.
  ::foo = 2; //Global variable.
}

A good reason I have found why you should avoid global namespace ‘global’s’, is, when a library or chunk of code has used the same name in a ‘type dependent’ object. Using a variable name that is obscure enough to not be reproduced is only an assurance, not a guarantee.

I posted an example here, with more info in the later posts: http://forum.arduino.cc/index.php?topic=124367.msg939621#msg939621

However here is the test code if you’d like to see it in action:

   //A global
   int i = 666;

   //A small object.
   template <typename T> struct Base{
     Base( int i_NewVal ) : i( i_NewVal ) {return;}
     int i;
   };
   
   template <typename T> struct Squared : public Base<T>{
     Squared( int i_NewVal ) : Base<T>( i_NewVal * i_NewVal ) {return;}
     T Result() { return i; }
   }; 

  void setup()
    {
      Squared< long > s_Square( 2 );
      
      Serial.begin( 9600 );
      Serial.print( "2 squared = " );
      Serial.print( s_Square.Result() );
      return;
    }
    
  void loop(){return;}