Singleton I love you, but you're bringing me down (re-uploaded)

I was sad to find out the "codingwithoutcomments" site was taken down. For the sake of a specific post from there, I went to waybackmachine.com and got that post, and I'm pasting it here.
I have no rights on this article, I just think it's important to keep this online for people to read. -so if by doing so might be brake any law or offend any person, please let me know and I'll remove it as soon as I get it.

Perpetually In Beta.

Singleton I love you, but you're bringing me down

with 36 comments

It was love at first sight. It was fall. The leaves were changing color. The air was cool and crisp, and my head was still reeling from reading about the Composite Pattern. I turned the page on my copy of the GOF, and there the Singleton was in his black button-up-parka and scarf saying:

"Use me to restrict initiation of a Class to a single Object. Use me to guarantee that one and only one instance of a given class exists during run-time."

And that was it. That was all he said. He was a straight-shooter, a maverick. He wasn't snobby or pretentious. Definitely not an elitist. His world-view was simple, concise. Not like any other pattern I had met before.

OK. Just to be clear. I'm not that type of programmer. I mean, I took it slow at first. First we just went Logging together and then we took a weekend trip to the serial port. But before I knew it, we were joined at the hip. We were going everywhere together.

"Oh Singleton," I exclaimed one day after instantiating him from my constructor (not passed, mind you) of a helper class of methods, "You're too good to be true."

Well, I think that kind of freaked Singleton out.

I knew something was up the day I tried to extend him and he barked at me and headed for the door. I found out he started seeing other people (he did have global access to all my classes now that I think about it — I knew I gave him too much space when I allowed him to control his own creation and life-cycle.)

I hired a Unit-Test to track him down, but that guy couldn't do anything. When I finally did get a hold of him, he told me everything — all the gritty details. His state, after all that time, had of course been retained. I yelled and screamed and told him I didn't want to hear any more. But he was relentless. Unceasing.

It was at that moment that I ended my relationship with the Singleton.

I told him, "Singleton, I love you. But you're bringing me down."

Single(ton), again.

Who among us hasn't smuggled into the break-room to nibble on a Singleton newton? I, like you, drank the Singleton kool-aid. At first Singletons were used appropriately. Then, they were used inappropriately. Then they were used really inappropriately. And somewhere between the appropriate and the inappropriate, you, like me, probably realized that something was amiss. Something was aloof, a little bit off.

Then I, like you, read "Singletons Considered Stupid" by Steve Yeggee:

Why is the Singleton so attractive? I'll be the first to admit: I liked it too. No, scratch that – I loved the Singleton. It felt like an old friend from the moment I laid eyes on it. It was simple and beautiful.

I'll tell you why: it's because the Singleton pattern is a throwback to non-OO programming. It's a lifeline for people who didn't understand a single word that the Gang of Four were trying to say. It's almost exactly the way I programmed back when I didn't know jack squat about OOP. The only significant difference is that instead of having a file with a bunch of global functions in it, I have a file with a CLASS that has a bunch of global functions. No need to worry my little head about how many of them to have, since you only need one! It's OOP made easy.

And my heart was broken.

Then I read article after article about why the Singleton was a piss poor Design Pattern.

I learned that Singletons were actually referred to as something called a "code smell." I didn't know if the smell was good or bad, but we figured it was bad.

I learned that Singletons violated something called the 'Single Responsibility Principle' which states that every class you create should do one thing and one thing only because a Singleton has two distinct responsibilities: policing the instances of itself and providing configuration information.

I learned that Singletons were bad for memory management. If no one uses it for awhile, its just going to sit and twiddle its thumbs.

I learned that the state of the Singleton never goes away. Persistent state is the enemy of unit testing. One of the things that makes unit testing effective is that each test has to be independent of all the others.

I learned that Singleton's are kind of impossible to sub-class because they are static methods and static methods are about "as flexible as granite."

I learned that Singletons are (mostly) used as glorified globals and if you use them in your project, your project becomes almost impossible to unit-test because your "objects can secretly get hold of things which are not declared in their APIs, and, as a result, Singletons make your APIs into pathological liars." Basically, when objects use Singletons they hide their dependencies.

I learned that maybe, just maybe you'll realize somewhere down the line that you actually need TWO instances of the Singleton. Then what, buddy?

