OVH Cloud OVH Cloud

Autour d'un singleton

14 réponses
Avatar
Programmer
J'ai utilisé le design pattern Singleton dans un développement. J'ai
donc implémenté une méthode (c'est juste du pseudo code, ne cherchez
pas les erreurs de C++) :

MonSingleton *MonSingleton::GetInstance()
{
if (instance == NULL)
instance = new MonSingleton();
return instance;
}

et dans le destructeur de ma classe je fait :

MonSingleton *MonSingleton::~MonSingleton()
{
delete instance;
}


Toutefois, je ne comprend pas bien à quel moment s'effectue la
destruction de l'instance, puisque je n'appelle jamais delete sur
l'objet de type MonSingleton, que je ne le manipule qu'à travers la
méthode statique GetInstance() (exemple :
MonSingleton::GetInstance()->MaFonction()).

J'avais pensé à une méthode statique ClearInstance() qui se chargerait
de faire le delete, mais cela m'étonne tout de même de devoir supprimer
l'instance explicitement en appelant cette méthode.

Pouvez vous me conseiller ?

4 réponses

1 2
Avatar
jeanpul
On 10 nov, 09:59, James Kanze wrote:
On Nov 10, 8:37 am, jeanpul wrote:



> On 2 nov, 17:43, Programmer wrote:
> > J'ai utilisé le design pattern Singleton dans un développement. J 'ai
> > donc implémenté une méthode (c'est juste du pseudo code, ne che rchez
> > pas les erreurs de C++) :
> > MonSingleton *MonSingleton::GetInstance()
> > {
> > if (instance == NULL)
> >    instance = new MonSingleton();
> > return instance;
> > }
> > et dans le destructeur de ma classe je fait :
> > MonSingleton *MonSingleton::~MonSingleton()
> > {
> > delete instance;
> > }
> > Toutefois, je ne comprend pas bien à quel moment s'effectue la
> > destruction de l'instance, puisque je n'appelle jamais delete sur
> > l'objet de type MonSingleton, que je ne le manipule qu'à travers la
> > méthode statique GetInstance() (exemple :
> > MonSingleton::GetInstance()->MaFonction()).
> > J'avais pensé à une méthode statique ClearInstance() qui se cha rgerait
> > de faire le delete, mais cela m'étonne tout de même de devoir sup primer
> > l'instance explicitement en appelant cette méthode.
> > Pouvez vous me conseiller ?
> Je vous conseille, tout d'abord, d'aller lire
> (http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
> par exemple) les arguments pour et contre l'utilisation des
> singleton.

