117

We have a class that holds configuration information for the application. It used to be a singleton. After some architectural review, we were told to remove the singleton. We did see some benefits of not using singleton in the unit testing because we can test different configurations all at once.

Without singleton, we have to pass the instance around everywhere in our code. It's getting so messy so we wrote a singleton wrapper. Now we are porting the same code to PHP and .NET, I am wondering if there is a better pattern we can use for the configuration object.

John Mill
  • 1,173
  • 2
  • 8
  • 5

13 Answers13

134

The Google Testing blog has a series of entries about avoiding Singleton (in order to create testable code). Maybe this can help you:

The last article explains in detail how to move the creation of new objects into a factory, so you can avoid using singletons. Worth reading for sure.

In short we move all of the new operators to a factory. We group all of the objects of similar lifetime into a single factory.

Eric Wilson
  • 51,818
  • 71
  • 192
  • 262
FrankS
  • 2,254
  • 3
  • 26
  • 32
  • 3
    *** Using dependancy injection to avoid singletons – Justin Aug 19 '09 at 15:39
  • These articles are as good as the Google C++ Programming Standards! –  Aug 19 '09 at 16:20
  • 2
    Well, not really. The 'Do not use static methods' advice goes straight against Scott Meyers / Herb Sutters' minimal interface principle for example. There are useful advice, but they lack the contribution of multiple minds. – Matthieu M. Nov 13 '09 at 09:51
  • @FrankS why you switched the order of links? It was in good chronological at first. – cregox Nov 13 '13 at 21:00
  • @Cawas actually no idea, that was more than four years ago, so I guess I had some reasons for it back then :-) – FrankS Dec 06 '13 at 08:26
  • I have a practical question. Say I have 25 classes providing various interfaces for my application daemon each interface has a single instance. How should I do dependency injection? Pack 25 references into master reference and pass it to all other classes on construction? – zzz777 Sep 07 '17 at 17:51
  • @zzz777 hard to tell without seeing some example of it, sounds like the main problem might be the architecture itself with might result in dependency injection that feels weird or wrong. Maybe create a full question with some basic examples - better than the comment area here. – FrankS Sep 08 '17 at 00:28
  • This is real life of a distributed application, we have a piece of code that provides services to 5 clients through common interface but itself is a client of 20 distinct services. So far we have (for historic reason) singleton objects that are initiated at startup, we can have static functions and it would not change anything. Dependency injection seem like a fine idea but how to practically do it for 20 services. – zzz777 Sep 09 '17 at 01:09
  • @zzz777 as I said before, the comment area here might be a wrong place for that. Singleton are a big Problem for sure and static functions won't help at all. But how to solve your concrete Problem should be either a new Question or it may be even worth hiring a consultant for that, as it seems to be a rather complex situation (if you are in germany/europe: http://code-quality.de) – FrankS Sep 13 '17 at 13:08
15

The best way is to use a Factory pattern instead. When you construct a new instance of your class (in the factory) you can insert the 'global' data into the newly constructed object, either as a reference to a single instance (which you store in the factory class) or by copying the relevant data into the new object.

All your objects will then contain the data that used to live in the singleton. I don't think there's much of a difference overall, but it can make your code easier to read.

gbjbaanb
  • 49,287
  • 10
  • 99
  • 143
  • 1
    I don't agree with the "best way" statement, but +1 for a good alternative. – tylermac Aug 19 '09 at 15:32
  • The problem with this approach is that every new object contains (or references) what can potentially be a huge gob of data. var_dump() on any of those gob-containing objects results very quickly in huge listings peppered freely with **recursion** warnings. It friggin ugly, can't be terribly efficient, and makes things seem haywire. However, I've not personally found a better way. I did bend the "factory" method into using the __construct() to reference a global. It feels like everything's bent over backwards, however, to avoid the dreaded Singleton... – FYA Dec 10 '11 at 03:45
  • 2
    @EastGhostCom: we might as well use the singleton and stop trying to make things difficult for ourselves :) – gbjbaanb Jan 05 '12 at 23:13