So I did what any completely sane Programmer would do. I ripped RIPPED the Singleton Pattern out of GOF and burned the pages while doing a triple hail mary and beat on, boat against the current, swearing never NEVER to use another Singleton for as long as I shall live.

Then, three weeks later, after I sobered up, I realized that all the stuff I learned about why Singletons were the devil incarnate was actually a form of "abstinence only" Design Pattern Education. I knew that I could avoid all the aforementioned problems by simply abstaining completely from using Singletons, but what I didn't know was what happened on the day when I wanted to use a single instance of a class and thought that the Singleton might be the best tool for the job?

Fine. Go ahead, use it.

First, before I answers the question posed above, let me address you. I know you. You're stubborn. You're going to use that Singleton until someone rips it from your cold, dead claws. If this is you, then just read on a little while longer then you can get back to uploading your favorite programming cartoon to stackoverflow.

If you do use Singletons, try to use dependency injection instead of calling getInstance() from the constructor.

Use this:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

rather than this:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

At the very least, using dependency injection allows you to do some unit testing of the class by adhering to good encapsulation principles. Using dependency injection might also stop Misko Hevrey from calling your APIa pathological liar. But probably not.

Check yo-self.

For all the rest of you still reading, before using a Singleton ask yourself, "is a Singleton really the best tool for the job?"

On my quest for the truth I discovered that there are actually very few "acceptable" reasons to use a Singleton.

One reason that tends to come up over and over again on the internets is that of a "logging" class. In this case, a Singleton can be used instead of a single instance of a class because a logging class usually needs to be used over and over again ad nauseam by every class in a project. If every class uses this logging class, dependency injection becomes cumbersome.

Logging is a specific example an "acceptable" Singleton because it doesn't affect the execution of your code. Disable logging, code execution remains the same. Enable it, same same. Misko puts it in the following way inRoot Cause of Singletons, "The information here flows one way: From your application into the logger. Even though loggers are global state, since no information flows from loggers into your application, loggers are acceptable."

I'm sure there are other valid reasons as well. Alex Miller, in "Patterns I Hate", talks of service locators and client side UI's also being possibly "acceptable" choices.

Single Instance Of A Class

In most cases, though, you probably got it wrong when you went to the ole' Singleton toolbox. What you probably wanted was a simple single instance of a class instead of a Singleton. There is absolutely nothing wrong with only wanting a single instance of a class. There are, however, way better ways of managing these instances then a "glorified global".

How do you achieve a Single Configuration Object without using a Singleton? Neal Ford in "The Productive Programmer" suggests "using a plain object plus a factory and delegating the individual responsibilities to each. The factory is responsible for the instance policing and the plain object deals only with configuration information and behavior." By using this technique, your code no longer smells as it now adheres to theSingle Responsibility Principle.

Misko Hevrey (who does testing for google) goes into much greater detail about this technique in his two fantastic blog posts entitled "How to Think About the 'new' Operator with Respect to Unit Testing" and "Where Have All the Singletons Gone?"

The idea is to have either classes with logic or classes with the new operator (factories). When you need a single instance of a logic class, you call on the factory to build that class. Using this technique, all the dependencies are automatically injected into this single instance in proper order and returned to you. All objects of a similar lifetime are grouped into this single factory.

Misko uses the example of building a "House."

class House {
  private final Kitchen kitchen;
  private final Bedroom bedroom;
  private boolean isLocked;
 
   public House(Kitchen kitchen, Bedroom bedroom) {
    this.kitchen = kitchen;
    this.bedroom = bedroom;
  }
 
  private boolean isLocked() {
    return isLocked;
  }
 
  private boolean lock() {
    kitchen.lock();
    isLocked = true;
  }
}

Notice that in the House class, there are no instances of "new." Remember, don't mix new and logic, baby. Like J-Lo and Puffy. All the dependencies needed to build a "House" are injected into the constructor. All the "new" stuff is in the HouseFactory (seen below).

class HouseFactory {
  House build() {
 
     Sink sink = new Sink;
     Dishwasher dishwasher = new Dishwasher;
     Refrigerator refrigerator = new Refrigerator;
     Kitchen kitchen = new Kitchen(sink, dishwasher, refrigerator);
 
	Bed bed = new Bed;
     Dresser dresser = new Dresser;
     Bedroom bedroom = new Bedroom(bed, dresser);
 
	House house = new House(kitchen, bedroom);
 
    return house;
 
  }
}
 
