views:

512

answers:

7

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.

  1. 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?

  2. 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?

  3. 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?

  4. 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.

+3  A: 

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.

Keith Nicholas
I like the idea of HardwareRegistry, but I think in this case I wouldn't need it. I would rarely, if ever, access a serial port from multiple locations; there would be one port in use by one thread dedicated to serving it. But I may use this pattern to register each "Instrument", since I don't know at compile time how many of which kind of instruments there are.All the other advice is well received and I need to consider how I would design in light of this. Appreciated.
drharris
A: 

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.

Amardeep
Unfortunately, my global Configuration singleton is what got me into this mess in the first place. So I'm trying to end any notion of a dumping ground for global objects, as much as possible. Good pointers on how to design the base/derived instrument classes, though!
drharris
+10  A: 

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.

Aren
Yeah, the example Configuration you mention is basically like mine now. It's a singleton class that serializes and deserializes its instance to an XML file upon instantiation. I should also note your example does not look thread-safe. At least locking the Current.get property should work. As far as the rest, I'm going to dig into Rx. It looks excellent, and exactly what I've been looking for. I've grown tired of events, and something implementing a true Observable pattern would work very well for us. Thanks for the pointer, and I'll update once I get the hang of it.
drharris
Yeah, It was a quick example. Except it's not a singleton, it holds a 'current' but that object is by no means the only one. You can load em and pass around, it just holds onto the last loaded config as the 'active' one. Might not be the best implementation, needs some tweaking, but it was a 5 min whip up for your question :)
Aren
@drharris You are correct. The getter needs some locking and another null check inside the lock, otherwise a possible race condition exists.
Chuck Conway
+1  A: 

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.
Oak
This is definitely understandable, and depending on the application I might would go this way. However, I really want to do things in a semantically proper way, and deriving every class from some custom base class seems a bit odd to me, in that it loses semantic meaning. While it's more work, I think adding a Configuration parameter to the constructor of every class that uses it makes more sense in understanding.
drharris
@drharris: I'm not sure this is the best way myself :) all I know is that it worked very well for me. I had a deep class hierarchy anyway, so I just needed to derive my one or two top-level classes from this new class (and change the constructors of them all).
Oak
+1  A: 

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.

TrueWill
I do know about DI, and IoC. However, I feel that many times, IoC can add unnecessary complexity to medium-sized applications. This isn't an enterprise, client-server application, just a single desktop app. I'm the sole programmer, so I feel that simply doing Constructor injection would be sufficient here. At some point, there's simply a tradeoff between complexity and tight coupling, and for this particular project I'm not willing to go quite that far. Unless you know of a really compact, simple framework (i.e. not Spring).
drharris
@drharris - I use and like Unity (including in desktop apps); StructureMap was also quite easy when I evaluated it. I prefer fluent configuration over XML. I agree with the complexity trade-off, but this would solve your Singleton (lifetime) and configuration coupling issues in one fell swoop. It's really very little code, and that code is localized (often to one high-level class).
TrueWill
P.S. http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx
TrueWill
A: 

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.

Donnie
I'm trying to make my application very multithreaded, so static would likely indeed be a bad idea. Now, I'm interested in the class hierarchy idea. My education limited us to learning: `class Cat extends Animal` and stuff like that, hardly the things you can carry into a real world implementation. I doubt I actually subclass more than 1-2 things per project because we never learned exactly what you can do (for real) using those kinds of strategies. Do you have example code (or a link) to something similar to what you're saying there?
drharris
+1  A: 
  1. 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.

  2. 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.

  3. 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.

  4. 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.

TerryP