Pas une référence particulièrement intéressante, étant donné que
l'auteur donne l'air de ne pas comprendre la motivation derrière
le modèle de conception. (Mais évidemment, beaucoup de
programmateurs C++ s'en servent pour résoudre des questions de
l'ordre d'initialisation, plutôt que pour limiter le nombre
d'instances à un.)




L'auteur fait un résumé, qui me semble assez pragmatique, sur les
problématiques
qui peuvent surgir lors de l'utilisation d'un tel concept. Cela
correspond
à son utilisation dans un contexte qui n'est pas adapté, mais c'est
une réalité que l'on
doit prendre en compte.

> Sinon, une déclaration "statique" de l'instance me paraît la
> plus adaptée pour garantir sa durée de vie pendant toute
> l'exécution du programme.

Une déclaration statique ne résoud pas les problèmes de l'order
d'initialisation, ni de l'ordre de destruction.

--
James Kanze



Tout à fait, seulement dans le "post" original, il n'est pas fait
mention d'un problème d'ordre d'initialisation.

Cordialement,

Fabien
Avatar
Michael Doubez
On 15 nov, 14:29, jeanpul wrote:
On 10 nov, 09:59, James Kanze wrote:



> On Nov 10, 8:37 am, jeanpul wrote:

> > On 2 nov, 17:43, Programmer wrote:
> > > J'ai utilisé le design pattern Singleton dans un développement. J'ai
> > > donc implémenté une méthode (c'est juste du pseudo code, ne c herchez
> > > pas les erreurs de C++) :
> > > MonSingleton *MonSingleton::GetInstance()
> > > {
> > > if (instance == NULL)
> > >    instance = new MonSingleton();
> > > return instance;
> > > }
> > > et dans le destructeur de ma classe je fait :
> > > MonSingleton *MonSingleton::~MonSingleton()
> > > {
> > > delete instance;
> > > }
> > > Toutefois, je ne comprend pas bien à quel moment s'effectue la
> > > destruction de l'instance, puisque je n'appelle jamais delete sur
> > > l'objet de type MonSingleton, que je ne le manipule qu'à travers la
> > > méthode statique GetInstance() (exemple :
> > > MonSingleton::GetInstance()->MaFonction()).
> > > J'avais pensé à une méthode statique ClearInstance() qui se c hargerait
> > > de faire le delete, mais cela m'étonne tout de même de devoir s upprimer
> > > l'instance explicitement en appelant cette méthode.
> > > Pouvez vous me conseiller ?
> > Je vous conseille, tout d'abord, d'aller lire
> > (http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
> > par exemple) les arguments pour et contre l'utilisation des
> > singleton.

> Pas une référence particulièrement intéressante, étant donn é que
> l'auteur donne l'air de ne pas comprendre la motivation derrière
> le modèle de conception. (Mais évidemment, beaucoup de
> programmateurs C++ s'en servent pour résoudre des questions de
> l'ordre d'initialisation, plutôt que pour limiter le nombre
> d'instances à un.)

L'auteur fait un résumé, qui me semble assez pragmatique, sur les
problématiques
qui peuvent surgir lors de l'utilisation d'un tel concept. Cela
correspond
à son utilisation dans un contexte qui n'est pas adapté, mais c'est
une réalité que l'on
doit prendre en compte.



Que doit on prendre en compte ? Le fait qu'il y a des patterns
utilisés/implémentés de façon incorrecte ?

> > Sinon, une déclaration "statique" de l'instance me paraît la
> > plus adaptée pour garantir sa durée de vie pendant toute
> > l'exécution du programme.

> Une déclaration statique ne résoud pas les problèmes de l'order
> d'initialisation, ni de l'ordre de destruction.

Tout à fait, seulement dans le "post" original, il n'est pas fait
mention d'un problème d'ordre d'initialisation.



Sauf que si il utilise une statique comme vous le proposez, il faudra
bien qu'il s'en préoccupe; et c'est bien la partie la plus facile
résolue avec "la construction à la première utilisation".

Ensuite, il reste tout de même d'ordre de destruction qui est la
question de l'OP et laisser un singleton mourir de sa belle mort (par
l'éboueur si j'ai bien suivit les autres fils de discussion :) ) reste
la solution qui pose le moins de problèmes.
Si le singleton doit faire quelque chose avant la destruction (rendre
une ressource globale comme de la mémoire partagée), on peut lui
adjoindre une fonction de nettoyage qui remet le singleton à un état
neutre et mettre quelques commentaires quant à son utilisation.

--
Michael
Avatar
jeanpul
On 15 nov, 17:51, Michael Doubez wrote:
On 15 nov, 14:29, jeanpul wrote:



> On 10 nov, 09:59, James Kanze wrote:

> > On Nov 10, 8:37 am, jeanpul wrote:

> > > On 2 nov, 17:43, Programmer wrote:
> > > > J'ai utilisé le design pattern Singleton dans un développemen t. J'ai
> > > > donc implémenté une méthode (c'est juste du pseudo code, ne cherchez
> > > > pas les erreurs de C++) :
> > > > MonSingleton *MonSingleton::GetInstance()
> > > > {
> > > > if (instance == NULL)
> > > >    instance = new MonSingleton();
> > > > return instance;
> > > > }
> > > > et dans le destructeur de ma classe je fait :
> > > > MonSingleton *MonSingleton::~MonSingleton()
> > > > {
> > > > delete instance;
> > > > }
> > > > Toutefois, je ne comprend pas bien à quel moment s'effectue la
> > > > destruction de l'instance, puisque je n'appelle jamais delete sur
> > > > l'objet de type MonSingleton, que je ne le manipule qu'à traver s la
> > > > méthode statique GetInstance() (exemple :
> > > > MonSingleton::GetInstance()->MaFonction()).
> > > > J'avais pensé à une méthode statique ClearInstance() qui se chargerait
> > > > de faire le delete, mais cela m'étonne tout de même de devoir supprimer
> > > > l'instance explicitement en appelant cette méthode.
> > > > Pouvez vous me conseiller ?
> > > Je vous conseille, tout d'abord, d'aller lire
> > > (http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.as px
> > > par exemple) les arguments pour et contre l'utilisation des
> > > singleton.

