So I came across this issues today and I couldn't find some meaningful explanation is there some non-subjective reason to use static methods when it comes to database interactions.
Right now I'm working on a project where everything is made through stored procedures and for example I have some regular methods like :
public void Delete(int clientID)
{
//calling store procedure
}
or
public void Save(int clientID)
{
//calling store procedure
}
but I also have :
public static Client GetByID(int id)
{
//calling stored procedure
}
or
public static int AddNew(string firstName, string lastName...)
{
//calling store procedure
}
and since I'm working with .NET for about 9 months and I've been using only Entity Framework and Repository Pattern I can't recall anywhere or any code where static methods were used. Not for standard CRUD operations, neither for more specific tasks related to the database.
So is this something related to the particular way that the database is accessed, is it some practice that can give (even a very small) performance boost, or it's just the developers approach and I shouldn't give it much of a thought when and when to not use static methods in my database related methods?
In the particular case of a data access layer I'd avoid static methods for one simple reason... coupling.
Static methods can't implement an interface, instance methods can. By using static methods one is essentially insisting against coding to an interface and instead coding to an implementation. Thus, everything which uses this data access layer is required to this this specific data access layer at all times.
No alternate implementations, no test stubs, no dependency inversion at all. The business logic has a dependency arrow pointing to an infrastructure concern (the data access layer), whereas that should be the other way around.
Additionally, it seems like this at least carries a greater risk of having problems with the disposal of resources. That might not be the case here, but it's really easy for it to become the case. What if a developer somewhere down the road has the bright idea to extract common lines of code into a class-level static method and property? Something like the Connection or DBContext object? That'll create some very interesting and very difficult-to-debug run-time errors.
On the other hand, if repositories were instances then they can simply implement IDisposable and make sure any class-level objects are correctly disposed.
Continuing (I guess I had more objections to the design than I thought), this feels very counter-intuitive to me from an object-oriented sense. Perhaps this one is just personal preference, but this is turning what would otherwise be a "repository object" into a "dumping ground of DB helper methods."
In a system like this I would expect the number of random one-off methods to grow significantly over time as developers make quick solutions to meet requirements without thinking about the overall architecture. Instead of a consistent and well-managed series of objects, you could very likely end up with a bloated and difficult-to-follow codebase.
Static methods are used when there is either no state, or shared state. If you have code that is merely calling stored procedures, then it may have no state other than a shared database connection string. This would be a valid use of static methods.
I think your last statement is correct; its just the previous developers approach.
I will say, though, that having those methods static is going to make your life a nightmare to create a testable product; if you have the power to change them to be instance based and create a set of unit tests that can test the app via mocks without needing a database it'll make your life easier in the long run.
We very rarely use them here in our company, although they can serve a purpose in utility classes or things of the sort that are simply calling functions. Depending on how many instances you would expect of a non-static class, they can also affect performance., but that would need to be a notable instance difference.
source - MSDN
Related
Im have a question.
I have just started a job with a new company that has one "Senior developer".
In a class he is doing this (Example):
class CarController{
public Cars GetCars(){
**Connection connect = new Connection(); // Create DB connection**
//and here some fetching of the data and returning it with a HTTP Response
}
public Cars GetCar(int id){
**Connection connect = new Connection(); // Create DB connection**
//and here some fetching the car with id, returning it with a HTTP Response
}
//and this pattern continues here...
}
I cant imagine that this is a good practise to keep creating the same instance of a class in each and every method to make call to the Database??
Isn't it also bad for the memory to keep creating instances everywhere?
In my opinion here we could use the repository pattern and only give access to the database class to the class the implements the Interface.
Right now we expose the Database class to the controller and the code is tight coupled!
He says that he cannot understand the concept of the respository an why Interfaces should be used in this case.
How do you convince a senior to refactor the code and also prove to him that his coding has no good structure?
How can i explain the cons in his code above in another way?
I cant imagine that this is a good practice to keep creating the same instance of a class in each and every method to make call to the Database? Isn't it also bad for the memory to keep creating instances everywhere?
It actually IS the best practice in this case. .NET pools database connections, so creating them generally isn't an expensive process. Reusing connections, however, can cause problems.
However, you should be disposing the connection as soon as you're done with it. A handy way of doing that is with a using statement:
using(Connection connect = new Connection()) // Create DB connection
{
//and here some fetching of the data and returning it with a HTTP Response
} // the connection is closed and disposed of here.
In my opinion here we could use the repository pattern and only give access to the database class to the class the implements the Interface. Right now we expose the Database class to the controller and the code is tight coupled!
Sure, that might be an improvement, but it's orthogonal to your first question. The repository should create the connection when needed and dispose of it when done.
How do you convince a senior to refactor the code and also prove to him that his coding has no good structure?
If you've just started, you might not be able to if you approach it that way. Just remember that most people (regardless of experience) don't like others to criticize their work. Instead, offer an alternative solution and offer some reasons why it's an improvement over the current design. A pragmatic approach would be to provide a situation in which the pattern in place causes problems (unit testing is the most obvious) and illustrate why a different design would solve that problem.
Instantiating objects directly isn't always bad
Creating object instances without using an IoC container is not always bad (imagine if we used Container.Resolve every time we wanted to create a string!) If a dependency is not a volatile dependency then it may not be a great candidate for DI.
No it is not expensive
Creating and disposing database connections over and over is not expensive (they are allocated from a pool and kept open anyway) and in fact is considered best practice.
Inject a DB connection?
In the case of a database connection, that connection must be tightly handled and disposed in a quick timeframe, so there is an argument to be made not to inject it. You certainly would not want the caller (or the composition root) to instantiate the connection and then require the consumer of the connection to Dispose it; that is a violation of of two commonly-held principles:
Scope that creates an instance should also destroy it
Injected instances should have longer lifespan than the object using the injected instance
Inject a factory?
Perhaps you could inject a database connection factory, but this is a little problematic because IDBConnection doesn't contain all the members found in SqlConnection. So if you want to use DI here you'd either need to supply a concrete instance (which is sealed, by the way, so no shims) or you'd need to strip away all the SQL-only features from your implementation. Same is true of SqlCommand -- IDBCommand only has a very small subset of the properties, and none of the async methods at all.
What would it gain you?
Would it get you loose coupling? Not really. You'd have sort of a fake loose coupling, but there is an implicit logical coupling between the data access classes and the SQL server database (for example, they have a schema in common). It's not like you could replace your SqlClient with an OracleClient and expect it to work. I've seen lots of folks try it, for years; if you are still trying you haven't caught on. It doesn't work. A feature-rich database client is going to have some hard dependencies on the database platform, period.
Would it be easier to unit test? Not sure. As I noted above, you can't really write shims or stubs because the SqlConnection, SqlCommand, SqlParameter, etc. are all sealed, and all have concrete methods not found in the interfaces. so no matter what, you are still going to be stuck mocking instead of stubbing.
What is the long term plan?
Maybe the plan is to replace all that low level SQL stuff with an EF at some point in the future. If so, it would be waste of time to retrofit DI into the DAL at this point, because it would all be thrown away in the end.
My conclusion
This is a judgment call. Your colleague is entitled to make it. I would focus on other, more obvious, lower-hanging fruit for refactoring.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I'm trying to learn the correct way to use classes in my code, when it's not something obvious like a set of customers, dogs inheriting from animals, etc.
I've broken off large sections of code into "features" such as Installer.cs, Downloader.cs, UiManager.cs. The only way I can find to have those classes interact with each others' properties and methods is to make them all static, which I've been told in another question is the wrong way to go.
So my problem is one of 3 things:
There is a way to make classes talk to each other that I just don't understand yet.
Classes should never try to talk to each other, but perform one-off actions and then return something back to main/form1, which the main class can then use to pass into another class for a one-off action.
Classes are really only useful for making lots of instances, and there's some other structure entirely I need to learn about for abstracting large chunks of functionality out from the main class.
All the tutorials I can find and lectures I watch seem to only tell you how classes work, but not when and how to use them in a real product.
EDIT - A more specific example:
Say I have one string that is central to the entire app, and needs to be seen and/or modified potentially by every class. How do I move that information around the code without either having everything in one class or making it static?
I can't see a way to let that string live in Form1 without making it static (because all the form events and functions would need to be able to see it to pass it to a class).
I can't see a way to put the string into another class without having to make the string and the whole class static, so other classes can see into it.
Maybe there's something I'm missing about actually instantiating the classes, and making objects interact with each other.
I think all your intuitions are right.
No, there's not. Static or instance.
It's a design choice (and there's a lot out there). I'm a pragmatic, so I consider a design pattern that generates spaguethi code a bad design pattern choice. But a bad design pattern for a project can be a good design pattern for another project. Try to read the Head First Design Pattern book.
Yes, there are interfaces and abstract classes.
A few more thoughts:
I don't think the use of static methods or classes must be avoided. What must be avoided is the miss use of a static method or class, like the miss use of everything inside a language. But is very hard to define what's a miss use of a static, and because static methods or classes are particulary dangerous, people like to say to avoid the static keyword at all. A static method will be in memory unless you end your application, so if you don't dispose a connection inside a static method, you will have a very bad day.
I have a utility project, and inside the utility project I have a data class. The data class provides access to the database. It's a static class. Why?
Well, first of all, it is static because the connection string comes from the webconfig. So I have a static constructor (runs once when the application starts and the class is mentioned) who reads the webconfig and store the string in a static private member variable. I think it's a lot better than read the webconfig file and create a scoped variable 10 bilion times day. The methods are static because they are simple enough, meaning that they don't need a lot of configuration to work, they just need a few parameters and they are used only in the data access project. All my website users are using the same instance of the method (the static one), but everyone uses the static method with different parameters, so they get different responses from it (they share the pipe, but they drink different water). It's only necessary extra care inside the method to clean everything (dispose every scoped instance), because if you don't they will stay in memory. And finally, my bussiness is about data manipulation, a non static data class means a lot more memory usage than a static one (the cpu usage is almost the same in both patterns).
public abstract class Data
{
[...]
static Data()
{
#if DEBUG
_Connection = ConfigurationManager.AppSettings["debug"];
#endif
#if RELEASE
_Connection = ConfigurationManager.AppSettings["release"];
#endif
[...]
}
[...]
}
In the end of the day I use static when:
If it is simple enough (that I can control every aspect);
If it is small enough (I use extension methods to validations, and they are static) and;
If it is heavy used.
Besides that, I use layers to organize my project (poco + factory pattern). I have a utility project, then a entity model project, then a access project, then a bussiness logic project, then a website, a api, a manager, and so on. The classes in the utility project don't interact each other, but the classes inside the entity model project do (a class can have a instance of another class inside it). The entity model project don't interact with the utility project because they have the same level, they interact each other in another level, in the access project, but it's more intuitive in a data manipulation project.
Classes talk to eachother when they have a reference, in order for A to pass a message to B, A needs a reference to B (either an instance or static reference)
Classes can either talk to each other, or return information to another class that controlls the whole process (this is actually a design pattern)
For abstracting information from the main class (or any class) you have interfaces and abstract classes
The Design patterns book from the Gang of Four it's a must read in this case.
Something else to keep in mind beside is the simplicity of your design, sometimes trying to fit to a design pattern just cause may end up creating more spaguethi code. As a rule of thumb always try to sepparate the presentation funcionality from the logic, and think of classes as persons talking to eachother and performing jobs (it's kinda weird iknow but sometimes it helps me to think this way)
I'm currently developing a C# MVC REST web api, and am trying to choose between one of two possibilities for our design.
Without getting too deep into our design, we intend to have a class for data access, which we'll call DataSource. Each DataSource will need to execute small, contained blocks of logic to correctly build an appropriate response. Due to a desire to be able to hot-load code in the future, we don't want to simply have these be functions on DataSource, instead we'd like them to be provided by other assemblies. We have a proof of concept of this implemented, and so far, so good.
What I'm trying to decide between is writing a static class with a single static ExecuteQuery function, or writing a factory method to create instances of these classes, which have an instance method called ExecuteQuery.
What are the performance considerations between creating multiple, short-lived objects every request, vs calling static methods?
Intuitively, static methods would be faster, but I'm already expecting that I'll run into a bit of a headache calling them through reflection (to support the hot-loaded code requirement).
If there's not a huge penalty for short-lived objects, then they might win out on simplicity alone.
Relevant information about our expect loads:
Response times in the 300ms - 800ms range
Average load of about 2000 web clients
Peak load of about 4000 clients
Clients doing queries every 2 - 5 seconds
Client peak rate of 1 query every second
Also, each DataSource would create a maximum of 8, average of 3 of these instances.
Use a static class, that delegates the calls to the implementation classes.
These implementation classes should implement a common interface, which will allow you to call methods on them without needing reflection. And of course, static methods can't implement interface methods. Interface implementations have to be instances, you need some kind of factory to instantiate them. If they live in external assemblies, I strongly suggest you take a look at the Managed Extensibility Framework (MEF), see http://msdn.microsoft.com/en-us/library/dd460648.aspx.
What are the performance considerations between creating multiple, short-lived objects every request, vs calling static methods? Given that these methods will do data access, the performance implications are totally completely and utterly negligable.
If you use MEF, the framework will create singleton-like instances for you.
If you role your own, and want to remove the need to create these objects multiple times, you can implement the Singleton pattern on them.
I assume each DataSource instance will make a new connection to the database. If so, then it would make sense to only have one instance. The only way to find out if "it's a huge penalty" is to create a mock-up of both solutions and profile and see if the impact is significant or not.
Since you do not seem to have many clients at once, so this also sits
will with the Singleton pattern.
Not many concurrent queries(mostly because of above statement).
You have a Defined specification of response time.
The only argument I can make for the Factory pattern is for "simplicity". If the project is truly time sensitive, then I guess you have no choice. But if you really want performance, go with Singleton.
Use MEF. No need to invent your own plugin framework. It will steer you towards instance methods exposed via interfaces. It is not uncommon to create per-request objects... the MVC framework does that all over the place. Per-request instances are a particularly good thing for data access scenarios so that you can support things like transactions/rollbacks in a way where one user's experience doesn't impact other users until you explicitly make it. Use response caching where appropriate if perf is a problem.
The main decision should be "does this object have state?"
If "No", then by all means, make it a static method.
IMHO .. PSM
I have used a lot of static methods in Data Access Layer (DAL) like:
public static DataTable GetClientNames()
{
return CommonDAL.GetDataTable("....");
}
But I found out that some developers don't like the idea of static method inside DAL. I just need some reason to use or not use static methods inside DAL.
Thanks
Tony
From purists' point of view, this violates all kinds of best practices (like, dependency on implementation, tight coupling, opaque dependencies, etc.). I would've said this myself, but recently I tend to move towards simpler solutions without diving too much in "enterprizey" features and buzzwords. Therefore, if it's fine with you do write code like this, if this architecture allows for fast development and is testable and, most important, solves your business problem -- its's just fine.
If I had to pick one reason not to use static methods, that would be that it limits your ability to write unit tests against your code. For example creating mocks for your DAL will be more difficult because there is not an actual interface to code against, just a bunch of static methods. This further limits you if/when you decide to adopt frameworks that require interfaces to support things like IoC, dependency injection etc.
That's Unit of Work, just static, isn't it?
Today I had an epiphany, and it was that I was doing everything wrong. Some history: I inherited a C# application, which was really just a collection of static methods, a completely procedural mess of C# code. I refactored this the best I knew at the time, bringing in lots of post-college OOP knowledge. To make a long story short, many of the entities in code have turned out to be Singletons.
Today I realized I needed 3 new classes, which would each follow the same Singleton pattern to match the rest of the software. If I keep tumbling down this slippery slope, eventually every class in my application will be Singleton, which will really be no logically different from the original group of static methods.
I need help on rethinking this. I know about Dependency Injection, and that would generally be the strategy to use in breaking the Singleton curse. However, I have a few specific questions related to this refactoring, and all about best practices for doing so.
How acceptable is the use of static variables to encapsulate configuration information? I have a brain block on using static, and I think it is due to an early OO class in college where the professor said static was bad. But, should I have to reconfigure the class every time I access it? When accessing hardware, is it ok to leave a static pointer to the addresses and variables needed, or should I continually perform Open() and Close() operations?
Right now I have a single method acting as the controller. Specifically, I continually poll several external instruments (via hardware drivers) for data. Should this type of controller be the way to go, or should I spawn separate threads for each instrument at the program's startup? If the latter, how do I make this object oriented? Should I create classes called InstrumentAListener and InstrumentBListener? Or is there some standard way to approach this?
Is there a better way to do global configuration? Right now I simply have Configuration.Instance.Foo sprinkled liberally throughout the code. Almost every class uses it, so perhaps keeping it as a Singleton makes sense. Any thoughts?
A lot of my classes are things like SerialPortWriter or DataFileWriter, which must sit around waiting for this data to stream in. Since they are active the entire time, how should I arrange these in order to listen for the events generated when data comes in?
Any other resources, books, or comments about how to get away from Singletons and other pattern overuse would be helpful.
Alright, here's my best shot at attacking this question:
(1) Statics
The Problem with static that you may be having is that it means different things in .NET and say, C++. Static basically means it's accessible on the class itself. As for it's acceptability id say it's more of something you'd use to do non-instance specific operations on a class. Or just general things like Math.Abs(...). What you should use for a global config is probably a statically accessed property for holding the current/active configuration. Also maybe some static classes for loading/saving setting the config, however the config should be an Object so it can be passed around manipulated, etc.
public class MyConfiguration
{
public const string DefaultConfigPath = "./config.xml";
protected static MyConfiguration _current;
public static MyConfiguration Current
{
get
{
if (_current == null)
Load(DefaultConfigPath);
return _current;
}
}
public static MyConfiguration Load(string path)
{
// Do your loading here
_current = loadedConfig;
return loadedConfig;
}
// Static save function
//*********** Non-Static Members *********//
public string MyVariable { get; set; }
// etc..
}
(2) Controller/Hardware
You should probably look into a reactive approach, IObserver<> or IObservable<>, it's part of the Reactive Framework (Rx).
Another approach is using a ThreadPool to schedule your polling tasks, as you may get a large number of threads if you have a lot of hardware to pool. Please make sure before using any kind of Threading to learn a lot about it. It's very easy to make mistakes you may not even realize. This Book is an excelent source and will teach you lots.
Either way you should probably build services (just a name really) for managing your hardware which are responsible for collecting information about a service (essentially a model-pattern). From there your central controller can use them to access the data keeping the program logic in the controller, and the hardware logic in the service.
(3) Global Configuration
I may have touched this subject in point #1 but generally that's where we go, if you find yourself typing too much you can always pull it out of there assuming the .Instance is an object.
MyConfiguration cfg = MyConfiguration.Current
cfg.Foo // etc...
(4) Listening For data
Again the reactive framework could help you out, or you could build up an event-driven model that uses triggers for incoming data. This will make sure you're not blocking on a thread till data comes in. It can reduce the complexity of your application greatly.
for starters, you can limit use of singleton through the "Registry" pattern, which effectively means you have one singleton which allows you to get to a bunch of other preconfigured objects.
This is not a "fix" but an improvement, it makes the many objects that are singletons a little more normal and testable. eg... (totally contrived example)
HardwareRegistry.SerialPorts.Serial1.Send("blah");
but the real problem seems to be you are struggling with making a set of objects that work nicely together. There's two kind of steps in OO.... configuring objects, and letting objects do their thing.
so perhaps look at how you can configure non singleton objects to work together, and then hang that off a registry.
Static :-
Plenty of exceptions to the rules here, but in general, avoid it, but it is useful for doing singletons, and creating methods that do "general" computing outside the context of an object. ( like Math.Min )
Data Monitoring :-
its often better to do as you hint at, create a thread with a bunch of preconfigured objects that will do your monitoring. Use message passing to communicate between threads (through a thread safe queue) to limit thread locking problems. Use the registry pattern to access hardware resources.
you want something like a InstrumentListner that uses an InstrumentProtocol (which you subclass for each protocol) to I dunno, LogData. The command pattern may be of use here.
Configuration:-
have your configuration information and use something like the "builder" pattern to translate your configuration into a set of objects set up in a particular way. ie, don't make your classes aware of configuation, make a object that configures objects in a particular way.
Serial Ports :-
I do a bunch of work with these, what I have is a serial connection, which generates a stream of characters which it posts as an event. Then I have something that interprets the protocol stream into meaningful commands. My protocol classes work with a generic "IConnection" of which a SerialConnection inherits..... I also have TcpConnections, MockConnections, etc, to be able to inject test data, or pipe serial ports from one computer to another, etc. So Protocol classes just interpret a stream, have a statemachine, and dispatch commands. The protocol is preconfigured with a Connection, Various things get registered with the protocol, so when it has meaningful data they will be triggered and do their thing. All this is built from a configuration at the beginning, or rebuilt on the fly if something changes.
Since you know about Dependency Injection, have you considered using an IoC container to manage lifetimes? See my answer to a question on static classes.
You (the OP) seem preoccupied with OO design, well, I'll put it this way when thinking about the static variables things. The core concept is encapsulation and reuse; somethings you could care less about reusing but you almost always want the encapsulation. If it's a static variable, it's not really encapsulated, is it? Think about who needs to access it, why, and how far you can HIDE it from client code. Good designs often can change their internals without much breakage to clients, that is what you want to think about. I agree with Scott Meyers (Effective C++) about many things. OOP goes way beyond the class keyword. If you've never heard of it it, look up properties: yes they can be static, and C# has a very good way of using them. As opposed to literally using a static variable. Like I hinted at the start of this list item: think about how not to shoot yourself in the foot later as the class changes with time, that's something many programmers fail to do when designing classes.
Take a look at that Rx framework someone mentioned. The threading model to use, for such a situation as you described, is not readily decidable without more specifics about the use case IMHO. Be sure you know what you're doing with threads. A lot of people can't figure out threads to save their lives; it's no that hard, being tread safe can be when (re)using code. Remember controllers should often be separate from the objects they are controlling (E.g. not the same class); if you don't know it, look up a book on MVC and buy gang of four.
Depends on what you need. For many applications a class that is almost entirely filled with static data, is good enough; like a singleton for free. It can be done very OO. Sometimes you would rather have multiple instances or play with injection, that makes it more complex.
I suggest threads and events. The ease of making code event driven is actually one of the nicer things about C# IMHO.
Hmm, killing off singletons...
In my experience, a lot of the more common uses that young programmers put singletons to, are little more than a waste of the class keyword. Namely something they meant as a stateful module being rolled into a highlander class; and there are some bad singleton implementations out there to match. Whether this is because they failed to learn what they're doing, or only had Java in college, I dunno. Back in C land, it's called a using data at file scope and exposing an API. In C# (and Java) you're kind of bound to it being a class more than many languages. OOP != class keyword; learn the lhs well.
A decently written class can use static data to effectively implement a singleton, and make the compiler do the leg work of keeping it one, or as one as you are ever going to get of anything. Do NOT replace singletons with inheritance unless you seriously know what the heck you are doing. Poorly done inheritance of such things, leads to more brittle code that knows waaaay to much. Classes should be dumb, data is smart. That sounds stupid unless you look at the statement deeply. Using inheritance IMHO for such a thing, is generally a bad thing(tm), languages have the concept of modules/packages for a reason.
If you are up for it, hey you did convert it to singletons ages ago right? Sit down and think a bit: how can I best structure this app, in order to make it work XXX way, then think how doing it XXX way impacts things, for example is doing this one way going to be a source of contention among threads? You can go over a lot of things in an hour like that. When you get older, you'll learn better techniques.
Here is one suggestion for an XXX way to start with: (visualize) write(^Hing) a composite controller class, that works as a manager over the objects it references. Those objects were your singletons, not the the controller holds them, and they are but instances of those classes. This isn't the best design for a lot of applications (particularly can be an issue in heavily threaded ones IMHO), but it will generally solve what causes most younglings to reach for a singleton, and it will perform suitably for a vast array of programs. It's uh, like design pattern CS 102. Forget the singleton you learned in CS 607.
That controlling class, perhaps "Application' would be a more apt ;), basically solves your need for singletons and for storing configuration. How to do it in a sublimely OO way (assuming you do understand OOP) and not shoot yourself in the foot (again), is an exercise for your own education.
If it shows, I am not a fan of the so called singleton pattern, particularly how it is often misused. Moving a code base away from it, often depends on how much refactoring you are prepared to use. Singletons are like global variables: convenient but not butter. Hmm, I think I'll put that in my quotations file, has a nice phrase to it...
Honestly, you know more about the code base and the application in question then anyone here. So no one can really design it for you, and advice speaks less then action, at least where I come from.
I limit myself to at most two singletons in an application / process. One is usually called SysConfig and houses things that might otherwise end up as global variables or other corrupt concepts. I don't have a name for the second one since, so far, I've never actually reached my limit. :-)
Static member variables have their uses but I view them as I view proctologists. A lifesaver when you need one but the odds should be a "million to one" (Seinfeld reference) that you can't find a better way to solve the problem.
Create a base instrument class that implements a threaded listener. Derived classes of that would have instrument specific drivers, etc. Instantiate a derived class for each instrument then store the object in a container of some sort. At cleanup time just iterate through the container. Each instrument instance should be constructed by passing it some registration information on where to send its output/status/whatever. Use your imagination here. The OO stuff gets quite powerful.
I recently had to tackle a similar problem, and what I did seemed to work well for me, maybe it will help you:
(1) Group all "global" information into a single class. Let's call it Configuration.
(2) For all classes which used to use these static objects, change them to (ultimately) inherit from a new abstract base class which looks something like
abstract class MyBaseClass {
protected Configuration config; // You can also wrap it in a property
public MyBaseClass(Configuration config) {
this.config = config;
}
}
(3) Change all constructors of classes deriving from MyBaseClass accordingly. Then just create one instance of Configuration at start and pass it on everywhere.
Cons:
You need to refactor many of your constructors and every place in which they are called
This won't work well if you do not derive your top-level classes from Object. Well, you can add the config field to the derived class, it's just less elegant.
Pros
Not a lot of effort to just change inheritance and constructors, and bang - you can switch all Configuration.Instance with config.
You get rid of static variables completely; so no problems now if, for example, your application suddenly turns into a library and someone is trying to invoke multiple methods concurrently or whatever.
Great question. A few quick thoughts from me...
static in C# should only be used for data that is exactly the same for all instances of a given class. Since you're currently stuck in Singleton hell you only have one instance of everything anyways, but once you break out of that this is the general rule (at least, it is for me). If you start threading your classes you may want to back off on static usage because then you have potential concurrency issues, but that's something that can be tackled later.
I'm not sure how your hardware actually works, but assuming that there's some basic functionality that's the same across all of them (like, how you interface with them at a raw data level or similar) then this is a perfect instance to create a class hierarchy. The base class implements the low level / similar stuff with virtual methods for descendant classes to override to actually properly interpret the data / feed it onward / whatever.
Good luck.