class Main {
  public static void(String...args) {
    House house = new HouseFactory().build();
    house.lock();
  }
}

In the "house" factory, when build() is called, kitchen is created and composed of sink, dishwasher, and refrigerator objects. Bedroom is created and composed of created bed and dresser objects. House is created, composed of kitchen and bedroom objects, then returned to the user.

Using this technique, you can see how easy it will be to achieve a single configuration object without the use of a Singleton. A single instance of HouseBuilder is instantiated in the main and with that comes single instances of house, kitchen, bedroom, sink, dishwasher, refrigerator, bed, and dresser.

Using this technique solves the issue of global state because "there is no global state at all. Every object only has references to what it needs directly! No passing around of objects which are not directly needed by the code. Dependencies are obvious since each object only asks for what it needs."

Using this technique solves the issue of memory management. All classes will be created and used when needed. No more Singletons sitting around and taking up memory while doing nothing at all.

Using this technique you can extend any of the classes you desire. Static methods are nowhere. No-sir.

Using this technique you can Unit-Test without fear of a wolf attack.

Plus, Misko adds:

If an object needs a reference to a new dependency it simply declares it. This change only affects the corresponding factory, and as a result, it is very isolated.

All of the new operators end up in the factories; application logic is devoid of new operators.

You group all of the objects with the same lifetime into a single factory (If the factory gets too big you can break it up into more classes, but you can still think of it as a single factory)

Look Lisa, I'm learnding

I loved Singletons.
Then I loved Singletons a bit too much.

Then I read Steve Yegge.
He broke my heart.

I sought answers.

If you are going to use Singletons I urge you to use Dependency Injection.
But really you should know that their are very few reasons to actually use a Singleton.
I think what you probably want is: a single instance of a class!
If this is true: try using an object plus a factory.
and Don't mix the "new" with the "logic" baby.

Written by codingwithoutcomments

October 8th, 2008 at 10:58 pm

Programming Paradigms – Lecture 6 – CS107 – Stanford University

without comments

The following is a brief overview of Lecture 6 of the ‘Programming Paradigms,” a programming class taught at Standford University. Screenshots and Code are included from the lecture. The ‘Programming Paradigms’ lectures can be found in iTunes. The link is on the Open Standford Website. The following lecture covers Implementing an Int Specific and Generic Stack in C/C++.

Int Specific Stack

stack.h
 
typedef struct{
	int * elems;
	int loglength;
	int alloclength;
} stack;
 
void StackNew(stack * s)
void StackDispose(stack * s)
void StackPush(stack * s, int value)
int  StackPop(stack * s)

The last lecture was left off with header file for a int specific stack being defined which includes a strcut called 'stack' and four functions. This lecture begins with defining StackNew and StackDispose for an int specific stack.

void StackNew(stack * s)
{
	s->loglength = 0;
	s->alloclength = 4
	s->elems = malloc(4 * sizeof(int))
	assert(s->elems != NULL);
}

When a new stack is allocated, the length is set originally to zero (because the stack is empty). Space is made for 4 elements, then malloc is used to allocate memory for those four elements. Malloc goes to the heap and finds 16 bytes of space, puts a "little halo" around the space, and then returns the base address of the memory. Assert confirms that elem is not equal to NULL just incase malloc fails for some reason. Asserts should be used to you clearly know where the program failed.

void StackDispose(stack * s)
{
	free(s);
}

StackDispose is trivial. The opposite of malloc, free is used. This gives the memory back to the heap.

void StackPush(stack * s, int value)
{
	if(s->loglength == s->alloclength){
		s->alloclength *= 2;
		s->elems = realloc(s->elems, s->alloclength * sizeof(int));
		assert(s->elems != NULL);
	}
 
	s->elemns[s->loglength] = value;
	s->loglength++;
}

In the function StackPush, you first want to check if you are out of memory to actually push value onto the Stack. If the current length of the stack is already equal to the allocated length, more memory will have to be allocated for the stack, else bad things will happen.

