Singletons: Pros, Contre, Design Concerns

Je l'admets. J'utilise des singletons. Je sais ce que vous pouvez tous dire, et franchement, en voyant toutes ces réponses sur Internet, en parlant des mauvais aspects des singletons, et en les déconseillant, j'ai vraiment remis en question mes pratiques de programmation.

J'ai déjà lu quelques articles dans StackOverflow concernant Singletons, mais je post cette question non seulement pour poser des questions à leur sujet, mais pour voir quelques idées sur la façon dont je les utilise dans mes programmes.

Je pense que je dois vraiment clarifier certaines choses ici et requestr des directions avant.

Alors considérons quelques cas où j'utilise beaucoup singletons:

  1. Pour créer des accesseurs à des variables globales, comme mon controller de vue racine, des controllers de vues spécifiques et toujours existants, l'état de l'application, mon context d'object géré global … des choses comme ça
  2. Pour créer des classs d'utilitaire dont le travail consiste à gérer l'set de l'application de données. Par exemple, je crée un Singleton qui va gérer ma database de caching, qui repose sur des données de base. Comme j'ai besoin de créer des caches et d'autres choses à mettre dans la database dans différentes vues, il m'a semblé préférable de créer une class qui gèrerait les inputs / sorties de la database (attention à la security des threads).
  3. Gestion des sessions réseau En fait, je l'utilise pour maintenir en vie une connection et envoyer quelque chose comme un PINg à un server toutes les XX secondes.

Je pense que cela résume tout. Je voudrais vraiment les opinions des autres développeurs sur le sujet.

Pensez-vous qu'il existe de meilleures solutions pour ces problèmes ci-dessus?

Pensez-vous qu'il existe toujours de meilleures alternatives aux singletons et qu'ils devraient être évités?

Est-il préférable en termes de multithreading d'oublier les singletons?

Toutes les recommandations et pensées seraient utiles, et les bienvenus.

Les singletons ne sont certainement pas toujours mauvais, mais comme vous le mentionnez, vous devez faire attention à la security des threads (sur ce sujet, consultez cet article sur l'initialisation singleton).

Une raison pour laquelle les singletons sont souvent décriés comme étant mauvais, c'est qu'ils peuvent rendre plus difficile de «mettre à l'échelle» des parties d'un programme s'ils dépendent trop d'un singleton et de son comportement. Vous mentionnez l'access à la database, un server ou une application de bureau peut commencer avec l'implémentation singleton pour gérer tous les besoins de database, puis essayer d'utiliser plusieurs connections pour accélérer les requêtes indépendantes. Rompre un tel code peut être très difficile.

Même dans une application iOS utilisant CoreData, il peut être utile de ne pas countr sur un ManagedObjectContext global sur votre délégué d'application ou sur un controller de vue racine.

Si vous transmettez à chaque controller de vue une reference à un ManagedObjectContext, vous pouvez gagner en flexibilité. La plupart du time, vous passez simplement le même context d'un controller de vue à l'autre, mais si vous décidez de le faire ultérieurement, vous pouvez par exemple créer un nouveau ManagedObjectContext pour une vue d'édition dans laquelle vous pouvez utiliser les fonctions d'annulation le context, mais seulement merge les changements dans le context "racine" si l'user décide de les sauvegarder ou les rejeter facilement autrement. Ou peut-être souhaitez-vous effectuer un traitement en arrière-plan sur un set d'objects. Si tout fonctionne dans le même context, vous aurez des problèmes de synchronisation.

  • Pour créer des accesseurs à des variables globales, comme mon controller de vue racine, des controllers de vues spécifiques et toujours existants, l'état de l'application, mon context d'object géré global … des choses comme ça

Les singletons sont des globaux. Envelopper un global avec un autre global n'aide vraiment pas.

  • Pour créer des classs d'utilitaire dont le travail consiste à gérer l'set de l'application de données. Par exemple, je crée un Singleton qui va exploiter ma database de caching, qui repose sur des données de base. Comme j'ai besoin de créer des caches et d'autres choses à mettre dans la database dans différentes vues, il m'a semblé préférable de créer une class qui gèrerait les inputs / sorties de la database (attention à la security des threads).

Bien sûr, mais cela n'a probablement pas besoin d'être un singleton. En effet, une partie de la design de Core Data est qu'il est valable d'avoir plusieurs MOC qui parlent au même magasin.

  • Gestion des sessions réseau En fait, je l'utilise pour maintenir en vie une connection et envoyer quelque chose comme un PINg à un server toutes les XX secondes.

Cela devrait être un singleton si le server peut imposer certaines limites de n-connections par user / adresse IP. Sinon, il n'a probablement pas besoin d'être un singleton.

Comme je le mentionne dans mon article de blog, la solution que je préfère est de faire en sorte que chaque object possède l'autre object. Par exemple, votre object MOC et vos objects de connection appartiennent à un ou plusieurs objects qui doivent travailler avec eux. Cela améliore la memory management et des ressources (les objects singleton ne meurent jamais) et rend la design globale de l'application beaucoup plus simple.