IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Design Patterns Discussion :

[Java] Pattern Facade et accès aux packages [Facade]


Sujet :

Design Patterns

  1. #1
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut [Java] Pattern Facade et accès aux packages
    Salut tout le monde,

    Bon je vais essayer d'être concis...
    Mon pb vient avec l'utilisation du design pattern Facade. Celui-ci me permet de "masquer" les autres classes de mon package et je voudrais aller un peu plus loin et "interdire" l'accès à ces autres classes afin de ne pas seulement proposer une interface de communication mais d'imposer l'utilisation de cette Facade.

    Je vais illustrer mes propos en vous schématisant l'architecture de mon appli :
    - Le package mon.package qui contient Facade
    - le package mon.package.businesslogic : Les interfaces qui définissent la couche métier de l'appli
    - le package mon.package.factory : Les factories qui me permettent de construire les objets métiers de mon appli (du package businesslogic)
    - le package mon.package.businesslogic.impl : l'implémentation des interfaces définissant la couche métier
    - le package mon.package.dao : La couche d'accès aux données.

    Je voudrais interdire l'accès aux packages businesslogic.impl et dao pour toutes les classes ne faisant pas parties du package mon.package. Cela permettra lors de la réalisation de l'interface graphique de garantir que seules les méthodes "autorisées" seront utilisées et qu'aucun développeur ne sera tenté d'appeler directement les méthodes des classes dao au lieu d'utiliser les fonctionnalités de la classe Facade.

    Voilà j'espère que qqu'un aura compris mon pb et que mieux encore il aura une solution à proposer!!

    Merci d'avance

    Manu

  2. #2
    Membre actif Avatar de bidi
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    262
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2004
    Messages : 262
    Points : 266
    Points
    266
    Par défaut
    Hmmm je n'ai pas l'impression que ce soit possible (je me trompe peut-être mais...)
    Le pattern façade permet de donner une vue simplifiée, de rajouter une couche d'abstraction, mais les fonctionnalités sous-jacentes peuvent quand même être accédées individuellement si on le désire...
    Le seul moyen que je vois est de ne pas documenter tes autres classes :-)

  3. #3
    Membre chevronné
    Avatar de Deadpool
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    1 312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 1 312
    Points : 2 011
    Points
    2 011
    Par défaut
    Ou alors,mais pas très propre, tu met toutes tes classes dans mon.package et tu vire le public devant la déclaration de tes classe sauf bien sur pour la classe Facade. Le modificateur par défaut correpondant à une vue package-view, les classes extérieures aux package mon.package n'auront pas accès à tes autres classes. Facade y aura bien accès puisqu'il fait partie du package. Et les classes extérieures auront bien accès à Facade puisqu'elle est déclarée en public.

    Il faut aussi plomber le package pour éviter que des petits malins tentent d' accéder à tes classes planquées en déclarant que leur classe fait partie de mon.package.

    -"Tout ça me paraît très mal organisé. Je veux déposer une réclamation. Je paye mes impôts, après tout!"
    -"JE SUIS LA MORT, PAS LES IMPÔTS! MOI, JE N'ARRIVE QU'UNE FOIS".

    Pieds d'argile (1996), Terry Pratchett 1948 - 2015
    (trad. Patrick Couton)

  4. #4
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut
    Merci,
    J'espérais une réponse un peu plus enthousiaste mais j’ai déjà pas mal galérer avant de poster ce message alors je n’étais pas trop optimiste (j’ai déjà essayé en trafiquotant les modificateurs d’accès sans succès ).
    Ta solution de ne pas documenter c’est un peu barbare qd même!
    J’ai tjs la solution de mettre toutes les classes dans le même package et de ne rendre publiques que celles qui doivent être vues de l’extérieur mais je ne trouve pas ça très joli ni très pratique qd on a un bon paquet de classes…


  5. #5
    Membre chevronné
    Avatar de Deadpool
    Homme Profil pro
    Inscrit en
    Novembre 2005
    Messages
    1 312
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2005
    Messages : 1 312
    Points : 2 011
    Points
    2 011
    Par défaut
    Le problème de java c'est qu'il ne gère pas de hierarchie de package comme il peut le faire pour les classes.

    Ca c'est dommage.

    -"Tout ça me paraît très mal organisé. Je veux déposer une réclamation. Je paye mes impôts, après tout!"
    -"JE SUIS LA MORT, PAS LES IMPÔTS! MOI, JE N'ARRIVE QU'UNE FOIS".

    Pieds d'argile (1996), Terry Pratchett 1948 - 2015
    (trad. Patrick Couton)

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Points : 568
    Points
    568
    Par défaut
    Certains te dirais que tu ne peux pas empecher un mauvais developpeur de faire n'importe quoi , du moment que tu documente bien et que tu precise bien de passer par la facade , tu as ta conscience pour toi !!
    UML avec VIOLET

  7. #7
    Membre actif Avatar de bidi
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    262
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2004
    Messages : 262
    Points : 266
    Points
    266
    Par défaut
    Sinon j'ai un truc crade :-p :-D
    Tu passes par réflexion dans ta façade et tu mets tes constructeurs en private :-)

  8. #8
    Membre actif Avatar de bidi
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    262
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2004
    Messages : 262
    Points : 266
    Points
    266
    Par défaut
    Par exemple tu déclare une classe Loader comme suit:

    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
    public class Loader {   
         
        /**
         * Constructeur privé
         */
        private Loader(){
            //
        }
        
        public void someMethod() {
           //
        }
    
    }
    puis dans ta façade tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Loader load = (Loader) Loader.class.newInstance();
    puis tu peux appeller les méthodes de Loader puisqu'elles sont publiques ;-)

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2003
    Messages
    509
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations forums :
    Inscription : Avril 2003
    Messages : 509
    Points : 568
    Points
    568
    Par défaut
    Citation Envoyé par bidi
    Par exemple tu déclare une classe Loader comme suit:

    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
    public class Loader {   
         
        /**
         * Constructeur privé
         */
        private Loader(){
            //
        }
        
        public void someMethod() {
           //
        }
    
    }
    puis dans ta façade tu fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Loader load = (Loader) Loader.class.newInstance();
    puis tu peux appeller les méthodes de Loader puisqu'elles sont publiques ;-)
    Et voila patatra tu viens de donner la solution aux utilisateur du package pour ne pas passer par la facade .
    Effectivement cette solution est pas propre mais elle fonctionnerais , sauf qu'en lisant le code de la facade , l'utilisateur pourrat tres facilement en faire autant !!
    UML avec VIOLET

  10. #10
    Membre actif Avatar de bidi
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    262
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2004
    Messages : 262
    Points : 266
    Points
    266
    Par défaut
    Ben ui, y'a pas de solution miracle ;-p ce n'est qu'un 'workaround' mais ça peu peut-être le dépanner ;-)

  11. #11
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut
    Merci pour ces idées originales!
    Bon je crois que finalement je vais garder ma conscience pour moi comme on me l'a proposé et que je vais éviter les trucs crades (même si j'apprécie l'idée!).
    Et je vais fouetter les développeurs qui n'utilisent pas la facade

  12. #12
    Membre chevronné
    Avatar de afrikha
    Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    1 600
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2005
    Messages : 1 600
    Points : 2 208
    Points
    2 208
    Par défaut
    Petite précision: le design pattern façade permet d'avoir une interface pour dialoguer avec un système sous-jacent complexe mais rien n'interdit de faire appel directement au sous-système.
    Voilà ça ne résout pas ton problème je sais, mais c'est juste pour éclairer un peu l'intention du design pattern façade.


    Mes publications
    Lisez
    Les régles du forum
    Pensez au bouton

  13. #13
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut
    C'est bien ce que j'avais compris pour le pattern facade mais j'espérais pouvoir forcer son utilisation...

  14. #14
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Dans le fonctionnement interne de ta facade, tu peux initialiser une variable ThreadLocal qui sera utilisé par les autres éléments de ton package.
    Si le ThreadLocal n'est pas initialisé, tu peux en déduire que tu n'es pas passé par la facade et partir en erreur technique (unchecked pour ne pas pourrir la signature des méthodes).
    Je vois bien cette solution implémentée avec une classe interne qui se chargera de l'accès au ThreadLocal (pas le temps d'ecrire le code, ptet tout a l'heure), pas très difficile et mutualisable sous forme d'un aspect avec l'aide d'un proxy dynamique (cela suppose l'utilisation de bonnes pratiques objet et de l'utilisation d'interfaces).

  15. #15
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut
    Je vais me pencher sur l'
    aspect avec l'aide d'un proxy dynamique
    car j'ai un peu du mal à tout bien situer mais je pense avoir à peu près compris ce que tu proposes.
    Si tu veux donner un morceau de code pour être sur que le message soit bien compris je n'ai rien contre !!!
    Merci en tout cas

  16. #16
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Première étape, définir des interfaces :
    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
    public interface Facade {
        public void doTiti();
        public void doToto();
        public void doTata();
        public SecuriteFacade getSecuriteFacade();
    }
    
    public interface SecuriteFacade {
        public boolean isPasseParFacade() throws SecuriteFacadeException;
    }
    
    public interface Dao1 {
        public void doLoad1();
        ...
    }
    
    public interface Dao2 {
        public void doLoad2();
        ...
    }
    Voila le code de la facade :
    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
    public class FacadeImpl implements Facade {
        private class SecuriteFacadeImpl implements SecuriteFacade {
            private static ThreadLocal passageDansFacade = new ThreadLocal();
    
            public SecuriteFacadeImpl() {
                passageDansFacade.set(Boolean.FALSE);
            }
            public boolean isPasseParFacade() throws SecuriteFacadeException {
                return ((Boolean)passageDansFacade.get()).booleanValue();
            }
    
            public void setPassageParFacade(boolean valeur) {
                passageDansFacade.set(new Boolean(valeur));
            }
        }
    
        public SecuriteFacadeImpl secu = new SecuriteFacadeImpl();
    
        public SecuriteFacade getSecuriteFacade() {
            return secu;
        }
    
        public void doToto() {
            secu.setPassageParFacade(true);
            ...
            secu.setPassageParFacade(false);
        }
        ...
    }
    Une classe helper :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class SecuriteFacadeUtils {
        ...
        public SecuriteFacadeUtils(SecuriteFacade secu) {
            this.secuFacade = secu;
        }
        public boolean estPasseParFacade() {
            return secuFacade.isPasseParFacade();
        }
    }
    Le code valable pour les DAO :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class Dao1Impl implements Dao1 {
        ...
        public void doLoad1() {
            secuFacadeUtil.estPasseParFacade();
            ...
        }
        ...
    }
    Concernant ce que je disais par rapport à l'aspect avec un proxy dynamique, j'ai dit une betise. Pour bien faire, il faudrait utiliser AspectJ car l'utilisation d'un proxy dynamique ne garantit en rien que le développeur n'utilisera pas l'objet wrappé directement.

    Pour info : http://java.sun.com/j2se/1.3/docs/guide/reflection/proxy.html

  17. #17
    Membre habitué Avatar de manube
    Homme Profil pro
    Responsable sécurité
    Inscrit en
    Mai 2004
    Messages
    180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations professionnelles :
    Activité : Responsable sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 180
    Points : 178
    Points
    178
    Par défaut
    Merci pour ces conseils éclairés!
    C'était bien ce que je pensais avoir compris mais par contre il me reste une petite question:
    Pourquoi utilises tu un ThreadLocal et pas simplement un boolean?

    Par contre je connaissais la programmation par Aspect que de nom et c'est vrai que ca a l'air plus qu'intéressant. Ca pourrait permettre de déléguer toute cette gestion à un aspect... donc peut-être même (je m'avance) de simplifier encore plus ton code... mais bon je m'avance...

  18. #18
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Citation Envoyé par manube
    Merci pour ces conseils éclairés!
    C'était bien ce que je pensais avoir compris mais par contre il me reste une petite question:
    Pourquoi utilises tu un ThreadLocal et pas simplement un boolean?
    Parceque je considerais que tu utilisais une seule instance de FacadeImpl et qu'elle devait donc être thread-safe.

    Citation Envoyé par manube
    Par contre je connaissais la programmation par Aspect que de nom et c'est vrai que ca a l'air plus qu'intéressant. Ca pourrait permettre de déléguer toute cette gestion à un aspect... donc peut-être même (je m'avance) de simplifier encore plus ton code... mais bon je m'avance...
    On peut simplifier mon code, mais pour cela il faut utiliser AspectJ ou un outil intervenant au niveau du byte-code. L'utilisation d'un framework plus léger basé sur des proxy dynamiques ne suffit pas à garantir la non utilisation de ta classe en dehors de la démarcation matérialisée par la facade.

    Une autre solution, un objet qui lance une exception et vérifie la stack trace :
    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
    public class Dao1Impl implements Dao1 {
        public LaClasseSecu secu;
    
        public void doLoad1() {
            secu.assertEstPasseParFacade();
            ...
        }
    }
    
    public class LaClasseSecu {
        public void assertEstPasseParFacade() throws RuntimeSecuFacadeException{
            try {
                throw ExceptionBidon();
            }
            catch (ExceptionBidon e) {
                StackTraceElement[] st = e.getStackTrace();
                boolean passeParFacade = doRechercheClass(FacadeImpl.class);            
                if (!passeParFacade)
                    throw RuntimeSecuFacadeException();
            }
        }
    ...
    }
    Avantage : pas de code dans la facade et également modélisable dans un aspect

  19. #19
    Membre confirmé Avatar de Satch
    Homme Profil pro
    Hypnothérapeute - Magicien
    Inscrit en
    Mars 2004
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Suisse

    Informations professionnelles :
    Activité : Hypnothérapeute - Magicien

    Informations forums :
    Inscription : Mars 2004
    Messages : 498
    Points : 645
    Points
    645
    Par défaut
    On est obligé de lancer une exception pour vérifier la stackTrace ?
    Parce que bon, c'est couteux.
    Je sais que désormais vivre est un calembour,
    La mort est devenue un état permanent,
    Le monde est aux fantômes, aux hyènes et aux vautours.
    Moi je vous dis bravo et vive la mort.

  20. #20
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par Satch
    On est obligé de lancer une exception pour vérifier la stackTrace ?
    Non on n'est pas obligé de la lancer. On peut se contenter de la créer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StackTraceElement[] st = new Exception().getStackTrace();
    Et avec Java 5.0 on peut même passer par la classe Thread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    StackTraceElement[] st = Thread.currentThread().getStackTrace();
    Citation Envoyé par Satch
    Parce que bon, c'est couteux.
    Ce qui est coûteux ce n'est pas de lancer l'exception, mais bien la génération du stack (cf ce message sur mon blog : Exception & Performance), donc dans tout les cas ce sera assez coûteux...

    Il faudrait donc limiter cela au developpement et le désactiver en release, soit via des aspects comme l'indique dlemoing, voir de la "compilation pseudo-conditionnelle" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (DEBUG==true) {
           assertEstPasseParFacade();
    }
    Voir même via les assert (code Java 1.4 minimum) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    assert assertEstPasseParFacade();
    a++

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Accès aux éléments de Java par défaut?
    Par sonia5 dans le forum Général Java
    Réponses: 3
    Dernier message: 25/01/2010, 20h47
  2. Accès aux sites https://subdomain.java.net impossible
    Par hugo123 dans le forum Général Java
    Réponses: 14
    Dernier message: 22/10/2009, 16h42
  3. packages et acces aux modules
    Par jfouche dans le forum Général Python
    Réponses: 7
    Dernier message: 04/10/2008, 11h45
  4. Erreur Java Accès aux données
    Par srenon dans le forum BIRT
    Réponses: 6
    Dernier message: 04/07/2007, 22h34
  5. [Corba/Java] Accès aux objets
    Par soa dans le forum CORBA
    Réponses: 4
    Dernier message: 16/01/2007, 19h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo