Citation:
Envoy� par
foetus
Je ne suis pas d'accord :mrgreen:
Lorsque je parle de "god object" (peut-�tre � tord) c'est l'objet principal que certaines biblioth�ques (surtout IHM comme Qt, VCL) ont besoin pour lancer l'application (et initialiser la fen�tre principale).
Et je ne parle pas d'h�ritage, polymorphisme, h�ritage multiple, ou autre ... juste de l'utilisation de cette classe principale (*).
Ah, ben oui, tu as effectivement une classe (QApplication, dans le cas de Qt) qui va mettre tout le syst�me en branle et s'assurer que tout sera correctement initialis�. Ce n'est pas une raison (et c'est l'un des reproche que je fais � Qt) pour connaitre cette classe pour pouvoir acc�der aux diff�rents services quelle regroupe. D'autant plus que les services en question sont TOUS mod�lis�s sous la forme d'une classe sp�cifique.
Ceci dit, le domaine de l'IHM est -- justement -- le contre exemple flagrant de ce qu'il faut faire � bien des �gards ;)
Citation:
Donc je trouve "�trange" que pour respecter les principes SOLID SRP OCP ou autres, on ne doit pas profiter de cette grosse classe (et de sa commodit�).
Surtout qu'un de ses r�les c'est l'initialisation au lancement (entre autres comme thread d'affichage ou les gros traits/ lignes de la logique IHM)
Oui, bien sur : il est important de veiller � ce que tout ce qui doit �tre initialis� pour fournir les services que l'on attend de la part d'une IHM soit initialis� de mani�re simple (ex, comme c'est le cas de Qt, en ayant une classe sp�cifique dont l'instanciation s'occupera de cr�er tous les �l�ments n�cessaires pour rendre ces services)
Citation:
Les managers sont d'ailleurs essentiellement initialis�s au d�marrage.
(je passe sur le probl�me qu'il peut y avoir � parler de "managers" ou de "gestionnaires"... je reviendrai dessus � la fin de mon intervention ;) )
Oui, et alors :question: Qu'est ce qui t'emp�che d'avoir une classe proche de
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class MaClasseEntreeApplication{
/* ... */
private:
/* juste au cas où on voudrait l'instancier deux fois */
static bool alreadyCreated_;
ThreadStack threads_;
EventHandlerCollection events_;
/* ... */
};
/* pour ne pas devoir passer par MaClasseEntreeApplication */
EventHanderlCollection & events(){
/* peu importe comment on le récupère */
}
ThreadStack threads(){
/* peu importe comment on le récupère */
}
.... someStuffWeWantToGet() {
/* ... */
} |
La loi de D�m�ter dit que, si un objet de type A manipule en interne un objet de type B, l'utilisateur du type A ne doit pas avoir connaissance du type B pour manipuler son objet de type A.
Mais il ne faut pas non (et encore moins) plus obliger l'utilisateur du type B � connaitre le type A pour pouvoir acc�der � son type B.
La plupart des biblioth�ques d'IHM sont apparues � une �poque o�
- la philosophie �tait proche du "tout objet" (comprend : fonctions membres uniquement), en ignorant volontairement les possibilit�s multi paradigme du C++
- l'approche du paradigme orient� objet �tait encore bien plus orient�e sur les donn�es manipul�es que sur les services rendus par les diff�rentes fonctionnalit�s (il suffit de voir le nombre de mutateurs pour s'en convaincre)
Alors, bien sur, dans un tel contexte, il devient sans doute impossible de se passer de la notion de singleton. Mais, si tu accepte l'id�e de cr�er des fonctions libres et que tu commences r�ellement � penser en termes de services et non en termes de donn�es manipul�es, tu te rendras compte qu'il n'y a rien qui soit fournit par ton singleton qui doive effectivement �tre disponible strictement partout et que, si tu as besoin de certaines fonctionnalit�s propos�es par ton singleton � plusieurs endroits, tu n'as absolument aucun besoin de pouvoir acc�der � l'ensemble de ces fonctionnalit�s.
D�s lors, si tu s�pare l'ensemble des fonctionnalit�s propos�es par ton singleton en autant de fonctionnalit�s distinctes et ind�pendantes, tu gagne la libert� de ne fournir que ce dont tu as r�ellement besoin � chaque moment et, surtout, tu gagne � ne pas �tre tent� de rajouter une d�pendance dont tu aurais pu te passer.
Citation:
Et lorsque tu parles de MVC, je voulais te faire remarquer que cette grosse classe peut faire office de contr�leur et ton manager de mod�le.
Apr�s, pour diff�rentes raisons (temps de d�marrage, maintenance, �volution...), tu peux le faire �voluer en un vrai MVC.
La question que je te poserai � ce sujet est : pourquoi attendre pour d�cider d'utiliser quelque chose dont tu as la garantie que tu devra de toutes mani�res y avoir recours :question:
Il sera beaucoup plus facile pour toi de mettre directement un MVC correct en route que de commencer en regroupant les fonctionnalit�s propres au(x) contr�leur(s) et celles propres au(x diff�rents) mo�le(s) et de devoir s�parer le tout "apr�s coup" parce que tu te rend compte que cela devient ing�rable ;)
Citation:
J'ai d� mal � voir un projet/ application avec lequel/ laquelle toutes les classes ont tr�s peu de d�pendances :whistle:
D�j� la classe principale (*) est un contre-exemple.
Ou alors un petit projet, une petite application.
Tu n'as alors jamais vu les projets sur lesquels j'ai travaill�...
Certains �taient de tr�s gros projets, et on limitait pourtant les d�pendances au stricte minimum. Et il y a parfaitement moyen de le faire ;)
Citation:
Parce que c'est bien joli d'avoir une arm�e de classes � 1 responsabilit�, de pouvoir les tester individuellement (**), etc..., mais apr�s il faut mettre en place tout le ciment pour cr�er/ d�truire et aussi passer le bon objet. Sans parler de ton projet qui explose en terme de classes/ fichiers.
Le ciment � mettre en place pour g�rer cette armada de petite classe est beaucoup plus simple que celui n�cessaire pour �viter de faire tomber tout un tas de classes monolithiques, je peux te l'assurer ;)
Citation:
Ton exemple de classes: TextureFactory, TextureLoader, TextureHolder, SoundFactory, SoundLoader, SoundHolder, ... cela fait un peu peur :? :?
Pourquoi est ce qu'il te fait peur :question:
Citation:
Une mise en situation: tu codes un jeu et tu dois prendre en compte 3 types de textures (png, DXT je-ne-sais-pas-quoi, et autre chose) et 2 types de sons.
Au lieu d'avoir 5 grosses classes + 1 manager "classe d�l�gu�e" (mais il y a s�rement d'autres fa�ons de coder) (et je signale au passage que si tu cherches un algo par rapport au mp3 ou au png, tu sais exactement o� il est) tu vas avoir (3xX + 2xY) classes.
Sans parler du fait que rien pour g�rer tout cela tu vas mettre en place de l'h�ritage (certes simpliste), mais un h�ritage quand m�me. Donc (3xX + X + 2xY + Y) classes
J'aurais surement un nombre de classes plus grand que 1 ou 2, ca je te l'accorde mais :
1 - Tr�s peu d'h�ritage:
- peut �tre pour faire la distinction entre les textures "donn�es" (issues de formats comme png ou jpeg) est les textures "fonctionnelles",
- peut �tre pour faire pareil au niveau de Sound (mais aucun lien entre Sound et Texture);
- Peut-�tre, au niveau des loader permettant de charger diff�rents formats de textures ou diff�rents formats de sons (mais, encore une fois, sans liens entre les SoundLoader et les TextureLoader, autres que leur interface, peut �tre)
2- J'aurais, effectivement, une TextureFactory et une SoundFactory qui me permettraient respectivement de "centraliser" la connaissances des diff�rents types d�riv�s, ce qui me permettrait de n'avoir pas besoin de savoir autre chose que le fait que je manipule une texture ou un son partout ailleurs
3- j'aurais effectivement un TextureHolder et un SoundHolder, qui se contenteraient de maintenir les textures (respectivement les sons) en m�moire "tant qu'ils sont utilis�s"
Citation:
Je pr�vois d�j� que tu vas me r�pondre que ton IDE c'est le plus puissant de la terre (VIM, Visual, ...)
A vrai dire, � titre perso, je code g�n�ralement avec un truc aussi simple que gedit (notepad++) et en utilisant les autotools sous linux... On peut trouver assez facilement des solutions "plus puissantes" pour faire le travail ;)
Et pourtant, le nombre de fichiers / de classes ne me fait absolument pas peur ;). Par contre, ce qui m'�nerve � chaque fois, c'est de voir une s�rie de tests unitaires planter parce que j'ai eu "le malheur" de vouloir int�grer une �volution � mon projet ;)
Citation:
que tu t'en fiches tu g�res X projets en m�me temps (donc tu n'es pas � quelques classes en plus)
J'ai effectivement, plusieurs projets perso en cours...
Mais ce n'est pas pour cela que je ne suis pas � "quelques classes de plus"... Si je ne suis pas � "quelque classes de plus", c'est parce que j'ai eu tr�s largement l'occasion de me rendre compte de tous le b�n�fice que l'on peut tirer � effectivement s�parer clairement les diff�rentes fonctionnalit�s ;)
Citation:
et que je n'ai jamais cod� sur/ maintenu un gros projet monolithique.
Je ne te connais pas assez pour dire cela ;)
Citation:
Et je peux rajouter que je code que des applications pas des biblioth�ques mais avec de la conception pour reprendre et r�utiliser "une colonne vert�brale".
Et, si je ne veux r�cup�rer qu'une vert�bre :question: je fais comment :question: je prend toute la colonne vert�brale, ou j'arrive � ne prendre que L4 sans trop me casser la t�te :question:
Citation:
�videment si tu ne te contrains pas par toi-m�me, tu vas avoir une arm�e de managers :mrgreen: :mrgreen:
On arrive bientot au bout... les explications vont venir ;)
Citation:
> les descriptions d'objets devrant �tre affich�s (les points qui les composent et les vertices qui relient ces point) sont aussi des ressources :
Pourquoi des ressources? :koi: :koi: Ce sont en r�gle g�n�rale des classes avec une logique ultra-ultra r�duite. Tellement r�duite que tu peux faire une classe=une ent�te seulement.
Je voulais parler des donn�es destin�es � �tre envoy�es � OpenGL que tu r�cup�res en lisant un fichier .obj ou 3ds ;)
Citation:
Par exemple: un Point 2D: x, y - un �l�ment dans une liste plate (
listview par exemple): texte ID - un utilisateur: ID, nom, pr�nom, soci�t�.
> une base de donn�e, pareil
C'est ce que j'appelle des "
App Datas"
Pour moi, il y a 2 types de "
App Datas"
- Beaucoup d'attributs, quasi aucune logique. Un "gros panier" (tr�s souvent en lecture seule) qu'on passe d'un objet � un autre.
- Tr�s peu d'attributs, mais beaucoup de logique. Par exemple: une base de donn�e. Tu vas avoir 2-3 "handles" et � c�t� toutes tes requ�tes SQL (et �ventuellement des proc�dures stock�es et des triggers).
Tout d�pend de la d�finition que tu fais du terme "ressources".
Le vrai probl�me, c'est que m�me si tu te limite aux seules "ressources informatiques" (en g�n�rale), la d�finition de ce terme est proche (selon wikipedia) de
Citation:
Envoy� par wikipedia
En informatique, les ressources sont des composants, mat�riels ou logiciels, connect�s � un ordinateur. Tout composant de syst�me interne est une ressource. Les ressources d'un syst�me virtuel incluent les fichiers, les connexions au r�seau, et les zones de m�moire.
En cela, ce que tu appelle App Datas ne sont rien d'autre que... des ressources ;)
Citation:
> Et le pire de tout, c'est sans doute la configuration
Pour moi, la configuration ce sont 2 m�thodes load/ save + une structure :mrgreen:
M�me une configuration comme Apache je ne pense pas que ce soit diff�rent.
Non, les fonctions load et save ne sont que les parties visibles de l'iceberg...
La partie non visible, c'est que, m�me s'il ne s'agit que d'une structure "POD", c'est bel et bien une ressource (quelque chose qui utilise de la m�moire) et qui utilis� quasiment partout dans le code, parce que l'on y m�lange all�grement les donn�es de configuration de tout et de n'importe quoi (ex : taille et r�solution d'affichage, volumes sonores divers, adresses des serveurs � contacter, nom d'utilisateur, ...)
Citation:
Et comme tu ne sauvegardes pas ta configuration souvent, ta grosse classe(*) peut la g�rer toute seule.
Je ne dis pas que la classe qui sert de point d'entr�e de l'application ne doit pas g�rer ta configuration d'une mani�re ou d'une autre; je dis:
- que tu ne devrais pas avoir besoin de passer par ta classe "point d'entr�e de l'applicaiton" pour acc�der � la configuration
- que tu n'a jamais besoin de toutes les donn�es que la configuration met � ta disposition :
- si tu est dans un contexte d'affichage, c'est la taille et la r�solution de l'�cran qui t'int�ressent;
- si tu est dans un contexte de requ�te SQL / connexion � un serveur, ce sont les adresses du serveur, le nom d'utilisateur,... qui t'int�ressent;
- si tu es dans un contexte sonore, ce sont les volumes sonores qui t'int�ressent
- ...
Citation:
Surtout que la configuration est charg�e au lancement.
Oui, elle sera sans doute charg�e au lancement de l'application et sauvegard�e (si modifi�e) � la fermeture de l'application.
Citation:
Et au passage, tu n'as pas de Configuration Manager en m�moire pour rien.
Ben, je dis justement qu'on n'en a pas besoin... En tout sous la forme d'un "gestionnaire de configuration", et surtout pas si cela sous entend de maintenir la configuration des diff�rents "modules" de notre application "m�lang�s" au sein d'une seule structure.
Je suis tout � fait d'accord pour dire qu'il doit "forc�ment" y avoir un endroit o� l'on regroupera toutes les configurations de tous les modules (ne serait-ce que parce que la configuration de tous les modules peut se retrouver dans un seul et unique fichier de configuration).
Mais on n'a absolument aucun besoin de savoir comment sont trait�s les sons quand on essaye de se connecter � un serveur distant!
[/QUOTE]
C'est s�r que si tu fais un manager sans r�fl�chir cela va �tre compliqu� par la suite :mrgreen:
Pour moi un manager c'est une "classe d�l�gu�e" vers des objets concrets qu'il contient. Une sorte de proxy, interface, ou patron de conception du m�me style.
Mais, ce que je fais, (<- Un gros mais), ton manager expose que des m�thodes classiques et/ ou "en lecture seule".
Pour un Texture Manager: get_texture/ list_textures.
Pour un Sound Manager: get_sound/ list_sounds.
Ainsi, tu peux facilement �changer les classes concr�tes: MP3_Sound_Manager, WAV_Sound_Manager.
[/QUOTE]Que le son soit au format mp3, au format wav ou au format whatTheFuck, tu t'en fous royalement... tout ce qui t'importe, c'est de pouvoir le jouer ;)
Et c'est justement parce que tu esp�re pouvoir profiter des comportements polymorphes pour tes sons ou tes textures (text.drawIt(context); pour une texture; sound.playIt(context); pour un son) qu'il est important de limiter la tentation de l'utilisateur de "celui qui r�cup�re une texture / un son" de chercher � savoir "quel en est le type r�el".
Et c'est pour cela qu'il est important de s�parer clairement les diff�rentes responsabilit�s (qui cr�e la texture ou le son, qui la/le charge, qui la/le maintient en m�moire), de mani�re � ce que l'utilisateur puisse recevoir une "r�f�rence" (qui sera en r�alit� un pointeur ou une r�f�rence C++) sur "une texture" ou sur "un son" et pour qu'il puisse savoir qu'il "doit faire avec", sans essayer de r�cup�rer le "type r�el" de sa texture ou de son son.
Citation:
Et � c�t� de cela, pr�voir un syst�me via ton Manager (***) pour r�cup�rer un objet concret et avoir une interface sp�cifique �tendue:
MP3_Sound_Manager::create_sound(), JPG_Texture_Manager::set_compression_level(), ...
Mais ca, c'est pas le gestionnaire qui doit s'en occuper...
la cr�ation d'un son est un m�canisme dont l'utilisateur n'a absolument rien � foutre et qui devrait �tre d�l�gu� � une fabrique (qui se d�charge d'une partie du travail sur diff�rents Loaders) et r�glage du niveau de compression JPEG, ca se g�re exclusivement au niveau de la s�rialisation (chargement /sauvegarde) du fichier.
Alors, que tu aies une fonction add(filename) qui passe par la fabrique pour ajouter une texture ou un son (selon ce que tu manipules) est tout � fait coh�rent, mais l'utilisateur de ce qui devient un TextureHolder ou un SoundHolder (une classe qui se contente de fournir les services relatifs au maintient des sons/des textures en m�moire) n'a absolument pas besoin de savoir comment le son / la texture ajout�e a �t� cr��e (et au paravant charg�e).
Citation:
D'ailleurs, je ne pense pas que ces m�thodes sp�cifiques soient utiles partout :mrgreen: :mrgreen:. Juste � des endroits pr�cis.
Raison de plus pour ne pas les rendre accessibles partout parce que disponibles dans l'interface d'une classe qui, par nature, risque de se retrouver "n'importe o�"...
Citation:
Toujours le m�me principe :whistle:: cela ne me d�range pas que ma classe Manager soit utilis�e � pleins d'endroits.
Parce que 0) c'est un peu son r�le (comme un frigo dans une cuisine) 1) j'ai contrains un grand nombre de ses m�thodes en lecture seule 2) effet "bottle neck" avec un point d'arr�t dans le manager 3) avec une recherche, je trouve toutes les occurrences
Tu obtiens exactement le m�me r�sultat mais en mieux en s�parant ton manager "monolithique" en diff�rentes classes aux responsabilit�s restreintes car:- C'est le role d'un TextureHolder de maintenir les textures en m�moire tant que tu en as besoin (mais c'est aussi celui d'un SoundHolder, sauf que tu n'auras que des sons ou des textures ;), un peu comme un frigo dans une cuisine
- tu mes un points d'arr�t sur un TextureHolder et tu es sur que chaque fois que tu passe sur ce point d'arr�t, c'est parce que tu manipule une texture. M�me chose pour les sons et ton SoundHolder, et pour n'importe quel autre type de ressource
- la recherche de ton instance de TextureHolder ou de ton instance de SoundHolder est beaucoup plus pr�cise que celle de ton Manager car tu n'en a rien � foutre des circonstances dans lesquelles tu manipules un son si tu cherche celles o� tu manipule une texture (et vice versa)
D�sol�, pour finir, je ferai mon spitch sur les "manager" demain ;)