> > Pas une référence particulièrement intéressante, étant donn é que
> > l'auteur donne l'air de ne pas comprendre la motivation derrière
> > le modèle de conception. (Mais évidemment, beaucoup de
> > programmateurs C++ s'en servent pour résoudre des questions de
> > l'ordre d'initialisation, plutôt que pour limiter le nombre
> > d'instances à un.)

> L'auteur fait un résumé, qui me semble assez pragmatique, sur les
> problématiques
> qui peuvent surgir lors de l'utilisation d'un tel concept. Cela
> correspond
> à son utilisation dans un contexte qui n'est pas adapté, mais c'est
> une réalité que l'on
> doit prendre en compte.

Que doit on prendre en compte ? Le fait qu'il y a des patterns
utilisés/implémentés de façon incorrecte ?




Oui, cela peut sembler assez naïf ou trivial, seulement on peut
parfois être attirer
par un "pattern" et vouloir absolument l'utiliser dans ses
développements et s'en mordre
les doigts beaucoup trop tard. C'est le sentiment que j'ai eu en
lisant le post original.

Pour revenir sur le singleton, avez-vous eu l'occasion de l'utiliser ?
et si oui pouvez-vous nous
expliquer dans quel contexte ?

Sauf que si il utilise une statique comme vous le proposez, il faudra
bien qu'il s'en préoccupe; et c'est bien la partie la plus facile
résolue avec "la construction à la première utilisation".



C'est vrai. Cependant, ce qui me gène c'est justement le double rôle
de getInstance. Comment puis-je déterminer si dans mon programme ce
que va
impliquer l'appel à getInstance ? Doit-on identifier ou se trouve "la
premiere utilisation" ?


Cordialement,

Fabien
Avatar
Michael Doubez
On 17 nov, 11:25, jeanpul wrote:
On 15 nov, 17:51, Michael Doubez wrote:



> On 15 nov, 14:29, jeanpul wrote:

> > On 10 nov, 09:59, James Kanze wrote:

> > > On Nov 10, 8:37 am, jeanpul wrote:

> > > > On 2 nov, 17:43, Programmer wrote:
> > > > > J'ai utilisé le design pattern Singleton dans un développem ent. J'ai
> > > > > donc implémenté une méthode (c'est juste du pseudo code, ne cherchez
> > > > > pas les erreurs de C++) :
> > > > > MonSingleton *MonSingleton::GetInstance()
> > > > > {
> > > > > if (instance == NULL)
> > > > >    instance = new MonSingleton();
> > > > > return instance;
> > > > > }
> > > > > et dans le destructeur de ma classe je fait :
> > > > > MonSingleton *MonSingleton::~MonSingleton()
> > > > > {
> > > > > delete instance;
> > > > > }
> > > > > Toutefois, je ne comprend pas bien à quel moment s'effectue l a
> > > > > destruction de l'instance, puisque je n'appelle jamais delete s ur
> > > > > l'objet de type MonSingleton, que je ne le manipule qu'à trav ers la
> > > > > méthode statique GetInstance() (exemple :
> > > > > MonSingleton::GetInstance()->MaFonction()).
> > > > > J'avais pensé à une méthode statique ClearInstance() qui se chargerait
> > > > > de faire le delete, mais cela m'étonne tout de même de devo ir supprimer
> > > > > l'instance explicitement en appelant cette méthode.
> > > > > Pouvez vous me conseiller ?
> > > > Je vous conseille, tout d'abord, d'aller lire
> > > > (http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827. aspx
> > > > par exemple) les arguments pour et contre l'utilisation des
> > > > singleton.

> > > Pas une référence particulièrement intéressante, étant do nné que
> > > l'auteur donne l'air de ne pas comprendre la motivation derrière
> > > le modèle de conception. (Mais évidemment, beaucoup de
> > > programmateurs C++ s'en servent pour résoudre des questions de
> > > l'ordre d'initialisation, plutôt que pour limiter le nombre
> > > d'instances à un.)

> > L'auteur fait un résumé, qui me semble assez pragmatique, sur les
> > problématiques
> > qui peuvent surgir lors de l'utilisation d'un tel concept. Cela
> > correspond
> > à son utilisation dans un contexte qui n'est pas adapté, mais c'e st
> > une réalité que l'on
> > doit prendre en compte.

> Que doit on prendre en compte ? Le fait qu'il y a des patterns
> utilisés/implémentés de façon incorrecte ?

Oui, cela peut sembler assez naïf ou trivial, seulement on peut
parfois être attirer
par un "pattern" et vouloir absolument l'utiliser dans ses
développements et s'en mordre
les doigts beaucoup trop tard. C'est le sentiment que j'ai eu en
lisant le post original.

Pour revenir sur le singleton, avez-vous eu l'occasion de l'utiliser ?
et si oui pouvez-vous nous
expliquer dans quel contexte ?



Dans le contexte d'une instance de classe remarquable (répondant de
façon précise à une interface), la logique du design demandait qu'on
ne puisse pas instancier la classe mais seulement utiliser une
instance. Mais c'était plus en réponse à une demande d'évolution qu 'un
design ex-nihilo.

J'utilise quotidiennement du code de James Kanze pour parser les
paramètres d'un programme et l'objet qui centralise la logique de
parsing est un singleton (si je me souviens bien, ce n'était pas le
cas dans sa bibliothèque gabi, le site étant indisponible, je ne peux
pas vérifier).

J'ai rarement vu l'utilisation pure de Singleton mais il est plutôt
utilisé comme paramètre par défaut de façon à synchroniser en un point
une logique de programme tout en laissant la possibilité de ne pas
l'utiliser localement (comme dans les tests unitaires) ou de le
changer.

De toutes façons, singleton est une notion boiteuse en informatique et
ne mérite pas vraiment le nom de pattern (au sens de solution à un
problème donné) car le problème est biaisé. Il part du principe que la
classe en elle même doit enforcer le fait de n'avoir qu'une seule
instance alors qu'en fait, c'est le codeur qui doit en prendre la
décision.

Donc, au final, un singleton n'existe que dans son utilisation
(contrôle de création d'instance, d'accès, d'état...) pas dans le
design de la base proprement dite.

D'ailleurs les bon exemples de singleton en C++ sont les versions
template (comme dans modern C++): la classe de base proprement dite
n'est pas un singleton et c'est le template qui gère la durée de vie
et l'accès à la globale et fournit un point d'accès unique.

> Sauf que si il utilise une statique comme vous le proposez, il faudra
> bien qu'il s'en préoccupe; et c'est bien la partie la plus facile
> résolue avec "la construction à la première utilisation".

C'est vrai. Cependant, ce qui me gène c'est justement le double rôle
de getInstance. Comment puis-je déterminer si dans mon programme ce
que va
impliquer l'appel à getInstance ?



Ce qui est bien. Il peut arriver que différentes politiques
s'attachent à l'accès de l'instance (par thread, dans une pool, par
délégation ...)
Par exemple l'instance de errno est aujourd'hui dépendante du thread.

Doit-on identifier ou se trouve "la premiere utilisation" ?



L'intérêt de getInstance est justement de ne pas avoir à le faire
sinon, c'est le compilateur qui gère le moment de la construction et
il peut arrive que la variable soit utilisée avant d'avoir été
construite (cf. "static initialisation order fiasco").

Dans un cas multithreadé, c'est mieux d'avoir un mécanisme qui
s'assure que getInstance a été appelé avant main() ou tout du moins
avant le démarrage du premier thread.

--
Michael
1 2