Too many singletones in a project is bad practice?

In almost every project, I create several classes that implement the Singleton pattern. For example, data manager - if there is some work with the file system, data loader - if the application connects to the Internet, different resource managers, etc. Sometimes there are up to 5-7 such classes, and I begin to feel that I am doing something wrong. Is it too wrong to use the Singleton pattern?

+4
source share
4 answers

Singletones are not necessarily problems - having one object that is an expert in his domain can be very useful, but explicitly coding a singleton in an object is almost always a bad idea (and often this is done poorly). It turns out that it is better to leave the application configuration, including the decision about which classes the oneton instances have, on a separate layer that specializes in this, such as Spring for Java. Thus, the control level can monitor what is singleton, that is, one element in a certain context (for example, within a session) and what should always be done again. This gives you the opportunity to focus on writing business logic.

For an example of why singletones can be problems and why they should be single controls / configurations, consider a class that manages a database connection. A classic case for a single that you could say. You would be right too until you find that your application has grown to such an extent that it has to integrate connections with two databases (this happens!), And then you have to unravel the whole mess. If you saved your code as an agnostic about whether it deals with loners or not, you will have a great chance to deal with all this by simply reconfiguring; some classes will be connected to one database, and some to another, but they will just do it with minimal clutter. (Everything that needs both ... well, why I said "great chance.")

Another example of why problems with Singletons may occur occurs when you write tests for your code. (You write tests, right?) Explicit singletones are very difficult to test because they are hard to set up and hard to isolate. You cannot correctly break them between trials because this implies the presence of many of them. If your application uses single packages only by configuration, the test configuration can easily change this, and you can make your tests much easier.

+4
source

There are many discussions on this topic. For some people, Singleton is considered an anti-pattern . However, this can be very useful, but as a rule, it is much more complicated than it seems. There are situations when its use is justified, for example, to have a unique entry point for data common to the entire application - and this is the difficult part, this is a global state in disguise, safe to use if and only if the data is immutable.

As a JEE6 note, the latest version of Java Enterprise Edition now includes support for the Singleton template as an EJB component. But think about it for a moment, it took six revisions of the standard to finally do it!

+1
source

Since TDD took its place, programmers have learned that testing singles is a pain, and he began to avoid it. The same effect can be achieved by entering the necessary classes / resources, such as connection manager, resource manager, etc. Thus, in a test environment, these classes can simply be mocked, entered, and tested.

On the other hand, in some cases, only using singleton seems to be the right way - to ensure that only one instance exists. That is, it is useful for connection pools, because it guarantees that at that moment there is one and only one instance, and there will be no leaks. (Note: not the whole implementation of a singleton template can really provide this. In Java, using enum is the right way - since the language itself ensures its uniqueness.)

In conclusion, my answer is yes, using too many singles is bad. Use the DI principle instead.

+1
source

An interesting article on singleton is an anti-pattern, although I do not quite agree. I never used a singleton as a standalone solution, I always associated it with a factory template, which, I think, discourages the state argument and encapsulation.

A good example of a singleton / factory solution is a database class. You can have several databases, each of which requires its own connection, but you do not want each call to create and create a new connection. You want to recycle common compounds to avoid land mines with “too many compounds”.

Something along the lines of:

/** * Database manager for handling database related stuff * Does use Zend_Db and Zend_Config */ class Database_Manager { protected static $dbos = array(); // Protected scope enforces encapsulation public static function getDbo($name) { // Init $hash = md5($name); // Attempt to use singleton if (array_key_exists($hash, self::$dbos)) { return self::$dbos[$hash]; } // Your db connection settings are set here either via // switch/case based on name, or loaded from a config file (yaml, xml, etc) $dbConnectionParams = array('your', 'connection', 'settings'); $config = new Zend_Config($dbConnectionParams); $dbo = Zend_Db::factory($config->database); // Adding to singleton so can be referenced in future calls self::$dbos[$hash] = $dbo; return $dbo; } 

In this example, the factory provides encapsulation, while singleton processes already created database objects.

At the end of the day, it is up to you and what you want to support along the way.

0
source

Source: https://habr.com/ru/post/1385465/


All Articles