Bonjour � tous,
Je reviens avec un probl�me similaire � celui ci : http://www.developpez.net/forums/d16...t-get-classes/ dont j'�tais d�j� l'auteur.
Pour r�sum� et vous �viter de (re)lire l'ancien post, mon projet se compose de :
* une petite dizaines de classes A, B, C ... qui repr�sentent des objets sp�cialis�s.
* une classe "core" qui s'occupe de faire �voluer en fonction du temps ma dizaine d'objets issus des classes A, B, C ...
* une classe "ui"
qui s'occupe de g�rer les interactions clavier/souris/joysticks qui utilise "core"
par exemple, l'appui sur une touche du clavier ex�cute la fonction correspondante � l'action cod�e dans "core" repr�sent�e par la touche.
* une classe "menu"
qui s'occupe d'un menu textuel qui utilise "core"
j'ai un menu qui est compos� d'une liste de commandes (repr�sent�es par des strings). lorsque l'on s�lectionne une commande, la classe menu ex�cute la fonction correspondante � l'action cod�e dans "core" repr�sent�e par la string.
* une classe "Script_Executor"
qui s'occupe de g�rer un langage de script fait maison qui utilise "core" (d�crite sch�matiquement ci dessous)
par exemple, la lecture d'une ligne de script ex�cute la fonction correspondante � l'action cod�e dans "core" repr�sent�e par la ligne de script correspondante.
ma classe "core" ressemble � ceci
En gros, j'ai trois classes qui utilisent massivement les fonctions de la classe code qui elle s'occupe des 10 objets.
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 // A, B , C , D... environ 10 classes ayant chacune 3 à 7 paires de get/set et d'appels de fonctions publiques à la classe en question. class A { private: double m_a1; int m_a2; bool m_a3; public: A() : m_a1(0), m_a2(0), m_a3(false) {} double get_a1() const {return m_a1;} int get_a2() const {return m_a2;} bool get_a3() const {return m_a3;} void set_a1(double a1) {m_a1 = a1;} void set_a2(int a2) {m_a2 = a2;} void set_a3(bool a3) {m_a3 = a3;} void fctA1(...) {...} void fctA2(...) {...} }; class B { private: double m_b1; double m_b2; bool m_b3; public: B() : m_b1(0), m_b2(0), m_b3(false) {} double get_b1() const {return m_b1;} double get_b2() const {return m_b2;} bool get_b3() const {return m_b3;} void set_b1(double b1) {m_b1 = b1;} void set_b2(double b2) {m_b2 = b2;} void set_b3(bool b3) {m_b3 = b3;} void fctB1(...) {...} void fctB2(...) {...} }; // core a une instance de chacune des classes ci-dessus class core { private: A m_a; B m_b; // ... //fonctions spécifiques et privées de core public: double get_a1() const {return m_a.get_a1();} int get_a2() const {return m_a.get_a2();} bool get_a3() const {return m_a.get_a3();} double get_b1() const {return m_b.get_b1();} double get_b2() const {return m_b.get_b2();} bool get_b3() const {return m_b.get_b3();} // ... void set_a1(double a1) {m_a.set_a1(a1);} void set_a2(int a2) {m_a.set_a2(a2);} void set_a3(bool a3) {m_a.set_a3(a3);} void set_b1(double b1) {m_b.set_b1(b1);} void set_b2(double b2) {m_b.set_b2(b2);} void set_b3(bool b3) {m_b.set_b3(b3);} // ... void fctA1(...) { A.fct1(...);} void fctA2(...) {A.fct2(...);} void fctB1(...) {B.fct1(...);} void fctB2(...) {B.fct2(...);} void fctB3(...) {B.fct3(...);} void fctB4(...) {B.fct4(...);} // ... //fonctions spécifiques et publiques de core }; class Script_Executor { private: core& m_core; // ... public: Script_Executor(core& param) : m_core(param) {} double get_a1() const {return m_core.get_a1();} int get_a2() const {return m_core.get_a2();} bool get_a3() const {return m_core.get_a3();} double get_b1() const {return m_core.get_b1();} double get_b2() const {return m_core.get_b2();} bool get_b3() const {return m_core.get_b3();} // ... void set_a1(double a1) {m_core.set_a1(a1);} void set_a2(int a2) {m_core.set_a2(a2);} void set_a3(bool a3) {m_core.set_a3(a3);} void set_b1(double b1) {m_core.set_b1(b1);} void set_b2(double b2) {m_core.set_b2(b2);} void set_b3(bool b3) {m_core.set_b3(b3);} // ... };
J'avais d�j� demand� de l'aide parce que core �tait embouteill� par trop de fonctions getClasseAMachin1() setClasseBMachin3() ... au point d'�tre illisible.
C'est toujours le cas.
J'ai �cout� vos remarques, acheter le livre "coder efficacement Bonnes pratiques et erreurs � �viter (en C++)" et je me suis retrouss� les manches.
La lecture du livre m'a permis entre autre de prendre connaissance de la loi de Demeter et des principes S.O.L.I.D. (au point de changer ma vie de programmeur.. Vraiment !!)
Maintenant mon application est un v�ritable chantier. Mon code se "clarifie" m�me si mes coll�gues voient surtout que je me focalise sur l'existant sans rien apporter de nouveau sur le court terme. Ce qui n'est pas la question.
J�ai parcouru mon projet, et j'ai recherch� � appliquer le plus possible la loi S de SRP. Ce fut tr�s enrichissant et intellectuellement stimulant.
J'ai modifi� les RTTI qui servaient de tests de base en grand nombre.
Je suis all� � la chasse aux set/get discutables en m�effor�ant de penser aux comportements et pas qu'aux donn�es.
Mais je bloque sur le principe ISP.
Dans mon projet clairement, "core" appara�t comme un "god object" qui contient tout et qui s'occupe de tout. Je suis arriv� � une classe quig�resynchronise ses objets (en fonction du temps) ET qui propose aux autres classes utilisatrices "ui", "menu" et "Script_Executor" des fonctions passerelles afin de respecter la loi de Demeter. Typique:
dans mes classes utilisatrices, j'ai par exemple la fonction:
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4 void core::flipTimeClasseA() { return classeA->flipTime; }
Voila pour la pr�sentation de mon probl�me. (D�sol� de la longueur !!!! )
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2 core->flipTimeClasseA();
Des solutions ?
J'ai cherch�, je ne suis pas rest� passif:
- j'ai cass� la loi de Demeter sur 2-3 objets [pour tester] et r�alis� un
dans mes classes utilisatrices, j'ai �cris :
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2
3
4 ClasseA* getClasseA() { return classeA; }
Option Core c'est le top, j'ai 15 fonctions en moins! Si je continue ainsi apr�s 10 getClasseXXX, mon fichier " core" est enfin d�pollu� de tous ce qui m�emb�tait alors. D'un point de vu personnel, j'ai rendu l'�criture du code plus complexe. Pour programmer la suite de l'application, il est n�cessaire alors d'avoir en t�te toutes les fonctions publiques ... la port�e des fonctions �taient avant d'un niveau (exemple: classeA vers core) et passe maintenant � 2 niveaux (exemple: classeA vers Core vers UI) . Je suis en d�faut par rapport au DIP
Code : S�lectionner tout - Visualiser dans une fen�tre � part
1
2 core->getClasseA()->flipTime();
Je n'en suis pas content.
- je cr�e une classe "core_acess"
C'est � dire une classe vide amie avec "core" qui reprend toutes les fonctions passerelles de core en acc�dant � la partie priv�e de "core" et qui sera alors l'interm�diaire entre "core" et les classes utilisatrices "Script_Executor", "menu", "ui".
Je n'en suis pas content non plus. j'ai l'impression alors de d�placer mon probl�me ailleurs et de ne pas mieux coller au principes du S.O.L.I.D.
Qu'en pensez vous ?
Que feriez vous � ma place ?
PS: merci d'�tre arriv� au bout de mon post, j'ai moi m�me cru ne pas y arriver.![]()
![]()
![]()
Partager