Actually, we want to go ahead and re-allocate the array. The previously allocated amount of memory is doubled. Then realloc is called. Realloc only exists in C, it doesn't exist in C++. Jerry says that he'll explain in a few weeks why realloc doesn't exist in C++. Realloc first sees if the memory can be allocated in place, meaning that realloc checks to see if the memory that comes after the previously allocated space in the heap is in use. If it isn't, it uses that memory. If it can't resize it in place, it copies all the elements over to a different block of memory, frees the old memory, and returns the address of the new memory.

If realloc is called with the first parameter being equal to NULL, it functions the same as a malloc command. This is useful if you don't want to call malloc once, then realloc every single time after that.

The doubling strategy is really popular because it only comes up once every 2^n times. 512 bytes of memory not big enough? Ok, let's allocate 1024. And so on.

int StackPop(stack *s)
{
	assert(s->loglength> 0);
	s->loglength--;
	return s->elems[s->loglength];
}

First, make sure that their is at least one object on the stack. Subtract one for loglength (the length of the stack), then return the new address of the stack which simulates the discarding of the last element on the stack.

Stack Using Generics

Next, the exact same stack functions will be implemented generically, not just for stack integers.

stack.h
typdef struct {
    void * elems;
    int elemSize;
    int loglength;
    int alloclength;
    ?? - Suspense Element
} stack;
 
void StackNew(stack * s, int elemSize);
void StackDispose(stack * s);
void StackPush(stack * s, void * elemAddr);
void StackPop(stack * s, void * elemAddr);

The above is the setup for the stack functions that will be implemented generically. Note that not all the information has yet been given as suspense element will be added later to the stack struct. 70% of the code for the generic stack functions is the same as the int specific stack functions.

void StackNew(stack * s, int elemSize)
{
	assert(s->elemSize > 0);
	s->length = 0;
	s->alloclength = 4;
	s->elemSize = elemSize;
	s->elems = malloc(4 * elemSize);
	assert(s->elems != NULL);
}

The second parameter (elemSize) tells the length of a single element, so malloc is used to pre-allocate 4 elements on the stack of size elemSize. Assert is used to make your life easier. It checks to make sure actual memory was allocated and to make sure elemSize was not accidentally set to zero.

void StackDispose(stack * s)
{
	free(s->elems);
 
}

StackDispose is again trivial.

void StackPush(stack *s, void * elemAddr)
{
	if(s->loglength == s->alloclength)
		StackGrow(s);
 
	void * target = (char *) s->elems + s->loglength * s->elemSize;
	memcpy(target, elemAddr, s->elemSize);
	s->loglength++;
 
}

In StackPush, if the stack needs more memory allocated, StackGrow() is called to allocate that memory. Target points to the block of memory already pre-allocated in the stack where the element will be copied.. Memcpy is used to do the actual copying of the element to that address. Remember to cast s->elems as a char * to trick the compiler because it cannot cast as a void *.

The word static has like 80 or 85 meanings in C++. Here is one more. When you see the word static decorating the prototype of a c or c++ function such as:

stack void StackGrow(stack *s)

This means that it is a private function that should not be advertised outside this file. In companies like Microsoft which deal with programs with tens of thousands of files, many times function names will conflict with each other if not made static.

static void StackGrow(stack *s)
{
	s->alloclength *=2;
	s->elems = realloc(s->elems, s->alloclength * s->elemSize);
}

StackGrow re-allocates double the amount of memory just like the int specific version.

void StackPop(stack *s, void * elemAddr)
{
	void * source = (char*) s->elems + (s->loglength - 1) * s->elemSize;
	memcpy(elemAddr, source, s->elemSize)
	s->loglength--;
}

In StackPop(), source points to the last chunk of data in memory on the stack. Memcpy copies that memory to the memory address, then the length of the stack is decremented thus "popping" off the memory from the stack.

When dealing with generics, it is very easy to get the program to compile because the compiler looks at all the void * declarations and stamps them as "good." However, when running a program implementing generics, it is very likely to crash.

Written by codingwithoutcomments

October 4th, 2008 at 10:23 pm

posted @ Sunday, September 8, 2013 2:45 PM
Print

Comments on this entry:

No comments posted yet.

Your comment:



(not displayed)

 
 
 
 

Live Comment Preview: