Le singleton nul
Julien on mai 27th 2008
Je le dirai honnêtement: je n'aime pas le pattern appelé singleton. Ce pattern était très utile il y a quelques années, avant l'émergence de techniques comme dependency injection (injection de dépendances) ou dependency lookup (recherche de dépendances). Malheureusement pour moi, ce pattern est probablement celui qui est le plus (mal!) utilisé dans le développement logiciel. Je l'admets volontiers, le singleton peut être utile dans de nombreux scénarios, mais sérieusement... pas partout! (Si vous n'avez aucune idée de ce dont je parle, le singleton est un pattern qui permet de s'assurer qu'il n'existera qu'une seule instance d'une classe donnée. Cette instance est créée sur demande, la première fois que la classe est utilisée)
Les principaux problèmes avec les singletons sont évidents:
- Vous ne contrôlez pas le moment auquel l'instance de la classe est créée. Si vous utilisez beaucoup de singletons dans vos projets, vous n'aurez aucune idée de l'ordre dans lequel les objets sont créés. Ce n'est pas un gros problème pour les petits logiciels, mais c'est plus inquiétant lorsque vous avez quelques centaines de millier de lignes de code...
- 99% du temps, l'implémentation utilisé pour le singleton nous lie à une classe spécifique. En conséquent, vous serez obligé de refactorisé le singleton ou d'utiliser des framewoks comme TypeMock si vous voulez tester votre code. (Vous pouvez également avoir un singleton qui offrira une point d'accès à la seule et unique instance d'une seconde classe en la castant en une interface. Problème: a moins que cette seconde classe soit aussi un singleton, rien ne garanti qu'il n'existe qu'une seule instance...)
- Les dépendances ne sont pas évidentes (ce qui peut également être un problème avec l'utilisation du pattern dependency lookup). Si vous avez un type A qui utilise un singleton de type B, rien dans la signature de A ne fera apparaitre la dépendance au grand jour. Par exemple, ce peut être un problème si vous n'êtes pas au courant qu'utiliser A peut provoquer quelques dizaines d'appels à la base de données par l'intermédiaire de B!
Cependant, j'ai récemment découvert un pattern pire que le singleton: je l'appelle le singleton nul ! C'est un concept très simple: le singleton peut échouer à s'instancier si une dépendance (un fichier de config, une base de données, un object distant, etc) n'est pas disponible. Dans ce cas, l'instance retournée par le singleton peut être nul. Voyons un exemple:
class NullSingleton { private static NullSingleton _instance; public static NullSingleton Instance { get { if (_instance == null) { if (CanAccessMyDependency()) { } } return _instance; } } private static bool CanAccessMyDependency() { // check if you can connect to the database for instance. } private NullSingleton() { } }
Qu'est ce qui est problématique avec cela?
- Si la dépendance n'est pas disponible, le singleton nul vérifiera à chaque accès le statut de la dépendance. Ce sera très probablement très lent (généralement c'est un appel en dehors du process).
- A chaque fois que vous accédez à l'instance du singleton, il faut vérifier si la référence n'est pas nulle. Ce qui ajoute un bruit considérable et force des traitements supplémentaires.
- Enfin, c'est contraire aux attentes usuelles à propos des singletons (c'est à dire que la classe devrait toujours retourner 1 et 1 seule instance, et non pas 0 ou 1 instance). Le comportement n'est donc pas évident, ce qui provoquera des bugs!
Faites vous une faveur: n'utilisez pas un "singleton nul" :-)
Filed in Qualité du code | No responses yet

