Facade, interface publique et interface "privee"
Le
Jean-Marc Bourguet
J'ai une classe qui est une Facade vers un sous systeme. Elle a donc
en membres publics les fonctions d'interfacage prevue pour etre
utilisee a l'exterieur du sous-systeme.
Le probleme est que les autres classes du sous-systeme ont besoin
d'acceder a des fonctions qui ne doivent etre utilisee que par le
sous-systeme.
Solutions possibles:
o mettre toute ces autres classes en friend de la classe Facade; ca
fait beaucoup d'amis, ca force certaines operations qui peuvent etre
implementee dans des namespaces prives a etre membre de ces classes
ou des fonctions publiques pour que ces fonctions soient friend, ca
empeche d'avoir des vraies fonctions privees a la Facade.
o faire une classe (friend de Facade, donc ce ne peut pas etre un
namespace) qui n'a que des membres statiques fournissant l'interface
supplementaires accessibles aux composants du sous-systeme.
L'indirection me gene.
o rendre protected l'interface "privee", faire une classe descendant
de Facade qui a des membres publics qui renvoient a cette interface
privee. A nouveau l'indirection me gene et la maniere d'avoir acces
a la classe fournissant l'interface privee n'est pas claire (ok, un
cast du pointeur fonctionne si on s'arrange pour ne construire que
des objects de cette classe, mais bon).
Quelqu'un a-t'il d'autres alternatives?
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
en membres publics les fonctions d'interfacage prevue pour etre
utilisee a l'exterieur du sous-systeme.
Le probleme est que les autres classes du sous-systeme ont besoin
d'acceder a des fonctions qui ne doivent etre utilisee que par le
sous-systeme.
Solutions possibles:
o mettre toute ces autres classes en friend de la classe Facade; ca
fait beaucoup d'amis, ca force certaines operations qui peuvent etre
implementee dans des namespaces prives a etre membre de ces classes
ou des fonctions publiques pour que ces fonctions soient friend, ca
empeche d'avoir des vraies fonctions privees a la Facade.
o faire une classe (friend de Facade, donc ce ne peut pas etre un
namespace) qui n'a que des membres statiques fournissant l'interface
supplementaires accessibles aux composants du sous-systeme.
L'indirection me gene.
o rendre protected l'interface "privee", faire une classe descendant
de Facade qui a des membres publics qui renvoient a cette interface
privee. A nouveau l'indirection me gene et la maniere d'avoir acces
a la classe fournissant l'interface privee n'est pas claire (ok, un
cast du pointeur fonctionne si on s'arrange pour ne construire que
des objects de cette classe, mais bon).
Quelqu'un a-t'il d'autres alternatives?
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Poser une question


un bloc d'accès public/protected/private. J'en souffre
régulièrement, lorsqu'il s'agit justement, au sein d'une même
classe, de mêler parties "fonctionnelles" (service exposé) et parties
"techniques" (collaboration avec le framework de l'application).
Comme je ne veux pas m'embarrasser d'une complexité supplémentaire
dans mon diagramme de classe, uniquement parce qu'il manque cette
portée réduite, j'emploie cette solution, MAIS en plaçant le
'friend' à la fin du bloc protected/private de déclaration des
membres qui le concernent. Je fais donc autant de blocs
private/protected que j'ai de portées de 'friend' différentes.
C'est purement visuel et malheureusement pas contrôlé par le
compilateur.
J'avais suggéré il y a quelques temps dans je ne sais plus quel
newsgroup sur le C++, l'idée que réduire la portée des 'friends'
pourrait être utile. Cela n'avait pas été compris, et l'on me
proposait plutôt de monter des usines à gaz pour quelque chose qui
devrait rester simple à exprimer.
pas encapsuler l'instance de la façade?
Pour moi, ce n'est pas l'indirection qui gêne, mais plutôt la
nécessité de créer une classe de plomberie pour contourner une
fonctionnalité manquante peu couteuse du C++.
En utilisant un outil de parsing et de génération de code comme
CodeWorker (http://www.codeworker.org), il serait facile de générer
l'indirection et de maintenir sa mise à jour automatiquement en cas de
changement de l'interface accessible aux composants du sous-système.
sous-classe ne doit pas être connue de l'extérieur, par les
utilisateurs des services de la façade (on n'expose pas le header
C++). Un peu selon le principe d'une interface. D'ailleurs, il faudrait
interdire l'instanciation de la classe mère de la façade, pour plus
de précaution (rendre tous les constructeurs protected).
Au sein des composants du système, il suffira donc de dynamic-caster
la façade en sa sous-classe pour travailler dessus.
Pour la redirection, l'automatiser comme pour la solution 2.
Personnellement, je retiendrais les solutions 1 et 3.
L'inconvénient de la première est que les 'friends' étendus à
l'ensemble des membres sont une insulte à une belle conception, et
dénaturent l'usage des accès réglementés protected/private... En
attendant que le C++ offre la portée réduite? Ce n'est pas la
solution à retenir sur un projet en équipe, à mon avis (propreté +
élégance sont importants pour bien supporter les futures
évolutions/refactorings du code, faits par des développeurs qui
ignoreront peut-être la présence/signification/origine de ces
'friends').
L'inconvénient de la dernière solution est qu'elle oblige à créer
une classe supplémentaire, conduisant à maintenir la redirection des
membres privés. Sachant que l'écriture de la redirection peut
s'automatiser, cette solution reste la plus élégante : on expose
quelque chose qui ressemble à une interface, et on peut le manipuler
au sein du framework. Je vote pour!
Cédric
Si j'ai bien compris le problème, j'aurais bien vu quelque chose du genre :
- une classe façade contenant toutes les fonctions nécessaires à tout
le monde (externe et interne) ;
- une classe façade cliente de la première qui réduit l'interface pour
l'extérieur
En gros, c'est le contraire de ta deuxième solution, mais sans avoir
besoin de friend.
Mais je n'ai peut-être pas bien compris le problème...
--
Arnaud
Non, c'est bien ca. C'est aussi une solution. (Tout comme d'ailleurs
une reanalyze de la Facade pour voir si c'est bien necessaire.).
A+
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
'friend'.
Finalement, j'ai une préférence pour une cinquième solution : classe
interface de la façade avec uniquement les membres publiques; classe
d'implémentation héritant de la façade, et implémentant les membres
publics + privés (ces derniers ne sont visibles qu'à ce niveau). Les
sous-composants doivent dynamic-caster dans la classe
d'implémentation, pour bénéficier de l'interface "privée" (non
exposée aux utilisateurs de la façade).
Pas de redirection. Pas de 'friend' non plus.
N.B. : on arrive toujours à se passer de 'friend' (contre-exemples?),
mais au prix de plus de code à taper et dont il faut maintenir la
cohérence. Ce qui n'est pas toujours souhaitable.
Mais la facade se met a comporter une tonne de membres virtuels (alors
qu'elle n'en a aucun pour le moment).
--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++...index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org