Static Keyword in Object Oriented Programming

First a disclaimer: I am by no means a well worldly experienced coder. I can write, I can code, I am rather good (in my humble and very small opinion) at puzzling through the ways to do something in code. By no means am I a master or guru. Part of this blog post is to share my thoughts - the other is to work through them and, if there are ever comments, learn from any mistakes in my thought process.


It is amusing to me, when I go to think about the structure of a project I am working on, sometimes I completely forget that a class or object can be Static, or I want to make something Static that really should never be.

First, let’s get the basic’s out of the way. What is a Static Object? In C# (Where I do most of my programming, so this is where my thoughts are coming from). There are tons of definitions and ways to explain what it means to make a Class or Method Static, but this is by far one of my favorites; From Techopedia.com:

Untitled-3.png

Static, in C#, is a keyword that can be used to declare a member of a type so that it is specific to that type. The static modifier can be used with a class, field, method, property, operator, event or constructor.

A static member of a class can be used to keep track of the instances created and maintain common data to be shared among all instances. It can be used in helper and utility classes, which usually contain generic methods that contain abstractions of pure logic. A static constructor is used to make entries in log files, as well as in wrapper class to load the dynamic link libraries (DLLs) required to execute unmanaged code.

In general, a static modifier can be used with data and functions that do not require an instance of a class to be accessed. It is mostly used when the data and behavior of a class do not depend on object identity. The use of static classes and members improves code efficiency.

I like this definition because it uses the phrase “abstractions of pure logic”. So many times I’ll see while diving through Stackoverflow or various tech forums someone answer to a question is “Just make it static.” Usually the question revolves around something like “I have two classes, and I want one to be able to reference the other inside…”

The insidious thing that seems to latch it’s temptation dripping claws into programmers making this reply is that Static can be accessed anywhere and everywhere in your code. This little fact just seems to scream “Yes! Use me!” when a coder is having trouble figuring out how to divide up their methods and their data. In my (limited) experience, if you are having trouble with making use of data between two different objects, then your code structure needs to be redesigned.