5

I might be stating the obvious here, but is there a reason why you can't use a dependency-injection framework such as Spring or Guice? (I believe Spring also is available for .NET as well now).

That way, the framework can hold a single copy of the configuration objects, and your beans (services, DAOs, whatever) don't have to worry about looking it up.

This is the approach I usually take!

4

If you use Spring Framework, you can just create a regular bean. By default (or if you explicitly set scope="singleton") only one instance of the bean is created and that instance is returned every time the bean is used in a dependency or retrieved via getBean().

You get the advantage of the single instance, without the coupling of the Singleton pattern.

Gene Gotimer
  • 6,781
  • 2
  • 27
  • 44
4

The alternative is passing in what you need instead of asking an object for things.

koen
  • 12,287
  • 9
  • 43
  • 49
4

don't accumulate responsibilites to a single configuration object since it will ends in a very big object that is both difficult to understand and fragile.

For example if you need another parameter to a particular class you change the Configuration object, then recompile all the classes that uses it. This is somewhat problematic.

Try refactoring your code to avoid a common, global and big Configuration object. Pass only required parameters to client classes:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

should be refactored to:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

a dependency injection framework will help a lot here, but it isn't stricly required.

dfa
  • 107,531
  • 29
  • 184
  • 223
  • Yes it's really good point. I have done this before. My big configuration object was implementing interfaces like MailServiceConf, ServerConf.. than Dependency Injection framework passes configuration to classes so my classes was not dependent on big Configuration object. – caltuntas Mar 24 '10 at 07:52
1

You can accomplish the same behavior of singleton by using static methods. Steve yegge explains it very well in this post.

Youssef
  • 718
  • 1
  • 10
  • 22
  • Actually the article is quite good, and it does not say you should use static methods instead. Instead he states that static methods are just singletons as well and at the end he recommends using the factory method pattern: "I'll close by saying that if you still feel the need to use Singleton objects, consider using the Factory Method pattern instead. ..." – FrankS Aug 19 '09 at 15:50
0

Is a class that contains only static methods and fields possible? I'm not sure of exactly what your situation is, but it might be worth looking into.

Thomas Owens
  • 107,741
  • 94
  • 299
  • 427
0

Maybe not very clean either, but you could maybe pass the information bits you want to have changed to the method that creates the singleton -- instead of using

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

you could call createSingleton(Information info) directly on application startup (and in the setUp-Methods of the unit tests).

assylias
  • 297,541
  • 71
  • 621
  • 741
Roland Ewald
  • 4,490
  • 3
  • 32
  • 44
0

Depends on what tooling/frameworks etc.. are being used. With dependency injection/ioc tools one can often still get singleton performance/optimizations by having the di/ioc container use singleton behaviour for the class required - (such as a IConfigSettings interface) by only ever creating one instance of the class. This could be still substituted out for testing

Alternately one could use a factory to create the class and return the same instance each time you request it - but for testing it could return a stubbed/mocked version

saret
  • 2,167
  • 11
  • 12
0

Review possibility to make configuration as callback interface. So your configuration sensitive code will look:

MyReuseCode.Configure(IConfiguration)

System-init code will look:

Library.init(MyIConfigurationImpl)
Dewfy
  • 21,895
  • 12
  • 66
  • 114
0

You could use a dependency injection framework to ease the pain of passing in the configuration object. A decent one is ninject which has the advantage of using code rather than xml.

Colin Gravill
  • 3,934
  • 1
  • 19
  • 16
-1

Singletons are not evil but the design pattern is flawed. I have a class that I only want to create a single instance of it during runtime but want to create multiple isolated instances during unit testing to ensure deterministic results.

DI using Spring, etc, is a very good option but not the only option.

hakre
  • 178,314
  • 47
  • 389
  • 754