Singleton overkill?

Eléphanteau du PHP | 22 Messages

17 juil. 2009, 12:26

Bonjour à tous,

Je suis nouveau dans la communauté et comme beaucoup de monde je suis venu pour une petite question :)

J'ai mit un peu de temps avant de savoir comment formuler ma question le plus simplement possible, j'espère donc que tout le monde comprendra :)

Voilà, j'ai lu pas mal de trucs sur php5 et la POO, car je voudrais créer une classe pour gérer ma connexion à la base de données. Beaucoup d'articles sur le design pattern "Singleton" reviennent mais personellement, peut être à cause de mon manque de connaissances, je trouve ça un peu overkill.

Donc j'ai écrit ma classe, qui à l'air de fonctionner comme il faut, mais je voudrais l'avis des experts.
Dois-je impérativement implémenter le pattern "Singleton" ou est-ce que ma solution sera suffisante pour m'assurer que mon objet de connexion n'est pas instantié plus d'une fois?

Merci :)
class SqlHelper
{
	# Fields
	private static $_host = 'localhost';
	private static $_user = 'user';
	private static $_password = 'password';
	private static $_dbname = 'dbname';
	private static $_pdoInstance = null;
	
	# Getter for $_pdoInstance
	private static function PdoInstance()
	{
		if( is_null( self::$_pdoInstance ) )
		{
			try
			{
	            self::$_pdoInstance = new PDO( 'mysql:host=' . self::$_host . ';dbname=' . self::$_dbname, self::$_user, self::$_password );
	            self::$_pdoInstance->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
        	}
        	catch ( PDOException $e )
        	{
            	die( 'Connection failed or database cannot be selected : ' . $e->getMessage() );
        	}
		}
		
		return self::$_pdoInstance;
	}
	
	# "Overloads"
	// plus un forward qu'un overload mais en static
	public static function Query( $statement )
	{
		return self::PdoInstance()->query( $statement );
	}
}
Cette solution me permet de lancer une query de la façon suivante (que j'apprécie, c'est pour ça que je m'embête pour si peu diront certains ;))
SqlHelper::Query( 'SELECT * FROM tb_Table' );
Just une petite note sur le "forward", la methode static pour Query, j'imagine qu'elle peut laisser pas mal de gens perplexe, mais je compte la remplacer pour la version 5.3.0 par:
public static function __callStatic( $method, $args )
{
	if( method_exists( self::PdoInstance(), $method ) )
		call_user_func_array( array( self::PdoInstance(), $method ), $args );
}

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 12:50

Hey :),

Disons que ce que tu as fait, c'est un singleton. Donc éviter de faire un singleton, en le remplaçant par un singleton, c'est pas mal ;-).

Édition : Bienvenue !
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 22 Messages

17 juil. 2009, 12:58

Hey :),

Disons que ce que tu as fait, c'est un singleton. Donc éviter de faire un singleton, en le remplaçant par un singleton, c'est pas mal ;-).
Hehe, c'est ce que je me disais... En fait, je voulais juste éviter l'implémentation qui revient dans les articles qui consistait à ajouter une méthode getInstance()...

Votre réponse est-elle donc une confirmation que ma classe (static) ne risque pas d'instantier un autre objet de connexion?
Bienvenue !
Merci! :)

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 13:02

Votre réponse est-elle donc une confirmation que ma classe (static) ne risque pas d'instantier un autre objet de connexion?
Exact.

Les modèles de conceptions ne sont pas des modes d'emploi qu'il faut suivre à la lettre, car ils doivent s'adapter à nos besoins. Il faut faire l'effort de comprendre ce que le modèle résoud comme problème et comment il le résoud. Une fois qu'on a compris, on l'adapte comme on veut. Ce que tu as fait prouve que tu as bien compris les tenants et les aboutissants de ce modèle de conception. Bravo :-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 22 Messages

17 juil. 2009, 13:08

Merci :)

Je viens de me commander 2 livres sur les design patterns justement pour ça :)

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 13:11

Si ce n'est pas indiscret, je peux savoir lesquels ?
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 22 Messages

17 juil. 2009, 13:14

Design patterns: Elements of reusable object-oriented software

et

Design Patterns Explained: A New Perspective On Object-Oriented Design

Un ami (programmeur C#.NET) me les a fortement conseillé. Le 2ème étant en fait une version plus light, car le 1er est assez lourd à lire, mais mon ami m'en a parlé comme un "eye-opener" :)

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 13:24

Je te recommande surtout (si tu es débutant) : Tête la première, Design Patterns. C'est un excellent livre, mais vraiment excellent. J'ai rarement vu un livre aussi bien. On s'amuse, les exercices sont très intéressants, les exemples très parlant, et c'est très complet. La vulgarisation ne se fait pas au détrimant de la technique ni de la vérité (on dit souvent des bêtises quand on vulgarise) etc.
Je te conseille de commencer par celui-là :-).
En plus, ça traite du Java, donc c'est très proche de PHP.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphanteau du PHP | 22 Messages

17 juil. 2009, 13:28

Oui j'ai hésité avec celui la aussi, car j'ai lu il y a bien longtemps un livre sur le Java de cette édition et elle était vraiment sympa. Je vais suivre ton conseil, merci! :)