For myself, I am of the opinion that data - in the form of Properties - should rarely, if ever, be stored in a Static Class. That data will be available everywhere, which makes it very tempting for something like a boolean that a valid user has logged in, or a universal bit of data that needs to be shared during one running of the program between multiple different objects. In the case of a boolean of user validity, it is very tempting to store it in a static object somewhere and just reference it at every point that needs to know if the user has the valid authorization to use that part of your program. (Isn’t this just what a Cookie is after all?")

This is a huge trap. That data can be changed anywhere and a coder may forget they did. They may forget in one instance to clear it when it needs to be, and then when another method goes to use it’s still sitting there, with the wrong set of data in it. 

To reference the Techopedia definition: Dynamic user dependent Data is NOT ABSTRACT.

Wrapping one’s head around what constitutes an Abstract bit of Data or Method is a difficult task! To me it is/was almost as difficult as the first time I started to use Test Driven Development procedures and trying to wrap my head around starting at the big picture and working down - without knowing what it will look like beforehand!

I have over the past week been googling around the web for articles on when to and when not to use Static objects and methods. Most of the links I click on are about the same: They say things like “It is slightly faster, but not in really a noticeable way” or “This is the definition, and things like the Math class are good for Static.

Nothing really seems to give any good examples that are broad enough to be iterated or expanded upon by a generic coder trying to learn their way through Static. (Which is another blogpost for another time - the difficulty in using some tutorials to learn the why, not just the how)


Note: This assumes you are starting a project fresh and you get to make all the choices in the way it works together. If you are in a group, as most projects are, you may not have that luxury. If you are inheriting an old code base… you most certainly do not have it. Sometimes, you have to do things less than the “Perfect Right” way, just to get it done. Don’t get hung up on the Right Way when you have to make it work too!

For me, I follow these rules when deciding to make a class or object Static.

  1. Does it contain no data that I need to reference often, and that data may be fluctuating by the user? If it doesn’t, then It has the potential to be Static.

  2. Does it only contain Methods that modify and return Data? Are any properties in it private or read only? This may be a good choice for static!

  3. Does it do the same thing, every time, and needs to be called at the same time, every time? Like a set of methods that set up everything in a directory structure, or connect to a database? This is a good case for Static… and Using! (Thinking of you, Entity Framework connections!)

Untitled-3.png

#1 there is by far my most defining thought on Static objects. If it contains any actual data (properties) not just methods, then that data better not ever need to be changed during the course of the program’s run or there is simply too great a chance for the data to be changed when it wasn’t supposed to or 

Let’s consider an exercise I’m working on.

It is a Grocery store receipt - In short, I need to program something that can take an item and a price and calculate the total of all things bought that day - a receipt. Simple enough, but the challenges in this particular exercise are that there are sales that need to be taken into account. Markdowns, BOGO, Discounts on more than one, and limits on how many items can apply for that discount. The final big restriction is that all the data for item prices and discounts needs to be held in memory - no database. Finally, I need to be writing this code from the concept that it is part of a larger structure of code, and will have a pseudo “API” for accessing the receipt functions from code outside this library (presumably a register).

Without a database, then that means I need to have an object that stores the names of items and their price, plus whatever sales are applicable. Logic dictates that I have a separate object that is my Receipt. How does the Receipt get the cost of an Item? 

There are three ways I can think of to go down this path.

Untitled-3.png
  1. Make the object holding the prices and discounts static. It would mimic a database then, always available. 

  2. Create a new instantiation of the object holding the prices, add all the data to it, and pass it through as part of the Constructor for the Receipt Object.

  3. Use a method in the object holding the prices to return an ItemObject, and pass that ItemObject through to the Receipt for buying/voiding.

#1 seems like the best situation here. It would mimic a database (which would be my preferred method of handling this exercise if it wasn’t for the restriction). It would always be available. I would only have to set it up once. I could make sure I was using the same price data for every single test.

There are two problems with this. First, if we are doing Test Driven Development procedures here (which I am, it's part of what I’m doing the exercise for) it makes it much more difficult to write tests for the fake database. If it is static, holding data, and I want to test a method for adding a new item to it… well the static version hasn’t changed since the last test. If I want to test adding a markdown to an item, or changing its default price… that will change the data for every other Test I wrote for this class.  This problem is a bit more abstract than one having to deal with real world applications - I can manipulate the Tests to work around it (building or tearing down the static object before and after each test for instance) but it is a lot more work than simply having a single “Setup()” method to build a quick fake repository of item prices and use that in every test, along with one or two unique situations for that particular test.

The second problem is, given this is supposed to mimic an API - how would a programmer know that the data for item prices is going to be just freely available to the Receipt part of the library? A whole new set of methods would have to be written to translate the foreign data - however it may be stored - into what is needed for the Receipt to access it.

Options 2 and 3 are just different levels of abstraction. Do I write the receipt expecting to receive items or expecting to receive a way to access any item I need at any time? Either is rather valid.

I chose the second way - pass a fully formed object of all the data regarding prices to the Receipt. Use methods on the object of price data to get prices into the Receipt (Data.PriceCheck(Item) for instance).

There are two reasons I chose this over simply passing a single Item to the Receipt Object.

  1. By passing an entire set of data, It makes it much easier to change both the Receipt code and the Tests to use a connection to a database instead of item data. Changing the Receipt Constructor to require, say an Entity Framework style connection instead of a fully formed object would require only a few lines different, and as single method to populate the now internal to Receipt ‘ItemRepository’ with the necessary information from the database.  Distinct. Compact. Encapsulated.

  2. By passing the data wholesale, I can draw out a single ‘Item’ to add to the Receipt for each one added. However, that Item can now be different than one that, from the outside, may look the same. For example, if there was Milk on sale for Buy One, Get One Free - the first milk added to the receipt would have the original price. The second milk - because I have the data for the sale already inside the receipt - would be added as a new Item with a different price. This allows for easier calculation of the price, and much easier in removing items from the Receipt.  Again. Encapsulation.

Finally, where would I want to use a Static class for this exercise? With the parameters as is, truthfully there isn’t a place I could see to use it. However, if you take this to it’s logical next step, a Static object containing methods to convert a Database of items and prices and sales into the internal object holding it for use of the Receipt would be ideal. The data that would be being converted would be outside the reach of this library to change, and it would need to be done the same way every time. Perfect for a Static class of methods to add the data to an internal object to be manipulated.

There is another place that could make use of a Static object. Sales. With all the various kinds of deals that have to be calculated, how does one go about doing it? I chose to have a few methods that take the basic Item, with data listed in its properties of what kind of sale it is part of, and then use a few methods to find out how many items are currently in the receipt, does adding this one make it work for a sale, if so change the price, ect. These methods would work well in a static object of their own - that would make them distinct and encapsulated from the Receipt. Which honestly, does a Receipt really need to know all about the sales? No, it just needs to know what this item costs. It doesn’t care if its the first can of tomato soup or the 150th, as long as it has a price. A Static Sale object could be used to do that, keeping the code clean and distinct.

Overall, this is just an exciting and interesting dive into what it means to be Static and why one would - or more likely than not in the onset of my opinion wouldn’t - use it. I can only hope that I didn’t make any egregious mistakes or assumptions in my methodology here (and if I did, please point them out so I can learn from it!) and that anyone who comes to my quiet corner of the web to read this takes something away from it - positive or negative - and adds another bit of knowledge to their toolbox.

Previous
Previous

COVID19 and Stretching your Buck For Food

Next
Next

Redbeard's Black Sea's Barracuda: Set #6285