I will discuss a production issue due to a static keyword and why we should avoid it as much as possible in Object oriented programming. One day, we suddenly started experiencing thousands of high-priority alerts in one of our applications. The exception was related to a queue not being able to process messages. A week prior, we created this queue for a feature, and everything has been running smoothly until now. What happened suddenly after a week? I looked to figure out the issue with the new code, but it turned out that it was all due to a static keyword in the legacy code. Let’s see how one static reference wreaked such havoc.
NoStaticInOOP

What is Static?

Static is a keyword in java, C#, etc. and can be used with methods, blocks, variables and nested classes. The apparent meaning of static is “stays the same”. A simple way to understand the static in Object Oriented Programming is that it is the same reference for all the class instances. You can access a class’s static method and variables without creating an object of the class by simply using the class name.

We must remember these essential properties about the static: static variables are initialized only once at the start of the execution and have a global state and scope. Global scope means accessing it from anywhere, and Global state means maintaining the state across all class objects.

Static is primarily used for managing memory but has more significant pitfalls than benefits. You can access static members using their class name, which you cannot change at runtime. Thus, static does not allow you to use polymorphism, making it challenging to support the open-closed principle, one of the SOLID principles. With a static member in a class, an instance now relies on a global variable(static variable), and it won’t be incorrect to say that it has lost control of its state. Different instances can modify each other’s state with static members. Testing also becomes inflexible with Static members as you can only test one feature or object in isolation; everything is integration testing with the global state.

Alright, but why the system sent messages to the wrong queue?

Let us see the code to understand it easily. It is a sample code representing an identical situation in our application.


/* This is excerpt from out Storage class where we create a queue */
private static CloudQueue _queue;

public StorageQueue(string connectionString, string queueName)
{
	try
	{
		var storageAccount = CloudStorageAccount.Parse(connectionString);
		var queueClient = storageAccount.CreateCloudQueueClient();
		_queue = queueClient.GetQueueReference(queueName);
		_queue.CreateIfNotExists();
	}
	catch (StorageException ex)
	{
		throw ex;
	}
}

Since the queue reference was static(private static CloudQueue _queue) and had a global state, the “_queue” was initialized and connected to a incorrect queue and messages were pushed there. It is tough to predict the value of the Static reference variables in a multi-threaded application running in production. In conclusion, we should always avoid using static. An easy rule of thumb is if there is any reason to consider that something will change in future, then you should not use static.

Learn more about Azure Queues here, Learn more about Static Keyword here