Mammouth du PHP | 965 Messages

17 juil. 2009, 13:44

Une petite question au passage un jour j'ai entendu un gars dire (un gars de symfony), si vous avez besoin d'un singleton poser vous 100 fois la questions de si vous en avez vraiment besoin, couchez vous et si le lendemain vous pensez que c'est bon reposez vous la question encore 100 fois.

J'avoue ne pas avoir trop compris pourquoi ?!

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 14:08

Bah moi non plus :-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Eléphant du PHP | 111 Messages

17 juil. 2009, 14:37

Une petite question au passage un jour j'ai entendu un gars dire (un gars de symfony), si vous avez besoin d'un singleton poser vous 100 fois la questions de si vous en avez vraiment besoin, couchez vous et si le lendemain vous pensez que c'est bon reposez vous la question encore 100 fois.
Peut être à cause de ça ? (java, valable pour php ?)

http://christophej.developpez.com/tutor ... ltithread/

Ou à cause de l'utilisation légèrement plus grande de la mémoire par rapport à une instance de classe non statique ?

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

17 juil. 2009, 14:41

Ceci n'est pas valable pour la création d'une instance, mais pour sa récupération.

Si, dans un code, tu appelles expressement un singleton, tu lies très fortement les 2 classes.
Dans le but de réduire ces liaisons, dans la logique Symfony, on déconseille l'utilisation "brute" des singletons pour passer par des accesseurs. Ces accesseurs là chargent une instance d'une classe qui peut devenir configurable.
Ainsi, il est possible d'étendre et de surcharger des classes entières du coeur d'un framework sans avoir a changer la moindre ligne de ce framework, juste la configuration

Exemple :
classe Logger
{
// ...

  /**
   *  Dans cette méthode, il est impossible de remplacer la classe SqlHelper par une autre
   */
  public function myMethod()
  {
    $dbaccess = SqlHelper::getInstance();
  }

  /**
   *  Dans cette méthode, et en imaginant que la méthode Config::getSqlHelperClassName() 
   *  récupère une variable de configuration, surcharger SqlHelper devient possible
   */
  public function myMethodBis()
  {
    $classname = Config::getSqlHelperClassName();
    $dbaccess = $classname::getInstance();
  }

// ...
}

Dans la même idée, Symfony, dans ses bonnes pratiques, recommande d'éviter de créer les instances de classes nécessaires au fonctionnement dans une méthode, toujours pour réduire les liaisons entre classes.
A la place, il est conseillé le principe d'injection de dépendances : chaque méthode prend en paramètre les instances dont elle a besoin.
Pour faciliter le travail avec cette logique, et éviter de devoir créer 60 instances pour utiliser une pauvre méthode, symfony met à disposition un composant dédié : http://components.symfony-project.org/d ... -Injection
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

ViPHP
ViPHP | 4674 Messages

17 juil. 2009, 16:01

J'aime bien le principe des injections de dépendances mais … ça n'a rien de nouveau, et je trouve que Symfony met ça trop en avant. Sans être dans la critique, je trouve que Symfony en parle comme si c'était une révolution, alors que non. C'est juste qu'on passe des objets au lieu de passer des chaînes de caractères (si je vulgarise). Donc on fait du Sf ou ZF à la place de PEAR. Wala …

En revanche, ce qui est bien foutu dans Sf, c'est la centralisation, ou l'abstraction, des dépendances (ce qu'ils appellent les conteneurs). Ça c'est très pratique (mais faut aimer le YAML ;-)).

Mais si on revient au sujet initial : c'est quoi le rapport avec les singletons ? C'est juste que leur abstraction ne peut pas marcher avec des singletons ? Bah si … je ne vois pas où les problèmes :-k ?

Et le problème avec les environnements multi-thread est intéressant. Je n'y avais pas pensé. Mais pour l'instant, PHP n'est pas 100% multi-thread et le problème ne se pose pas encore, mais ça ne devrait pas tarder :-).
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

17 juil. 2009, 16:40

J'aime bien le principe des injections de dépendances mais … ça n'a rien de nouveau, et je trouve que Symfony met ça trop en avant. Sans être dans la critique, je trouve que Symfony en parle comme si c'était une révolution, alors que non. C'est juste qu'on passe des objets au lieu de passer des chaînes de caractères (si je vulgarise). Donc on fait du Sf ou ZF à la place de PEAR. Wala …
Ah, je l'avais pas pris comme ça :?

L'équipe Symfony insiste fortement sur le fait qu'une bonne application Symfony c'est plus que l'utilisation du framework, mais également l'utilisation des bonnes pratiques. Et comme ils considère cet aspect comme une des bonnes pratiques de base et insiste sur le fait qu'il faut l'utiliser.
Voilà ma version de ce qui est dit. ;)
Mais si on revient au sujet initial : c'est quoi le rapport avec les singletons ? C'est juste que leur abstraction ne peut pas marcher avec des singletons ? Bah si … je ne vois pas où les problèmes :-k ?
Relis bien mon message ! le problème n'est pas l'utilisation intrinsèque des singletons, mais la manière d'utiliser un singleton. ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer