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

Java Discussion :

Java, un bon choix pour mes besoins ?


Sujet :

Java

  1. #1
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut Java, un bon choix pour mes besoins ?
    Bonjour,

    Je suis un fervent défenseur du C++ et depuis quelques temps déjà je travaillais sur un projet de jeu en C++.
    Je voulais entre-autre :
    • répartir tout le jeu dans un système de pluggin pour permettre à tous de "moder" ce jeu sans recompiler tout le projet ainsi que de pouvoir changer les dépendances (bibliothèques) si l'une d'entre elle n'était pas supportée sur une plateforme ou devenait obsolète ;
    • permettre l'exécution du programme via navigateur (en jouant un peu avec les Websocket et un serveur en Node.js, le principe est assez simple).



    Sauf que je rencontre pas mal de problèmes :

    • le système de pluggin est relativement long à développer ;
    • l'exécution via navigateur prendra aussi un certain temps et demandera soit que tous les calculs soient effectués côté serveur, soit de réécrire un client en JavaScript ;
    • la non-portabilité des exécutables me dérange aussi quelque peu, je peux difficilement demander aux utilisateurs de compiler eux-même (s'il faut recompiler des dépendances, ou autre ça peut très vite devenir "enquiquinant").





    Même si je ne porte pas vraiment le Java dans mon cœur, je suis très sérieusement en train de songer à cette possibilité, ceci :

    • me fera gagner un peu de temps pour la partie "exécution via navigateur" grâce aux applets ;
    • facilitera le système de pluggin (un pluggin sera alors un .class qu'on chargera dynamiquement ?) ;
    • m'évitera quelques cheveux blancs quant à la portabilité de mon jeu ;
    • permettra une exécution sur téléphones (?)



    Mais je me pose quelques questions :

    • niveau performances, est-ce qu'il pourra tenir correctement de la 3D ? En effet, il est très difficile de faire des scènes 3D "légères" et sur des prototypes en C++ que j'ai réalisé (affichage de 9*6 objets identiques), je pouvais avoir un nombre de FPS relativement faible. Java ayant des bibliothèques encapsulant openGL, je suppose que les performances sont relativement égales ? Mais j'entends dire que le Java serait 30% à 70% moins performants que des langages natifs par rapport à la 3D ;
    • est-ce que l'exécution sur téléphone est réaliste par rapport aux performances des téléphones actuels ? Est-ce que vous pensez qu'il pourrait y avoir des adaptations à faire ? Si oui, lesquelles ?
    • En revanche, j'ai entendu dire que le Garbage collector posait quelques problèmes de performances pour ce type d'application, est-ce qu'il y a moyen de pallier cela ?
    • est-ce que le Java vous semble un bon choix pour ce cas là ?





    Est-ce que vous auriez d'autres conseils à me donner ?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Je ne peux pas te répondre sur tous les points (en particulier sur la partie mobile où je n'y connais rien), mais à mon avis, oublie l'argument "applet" pour l'exécution côté navigateur, la technologie semblant virer à l'obsolescence, probablement à cause de nombreux problèmes de sécurité. Pour la partie plugin, regardes du côté OSGI : c'est, à mon avis, un excellent support pour la gestion de la modularité (notamment multi-plateforme).

    Globalement, je verrasi bien une solution hybride java/osgi, C/C++ (via JNI, comme par exemple JOGL pour la 3D) + javascript pour l'exécution côté navigateur (via des bibliothèques style angular, par exemple, pour gagner du temps sur les dev).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Niveau performance, si tu es limité par le GPU tu ne devrais voir quasiment aucune différence. Chaque appel à une fonction native (OpenGL par exemple) aura un léger surcout qui devrait être négligeable par rapport au temps que prendra la fonction.
    L'exception étant : si tu as de très nombreux (et court) appels à DrawPrimitives / DrawIndexedPrimitives, là tu sentira vraiment le surcout. Mais si c'est le cas, tu auras de toutes façons des performances faibles aussi en C++ : surement un problème de conception / optimisation.

    Si tu es limité par le CPU, alors le passage à Java se fera sentir.

    Pour la portabilité du code, tu peux fournir un exe Windows, et les sources. Un utilisateur de Linux à déjà probablement dû compiler lui-même de nombreux programmes et devrait savoir le faire.
    Mais sur ce point... C'est vrai que le C++ c'est pas la joie.

  4. #4
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Merci pour vos réponses,

    Citation Envoyé par joel.drigo Voir le message
    Pour la partie plugin, regardes du côté OSGI : c'est, à mon avis, un excellent support pour la gestion de la modularité (notamment multi-plateforme).
    Ceci me semble très intéressant et m'évitera de devoir le coder moi-même.
    Par contre je ne trouve pas vraiment de détails "buvables" quant à son fonctionnement

    Citation Envoyé par joel.drigo Voir le message
    javascript pour l'exécution côté navigateur (via des bibliothèques style angular, par exemple, pour gagner du temps sur les dev).
    Le problème c'est qu'il faudra réécrire une partie du code en JavaScript
    Peut-être vaudrait-il mieux créer un client "léger" qui téléchargera les ressources qu'à partir du moment où il en aura besoin ?

  5. #5
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Le problème c'est qu'il faudra réécrire une partie du code en JavaScript
    Regarde du coté de emscripten, il est possible que tu n'ai pas grand chose à changer / refaire.
    (Niveau performance ça à l'air correct, en particulier avec asm.js.)

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Regarde du coté de emscripten, il est possible que tu n'ai pas grand chose à changer / refaire.
    (Niveau performance ça à l'air correct, en particulier avec asm.js.)
    Je connais emscripten, mais :
    • j'ai peur que cela ne pose des problèmes si j'utilise trop de bibliothèques
      • il faudra compiler les bibliothèque pour emscripten ;
      • avoir trop d'indirection risque de se voir au niveau des performances ;
      • certaines bibliothèques pourrait ne pas être compatibles avec emscripten (?)

    • pour l'utilisation de la 3D, je ne sais pas si tous les navigateurs vont supporter la charge requise par emscripten.

  7. #7
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Pour avoir un peu trempé dans ce genre de problématique, franchement, l’exécution sur navigateur, il n'y a pas de solution idéale. Comme déjà dit, les applets sont en train de devenir obsolètes. Si tu veux faire de la 3D, tu seras obligé de les signer. Et si tu ne le fait pas par un vrai certificat (payant), les utilisateurs devront mettre la sécurité java au minimum et elles risquent de ne plus fonctionner à tout moment (le message d'avertissement actuel prévient que les applets non signées par certificat reconnu seront bloquées ultérieurement).

    Concernant le passage Java desktop <-> Android, c'est loin d’être aussi facile qu'on pourrait le croire. Le plus simple, selon moi, serait d'utiliser un moteur 3D qui est déjà compatible. Par exemple JMonkey qui est open source et gratuit. Il y a pas mal de videos qui trainent sur ce moteur qui montrent des exemples. Ca donne une idée des performances. Ceci dit, dans le monde du C++, des moteurs capables de générer du code ou des exécutables pour android existe peut être aussi...

    Au sujet des performances, franchement, je ne suis pas sur qu'il y ait une si grosse différence. Quand on voit ce que font certains jeux, on se dit que ceux qui mettent à genoux une carte graphique en affichant 15 modeles 3D ne s'y prennent pas comme il faut. Meme s'il faut reconnaitre que c'est plus simple de dire que l'outil est mauvais plutot que de reconnaitre que l'architecture choisie ne convient pas

  8. #8
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    As-tu regardé du coté de Unity pour les jeux 3D qui s'exécutent dans le navigateur du client ?
    Le développement se fait au choix en C# ou JavaScript il me semble. Après je ne sais pas si ce code est ensuite exécuté dans une VM ou bien compilé en binaire.
    Mais bon, que ce soit en Java ou C# les problèmes liés au Garbage Collector seront les mêmes.
    Pour faire des mods je ne suis pas sur. Et puis Minecraft ne se lance pas à partir du navigateur il me semble ?

    PS: Si je puis me permettre : "Même si je ne porte pas vraiment le Java dans mon cœur", pourquoi ?
    Je suis moi-même développeur C++, et pourtant je ne peux pas nier les qualités de Java.
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    PS: Si je puis me permettre : "Même si je ne porte pas vraiment le Java dans mon cœur", pourquoi ?
    Je suis moi-même développeur C++, et pourtant je ne peux pas nier les qualités de Java.
    Java a certes des qualités mais je n'aimes pas certaines décisions qui ont été prises par les créateurs du Java :
    • tout hérite de Object ;
    • héritage multiple interdit, sauf qu'on peut "implémenter" plusieurs interfaces ce qui ressemble assez à une forme d'héritage
    • pas de destructeurs à proprement parler (finalize qui est "peut-être" appelé) ;
    • on ne peut pas vraiment séparer les prototypes de l'implémentation, je trouve, personnellement, que ça pose des problèmes de relecture du code (ou alors, il faut créer une interface) ;
    • il me semble que tout a une sémantique d'entité et on ne peut pas créer de classe à sémantique de valeur si je ne m'abuse ;
    • on gère la mémoire à notre place, plutôt que de nous donner un "choix".
    • pour les prototypes de méthodes, certaines choses me paraissent lourdes car il faut les vérifier soit-même à la main
      • pas d'entiers non-signés
      • pas d'indications pour spécifier non-nuls

    • il ne me semble pas qu'une méthode puisse retourner un objet constant (?), il faut donc faire une copie de l'objet avant de retourner sa copie si je ne m'abuse.
    • l'ancienne gestion des I/O par "couche" me paraissait lourde et peu pratique.



    Et par rapport au C++, je regrette :

    • la surcharge d'opérateurs
    • les templates (même si je ne les utilise pas souvent).



    Mais bon, je ne vais tout de même pas me mettre à troller en territoire ennemis.

  10. #10
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Neckara Voir le message
    tout hérite de Object ;
    C'est normal, car grâce à ce super type, les classes peuvent bénéficier de la méthode equals() par exemple.
    Java ne possédant pas de surcharge d'opérateur cela devient utile.
    La surcharge d'opérateur peut te manquer, mais le fait d'en avoir peut pousser les développeurs à les utiliser pour des opérations qui ne sont pas cohérentes, comme : "Mouton > Oiseau".
    Seule la classe String possède des bonus par défaut (pour concaténer avec "+" par exemple), il aurait peut-être été agréable d'en avoir pour BigDecimal et BigInteger, mais ce n'est pas le cas.


    Citation Envoyé par Neckara Voir le message
    héritage multiple interdit, sauf qu'on peut "implémenter" plusieurs interfaces ce qui ressemble assez à une forme d'héritage
    Ça reste une forme d'héritage avec une classe ne possédant que des méthodes virtuelles pures, l'idée étant d'éviter le Deadly Diamond Of Death, problème qu'on peut rencontrer dans les langages comme C++ ou Python.
    L'héritage multiple n'a jamais été un gros problème lorsque la conception est bonne (avec les bons design pattern).
    De plus en Java 8, il est possible d'avoir des méthodes par défaut, ou des méthodes static dans les interfaces, afin de combler les lacunes des frameworks qui essayent de garder la rétrocompatibilité.


    Citation Envoyé par Neckara Voir le message
    pas de destructeurs à proprement parler (finalize qui est "peut-être" appelé) ;
    Il n'y a pas besoin de destructeur pour libérer les ressources en Java. Les instances sont libérés automatiquement grâce à la VM.
    Il reste toujours des ressources à libérer, si tu ouvres un fichier par exemple, il faut le fermer avec close().
    De plus depuis Java 7, il est possible d'utiliser une sucre syntaxique (try-with-ressources lien doc), qui te permet d'entrer moins d'instructions, et le fichier sera fermé proprement (implicitement mais de façon déterminé).


    Citation Envoyé par Neckara Voir le message
    on ne peut pas vraiment séparer les prototypes de l'implémentation, je trouve, personnellement, que ça pose des problèmes de relecture du code (ou alors, il faut créer une interface) ;
    Il y a longtemps, mon enseignant C++ nous avait dit qu'un avantage de séparer les prototypes de l'implémentation était de cacher l'implémentation au client. Donc rendre celui-ci dépendant de votre produit en somme.
    Personnellement je travaille avec des IDE, et j'ai horreur de séparer la structure de ma classe de son implémentation. Sinon ça fait 2 fichiers à ouvrir. Donc si j'ai 8 classes ouvertes, je devrais en avoir 8 de plus pour l'implémentation (ce qui fait beaucoup d'onglets).
    Donc même en C++ je place l'implémentation au sein de la classe.
    Le fait est que grâce à l'IDE, je peux rapidement atteindre une méthode que je veux au sein de la même page.


    Citation Envoyé par Neckara Voir le message
    il me semble que tout a une sémantique d'entité et on ne peut pas créer de classe à sémantique de valeur si je ne m'abuse ;
    En effet, à part les 8 variables primitives (int, double etc...), tout est classe...
    Mais plus pour longtemps, en Java 9 il est fort probable que nous ayons les Value Types.
    Article récent qui traite du sujet ici.


    Citation Envoyé par Neckara Voir le message
    on gère la mémoire à notre place, plutôt que de nous donner un "choix".
    Oui, d'où l'intérêt de Java, aller à l'essentiel des choses.
    Aujourd'hui en C++ on te donne le choix entre des pointeurs qui risquent de te causer des problèmes de fuite de mémoire lorsque tu as une exception, et des pointeurs intelligents dont la syntaxe est imbuvable.


    Citation Envoyé par Neckara Voir le message
    pour les prototypes de méthodes, certaines choses me paraissent lourdes car il faut les vérifier soit-même à la main
    Je n'ai pas compris


    Citation Envoyé par Neckara Voir le message
    pas d'indications pour spécifier non-nuls
    En Java 8, tu as des annotations pour spécifier les non-nuls. Lien ici. Mais je t'avouerais que je ne me suis pas suffisamment formé là-dessus.
    Aussi, peut-être que je confonds avec autre chose. Comment fait-t-on pour spécifier les non-nuls en C++ ?


    Citation Envoyé par Neckara Voir le message
    l'ancienne gestion des I/O par "couche" me paraissait lourde et peu pratique.
    Oui, c'est pour cela que depuis Java 7, tu as la classe Paths.
    Au faite, peux-tu me rappeler comment on fait, de façon standard en C++, pour gérer les répertoires ?


    Citation Envoyé par Neckara Voir le message
    les templates (même si je ne les utilise pas souvent).
    Les génériques, cousin du template :p


    Citation Envoyé par Neckara Voir le message
    il ne me semble pas qu'une méthode puisse retourner un objet constant (?), il faut donc faire une copie de l'objet avant de retourner sa copie si je ne m'abuse.
    En Java tu as des constantes (final), mais en effet, tu ne peux pas forcer une méthode à te retourner un attribut qui est final. Ensuite le développeur suffisamment malin saura faire la distinction entre retourner la référence, ou une copie de son objet, voir même créer un type immuable.


    Pour les entiers non signés, oui, ça peut être utile pour allonger la plage de valeur. Mais ce n'est pas quelque chose de catastrophique non plus (ils ne l'ont peut-être pas ajouté à cause du fait que le langage soit multiplateforme, ou bien par simplicité). Une fois on m'a fait la reproche comme quoi on pouvait mettre des valeurs négatives au niveau de l'indice d'un tableau en Java, à cause du fait qu'il manque les types non signés... ah bon, parce qu'on ne vérifie plus la valeur min et max du tableau ?
    Et puis celui qui ne tombe pas dans le piège du < 0 avec un type non signé, tombera peut-être dans celui du array index out of bound.
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  11. #11
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Bon, je pense que j'ai eu mes réponses sur ce sujet, je vais le passer en résolu.

    On va partir un peu en HS, mais je pense que cela pourra m'être très instructif^^.

    Citation Envoyé par Gugelhupf Voir le message
    La surcharge d'opérateur peut te manquer, mais le fait d'en avoir peut pousser les développeurs à les utiliser pour des opérations qui ne sont pas cohérentes, comme : "Mouton > Oiseau".
    Donc à cause de "mauvais programmeurs", on sanctionne tous les "bons programmeurs" ?
    Si on suit cette logique, on pourrait nous empêcher d'écrire des logiciels car cela pourrait pousser les développeurs à les utiliser pour écrire des logiciels qui ne serait pas "cohérent"/bogué.

    De plus, ceci n'empêche pas de faire : max(mouton, oiseau); ou mouton.isGreaterThan(oiseau);Personnellement, je préfère avoir des règles tacites :
    • comparaisons "absolues" entre entité interdite car cela n'a aucun sens ;
    • les opérateurs doivent conserver leurs signification



    Ça reste une forme d'héritage avec une classe ne possédant que des méthodes virtuelles pures, l'idée étant d'éviter le Deadly Diamond Of Death, problème qu'on peut rencontrer dans les langages comme C++ ou Python.
    Le problème, c'est qu'en tentant d'éviter un cas particulier, on restreint les possibilités alors qu'il pourrait exister des solutions, je pense, moins radicales.

    L'héritage multiple n'a jamais été un gros problème lorsque la conception est bonne (avec les bons design pattern).
    Dans certains rares cas, il permet d'éviter un peu de duplication de code tout en restant cohérent, mais je reconnais que c'est assez rare d'utiliser de l'héritage multiple.

    De plus en Java 8, il est possible d'avoir des méthodes par défaut, ou des méthodes static dans les interfaces, afin de combler les lacunes des frameworks qui essayent de garder la rétrocompatibilité.
    Des "méthodes par défaut" ?? Mais ce n'est plus des interfaces alors

    Il n'y a pas besoin de destructeur pour libérer les ressources en Java. Les instances sont libérés automatiquement grâce à la VM.
    Il reste toujours des ressources à libérer, si tu ouvres un fichier par exemple, il faut le fermer avec close().
    Seule la mémoire est libérée par défaut, mais pas les autres ressources, donc si on oublie un close(), cela peut devenir assez coûteux.
    Le fait de libérer toutes les ressources à la destruction de l'objet, permet justement d'éviter ce genre de problème.

    De plus depuis Java 7, il est possible d'utiliser une sucre syntaxique (try-with-ressources lien doc), qui te permet d'entrer moins d'instructions, et le fichier sera fermé proprement (implicitement mais de façon déterminé).
    J'en ai entendu parler, mais gère-t-il bien tout types de ressources ?
    De plus j'ai un peu l'impression que c'est une sorte de "rustine" pour tenter de combler ce petit défaut du Java.

    Personnellement je travaille avec des IDE, et j'ai horreur de séparer la structure de ma classe de son implémentation. Sinon ça fait 2 fichiers à ouvrir. Donc si j'ai 8 classes ouvertes, je devrais en avoir 8 de plus pour l'implémentation (ce qui fait beaucoup d'onglets).
    Là c'est plus un problème dû à l'IDE.
    Pour passer de l'en-tête au fichier source, avec un bon IDE, c'est fait en même pas 0,5 secondes (un clic sur un prototype ou un raccourcit touche).
    Pour les onglets... personnellement j'ai tout le temps la liste des fichiers du projet à ma droite et c'est elle que j'utilise pour naviguer.

    Donc même en C++ je place l'implémentation au sein de la classe.
    Ce que je trouve dommage, c'est quand on se retrouve avec une classe de 300 lignes ou plus, on ne peut pas voir d'un simple coup d’œil toutes les membres de la classe, il faut générer la doc pour avoir une vision d'ensemble claire.



    En effet, à part les 8 variables primitives (int, double etc...), tout est classe...
    Mais plus pour longtemps, en Java 9 il est fort probable que nous ayons les Value Types.
    Article récent qui traite du sujet ici.
    Très intéressant


    Oui, d'où l'intérêt de Java, aller à l'essentiel des choses.
    Sauf que parfois, on veut pouvoir gérer soit-même sa mémoire et Java n'offre pas cette possibilité ce qui est assez dommage.
    Il aurait été intéressant d'avoir par exemple :
    • par défaut
      • allocation automatique, libération à la fin du bloc/destruction de la classe
      • allocation avec le garbage collecteur (new)

    • si on le spécifie explicitement
      • gestion via ce que le dev veut.



    Aujourd'hui en C++ on te donne le choix entre des pointeurs qui risquent de te causer des problèmes de fuite de mémoire lorsque tu as une exception,
    Avec les containers et le principe RAII, cela pose un peu moins de problèmes.

    et des pointeurs intelligents dont la syntaxe est imbuvable.
    Personnellement, je les trouve loin d'être imbuvable.


    Je n'ai pas compris
    Il faut que tu vérifie toi-même si la valeur n'est pas nulle ou négative, ensuite il faut lancer une exception, mettre dans le prototype de ta fonction que tu lance une exception, mettre un try/catch, etc.


    En Java 8, tu as des annotations pour spécifier les non-nuls. Lien ici. Mais je t'avouerais que je ne me suis pas suffisamment formé là-dessus.
    Aussi, peut-être que je confonds avec autre chose.
    Je ne connaissais pas, il faudrait que je teste un de ces jours.
    En même temps Java 8 est un peu récent non?

    Comment fait-t-on pour spécifier les non-nuls en C++ ?
    Passage par copie ou par référence.

    Oui, c'est pour cela que depuis Java 7, tu as la classe Paths.
    ? Non je parlais des :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new BiduleStreamInput(new BiduleReaderInput(new BiduleBufferInput(new BiduleInput) ) )
    D'ailleurs, il ne me semble pas qu'on pouvait ouvrir des fichiers en lecteur et écriture ?

    Au faite, peux-tu me rappeler comment on fait, de façon standard en C++, pour gérer les répertoires ?
    On utilise boost (c'est un coup bas ce que tu nous fais là).


    Les génériques, cousin du template :p
    Oui, j'ai un peu oublié .

    Il y a des spécialisation de génériques ? :p (moi aussi j'sais faire des coups bas )
    Il ne me semble pas (à vérifier) qu'on puisse passer d'autres choses que des noms de classes aux génériques ?


    En Java tu as des constantes (final), mais en effet, tu ne peux pas forcer une méthode à te retourner un attribut qui est final. Ensuite le développeur suffisamment malin saura faire la distinction entre retourner la référence, ou une copie de son objet, voir même créer un type immuable.
    Oui mais les copies peuvent être coûteuses ou incohérente et créer une classe immuable est trop long, pour nous, pauvres développeurs fainéants.


    Pour les entiers non signés, oui, ça peut être utile pour allonger la plage de valeur. Mais ce n'est pas quelque chose de catastrophique non plus (ils ne l'ont peut-être pas ajouté à cause du fait que le langage soit multiplateforme, ou bien par simplicité). Une fois on m'a fait la reproche comme quoi on pouvait mettre des valeurs négatives au niveau de l'indice d'un tableau en Java, à cause du fait qu'il manque les types non signés... ah bon, parce qu'on ne vérifie plus la valeur min et max du tableau ?
    Et puis celui qui ne tombe pas dans le piège du < 0 avec un type non signé, tombera peut-être dans celui du array index out of bound.
    Ben on a plus qu'une vérification à faire au lieu de deux, c'est autant de risques en moins d'avoir une erreur.

    Sinon si je veux avoir une distance, cette dernière ne pouvant être négative, je vais me payer une vérification gratuite .
    Cela peut même permettre, lorsqu'on attend un entier positif ou égal à -1 dans un cas d'erreur, de considérer que la valeur maximale pouvant être prise par le type sera le cas d'erreur et ainsi de n'avoir qu'une vérification à faire.



    En tout cas, je trouve que ce type d'échange est très instructif malheureusement, cela se transforme trop souvent en guerre de religion ou en troll.
    Je suis assez content de pouvoir avoir un échange constructif et serein avec vous alors que je critique un peu un langage que vous semblez aimer .
    (bon, je reconnais troller parfois sur le chat, mais bon, c'est le chat quoi )

  12. #12
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    Il n'y a pas besoin de destructeur pour libérer les ressources en Java. Les instances sont libérés automatiquement grâce à la VM.
    Il reste toujours des ressources à libérer, si tu ouvres un fichier par exemple, il faut le fermer avec close().
    C'est justement à ça que sert un destructeur, on à la garantie que la ressource sera relachée dès que l'objet est détruit.
    A priori un équivalent à "try-with-ressources", mais directement intégré à la classe.

    Citation Envoyé par Gugelhupf Voir le message
    En Java 8, tu as des annotations pour spécifier les non-nuls. Lien ici. Mais je t'avouerais que je ne me suis pas suffisamment formé là-dessus.
    Aussi, peut-être que je confonds avec autre chose. Comment fait-t-on pour spécifier les non-nuls en C++ ?
    En C++ un pointeur peut être nul (et réassigné), c'est très proche d'une référence en Java. En C++ une référence ne peut pas être nulle (ni réassignée)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int i, j = 42;
    int *p = nullptr; // pointeur null
    p = &i; // qui pointe maintenant sur i
     
    int& r = i; // r est une ref sur i, r est forcément non nulle
    r = j; // equivalent à i = j, une ref ne peut pas être réassignée
    Citation Envoyé par Gugelhupf Voir le message
    Au faite, peux-tu me rappeler comment on fait, de façon standard en C++, pour gérer les répertoires ?
    Boost.filesystem, normalement bientôt ajouté à la norme.

    Citation Envoyé par Gugelhupf Voir le message
    Les génériques, cousin du template :p
    Venant du C++, les generics (Java ou C#) c'est vraiment le gros point noir de ces langages, le fait de devoir définir des interfaces limite vraiment l'utilisation.
    (En tout cas, c'est ce qui me dérange le plus).

  13. #13
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Neckara Voir le message
    max(mouton, oiseau); ou mouton.isGreaterThan(oiseau);
    Je joue sur les mots mais dire que Mouton "est supérieure à" (greaterThan) Oiseau n'a aucun sens.
    Dire que Mouton est "plus grand" (biggerThan) ou "plus gros" (fatterThan) que Oiseau oui.
    Le fait est que à part les types particuliers comme String, des entiers/décimaux, des types monétaires, et dates/heures, utiliser des opérateurs n'est pas utile, ou peut pousser à un mauvais usage des conventions d'écriture du langage Java.


    Citation Envoyé par Neckara Voir le message
    Des "méthodes par défaut" ?? Mais ce n'est plus des interfaces alors
    Si tu considères qu'une interface ne peut être constitué que de méthode virtuelle pure, les interfaces Java ne sont plus de vraies interface


    Citation Envoyé par Neckara Voir le message
    Seule la mémoire est libérée par défaut, mais pas les autres ressources, donc si on oublie un close(), cela peut devenir assez coûteux.
    Le fait de libérer toutes les ressources à la destruction de l'objet, permet justement d'éviter ce genre de problème.
    Citation Envoyé par Iradrille Voir le message
    C'est justement à ça que sert un destructeur, on à la garantie que la ressource sera relachée dès que l'objet est détruit.
    Normalement, on est censé savoir quand et où on souhaite fermer un fichier, pas forcément à la fin d'un bloc pour faire intervenir le RAII (même en C++ tu as une méthode close() pour fermer ton oftream). Aussi ce type de ressource est généralement utilisé au sein d'un même bloc, donc sa manipulation n'est pas aussi complexe que les objets qu'on est susceptible de trimballer d'objet à objet.


    Citation Envoyé par Neckara Voir le message
    J'en ai entendu parler, mais gère-t-il bien tout types de ressources ?
    De plus j'ai un peu l'impression que c'est une sorte de "rustine" pour tenter de combler ce petit défaut du Java.
    Tous les types de ressource qui implémente l'interface AutoCloseable, il ne reste plus qu'à croiser les doigts pour que la méthode close() soit implémenté correctement
    Rustine non, c'est une syntaxe sucrée qui garanti (finally) qu'à la fin de ton bloc, tu vas fermer ta ressource.


    Citation Envoyé par Neckara Voir le message
    Là c'est plus un problème dû à l'IDE.
    Pour passer de l'en-tête au fichier source, avec un bon IDE, c'est fait en même pas 0,5 secondes (un clic sur un prototype ou un raccourcit touche).
    Pour les onglets... personnellement j'ai tout le temps la liste des fichiers du projet à ma droite et c'est elle que j'utilise pour naviguer.
    Ayant pratiqué les 2 types de développements (séparation prototype/implémentation, fichier unique par classe), j'en suis resté au second.


    Citation Envoyé par Neckara Voir le message
    Ce que je trouve dommage, c'est quand on se retrouve avec une classe de 300 lignes ou plus, on ne peut pas voir d'un simple coup d’œil toutes les membres de la classe, il faut générer la doc pour avoir une vision d'ensemble claire.
    Je ne sais pas quel IDE tu utilises, mais moi, en un coup d'oeil je peux voir les membres de la classe (inférieur à 0,5 secondes garanti ) :
    Pièce jointe 146046



    Citation Envoyé par Neckara Voir le message
    Avec les containers et le principe RAII, cela pose un peu moins de problèmes.
    Je ne vois pas trop ce que peuvent faire les containers et le RAII contre les exceptions générés dans le constructeur de ta classe (voir ceci).


    Citation Envoyé par Neckara Voir le message
    Il faut que tu vérifie toi-même si la valeur n'est pas nulle ou négative, ensuite il faut lancer une exception, mettre dans le prototype de ta fonction que tu lance une exception, mettre un try/catch, etc.
    Oui, mais préciser dans le prototype de ta méthode que ta méthode est susceptible de lancer une exception (throws) est une excellente manière de documenter ton code (tous les langages de haut niveau ne le font pas si ça peut te rassurer). Et puis cela suit une logique, si la méthode d'une classe Parente lance une exception d'un certain type, celui de la méthode Enfant doit elle aussi lancer une exception de ce type, histoire de ne pas dénaturer le comportement de base de la méthode.
    Ce n'est pas pour embêter le développeur avec les try/catch, l'approche est défensive.


    Citation Envoyé par Neckara Voir le message
    En même temps Java 8 est un peu récent non?
    Il a longtemps été attendu, mais oui, il vient de sortir récemment (18 mars 2014)


    Citation Envoyé par Neckara Voir le message
    ? Non je parlais des :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    new BiduleStreamInput(new BiduleReaderInput(new BiduleBufferInput(new BiduleInput) ) )
    D'ailleurs, il ne me semble pas qu'on pouvait ouvrir des fichiers en lecteur et écriture ?
    C'est justement pour éviter tous ces InputStreamBidules imbuvables que tu as la classe Paths depuis Java 7.
    Ouvrir en lecture et ouverture en même temps, non je ne crois pas, d'ailleurs, si cette possibilité n'est pas fournit, c'est qu'il doit forcément y avoir une raison.


    Citation Envoyé par Neckara Voir le message
    Il y a des spécialisation de génériques ? :p (moi aussi j'sais faire des coups bas )
    Il ne me semble pas (à vérifier) qu'on puisse passer d'autres choses que des noms de classes aux génériques ?
    Les génériques de base s'utilisent presque de la même manière que les templates de base.
    Il n'y a pas de spécialisation ou de variadic template en Java... tout comme il n'y a pas de covariance et contravariance en C++
    Mais sincèrement, en C++, j'ai rarement eu à utiliser la spécialisation, la syntaxe est juste lourde à mettre en place.
    L'inconvénient en Java, contrairement au C# et C++, c'est que tu ne peux pas utiliser les types primitifs, il faut utiliser les Wrapper ("Integer" au lieu de "int" par exemple).
    Un autre contrairement au C++, c'est l'instanciation du type template que tu ne peux pas.
    Le compilateur C++, tout ce qu'il fait, c'est dupliquer du code (alourdir le binaire), ce qui n'est pas le cas en Java, qui lui cast (perte de performance). Pour C# c'est encore autre chose.


    Citation Envoyé par Neckara Voir le message
    Oui mais les copies peuvent être coûteuses ou incohérente et créer une classe immuable est trop long, pour nous, pauvres développeurs fainéants.
    Peut-être.. Je ne sais pas, mais un jour un gourou du C++ m'a répondu cela :
    @lmghs
    il est parfois plus efficace de copier que de prendre des références. Il y a quelques articles à ce sujet sur cpp-next. Sans parler des rvalue-references qui changent encore la donne.
    [...]
    Parfois sur des objets plus gros cela donne aussi de meilleures performance. D'où que je t'envoie sur cpp-next. Les infos sont là bas.

    Citation Envoyé par Neckara Voir le message
    Passage par copie ou par référence.
    Citation Envoyé par Iradrille Voir le message
    En C++ un pointeur peut être nul (et réassigné), c'est très proche d'une référence en Java.
    Je vais jouer sur les mots, mais il n'y a pas de référence en Java, c'est un abus de langage.
    Suite à l'exemple, je comprends mieux de quoi il s'agit merci
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  14. #14
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    Oui, mais préciser dans le prototype de ta méthode que ta méthode est susceptible de lancer une exception (throws) est une excellente manière de documenter ton code (tous les langages de haut niveau ne le font pas si ça peut te rassurer).
    Mais ça ne rend pas le code dur à maintenir ?
    par exemple
    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
    // ne pas faire attention à la syntaxe, j'ai pas d'IDE / compilo Java sous la main
    class Foo {
       public Foo() { }
       public void bar() throw SomeException {
           throw new SomeException();
       }
    };
     
    class Baz {
       private Foo foo;
       public Baz() { foo = new Foo(); }
       public void fct() throw SomeException {
          foo.bar();
       }
    };
    Si par la suite Foo::bar devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public void bar() throw SomeException, SomeOtherException {
       if(...) {
           throw new SomeException();
       }
       else {
          throw new SomeOtherException();
       }
    }
    Il faut modifier Baz::fct (et toutes les fonctions utilisant Foo::bar), ou alors il est inutile de préciser que Baz::fct peut "laisser passer" les exceptions de Foo::bar ?

    Citation Envoyé par Gugelhupf Voir le message
    Je ne vois pas trop ce que peuvent faire les containers et le RAII contre les exceptions générés dans le constructeur de ta classe (voir ceci).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class A {
    	std::unique_ptr<int> i;
    	std::unique_ptr<int> j;
     
    public:
    	A(A const &) = delete;  
    	A& operator= (A const &) = delete;
     
    	A() : i(new int(314)), j(new int(42)) { }
    };
    Le RAII (utilisé en interne par std::unique_ptr) résout le problème.

    Citation Envoyé par Gugelhupf Voir le message
    Je vais jouer sur les mots, mais il n'y a pas de référence en Java, c'est un abus de langage.
    Suite à l'exemple, je comprends mieux de quoi il s'agit merci
    Rhoo tu chipote, tu sais très bien de quoi on parle.

    edit

    Citation Envoyé par Gugelhupf Voir le message
    Normalement, on est censé savoir quand et où on souhaite fermer un fichier, pas forcément à la fin d'un bloc pour faire intervenir le RAII (même en C++ tu as une méthode close() pour fermer ton oftream).
    Tout comme on est sensé savoir quand supprimer un objet pour relacher la mémoire. On peut fermer un fichier manuellement, mais si on le fait pas, on à quand même la garanti qu'il sera fermé dès que l'objet sera détruit.

  15. #15
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    Je joue sur les mots mais dire que Mouton "est supérieure à" (greaterThan) Oiseau n'a aucun sens.
    Dire que Mouton est "plus grand" (biggerThan) ou "plus gros" (fatterThan) que Oiseau oui.
    Je n'ai pas dit le contraire.

    Le fait est que à part les types particuliers comme String, des entiers/décimaux, des types monétaires, et dates/heures, utiliser des opérateurs n'est pas utile, ou peut pousser à un mauvais usage des conventions d'écriture du langage Java.
    Tu oublies les conteneurs, classes de lectures/écriture, tout ce qui est foncteurs et pointeurs.
    Le opérateurs de conversions implicites peuvent être assez utile comme une conversion vers :
    • std::string pour afficher une classe, en Java il faut appeler une méthode ToString() ;
    • bool pour voir s'il n'y a pas eu d'erreur (ex, lecture de fichier)


    On peut aussi interdire la copie d'entité, optimiser la copie de valeurs.
    Les opérateurs sont donc loin d'être inutiles.
    Je pense donc que l'utilité est bien supérieur au risque qui est même inexistant chez un bon nombre de développeurs.


    Normalement, on est censé savoir quand et où on souhaite fermer un fichier, pas forcément à la fin d'un bloc pour faire intervenir le RAII (même en C++ tu as une méthode close() pour fermer ton oftream).
    Je n'ai pas dit le contraire, mais avoir une libération automatique éviter des bogues.
    D'ailleurs, rien n'interdit de vouloir libérer la ressource à la fin du bloc ou à la destruction de la classe, ce qui est loin d'être rare.

    Aussi ce type de ressource est généralement utilisé au sein d'un même bloc, donc sa manipulation n'est pas aussi complexe que les objets qu'on est susceptible de trimballer d'objet à objet.
    Donc tu ouvres et tu ferme ta base de donnée à chaque requête pour utiliser la ressource au sein d'un même bloc ? (ok, je troll)
    Un bon nombre de ressources doivent rester ouverte au-delà du bloc où elles sont utilisée.

    Tous les types de ressource qui implémente l'interface AutoCloseable, il ne reste plus qu'à croiser les doigts pour que la méthode close() soit implémenté correctement
    Rustine non, c'est une syntaxe sucrée qui garanti (finally) qu'à la fin de ton bloc, tu vas fermer ta ressource.
    A la fin du bloc, pourquoi pas, mais est-ce que ceci marche aussi lors de la destruction de la classe ? Est-on sûr que finally sera appelé ?

    Je ne sais pas quel IDE tu utilises, mais moi, en un coup d'oeil je peux voir les membres de la classe (inférieur à 0,5 secondes garanti ) :
    Je ne suis pas vraiment convaincu, la fenêtre doit prendre quand même pas mal de place si le prototype d'une méthode est un peu longue et a des throws.

    Je ne vois pas trop ce que peuvent faire les containers et le RAII contre les exceptions générés dans le constructeur de ta classe (voir ceci).
    C'est simple, on évite de lancer des exceptions dans un constructeurs.
    Si la construction peut échouer, soit on passe par une factory, soit on passe par une méthode MaClasse::create(), soit on donne une fonction pour vérifier la cohérence de la classe.

    Ce n'est pas pour embêter le développeur avec les try/catch, l'approche est défensive.
    Déjà, il pourrait envoyer l'exception automatiquement, c'est toujours cela de gagné.
    Ensuite, il suffit de fonction toute simples de conversion, pour ne plus à avoir à mettre des try/catch lors de l'appel des fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @nonnull Toto  t = coallapse(toto, new Toto(58) );
     
    if( toto != null )
    {
        @nonnull Toto t = coallapse(toto, null); // lance une exception si toto est null
         foo( toto) ;
    }
    else
    {
         // I do what I want.
    }
    Ensuite, c'est avant tout à l'appeleur de vérifier qu'il envoie bien des données valides, donc en théorie de try/catch devrait être inutile.
    Ce qui n'empêche pas la classe de vérifier elle-même la cohérence des données reçues, mais avec nonnull ou non-signé, elle n'a plus besoin de le faire.


    Ouvrir en lecture et ouverture en même temps, non je ne crois pas, d'ailleurs, si cette possibilité n'est pas fournit, c'est qu'il doit forcément y avoir une raison.
    Ben personnellement, je n'en vois pas la raison .


    Il n'y a pas de spécialisation ou de variadic template en Java... tout comme il n'y a pas de covariance et contravariance en C++
    En effet, par contre il faut faire attention de ne pas les utiliser pour des containers

    Peut-être.. Je ne sais pas, mais un jour un gourou du C++ m'a répondu cela :
    @lmghs
    En C++,
    Cela ne me paraitrait pas logique dans le cas où on utiliserait des références.


    Vous allez finir par me faire louper mon car

  16. #16
    Membre chevronné
    Inscrit en
    Mai 2006
    Messages
    1 364
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 1 364
    Points : 1 984
    Points
    1 984
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Bon, je pense que j'ai eu mes réponses sur ce sujet, je vais le passer en résolu.
    Quand tu auras décidé, est ce que tu pourrais poster l'outil que tu vas utiliser (meme si ce n'est pas java) ? C'est une question que je me suis deja posée et je n'ai pas trouvé de réponse idéale donc ca m'interesse de voir ce que les autres choisissent dans le meme cas

    Concernant Java/C/C++, j'ai un peu le chemin inverse. A la base, j'ai fait du C. puis du Java et en ce moment, je fais un peu de c++ (via des projets de jeux open source). Quand je suis arrivé sur Java, je trouvais embetant de ne pas avoir de macros et je trouvais le coté multiplateforme pas forcement tres utile. Mais la, pour rejouer un peu avec c++, je me rends compte à quel point c'est galere. Pour s'en rendre compte, il suffit de télécharger n'importe quel projet open source puis de compiler via MSVS, MinGW et Linux GCC. Deja, il y a de fortes chances que le projet ne compile pas sur les 3 (et je ne parle meme pas des autres compilateurs). Ensuite, quand on regarde les sources, il y a des flags sur les compilateurs dans tous les sens, c'est pas évident de savoir quel code est utilisé ou non.

    Un autre truc qui me gene avec les macros, c'est les comportements différents en fonction de l'ordre des include (en général, une macro redefinit une fonction avec un nom un peu trop générique et ca pete le header suivant).
    Quand à la séparation header/implementation, je pense comme Gugelhupf pour les memes raisons. C'est compliqué à lire et ca oblige à passer d'un fichier à l'autre. Et quand on veut modifier le prototype d'une fonction, il faut le faire 2 fois. C'est galère.

  17. #17
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par hwoarang Voir le message
    Concernant Java/C/C++, j'ai un peu le chemin inverse. A la base, j'ai fait du C. puis du Java et en ce moment, je fais un peu de c++ (via des projets de jeux open source). Quand je suis arrivé sur Java, je trouvais embetant de ne pas avoir de macros et je trouvais le coté multiplateforme pas forcement tres utile. Mais la, pour rejouer un peu avec c++, je me rends compte à quel point c'est galere. Pour s'en rendre compte, il suffit de télécharger n'importe quel projet open source puis de compiler via MSVS, MinGW et Linux GCC. Deja, il y a de fortes chances que le projet ne compile pas sur les 3 (et je ne parle meme pas des autres compilateurs). Ensuite, quand on regarde les sources, il y a des flags sur les compilateurs dans tous les sens, c'est pas évident de savoir quel code est utilisé ou non.
    C'est effectivement quelque chose de bien chiant en C++, si seulement ça pouvait être standardisé...

    Pour les macros elles sont principalement utilisées pour définir des configurations : une fonction qui agit différemment en Debug et Release, l'import / export de fonctions dans les DLL etc.. (et protéger les includes).

    En dehors de ça, l'utilisation de macros reste très rare et il faut avoir une bonne raison pour les utiliser : en C c'est la seule façon d'éviter des gros copier / coller, en C++ on à largement les outils pour s'en sortir sans macros : templates, constepr, surcharge de fonctions etc..
    Si jamais on doit utiliser des macros, cette une bonne pratique de les undef dès qu'elles ne servent plus.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #define ITER_5(a) (foo((a)); foo((a)+1); foo((a)+2); foo((a)+3); foo((a)+4);)
    #define ITER_25(a) (ITER_5((a)); ITER_5((a)+5); ITER_5((a)+10); ITER_5((a)+15); ITER_5((a)+20);)
     
    void foo(int i) { std::cout << i << " "; }
    ITER_25(0);
     
    #undef ITER_5
    #undef ITER_25
    Pour dérouler une boucle à la main par exemple (c'est généralement inutile vu qu'un compilo sait le faire).
    Puis une erreur de syntaxe dans une macro et ça devient vite un bordel monstre à corriger, les macros c'est vraiment en dernier recours.

  18. #18
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par hwoarang Voir le message
    Quand tu auras décidé, est ce que tu pourrais poster l'outil que tu vas utiliser (meme si ce n'est pas java) ? C'est une question que je me suis deja posée et je n'ai pas trouvé de réponse idéale donc ca m'interesse de voir ce que les autres choisissent dans le meme cas
    Déjà, je vais adopter une approche plus POC au lieu de l'approche POO que j'adoptais tout en faisant du pseudo "POC" vu que je séparais mon code en "modules".

    Ensuite, je vais essayer d'aller à l'essentiel et de faire simple.
    Au départ, je voulais générer une interface C à partir de code ou de pseudo code C++ pour les modules pour des questions de portabilités, à partir de ce pseudo-code, je pensais pouvoir générer automatiquement un "squelette" pour mon module permettant ainsi d'écrire le module dans divers langages. Mais cela prend trop de temps à réaliser.
    Je vais donc :


    • fournir des interfaces C++, si une personne veut faire un module en C, il le compilera en C++ et puis voilà ;
    • ne pas me soucier de la possibilité d'écrire des modules dans d'autres langages, on verra cela plus tard.



    Pour l'exécution via navigateur, je pense que je vais plutôt privilégier un "client léger" qui téléchargera les ressources petit à petit.

    Donc au final, je vais sûrement continuer en C++, je continue de réfléchir un peu.



    Pour s'en rendre compte, il suffit de télécharger n'importe quel projet open source puis de compiler via MSVS, MinGW et Linux GCC. Deja, il y a de fortes chances que le projet ne compile pas sur les 3 (et je ne parle meme pas des autres compilateurs).
    Si le code est portable, peut-être à l'exception de quelques petites erreurs, il n'y a pas de raison.



    Ensuite, quand on regarde les sources, il y a des flags sur les compilateurs dans tous les sens, c'est pas évident de savoir quel code est utilisé ou non.
    Soit tu regardes du code très sale, ce qui est un très mauvais exemple, soit tu regardes des fichiers de bibliothèques standard ou autre qui sont en effet imbuvables.

    Un autre truc qui me gene avec les macros, c'est les comportements différents en fonction de l'ordre des include (en général, une macro redefinit une fonction avec un nom un peu trop générique et ca pete le header suivant).
    Il y a des conventions pour éviter cela. De plus, en C++, avec les fonctions inline et les variables réellement constantes, l'utilisation de macro est très très rares.


    Quand à la séparation header/implementation, je pense comme Gugelhupf pour les memes raisons. C'est compliqué à lire et ca oblige à passer d'un fichier à l'autre. Et quand on veut modifier le prototype d'une fonction, il faut le faire 2 fois. C'est galère.
    Compliqué à lire ? Au contraire je trouve.
    Pour passer d'un fichier à l'autre, c'est presque automatique. Pour modifier le prototype, un bon IDE modifiera le prototype aux deux endroits.



    Citation Envoyé par Iradrille Voir le message
    Si jamais on doit utiliser des macros, cette une bonne pratique de les undef dès qu'elles ne servent plus.
    Un gros +

  19. #19
    Modérateur
    Avatar de Gugelhupf
    Homme Profil pro
    Analyste Programmeur
    Inscrit en
    Décembre 2011
    Messages
    1 320
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Analyste Programmeur

    Informations forums :
    Inscription : Décembre 2011
    Messages : 1 320
    Points : 3 741
    Points
    3 741
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Le RAII (utilisé en interne par std::unique_ptr) résout le problème.
    Si on part du principe que tous les attributs initialisés dans un constructeur doivent être placé dans un pointeur intelligent, alors beaucoup de pointeurs nus devront être transformés en pointeur intelligent non ?
    Je pense qu'il faudrait améliorer le système des pointeurs et constructeurs pour les rendre plus safe, utiliser un moyen détourné qui alourdit la syntaxe (pointeur intelligent), sous prétexte peut-être que cela risquerait autrement d'impacter négativement les performances... Je ne sais pas, il faut juger le pour et le contre, trouver un moyen d'optimiser cet ensemble.


    Citation Envoyé par Neckara Voir le message
    • std::string pour afficher une classe, en Java il faut appeler une méthode ToString() ;
    On peut redéfinir la méthode toString(), sans forcément avoir besoin de l'appeler explicitement : System.out.println(monObjetQuiRedefinitToString);

    Citation Envoyé par Neckara Voir le message
    Donc tu ouvres et tu ferme ta base de donnée à chaque requête pour utiliser la ressource au sein d'un même bloc ? (ok, je troll)
    Oui et non, je me sers d'un pool donc la connexion n'est pas fermée.
    Je ne me rappel plus d'avoir vu un standard équivalent à l'API JDBC en C++, donc à part utiliser des API en C tous différents en fonction du SGBD (j'ai aussi trollé)
    Bon blague à part, on peut voir sur isopp qu'un SG11 – Databases Discussion of database-related library interfaces for C++ est toujours en discussion. Mais ça fait un peu tard.


    Citation Envoyé par Neckara Voir le message
    A la fin du bloc, pourquoi pas, mais est-ce que ceci marche aussi lors de la destruction de la classe ? Est-on sûr que finally sera appelé ?
    C'est un peut comme le RAII, qu'est-ce qui m'assure que mon destructeur sera appelé ?
    Le finally sera appelé même si tu as un return dans ton bloc try. Par contre si tu fais un exit de façon explicite, non il ne sera pas appelé.


    Citation Envoyé par Neckara Voir le message
    Je ne suis pas vraiment convaincu, la fenêtre doit prendre quand même pas mal de place si le prototype d'une méthode est un peu longue et a des throws.
    Peut-être, mais c'est ce que commence à faire le C++ en ajoutant des mot-clés comme final et override afin de rendre plus explicite le code.


    Citation Envoyé par Iradrille Voir le message
    Mais ça ne rend pas le code dur à maintenir ?
    La signature de la méthode parente est censée indiquer toutes les exceptions qu'elle est susceptible de lancer, ainsi que ses implémentations.
    L’implémentation, peut lancer moins d'exception, mais pas d'exception supplémentaire.
    Si durant la phase de développement tu t’aperçois du fait que durant la phase de conception tu as oublié d'ajouter une exception dans la signature de la méthode parente, il est possible d'ajouter cet exception dans la signature de la méthode parente. Ça ne "cassera" pas le programme.



    J'ai regroupé le thème lié à la gestion des exceptions :
    Citation Envoyé par Neckara Voir le message
    • bool pour voir s'il n'y a pas eu d'erreur (ex, lecture de fichier)
    Pour les erreurs, c'est du try/catch avec IOException. On ne va pas se servir d'un bool pour dire "false" lorsque chose ne va pas bien (on n'est plus en C), ici on peut donner plusieurs raisons au problème survenu.
    Citation Envoyé par Neckara Voir le message
    Ensuite, c'est avant tout à l'appeleur de vérifier qu'il envoie bien des données valides, donc en théorie de try/catch devrait être inutile.
    Je ne crois pas que ce soit aussi simple. Quand tu développes une application, tu ne connais pas forcément l'implémentation des API externes. Donc comment savoir à l'avance les types d'erreurs que tu pourrais avoir ? Et même si tu les connaissais et que tu avais dix types d'exception à vérifier, exécuter 10 if avec une fonction booléenne ce n'est pas très propre.
    Citation Envoyé par Neckara Voir le message
    C'est simple, on évite de lancer des exceptions dans un constructeurs.
    Si la construction peut échouer, soit on passe par une factory, soit on passe par une méthode MaClasse::create(), soit on donne une fonction pour vérifier la cohérence de la classe.
    Mon pneu est sous gonflé, mais comme j'ai la flemme d'aller à la station, je vais forcer avec ma pompe à vélo
    Éviter volontairement de lancer des exceptions dans un constructeur... c'est un peu dommage non ?
    N'hésitez pas à consulter la FAQ Java, lire les cours et tutoriels Java, et à poser vos questions sur les forums d'entraide Java

    Ma page Developpez | Mon profil Linkedin | Vous souhaitez me contacter ? Contacter Gokan EKINCI

  20. #20
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Gugelhupf Voir le message
    Si on part du principe que tous les attributs initialisés dans un constructeur doivent être placé dans un pointeur intelligent, alors beaucoup de pointeurs nus devront être transformés en pointeur intelligent non ?
    Sûrement pas, il n'est pas utile d'utiliser un pointeur pour chaque attributs, d'ailleurs, je pense qu'on utilise assez peu de pointeurs en C++ dans les attributs des classes.

    qui alourdit la syntaxe (pointeur intelligent)
    On a des typedef.

    sous prétexte peut-être que cela risquerait autrement d'impacter négativement les performances...
    Je ne comprend pas le sens de ta phrase.

    On peut redéfinir la méthode toString(), sans forcément avoir besoin de l'appeler explicitement : System.out.println(monObjetQuiRedefinitToString);
    Parce que println prend un Object et appelle lui-même toString().


    donc à part utiliser des API en C tous différents en fonction du SGBD (j'ai aussi trollé)
    Il y a beaucoup d'API en C++. Sinon il me semble que Qt fournit une interface permettant de se connecter à pas mal de SGBD, je me demande si boost n'en fait pas de même d'ailleurs.

    C'est un peut comme le RAII, qu'est-ce qui m'assure que mon destructeur sera appelé ?
    Le destructeurs sera forcément appelé avec le RAII, c'est d'ailleurs sont but.


    Peut-être, mais c'est ce que commence à faire le C++ en ajoutant des mot-clés comme final et override afin de rendre plus explicite le code.
    Oui et ?
    Je parle de la fenêtre listant les membres qui devrait être assez grosse, pas du langage Java.

    Pour les erreurs, c'est du try/catch avec IOException. On ne va pas se servir d'un bool pour dire "false" lorsque chose ne va pas bien (on n'est plus en C), ici on peut donner plusieurs raisons au problème survenu.
    Ce n'est pas parce que tu retournes un booléen en cas d'erreurs que tu ne peux pas récupérer la description de l'erreur...

    Et ce n'est pas parce qu'on a des exceptions, qu'il faut les utiliser à tout va.
    Les cas d'exceptions doivent rester "exceptionnels". Si c'est une "erreur fréquente", utiliser une exception est incohérent.

    En plus utiliser des exception à tout va, c'est lourd pour pas grand chose, surtout quand on peut traiter l'erreur directement.

    Quand tu développes une application, tu ne connais pas forcément l'implémentation des API externes
    ????? On s'en moque de l'implémentation, ce qu'il nous faut c'est le prototype qui nous donne déjà des indications sur les valeurs acceptées.

    Et même si tu les connaissais et que tu avais dix types d'exception à vérifier, exécuter 10 if avec une fonction booléenne ce n'est pas très propre.
    ??????

    Mon pneu est sous gonflé, mais comme j'ai la flemme d'aller à la station, je vais forcer avec ma pompe à vélo
    ??????

    Éviter volontairement de lancer des exceptions dans un constructeur... c'est un peu dommage non ?
    J'ai rien dit, le C++ disposerais d'une syntaxe pour lancer les exceptions proprement à partir du constructeur :

    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
    A::A() throw (int)
    try
    {
        pBuffer = NULL;
        pData = NULL;
        cout << "Début du constructeur" << endl;
        pBuffer = new char[256];
        cout << "Lancement de l'exception" << endl;
        throw 2;
        // Code inaccessible :
        pData = new int;
    }
    catch (int)
    {
        cout << "Je fais le ménage..." << endl;
        delete[] pBuffer;
        delete pData;
    }
    Et le destructeur ne sera jamais appelé.

    Comme quoi j’apprends encore des choses ^^.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 04/04/2013, 10h04
  2. Réponses: 58
    Dernier message: 29/10/2010, 12h35
  3. Faire le bon choix pour ?
    Par Benew dans le forum Débuter
    Réponses: 1
    Dernier message: 07/04/2008, 21h02
  4. Quel écran pour mes besoins?
    Par virgul dans le forum Périphériques
    Réponses: 11
    Dernier message: 26/04/2006, 15h44
  5. Serveur FTP - Lequel choisir pour mes besoins
    Par etumed dans le forum Réseau
    Réponses: 3
    Dernier message: 19/03/2006, 13h58

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