Commentaires

  1. Avatar de Gugelhupf
    • |
    • permalink
    Bonjour @avdyk,

    Merci pour ton retour, en ce qui concerne la clarté, la documentation Oracle dit (source) :
    its purpose is to help design more-comprehensible APIs so that by just reading the signature of a method, you can tell whether you can expect an optional value. This forces you to actively unwrap an Optional to deal with the absence of a value.
    Pour ce qui est de l'efficacité (performances ?), je n'ai pas testé, mais il semblerait que le fait de wrapper/unwrapper avec Optional n'impacte pas sur les performances.

    Optional est un objet comme un autre, mais si un Optional est null au lieu d'être vide, la feature perd son intérêt.

    P.-S. : Une petite syntaxe stream pour le coalesce en Java 8 : String a = Stream.of( null, null, "valeur defaut").filter( Objects::nonNull ).findFirst().get();
  2. Avatar de avdyk
    • |
    • permalink
    Bonjour,

    Utiliser isPresent() à la place de la comparaison du null n'apporte pas grand chose, ni en terme d'efficacité, ni en terme de clarté. Il est plus intéressant de profiter des méthodes d'Optional pour effectuer les opérations si l'Optional contient une valeur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    final String test = " hello "; // essayer avec d'autres valeurs et null
    Optional.ofNullable(test)
                    .map(String::trim)
                    .filter(s -> s.length() > 0)
                    .ifPresent(System.out::println);
    Si on veut fournir une valeur par défaut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    String test = " hello "; // essayer avec d'autres valeurs et null
    final String withDefault = Optional.ofNullable(test)
                    .map(String::trim)
                    .filter(s -> s.length() > 0)
                    .orElse("Valeur par défaut");
    Tester si un Optional n'est pas null ne signifie pas qu'on a rien compris car un Optional pourrait être null. L'évolution des habitudes de programmation en Java veut qu'on ne teste plus si une collection, un tableau ou un Optional est null car c'est une mauvaise habitude de fournir une instance nulle. Il est recommandé de retourner Optional.empty(), une collection ou un tableau vide.

    Dans le cas d'un Optional, le null serait plutôt un bug et l'utilisateur de l'application ne pourrait rien y faire.
  3. Avatar de mOuLi
    • |
    • permalink
    Citation Envoyé par eclesia
    Utiliser plutot Collections.EMPTY_LIST pour ne pas créer d'objet inutilement.
    Depuis Java5, il vaut même mieux privilégier Collections.emptyList() applicable aux listes avec génériques
  4. Avatar de eclesia
    • |
    • permalink
    Utiliser plutot Collections.EMPTY_LIST pour ne pas créer d'objet inutilement.

    Il y a aussi les @NotNull @Nonnull ...etc... dans divers projets de validation de contraintes.
  5. Avatar de hwoarang
    • |
    • permalink
    Citation Envoyé par bouye
    Je pense surtout que tu ne comprends que définir cela dans une interface permet de varier l’implémentation. Après il n'y a pas 36 millions de façon de faire pour invoquer une méthode d'une autre classe : soit elle est publique soit elle est package protected. Et comme justement on parle d'une interface ça élimine d'office le package protected.
    sisi, je comprends bien. Et, justement pour la raison que tu donnes toi meme, à mon avis, la methode de notification ne devrait pas etre dans l'interface.
    Pour s'en convaincre, il suffit d'imaginer ce que peuvent etre amenées à faire des fonctions/objets qui manipuleraient des Observables. De maniere assez evidente, ils vont vouloir s'enregistrer (donc la fonction addObserver est, évidemment, obligatoire). Par contre, ils ne voudront pas forcer une notification (appeler notifyObservers). Pire, comme cette fonction est dans l'interface, elle est public et peut donc etre appelée. C'est ca qui me derange. D'ailleurs, tu remarqueras que dans ton propre exemple, tu n'appelles pas la fonction de notification

    Encore une fois, à l'implementation, utiliser une fonction parait etre un choix evident. Par contre, à mon sens, il ne devrait pas etre dans l'interface.

    Sinon, par rapport aux moyens que tu donnes de corriger ce probleme, je suis d'accord avec toi mais je pense que c'est encore mieux de ne pas mettre cette contrainte quand on refait le pattern (si on utilise l'Observable du JDK, ce que tu proposes est necessaire mais tant qu'à refaire le pattern, autant ne pas remettre la fonction de notification).
  6. Avatar de bouye
    • |
    • permalink
    Je pense surtout que tu ne comprends que définir cela dans une interface permet de varier l’implémentation. Après il n'y a pas 36 millions de façon de faire pour invoquer une méthode d'une autre classe : soit elle est publique soit elle est package protected. Et comme justement on parle d'une interface ça élimine d'office le package protected.

    Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    public interface ZeObserver {
         public void coucou(Result result);
    }

    Maintenant, ceci dit, on est pas obligé non-plus d’étendre l'interface dans l'objet observateur, il existe d'autres manières de faire qui permettent de cacher la chose et ainsi permettent d’éviter qu'une tierce-partie puisse invoquer cette méthode :
  7. Avatar de hwoarang
    • |
    • permalink
    Citation Envoyé par bouye
    Il serait difficile de faire autrement en Java justement car le contenu des interfaces est public
    Ce que je proposais, c'etait juste de ne pas mettre la fonction de notification dans l'interface. Apres tout, à l'implementation, je ne vois pas pourquoi je serais obligé d'utiliser une fonction (alors que je pourrais m'amuser à duppliquer une boucle foreach ). Plus sérieusement, c'est surtout exposer la fonction de notification qui me pique un peu les yeux ^^
  8. Avatar de bouye
    • |
    • permalink
    Il serait difficile de faire autrement en Java justement car le contenu des interfaces est public. Il reste possible de le faire avec une classe abstraite mais alors on retombe sur le fait qu'il n'est pas possible d'avoir un héritage multiple.

    À noter que, oui, ces classes sont là depuis le JDK 1.0 mais qu'elles sont mises de coté dès le JDK 1.1 avec l'ajout des listeners et des events qui sont une autre manière d'aborder le pattern observer (pas réservée a AWT/Swing/GUI contrairement à ce que la plupart des gens peuvent croire).
  9. Avatar de hwoarang
    • |
    • permalink
    J'avais bien remarqué que c'était une interface
    A mon avis, ce n'est pas une bonne chose de mettre dans l'interface cette methode pour les raisons que j'ai donné. De maniere générale, je pense qu'il est préférable de ne laisser public que ce qui doit l'etre (et donc, qui doit etre utilisé par une autre classe à un moment ou un autre - ce qui n'est pas le cas de la fonction qui notifie les observers).

    Mais bon, ce n'est que mon avis, chacun est libre de faire comme il veut ^^
    Et sur le fond, ca ne change rien à la description du pattern.
  10. Avatar de Gugelhupf
    • |
    • permalink
    Bonsoir hwoarang, et merci

    Mon Observable est une interface et une interface ne peut avoir que des méthodes de visibilité public, même si on ne précise pas le mot-clé public, on n'a pas de visibilité private-package, mais public pour une interface. D'ailleurs bien que le Observable du JDK soit une classe, sa méthode notifyObservers() est elle aussi public.
  11. Avatar de hwoarang
    • |
    • permalink
    Bonjour,

    Le tuto me parait clair et efficace.

    Par contre, je trouve que declarer "public void notifyObservers(T data);" dans l'Observable est une erreur parce qu'elle rend publique une fonction interne de la classe (c'est elle et elle seule qui sait quand elle doit notifier les observers). Et, meme si je suis d'accord avec toi pour dire qu'une fonction pour notifier les observers est appropriée, à l'implémentation, je ne vois pas trop pourquoi on l'obligerait.

    Dans tous les cas, merci pour le tuto, ca aidera les debutants à comprendre ce pattern ^^
  12. Avatar de Gugelhupf
    • |
    • permalink
    Bonjour @ddoumeche,

    Merci pour ton retour

    J'ai créé cet API car ce dernier répond à des problèmatiques que je n'ai pas trouvé sur le marché :
    • Comment réaliser des aggrégats et des jointures sur des objets Java ? L'API Stream de Java 8 ne le permet pas de manière aisée.
    • Mon client me fournit une extraction de sa BDD relationnel au format CSV/Excel (ou autre), comment dénormaliser la donnée assez rapidement pour placer son contenu dans une base NoSQL ?
    • L'API peut être exploitée à d'autres fins aussi...

    N'hésitez pas à me faire des retours pour que je puisse améliorer l'API
  13. Avatar de Gugelhupf
    • |
    • permalink
    Bonsoir Malick,

    Un grand merci pour ton aide. J'avais oublié d'ajouter cette partie, je viens de le faire à l'instant

    Cordialement,
  14. Avatar de Malick
    • |
    • permalink
    Gugelhupf

    Super ton article. Toutefois il manque ce chapitre :

    TP CORBA Chapitre 5 : Implémentation (partie cliente)
  15. Avatar de ddoumeche
    • |
    • permalink
    Cela a l'air très jeune, mais extrêmement innovant et puissant.

    Pourquoi avoir eu besoin d'un tel projet dans une replication de base de données ?
  16. Avatar de Gugelhupf
    • |
    • permalink
    J'ai mis 7 parce que je faisais référence à la version 7 du package summary. Je pense que je vais juste enlever le chiffre pour éviter les confusion. Celui qui clique sur JSR-311 verra que JAX-RS est apparue avec Java EE 6.
  17. Avatar de kolodz
    • |
    • permalink
    Note :JAX-RS est présent dans Java EE depuis la version 6.
  18. Avatar de danielhagnoul
    • |
    • permalink
    Sous réserve de davantage de tests, il me semble que la méthode deepcopy récursive fonctionne bien.

    J'ai fait quelques tests avec prototype et avec class. Ci-dessous le code avec class :

    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
    function clone( originalObject ){ 
        if ( ( typeof originalObject !== 'object' ) || originalObject === null ){ 
          throw new TypeError( "originalObject parameter must be an object which is not null" ); 
        } 
     
        function deepProto( originalObject ){
          let deepCopy = Object.create( Object.getPrototypeOf( originalObject ) );
          
          for ( let attribute in originalObject ){
            deepCopy[ attribute ] = originalObject[ attribute ];
            
            if ( typeof originalObject[ attribute ] === 'object' && originalObject[ attribute ] !== null ){ 
              deepCopy[ attribute ] = deepProto( originalObject[ attribute ] );
            }
          }
          
          return deepCopy;
        }
        
        return deepProto( originalObject ); 
    }
    
    const
      kGetType = function( Obj ){
        return Object.prototype.toString.call( Obj ).match( /\s([a-zA-Z]+)/ )[ 1 ].toLowerCase();
      },
      kPays = Symbol( 'Pays' ),
      kPaysType = 'string',
      kSetPays = function( obj, value ){
    
        if ( kGetType( value ) === kPaysType ){
          obj[ kPays ] = value;
            
        } else {
          throw `Type des paramètres incompatibles.
            pays : ${ kPaysType } attendu`;
        }
        
        return obj;
      };
      
    class Foo {
      constructor( levelName, obj, pays ){
        this.levelName = levelName;
        this.deep = obj;
        this.Obj1 = {
          "test" : "hello",
          "Obj2" : {
            "test" : "bonjour"
          }
        }
        kSetPays( this, pays );
      }
      method1(){
        console.log("This method works !");
      }
      get pays( ){
        return this[ kPays ];
      }
      set pays( value ){
        kSetPays( this, value );
      }
    };
    
    let originalObject = new Foo(
      "Level 1", 
      new Foo(
        "Level 2", 
        new Foo( "Level 3", null, "USA" ),
        "France"
      ),
      "Belgique"
    );
    
    let copy = clone( originalObject );
    
    console.log( originalObject.Obj1 === copy.Obj1 );
    console.log( originalObject.deep.Obj1 === copy.deep.Obj1 );
    console.log( originalObject.deep.deep.Obj1 === copy.deep.deep.Obj1 );
    
    console.log( originalObject.Obj1.Obj2 === copy.Obj1.Obj2 );
    console.log( originalObject.deep.Obj1.Obj2 === copy.deep.Obj1.Obj2 );
    console.log( originalObject.deep.deep.Obj1.Obj2 === copy.deep.deep.Obj1.Obj2 );
    
    copy.deep.deep.pays = "Luxembourg";
    
    console.log( originalObject.deep.deep.pays , copy.deep.deep.pays );
  19. Avatar de marc.collin
    • |
    • permalink
    Citation Envoyé par Gugelhupf
    Oui tu peux directement compiler en natif avec Java aussi, en utilisant des outils comme GCJ.

    il y a pu trop de nouveauté pour GCJ depuis un moment
    il y a excelsiorjet mais c'est très cher
  20. Avatar de Gugelhupf
    • |
    • permalink
    Oui tu peux directement compiler en natif avec Java aussi, en utilisant des outils comme GCJ.
Page 1 sur 3 123 DernièreDernière