Avoid magic numbers

Hard coding number literals into code is generally considered a bad idea. The problem with using a number literal instead of a named constant is that the purpose of that number is unknown to the reader. The number appears in code as if by magic. Consider the following code:

M5Object* pUfo = M5ObjectManager::CreateObject(AT_Ufo); 
pUfo->pos.x = M5Random::GetFloat(-100, 100);
pUfo->pos.y = M5Random::GetFloat(-60, 60);

It is hard to know why those four numbers were chosen. It is also hard to know how the program will be changed if the values are modified. Code like this would be much more readable and maintainable if the named constants or variables were used:

M5Object* pUfo = M5ObjectManager::CreateObject(AT_Ufo); 
pUfo->pos.x = M5Random::GetFloat(minWorldX, maxWorldX);
pUfo->pos.y = M5Random::GetFloat(minWorldY, MaxWorldY);

After the change, it is much easier to understand that the position of the new UFO is being randomly placed within the world. We can understand that if we change the values, the possible starting location of the UFO would either be outside of the world, or constrained to a tighter rectangle around the center of the world.

Besides being hard to read and understand, using magic numbers makes the code hard to maintain and update. Let's say we have an array of size 256. Every loop that needs to manipulate the array must hardcode the value 256. If the array size needs to be larger or smaller, we would need to change every occurrence of 256. We can't simply do a find and replace because it is very possible that 256 is used elsewhere in the code for a completely different reason. Instead we must look through every occurrence of the number and make sure that we are changing the code correctly. If we miss even one, we could create a bug. For example, if we are changing the size of the array to something smaller, such as 128. Any loops that still treat the array as if it had size 256 will cause undefined behavior:

int buffer[256]; 

//Some function to give start values
InitializeBuffer(buffer, 256);

for(int i = 0; i < 256; ++i)
std::cout << i " " << std::endl;

As before, it is better to use a named constant instead of a magic number. The constant is more readable and easy to change because it only needs to be changed in one place. It is also less likely to cause bugs because we are only changing the values associated with the array. We won't accidentally change a value we shouldn't or miss a value that we should change:

const int BUFFER_SIZE = 256;  
int buffer[BUFFER_SIZE];

//Some function to give start values
InitializeBuffer(buffer, BUFFER_SIZE);

for(int i = 0; i < BUFFER_SIZE; ++i)
std::cout << i " " << std::endl;

Another important reason we don't want to use magic numbers is that they are inflexible. Throughout this book, we try to emphasize the benefits of reading data from a file. Obviously, if you hardcode a value, it can't be read from a file. In the preceding example, if BUFFER_SIZE ever needs to be changed, the code needs to be recompiled. However, if the size of the buffer is read from a file at runtime, the code only needs to be compiled one time and the program will work for buffers of all sizes:

int bufferSize = GetSizeFromFile(fileName);  

//we can Dynamically allocate our buffer
int* buffer = new int[bufferSize];

//Some function to give start values
InitializeBuffer(buffer, bufferSize);

for(int i = 0; i < bufferSize; ++i)
std::cout << i " " << std::endl;

delete [] buffer;//We must remember to deallocate

In the preceding example, we must remember to deallocate the buffer. Remember, that probably won't be the usual case because for arrays, we could always use an STL vector. The more general case is that we are reading ints or floats from a file. These could be used for anything from screen resolution, to player speed, or even the time interval between spawning enemies.

As with all rules, there are a few exceptions or special cases where it might be fine to hardcode numbers. The numbers 0 and 1 are generally consider OK. These might be used as the initialization values for ints or floats, or just the starting index for an array.

Your goal is to make your code as readable and flexible as possible, so a named constant is almost always going to be better than a hardcoded number. Do your best to make sure that your code can be understood by others. Your code isn't more readable if you simply have a variable named ZERO or TWO, so you should use your best judgment and perhaps ask another programmer if you think the meaning is unclear.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.189.186