Virtual Developer Workshop: Containerized Development with Docker
If there's one thing I see, get asked many, many times especially by new developers working on .NET and that's the age old question of:
"How do I know when it's appropriate to use a static construct?"
Well, to be perfectly honest, in all the years I've been writing .NET code, I still ask myself the very same question. Not quite with the same frequency I used to, granted, but I do still ask myself, especially in the first incarnation of a bit of code.
So, does this mean that the question can't actually be answered? No, not at all; it just means that it's one of those things that you have to evaluate for every single project you do. As you gain experience, you'll learn to instinctively recognise certain patterns, patterns that will start to steer you towards good design in your code, and, like me, the frequency with which you ask yourself the question will start to diminish.
The underlying question however, well, that's a different thing entirely.
Why on Earth Is It Such a Hard Question to Answer?
In my mind, this stems from the fact that many developers don't really see, or understand, the differences between Static and Non-Static constructs. Myself, I originally did advanced-level C++ back in the 1990's and, for a C++ developer, understanding this concept was part of the mantra of being a C++ developer. In today's world, however, with nicely typed languages such as C#, the lines have become a little more blurred.
Many of the newer developers I speak to and read questions from seem to be of the persuasion that static means exactly that. It stays in one place, and as such, the run-time doesn't have to check where/how to call it, and so access is generally faster. Well, there is an element of truth in that, but it's also by no means the full story.
The Full Story...
The biggest underlying difference is that static classes are NOT instantiated. That is, you can use them without having to 'new them up'.
Now, to some, this might seem counter intuitive, especially if you've been trained in the more modern "text book" ways of object-orientated software development, where you're taught that all objects should be 'newed up' when needed and disposed of when finished with.
Let's just stop to think about this for a moment.
Without the ability to use static code, patterns like the Factory & Singleton patterns wouldn't be useable, or, at the very least, they would be so complicated that it would be easier to do things different ways. Without the ability to use static code, all your utilities would have to be re-created every time you wanted to use them, not at all fun from a memory perspective.
And, many other patterns and practices we employ today would be wholly impractical and difficult to follow.
So, Why Is It So Hard to Decide?
Because software development is hard, the .NET environment tries to hold your hand as much as it possibly can, and to a lesser extent you have an enormous amount of power and flexibility at your finger tips, but you, the developer, still have to make decisions that may or may not break your project. The key to making this task easy is not answering the questions like "Static versus Non-Static," but more about looking at what .NET has available to help you achieve your given task, and architecting your solution with a lot of thought and experimentation.
Don't be afraid to sit down and code both a static and a non-static version of a routine you have in mind, and then test both of them, in production if you have to. Find out which one works best.
Me, personally? Well, I find using static code works best when I have common abstractions that I intend to use in multiple places. In fact, if I have multiple code that's used across multiple projects in a solution, I'll even put that code into a purely static class library in a project all of its own, and then reference that where needed.
If I find that a given class needs some initialisation, however, for example a POCO that has a generic collections list in it, then making that non-static is sensible, because then you can create a constructor that initialises said list with an empty list. Doing this means that you know, in the future, every time you new up a copy of that object, you're going to have an empty list ready to add and remove things to/from.
Of course, this is not the absolute be all and end all of this, not by any stretch of the imagination.
A singleton, for example, combines both approaches. It provides a static, always-callable entry point, but in the background if it needs to be. It will new up a concrete instance of any object that it makes use of, and then return via the static interface the reference to that object.
To answer the question, experimentation is the key. Find out which works best for the project you're writing.
That's all for this week. We'll get back to something a bit more technical in the next post. Until then, keep on coding.
If you have any suggestions or ideas for posts you'd like to see, please feel free to reach out to me on Twitter as @shawty_ds, or come and hunt me down in the Lidnug Linked.NET users group on Linked-In that I help run. I'll be more than happy to produce posts on specific topics of interest.