At the opposite end of complex designs, you may find programs that use too few abstractions hiding a number of assumptions deep inside the code. Two chief and easily recognizable culprits in this area are fixed buffer sizes and magic numbers. Although nowadays C++, Java, and .NET come with a feature-rich container framework, one can still find code that instead of using the platform’s vector container—which implements a growable array of objects—it declares a fixed-size array. The number of elements that the array will hold is hidden within the code, and the reasons for choosing that particular number are often similarly hidden within the programmer’s mind. This code will crash when it faces more elements than those originally planned for, and in some cases, it may even expose the program to a buffer overflow attack.
Numbers appearing out of the blue don’t only occur in array declarations. They come in many shapes and sizes, and they are aptly termed magic numbers. We can’t avoid them, because at some point we do need, for example, to specify that TCP packets are identified by the number 6, and UDP packets by the number 17. However, directly embedding these numbers in the code makes the code difficult to understand and maintain.