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

Langage Java Discussion :

Cherche recommandations/normes d'écriture pour Java 1.6


Sujet :

Langage Java

  1. #61
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Yomhgui Voir le message

    Ce qui me surprend, c'est quand tu dis que le type n'est pas connu. De manière factuelle, si le type est connu lors de la compilation, il n'y a pas de raison qu'il ne le soit pas en runtime.
    A la compilation tu connait le type d'une instance particulière, vue depuis l'extérieur de la classe. Quand tu compile la classe générique -> le type n'est pas connu. Quand tu passe ton instance generics à des méthodes qui prennent, par exemple un List<?>, tu perd aussi cette information. Les generics sont une aide à la compilation, la pluspart des infos relative au generics sont perdus à la compilation. Par exemple, si je fait

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<String> l = ...;
    Object o = l;
    aucun code ne me permettra de récupérer les paramètres generics de "o", par contre un o.getClass().getName() me retournera bien "java.util.ArrayList" par exemple.

  2. #62
    Membre émérite
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Points : 2 582
    Points
    2 582
    Par défaut
    Citation Envoyé par Yomhgui Voir le message
    PS3: Je me souviens d'avoir trouvé un article très intéressant sur la question de l'allocation des tableaux génériques (l'impossibilité de...) mais j'ai ma dose pour ce soir. Je tacherai de le remettre en référence ici demain.
    Oui, c'est parce que le type générique est pas connu à l'exécution est que ça fiche le pataques.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // FAUX CODE
    Toto<Truc>[] totoTruc = new Toto<Truc>[10]; // ici le type à l'exécution est juste Toto[]
    Object[] oTotoTruc = tototruc; // valide
    oTotoTruc[0] = new Toto<Ouille>(); // réussirait, puisque le seul type connu à l'exécution est Toto[].
    // comme totoTruc est toujours adressable, on pourrait y lire des éléments non conformes
    // à la déclaration !
    Voir Can I create an array whose component type is a concrete parameterized type?
    Mieux que Google, utilisez Sur Java spécialisé sur la plate-forme java !
    Pour réaliser vos applications Java dans le cadre de prestations, forfait, conseil, contactez-moi en message privé.

  3. #63
    Membre régulier
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 71
    Points : 90
    Points
    90
    Par défaut
    En même temps tu te voyais avec une API "Collections 2" incompatible avec l'API de Collections actuelles ???
    Aucun doutes, ça aurait eu un côté difficile à faire avaler... (quoique je note quand même que tous les éditeurs ne s'embarrassent pas toujours avec ce genre de considérations).

    Bon, après quelques réflexions sur le sujet, je ne suis même pas certain que le seule problématique de compatibilité ascendante soit en cause. Il me semble que, quand on crée une classe C paramétrée : C<T>, le comportement du compilateur est assez différent de ce qui se passe en C++ où, dans le code compilé, on trouve autant de classes différentes qu'il y a d'utilisation de la classe paramétrée avec des paramètres différents (si mes lointain souvenir du C++ sont exacts).

    Dans le byte code Java, il ne doit y avoir qu'une seule définition de classe qui ne garde pas de trace du fait qu'elle possède un paramètre. Ce qui doit faire que, compatibilité ascendante où pas, on ne peut connaitre dans la classe compilée que la borne supérieure du paramètre déclaré dans le source.

    Je me trompe ?

    D'ailleurs, j'ai fait un petit essai simple, pas avec des classes mais avec des méthodes paramétrées:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private static <T> T get(final Class<T> c) {
        try {
            return c.newInstance();
        } catch (final Exception e) {
            return null;
        }
    }
     
    public static void main(final String[] args) {
        final String s = get(String.class);
        final Float f = get(Float.class);
    }
    Le byte code du main donne:

    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
      // access flags 9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 61 L0
        LDC Ljava/lang/String;.class
        INVOKESTATIC p/C.get(Ljava/lang/Class;)Ljava/lang/Object;
        CHECKCAST java/lang/String
        POP
       L1
        LINENUMBER 62 L1
        LDC Ljava/lang/Float;.class
        INVOKESTATIC p/C.get(Ljava/lang/Class;)Ljava/lang/Object;
        CHECKCAST java/lang/Float
        POP
       L2
        LINENUMBER 63 L2
        RETURN
       L3
        LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
        MAXSTACK = 1
        MAXLOCALS = 1
    Et il n'y a bien qu'un seule définition de méthode get(Class), pas deux méthodes dont les noms auraient été décorés en get@String(...) : String et get@Float(...) : Float par exemple. C'est bien l'érésure du paramètre qui à cette conséquence. Les CHECKCAST ne sont pas prêts de disparaitre du byte code...

  4. #64
    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
    Citation Envoyé par Yomhgui Voir le message
    Aucun doutes, ça aurait eu un côté difficile à faire avaler... (quoique je note quand même que tous les éditeurs ne s'embarrassent pas toujours avec ce genre de considérations).
    C'est ce qui a été fait dans C# 2.0, mais le langage était bien plus jeune et cela impactait bien moins de programme et de librairie que cela n'aurait été le cas en Java...

    Citation Envoyé par Yomhgui Voir le message
    Bon, après quelques réflexions sur le sujet, je ne suis même pas certain que le seule problématique de compatibilité ascendante soit en cause. Il me semble que, quand on crée une classe C paramétrée : C<T>, le comportement du compilateur est assez différent de ce qui se passe en C++ où, dans le code compilé, on trouve autant de classes différentes qu'il y a d'utilisation de la classe paramétrée avec des paramètres différents (si mes lointain souvenir du C++ sont exacts).
    En effet en C++ chaque utilisation avec un type différent génère une duplication de code. C'est comme si on faisait des copier-coller, sauf que c'est bien plus pratique car c'est le compilateur qui s'en charge (c'est pour cela que les codes utilisant les templates DOIVENT se trouver dans le .h).

    Sauf erreur il y a un mécanisme similaire dans C#...

    Citation Envoyé par Yomhgui Voir le message
    Dans le byte code Java, il ne doit y avoir qu'une seule définition de classe qui ne garde pas de trace du fait qu'elle possède un paramètre. Ce qui doit faire que, compatibilité ascendante où pas, on ne peut connaitre dans la classe compilée que la borne supérieure du paramètre déclaré dans le source.

    Je me trompe ?
    Non c'est exactement cela : à l'exécution tu ne peux savoir que ce qui est indiqué dans le code source de la classe, mais tu ne peux pas connaitre le type paramétré utilisé par chaque instance.



    A noter que cette approche n'a pas forcément que des désavantages (le coût des casts étant relativement faible), puisqu'il permet de gérer facilement la covariance/contra-variance sur les types paramétrés.

    a++

  5. #65
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2006
    Messages : 230
    Points : 310
    Points
    310
    Par défaut Go Ahead: Next Generation Java Programming Style
    [Edit Ricky81](suite à fusion, ne blamez pas l'auteur ;-) [/Edit]

    Bonjour,

    Ci-après un billet de Stephan Schmidt tiré de son blog.

    Vos opinions ?

    Many companies and developers move away from Java to new languages: Ruby, Python, Groovy, Erlang, Scala. You might be trapped with Java.

    Even if you’ve trapped, you can change your programming style and reap some of the benefits of those new languages. In the last 15 years Java programming style has changed significantly:

    1. Final is your new love: More and more Java developers in the teams I’ve worked with, started to use final. Making variables final prevents changing those values. Most often, if you reasign a value, it’s a bug or you should use a new variable. Final prevents bugs and makes code easier to read and understand. Make everything immutable.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          final Foo bar = new Foo();
    I’ve written more about this topic in “All variables in Java must be final”.

    2. No setters. Many Java developers automatically – sometimes with the evil help of an IDE – write setters for all fields in their classes. You should not use setters. Think about each setter you want to write, are they really necessary for your fields? Better create new copies of your objects if values change. And try to write code without getters either. Tell, don’t ask tells you more about the concept.

    3. Do not use loops for list operations. Learning from functional languages, looping isn’t the best way to work on collections. Suppose we want to filter a list of persons to those who can drink beer. The loop versions looks like:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
          List<Person> beerDrinkers = new ArrayList<Person>();
          for (Person p: persons) {
              if (p.getAge() > 16) {
          	    beerDrinkers.add(p);
              }
          }
    This can – even in Java – be rewritten to a more a functional programming style. For example using Google collections filter:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
          Predicate<HasAge> canDrinkBeer = new Predicate<HasAge>() {
              public boolean apply(HasAge hasAge) {
                  return hasAge.getAge() > 16;
              }
          };
     
          List<Person> beerDrinkers = filter(persons, canDrinkBeer);
    As remarked by Dave Jarvis, I should have dropped the getter, and he’s right ;-)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          Predicate canDrinkBeer = new Predicate() {
               public boolean apply(HasAge hasAge) {
                   return hasAge.isOlderThan( 16 );
              }
          };
    which would lead to better code down the road:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          Predicate canDrinkBeer = new Predicate() {
              public boolean apply( HasAge hasAge, HasAge otherAge ) {
                  return hasAge.isOlderThan( otherAge );
              }
          }
    The predicate version is slightly larger, but consists of two parts. Each one is easier to understand. While the loop version gets unreadable fast with new requirements, the functional version can easily be combined,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          List beerDrinkers = filter(filter(persons, canDrinkBeer), isMale);
    More on this at the Metaphysical Developer.

    4. Use one liners: Write concise code. Java is a noisy language. But don’t make it noiser as it needs to be. Instead of

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
          public int add(int a, int b)
          {
            int result = a + b;
            return result;
          }
    write
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
          public int add(int a, int b) { return a + b; }
    IDEA and possibly other IDEs can keep oneliners formatted as oneliners, if you tell them so.

    5. Use many, many objects with many interfaces. Domain driven design currently makes a big splash. A class should be splitted into many roles, implementing many interfaces. This way the class is reusable.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
          public class Person implements Nameable, Hireable, LivesAt {
             ...
          }
     
          public interface Nameable {
            String getName();
          }
     
          Methods should be written to only work on roles, not classes. This way methods can work on more objects. Another benefit is lower coupling.
     
          public void print(Nameable name) {
            System.out.println(name.getName());
          }
    I’ve written more about that in “Never, never, never use String in Java “.

    6. Use Erlang-Style Concurrency. The Java concurrency primitives like locks and synchronized have been proven to be too low level and often to hard to use. There are better ways to write concurrent code. Erlang Style concurrency is one of them – in Java there are many ways to achive this in Java – I’ve written about them here. Newer ones are Akka and Actorom. You can also use Join/Fork or the myriad of data structures in java.util.concurrent.

    7. Use Fluent Interfaces. Fluent interfaces can make your code much more readable and shorter. A very good example is the MapMaker API in Google Collections:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
           ConcurrentMap graphs = new MapMaker()
                 .concurrencyLevel(32)
                 .softKeys()
                 .weakValues()
                 .expiration(30, TimeUnit.MINUTES)
                 .makeComputingMap(
                     new Function() {
                       public Graph apply(Key key) {
                         return createExpensiveGraph(key);
                       }
                     });
    8. Data Transfer Objects without setters and getters. If you have simple data holders or data transfer objects, don’t write boiler plate code with getters and setters. I know this is heresy in Java, but just use public fields. Instead of

    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
          public class Point {
             private int x;
             private int y;
     
             pulic Point(int x, int y) {
                this.x = x;
                this.y = y;
             }
             public int setX(int newX) {
                x = newX;
             }
             public int getX() {
               return x;
             }
             ...
          }
          ...
          int x = p.getX();
          int y= p.getY();
    write

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
          public class Point {
             public final int x;
             public final int y;
     
             pulic Point(int x, int y) {
                this.x = x;
                this.y = y;
             }
          }
          ...
          int x = p.x;
          int y = p.y;
    Refactoring is easy, should you need it. If you do not control all the code and it’s usage, you might need to be more careful though.

    This tips lead to better Java code. Try them in your next Java class. What do you think? I’d like to hear how your Java coding style has changed in the last 10 years.

    Update: Some thoughts to Cedrics thoughts.

    As the author of the post, your thoughts are appreciated, some of mine:

    “Besides, it’s convenient to be able to mutate object if you want to use pools.”

    No setters doesn’t mean you can’t mutate objects, it’s just that plain setters are not object oriented thinking. How about stop() vs. setStop(true);

    “I think the first example is more readable than the second one that uses Predicates.”

  6. #66
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Mouais,

    il y a quand même quelques points avec lesquels je ne suis pas d'accord du tout. En fait tout dépend du projet (voire de la partie du projet) sur lequel on bosse et les priorités qu'on se donne (flexibilité, réutilisabilité, performance, clarté du code, ...).

    Balancer des règles sans préciser le contexte, laissant penser qu'une règle est toujours valable dans tous les cas, est amha une erreur courante du niveau du développeur moyen à la recherche de LA réponse universelle. En développement comme dans beaucoup d'autres domaines, "choisir, c'est renoncer" comme dirait l'autre

    Comme dans la vraie vie, la réalité des choses dépend fortement du contexte et des contraintes inhérentes au projet. Rien n'est jamais tout blanc ou tout noir. Quelques exemples:

    - "Final is your new love": j'expériemente acutellement l'abus de ce genre de pratique dans un framework Java (pulpcore) où l'immense majorité des méthodes sont déclarées 'final'. Le résultat est que tant qu'on reste "dans les clous" de l'utilisation prévue par le concepteur, tout va bien. Mais dès qu'on veut faire quelque chose d'un peu plus spécifique, on se retrouve très vite complètement enfermé dans un carcan rigide, l'opposé même de la notion de framework. En résumé, autant ce genre de pratique peut-être bénéfique (notamment pour déceler les bugs dès l'écriture du code), autant dans le cas d'un code destiné à être réutilisé et/ou adapté (framework, librairie plus ou moins générique) ça devient vite une contrainte supplémentaire totalement inutile.

    - "Do not use loops for list operations": bien que la solution proposée soit plus "élégante", la compacité et l'approche "classique" du code dans le premier exemple rend la relecture du code bien plus 'compréhensible' amha.

    - "No setters" / "Data Transfer Objects without setters and getters": pas toujours: il est parfois extrêmement utile de pouvoir intercepter les appels aux getters/setters pour du debug, la POA, ou pour une classe dérivée qui veut adapter la valeur sotckée/retournée.

    Tout ça pour dire que, quelles que soient les règles édictées, elle ne peuvent jamais être universelles ; Et même si elles me paraissent toutes plus ou moins pertinentes dans un contexte donné, amha son billet aurait beaucoup gagné à présenter pour chacune de ses règles leurs propres limites.
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  7. #67
    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,

    Personnellement je trouvais que tout cela s'adapte mal au cas général, et que c'était donc franchement abusé de présenter cela comme de nouvelles règles de programmation

    a++

Discussions similaires

  1. Cherche une API de report pour JAVA
    Par MaxLaMenaX dans le forum Documents
    Réponses: 6
    Dernier message: 10/04/2009, 08h54
  2. Cherche un outil de reporting comme BIRT pour Java
    Par tiboudchou dans le forum Autres outils décisionnels
    Réponses: 4
    Dernier message: 02/01/2007, 14h25
  3. Votre EDI préferé pour Java (2003-2004) ?
    Par christopheJ dans le forum EDI et Outils pour Java
    Réponses: 73
    Dernier message: 17/10/2005, 17h05
  4. Réponses: 4
    Dernier message: 16/10/2005, 18h30
  5. Profiler pour Java
    Par donde dans le forum Tests et Performance
    Réponses: 1
    Dernier message: 10/02/2003, 17h36

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