Publicité
+ Répondre à la discussion
Page 5 sur 10 PremièrePremière 123456789 ... DernièreDernière
Affichage des résultats 81 à 100 sur 194
  1. #81
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Pour le site, je pensais à faire un truc simpliste le temps qu'un truc plus élaboré naisse, un truc avec 0 scripts derrière, mais qui te permet de coller des liens vers des pages ayant du contenu qui ne bouge pas et d'autres pour les trucs plus évolués (et temporairement externe)... En fait, ce qu'on pourrait bêtement appeler un prototype ou un premier jet.
    Je sais bien que ce serait dommage de tout faire à la main, et mon propos n'a jamais été de t'encourager à ça (la phrase où je dit, entre parenthèses d'ailleurs, que ça serait ma tendance naturelle n'était pas là pour indiquer que c'est ce qu'il faut faire, et même le contraire).

    Sinon, c'est une excellente chose de reprendre la conception.
    Vous comptez refaire la conception à 0, ou tenter de sauver ce qui existe?
    Ah, et je ne sais pas si tu connais cet outil, mais je le trouve assez pratique pour indiquer les endroits sur lesquels il y a une trop grosse complexité, et donc peut être une erreur de conception: CCCC. Si vous comptez ne pas repartir de 0, ça pourra aider. (A noter tout de même: il ne gère pas totalement les template, donc en cas d'usage intensif de la programmation générique, il faut réfléchir un peu plus pour comprendre les résultats.)
    Il y a aussi dans ce cas ce site la qui pourrait t'intéresser: http://refactoring.com/ (qui ne contiens que quelques trucs utiles, mais la plupart des "astuces" sont triviales et/ou orienté java je dirais)

    PS: je serai très curieux de voir les divers documents de conception.

  2. #82
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Pour le site, je pensais à faire un truc simpliste le temps qu'un truc plus élaboré naisse, un truc avec 0 scripts derrière, mais qui te permet de coller des liens vers des pages ayant du contenu qui ne bouge pas et d'autres pour les trucs plus évolués (et temporairement externe)... En fait, ce qu'on pourrait bêtement appeler un prototype ou un premier jet.
    Là on a regardé avec le programmeur web, on semble bien intéressé par Drupal. Dès dimanche, on fixe ce qu'il faut faire sur le site et une semaine après je pense que ce sera fini.

    Citation Envoyé par Freem Voir le message
    Sinon, c'est une excellente chose de reprendre la conception.
    Vous comptez refaire la conception à 0, ou tenter de sauver ce qui existe?
    On va refaire à partir de 0 comme on a eu pas mal de nouvelles idées.

    Citation Envoyé par Freem Voir le message
    Il y a aussi dans ce cas ce site la qui pourrait t'intéresser: http://refactoring.com/ (qui ne contiens que quelques trucs utiles, mais la plupart des "astuces" sont triviales et/ou orienté java je dirais)
    J'ai déjà entendu parler du refactoring, je pense qu'il est temps que je me renseigne^^


    Citation Envoyé par Freem Voir le message
    PS: je serai très curieux de voir les divers documents de conception.
    Là on a commencé le cahier des charges ce matin même. Je pense qu'on va attendre que le site soit prêt (environ 2 semaines) et que le cahier des charges fasse plus de 3 pages (+ 2 schémas )

  3. #83
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Le refactoring, c'est l'art de modifier un programme pour améliorer un aspect dans lequel il pèche, mais sans altérer ses fonctionnalités (ni pour en ajouter explicitement - bien que ça puisse en ajouter via le gain de souplesse - , ni pour en supprimer). L'intérêt étant de rendre le code soit plus performant, soit plus souple, soit plus lisible, soit n'importe quelle combinaison de ces 3 la.

    Je ne dis pas que ça ne représente rien en terme de temps de travail, loin de la, mais l'avantage que ça a, pour moi, c'est que ce qui marche n'a pas besoin d'être refait. Du coup, tu ne te décourage pas, ni toi, ni ton équipe, parce que refaire le même truc c'est pas vraiment motivant.
    Et puis, refaire un truc t'expose au risque de le refaire mal, tandis que de l'améliorer par petits pas permet d'avoir une progression dans l'absolu, même si elle est lente.
    Un autre avantage, c'est que tu es obligé de relire du vieux code. Du coup, tu te poses naturellement des questions sur le pourquoi ça a été fait comme ça, donc tu peux éviter de tomber dans les mêmes erreurs par la suite (quand il y en avait).

    Un "défaut" évident par contre, c'est qu'il faut se contraindre a y aller par de très petites modifications, ce qui peut "flooder" le changelog avec une multitude de commit. Mais bon, ce "défaut" permet de retrouver exactement quel commit a introduit un problème, si jamais, donc ce n'en est pas vraiment un.

    PS: j'ai jeté un coup d'oeil vite fait au code (vite fait signifie rapidement, sans regarder tout).
    Je dirai qu'il est plutôt propre, donc sûrement réutilisable.
    J'y ai trouvé 3 "soucis" (on ne peux pas vraiment appeler ça des soucis, en fait, puisque ça tiens plus du style qu'autre chose):
    _ l'ensemble des fichiers que j'ai consultés semblent très fortement couplés à SFML, ajoutant des vérifications et traitements dans des classes qui ne semblent pas devoir s'en charger. Ajouter quelques classes triviales pour masquer les usages de SFML pourrait mieux séparer la mécanique et la logique.
    _ une imbrication de namespaces des plus impressionnante, qui parfois remplace des énumérations nommées. Par exemple:
    Code :
    1
    2
    3
    4
    5
     
        namespace BOUTON
        {
            enum{CONEXION, LIGNE, PVP, HORS_LIGNE, EDITEUR, PARAM, QUITTER};
        }
    pourrait être remplacé par "enum BOUTON{CONEXION, LIGNE, PVP, HORS_LIGNE, EDITEUR, PARAM, QUITTER};".
    Autre exemple, l'omniprésence du namespace LD, qui me semble inutile puisque l'on sait que chaque fichier appartiens au programme LD... non? Les namespace, c'est bien, mais la, je trouve qu'il y a excès (j'ai vu une zone avec 4 namespace imbriqués)
    _ pas de distinction entre les variables locales à une méthode et les variables membres de la classe.
    _ un amour profond des pointeurs. Je comprend bien leur intérêt, mais selon moi, à plusieurs moments vous en utilisez inutilement
    _ mélange des langues: "makeLisible" fait bizarre par exemple, ou "PairHash::old" et "PairHash::nouv" (bon au final on comprend c'est juste qu'on ne sait pas sur quel pied danser)
    _ code en Français => aucun risque de voir un non francophone participer
    _ réinvention de la roue pour des choses mineures pour lesquelles des bibliothèques existent (genre, gestion des fichiers/dossiers avec les '/' et '\' => boost::filesystem est très simple d'utilisation, par exemple)
    Mais au final, rien qui ne justifie une écriture totale, à mon humble avis.

    Il faudra que je m'amuse à faire un schéma de l'existant pour voir, mais avec ce que j'ai vu, je ne suis pas persuadé qu'il soit nécessaire de reprendre à 0.
    Evidemment, je n'ai pas tout regardé, et n'ai même pas essayé de compiler, alors pour l'exécution...

  4. #84
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Bonjour, merci pour ta réponse très constructive,

    Citation Envoyé par Freem Voir le message
    Je ne dis pas que ça ne représente rien en terme de temps de travail, loin de la, mais l'avantage que ça a, pour moi, c'est que ce qui marche n'a pas besoin d'être refait. Du coup, tu ne te décourage pas, ni toi, ni ton équipe, parce que refaire le même truc c'est pas vraiment motivant.
    Et puis, refaire un truc t'expose au risque de le refaire mal, tandis que de l'améliorer par petits pas permet d'avoir une progression dans l'absolu, même si elle est lente.
    Le fait d'avoir passé plusieurs semaines à réfléchir nous a permis d'avoir une meilleurs idée du jeu final et de voir ce qu'il nécessite plus en détail. Il est donc très probable qu'on ai à refaire entièrement la structure du client.
    Mais si je n'exclue pas la possibilité de quelques copié-collé quand ça nous arrangera.


    Citation Envoyé par Freem Voir le message
    Un "défaut" évident par contre, c'est qu'il faut se contraindre a y aller par de très petites modifications, ce qui peut "flooder" le changelog avec une multitude de commit. Mais bon, ce "défaut" permet de retrouver exactement quel commit a introduit un problème, si jamais, donc ce n'en est pas vraiment un.
    Déjà que je suis assez fainéant pour les commits...
    Est-ce qu'un commit par soir suffirait? (Sinon faut que je m'amuse à intégrer github à QtCreator).

    Citation Envoyé par Freem Voir le message
    _ l'ensemble des fichiers que j'ai consultés semblent très fortement couplés à SFML, ajoutant des vérifications et traitements dans des classes qui ne semblent pas devoir s'en charger. Ajouter quelques classes triviales pour masquer les usages de SFML pourrait mieux séparer la mécanique et la logique.
    ça me fait toujours bizarre d'encapsuler une encapsulation^^
    J'essayerais d'y penser.

    Citation Envoyé par Freem Voir le message
    _ une imbrication de namespaces des plus impressionnante, qui parfois remplace des énumérations nommées. Par exemple:
    Code :
    1
    2
    3
    4
    5
     
        namespace BOUTON
        {
            enum{CONEXION, LIGNE, PVP, HORS_LIGNE, EDITEUR, PARAM, QUITTER};
        }
    pourrait être remplacé par "enum BOUTON{CONEXION, LIGNE, PVP, HORS_LIGNE, EDITEUR, PARAM, QUITTER};".
    Mais si je fait : BOUTON::LIGNE avec ta proposition cela ne marcherais pas il me semble. Le but du namespace est de "trier" toutes les constantes pour éviter de se perdre.

    Citation Envoyé par Freem Voir le message
    Autre exemple, l'omniprésence du namespace LD, qui me semble inutile puisque l'on sait que chaque fichier appartiens au programme LD... non? Les namespace, c'est bien, mais la, je trouve qu'il y a excès (j'ai vu une zone avec 4 namespace imbriqués)
    Le namespace LD est utilisé pour deux raisons :
    - si jamais une personne veut reprendre les sources et ajouter 2/3 trucs;
    - et je trouve que ça fait classe d'avoir son propre namespace
    C'est surtout qu'à l'origine on voulait proposer une bibliothèque de classes utiles que n'importe qui aurait pu réutiliser mais actuellement je pense qu'il vaut mieux ne pas se compliquer la vie et se concentrer uniquement sur le jeu.


    Citation Envoyé par Freem Voir le message
    _ pas de distinction entre les variables locales à une méthode et les variables membres de la classe.
    J'ai dû le faire à 2/3 endroits mais je dois avouer que ça vient surtout d'un manque d'habitude et surtout qu'habituellement je fais gaffe donc je n'en ai jamais réellement ressenti le besoin.
    Citation Envoyé par Freem Voir le message
    _ un amour profond des pointeurs. Je comprend bien leur intérêt, mais selon moi, à plusieurs moments vous en utilisez inutilement
    Je ferais donc mieux d'utiliser plus de références?
    Citation Envoyé par Freem Voir le message
    _ mélange des langues: "makeLisible" fait bizarre par exemple, ou "PairHash::old" et "PairHash::nouv" (bon au final on comprend c'est juste qu'on ne sait pas sur quel pied danser)
    Je dois avouer que je ne réfléchis pas longtemps pour trouver des noms de variables.
    Citation Envoyé par Freem Voir le message
    _ code en Français => aucun risque de voir un non francophone participer
    Le problème c'est qu'il faut aussi que les personnes qu'on recrutent comprennent l'anglais.
    Pour le cahier des charges ou la documentation, je me vois très mal la faire en anglais.
    Citation Envoyé par Freem Voir le message
    _ réinvention de la roue pour des choses mineures pour lesquelles des bibliothèques existent (genre, gestion des fichiers/dossiers avec les '/' et '\' => boost::filesystem est très simple d'utilisation, par exemple)
    J'ai eu quelques difficultés à installer certains bibliothèques donc j'ai toujours préféré en utiliser le moins possible. Et dans un autre sens, il faut aussi savoir que ça existe.

    Citation Envoyé par Freem Voir le message
    Il faudra que je m'amuse à faire un schéma de l'existant pour voir, mais avec ce que j'ai vu, je ne suis pas persuadé qu'il soit nécessaire de reprendre à 0.
    Evidemment, je n'ai pas tout regardé, et n'ai même pas essayé de compiler, alors pour l'exécution...
    L'exécution devrait marcher parfaitement (par contre il faut bien avoir toutes les images et sons).

    Pour le moment je suis sûr d'une chose : je ne continu pas sans avoir fini le cahier des charges. En effet ce dernier me permet de savoir un peu tout ce dont j'aurais besoin, tout ce qu'il faudra avoir...

    Ensuite, je pense qu'il sera plus facile pour nous de reprendre à 0 en faisant éventuellement des copiés/collé que de reprendre le code.
    Je pense que ça va surtout dépendre des diagrammes UML qu'on obtiendra une fois qu'on aura fini le cahier des charges.

  5. #85
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Citation Envoyé par Neckara Voir le message
    Bonjour, merci pour ta réponse très constructive,
    Mais de rien

    Citation Envoyé par Neckara Voir le message
    Déjà que je suis assez fainéant pour les commits...
    Est-ce qu'un commit par soir suffirait? (Sinon faut que je m'amuse à intégrer github à QtCreator).
    J'ai aussi un peu de mal a m'y mettre, pour être entièrement franc. Cependant, je me suis félicité à plusieurs reprises de procéder de la façon "1 commit == 1 raison".
    Pourquoi? Parce qu'il m'est déjà arrivé de casser mon code avec une "modification mineure à côté de ce qui m'intéresse vraiment", mais comme j'avais effectué des commits séparés, j'ai pu isoler très précisément quelle modif à tout cassé, et juste invalider le commit en question.
    Accessoirement, git n'est pas intégré à mon IDE: je garde juste en permanence une console sur un bureau (j'adore les bureaux virtuels... couplés à des tiling window manager c'est juste énorme), qui me permet d'effectuer pas mal de "tâches annexes" style commits, modifications de fichiers de configuration, lancement d'outils annexes (CCCC, cppcheck, doxygen, ce genre de 'gadget') donc je commit très vite, si je n'ai fait que me concentrer sur une modification: swith sur la console, "git diff" pour vérifier (jamais trop prudent) et git commit -am "...".
    Bon, quand je me laisse aller à mes ardeurs (a tripatouiller partout) c'est un peu plus long pour sélectionner ce que je veux commiter, c'est sûr...
    Après, tu commit quand tu veux, c'est juste que plus souvent et plus atomiques sont tes commits, plus c'est simple d'identifier LA modification qui à tout pété.

    Citation Envoyé par Neckara Voir le message
    ça me fait toujours bizarre d'encapsuler une encapsulation^^
    J'essayerais d'y penser.
    Bah, je parle pas d'encapsuler une encapsulation, je parle de réduire ta dépendances aux librairies que tu utilises, c'est à dire que si tu effectues des traitements spécifiques à une librairie, les coller dans une classe séparée te permet d'isoler la dépendance.
    Imagines que par la suite tu t'aperçoives que cette lib, finalement, elle n'est pas adaptée à tes besoins... Si tu as isolé ses usages dans un module spécialisé, tu n'as pas besoin de relire ton code principal pour te souvenir comment tu as fait: il suffit de modifier les classes triviales qui encapsulaient la fonctionnalité dont tu avais besoin.
    Naturellement, je ne dis pas de faire ça si tu l'utilisation de ladite librairie est extrêmement simple, localisée et/ou dans une partie du code non critique de ton programme (je pense à boost::filesystem dans mon code, par exemple: je ne m'en sers presque que dans 3 classes n'influant pas sur le "coeur du métier" du programme, sans traitement spécifique autour. Donc je n'avais pas de raison de l'encapsuler. En revanche, avec openGL, je ne me suis pas privé d'abstraire les notions de vertex et de couleur. Si demain j'utilise directX - mouarf - je n'aurai que 2 classes à modifier, parfaitement identifiées).
    Par contre, si une lib est utilisée par le coeur de ton programme, je pense que c'est justifié.

    Citation Envoyé par Neckara Voir le message
    Mais si je fait : BOUTON::LIGNE avec ta proposition cela ne marcherais pas il me semble. Le but du namespace est de "trier" toutes les constantes pour éviter de se perdre.
    [/code]
    Si.
    Puisque le rôle d'une énumération, c'est de créer un type, un peu comme bool.
    bool, ça se traduit exactement comme ça: enum bool{false=0,true}; et tu en connais l'utilisation... (enfin, j'espère )

    Citation Envoyé par Neckara Voir le message
    Le namespace LD est utilisé pour deux raisons :
    - si jamais une personne veut reprendre les sources et ajouter 2/3 trucs;
    - et je trouve que ça fait classe d'avoir son propre namespace
    C'est surtout qu'à l'origine on voulait proposer une bibliothèque de classes utiles que n'importe qui aurait pu réutiliser mais actuellement je pense qu'il vaut mieux ne pas se compliquer la vie et se concentrer uniquement sur le jeu.
    Ben, à ta guise si tu trouves que ça fait classe
    Les bibliothèques de classes, tu les feras, ne t'en fais pas, mais elles seront pour ton exécutable. Tout code n'est pas forcément réutilisable, et les namespace sont juste utiles (à mon sens) pour distinguer des modules indépendants, et réduire les emm***** dues aux noms déjà utilisés.

    Citation Envoyé par Neckara Voir le message
    J'ai dû le faire à 2/3 endroits mais je dois avouer que ça vient surtout d'un manque d'habitude et surtout qu'habituellement je fais gaffe donc je n'en ai jamais réellement ressenti le besoin.
    C'est plus une question de style qu'autre chose, et je ne trouve pas d'exemple intéressant dans ce que j'ai écrit (code trop trivial... j'aurai dû m'y attendre vu que je n'ai pas de méthodes de plus de 40 lignes de code...)

    Citation Envoyé par Neckara Voir le message
    Je ferais donc mieux d'utiliser plus de références?
    Ca dépend des besoins, si as un moment tu as besoin de faire de l'arithmétique de pointeurs, et/où d'une association qui peut être nulle, gardes les.
    Mais autant que faire se peut, utilises des références, elles ont l'immense avantage de t'épargner du code (constructeurs par copie, opérateur d'assignation, destructeur, notamment) et permettent un comportement moins aléatoire (crash aussitôt si une affectation est mauvaise, parce qu'une ref ne peut être nulle, alors que le pointeur attendra que tu y accèdes réellement, ce qui peut être bien plus tard).

    Mais il n'empêche que les pointeurs restent nécessaires dans pas mal de situations, genre:
    • les conteneur d'objets polymorphes (quoique, j'ai récemment appris l'existence de boost::ptr_container, bien pratique)
    • interactions avec des lib qui les utilisent (le cas le plus fréquent où on ne peut s'en passer je pense)

    Et sûrement quelques cas que j'oublie, naturellement.

    Citation Envoyé par Neckara Voir le message
    Je dois avouer que je ne réfléchis pas longtemps pour trouver des noms de variables.
    En même temps, je dois admettre que c'est parfois chiant mais c'est cette fameuse propension à écrire des mixes d'anglais/français pour les noms qui m'a fait utiliser définitivement que des mots anglais: ça fait moins étrange
    Citation Envoyé par Neckara Voir le message
    Le problème c'est qu'il faut aussi que les personnes qu'on recrutent comprennent l'anglais.
    Pour le cahier des charges ou la documentation, je me vois très mal la faire en anglais.
    Oui, après, c'est sûr que si l'équipe de dev n'est pas à l'aise avec l'anglais, vaut mieux rester en français. C'est juste qu'il n'y a aucune chance que ton équipe s'agrandisse d'anglophones, notamment.
    Citation Envoyé par Neckara Voir le message
    J'ai eu quelques difficultés à installer certains bibliothèques donc j'ai toujours préféré en utiliser le moins possible. Et dans un autre sens, il faut aussi savoir que ça existe.
    C'est sûr que parfois c'est pénible a installer/configurer pour ton projet, (notamment sous windows, sans vouloir troller) mais comparé au temps que ça peut faire gagner en chasse aux bugs, je trouve que ça vaut quand même pas mal le coup.
    Et je ne peux qu'approuver pour le fait qu'il faille savoir que ça existe (si seulement j'avais connu certaines lib de boost plus tôt, je me serai épargné pas mal de galères)

    Citation Envoyé par Neckara Voir le message
    Pour le moment je suis sûr d'une chose : je ne continu pas sans avoir fini le cahier des charges. En effet ce dernier me permet de savoir un peu tout ce dont j'aurais besoin, tout ce qu'il faudra avoir...

    Ensuite, je pense qu'il sera plus facile pour nous de reprendre à 0 en faisant éventuellement des copiés/collé que de reprendre le code.
    Je pense que ça va surtout dépendre des diagrammes UML qu'on obtiendra une fois qu'on aura fini le cahier des charges.
    Sage décision. Il faut juste essayer d'éviter les trucs super pénibles à implémenter, ou au moins être capable d'implémenter un truc fonctionnel sans que ces fameuses "killer feature" ne soient présentes: un truc qui marche est toujours plus motivant. Mais bon, j'imagine que tu es courant de ça

  6. #86
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Accessoirement, git n'est pas intégré à mon IDE: je garde juste en permanence une console sur un bureau (j'adore les bureaux virtuels... couplés à des tiling window manager c'est juste énorme), qui me permet d'effectuer pas mal de "tâches annexes" style commits, modifications de fichiers de configuration, lancement d'outils annexes (CCCC, cppcheck, doxygen, ce genre de 'gadget') donc je commit très vite, si je n'ai fait que me concentrer sur une modification: swith sur la console, "git diff" pour vérifier (jamais trop prudent) et git commit -am "...".
    La je compile malheureusement sous Windows, donc pour automatiser...
    QtCreator devrait pouvoir me permettre de faire les commit correctement, pour doxygen, ça reste assez rapide et je peux toujours déléguer^^


    ^
    Citation Envoyé par Freem Voir le message
    Bah, je parle pas d'encapsuler une encapsulation, je parle de réduire ta dépendances aux librairies que tu utilises, c'est à dire que si tu effectues des traitements spécifiques à une librairie, les coller dans une classe séparée te permet d'isoler la dépendance.
    Imagines que par la suite tu t'aperçoives que cette lib, finalement, elle n'est pas adaptée à tes besoins... Si tu as isolé ses usages dans un module spécialisé, tu n'as pas besoin de relire ton code principal pour te souvenir comment tu as fait: il suffit de modifier les classes triviales qui encapsulaient la fonctionnalité dont tu avais besoin.
    Par contre nous allons utiliser Irrlicht, or on fait presque tout le temps appel à celle-ci donc je ne sais pas si ça vaut vraiment le coup ni même pour Irrlicht. Pour la BDD ou la SFML qu'on utilise un peu moins, je serais plutôt d'accord avec toi.

    Citation Envoyé par Freem Voir le message
    Si.
    Puisque le rôle d'une énumération, c'est de créer un type, un peu comme bool.
    bool, ça se traduit exactement comme ça: enum bool{false=0,true}; et tu en connais l'utilisation... (enfin, j'espère )
    Mais tu fait : bool x = true; et non TypeMachin x = bool::true;.


    Citation Envoyé par Freem Voir le message
    Ben, à ta guise si tu trouves que ça fait classe
    Les bibliothèques de classes, tu les feras, ne t'en fais pas, mais elles seront pour ton exécutable. Tout code n'est pas forcément réutilisable, et les namespace sont juste utiles (à mon sens) pour distinguer des modules indépendants, et réduire les emm***** dues aux noms déjà utilisés.
    Il me permettent aussi de "trier" des constantes ou des fonctions (plutôt que de faire une classe incohérente avec des méthodes statiques).


    Citation Envoyé par Freem Voir le message
    Oui, après, c'est sûr que si l'équipe de dev n'est pas à l'aise avec l'anglais, vaut mieux rester en français. C'est juste qu'il n'y a aucune chance que ton équipe s'agrandisse d'anglophones, notamment.
    Après on peut toujours traduire... Mais en même temps je ne suis pas bilingue donc pour certains commentaires... J'essayerais tout de même de voir ce que je pourrais faire.

  7. #87
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    L'automatisation sous windows est tout aussi possible, les .bat, ça existe
    Bon, je t'accorde que la ligne de commande est moins puissante, cela dit. (Mais personnellement, je tape les commandes manuellement, parce que "git diff; git commit -am 'message'" ce n'est pas long, et pour savoir exactement quel message je mets, j'ai besoin de voir un résumé de ce que j'ai touché . De toute façon, C::B n'a pas de plugin pour git, à ce que je sais)

    Pour ce qui a trait à irrlicht (que je ne connais que de nom) je dirais que ça dépend: effectivement, si ça te permet d'avoir des choses toutes faites avec lesquelles les interactions sont simples, ça ne sert à rien. En revanche, si dès l'instant où tu manipules irrlicht, il te faut jongler avec des pointeurs, selon la façon dont ces pointeurs s'initialisent/se libèrent, ça peut être une bonne idée d'isoler irrlicht.
    Je ne sais pas comment ça marche, mais si c'est comme la SDL ou il faut en permanence jongler avec des "SDL_Surface *" qui doivent gérer le fait que la surface risque de se vider... Quand j'avais eu a manipuler ça, j'avais personnellement fait une classe bitmap, qui me permettait les même manipulations que la SDL avec quelques options supplémentaires selon mes besoins.
    Le code était plus lisible, plus stable et le corps de mon code ne connaissais absolument pas la SDL (ce qui me permettra de remplacer par SFML en ne faisant qu'ajouter quelques classes dont l'interface existe déjà... mais vu que SDL as des bugs bizarres et SFML des trous, je sais pas quand je reprendrai ma propre lib). La seule conséquence possible serait une légère perte de performance, sauf que pour contrer ce souci, il est possible d'utiliser les méthodes inline.
    En gros, ce que je conseille avec cette histoire d'encapsuler les dépendances, ce n'est ni plus ni moins que le fameux MVC, c'est à dire séparer le traitement principal (gestion des personnages et leurs interactions avec le monde) des interfaces (que ce soit BDD, fichier, réseau, écran ou clavier ne change pas que ça reste des interfaces). Et personnellement, les interfaces, j'en connaît que 3 types: entrée, sortie, entrée/sortie. L'intérêt d'encapsuler, c'est que tu te retrouves avec des trucs plus ou moins génériques, et il te "suffit" d'ajouter une implémentation à une interface pour supporter une nouvelle interface, sans toucher au code qui fait le véritable boulot.

    Un exemple tiré de ton code ou encapsuler aurait été intéressant:
    Projet\ClientGui\soundmanager.cpp
    Regardes les fonctions "xxxMusic" et "xxxSon": quelles sont les différences entre elles?
    Réponse: le type d'objet manipulé, et, dans un cas, le nom de la fonction utilisée (loadFromFile contre openFromFile. C'est d'ailleurs assez illogique, mais bon, pour le coup c'est un excellent exemple de l'intérêt de définir ses propres interfaces).
    Du coup, si tu avais créé une classe interface Sfx, avec SfxMusic et SfxSoundBuffer qui en héritent, tu aurais pu oublier dans ton code que les classes SoundBuffer et Music ont des interfaces différentes, simplement en créant dans la classe abstraite des fonctions virtuelles pures (virtual ... =0) qui sont implémentées par SfxMusic et SfxSoundBuffer de sorte a appeler la bonne fonction (exemple: "openFile" => loadFromFile ou OpenFile). Quant à l'objet manipulé, (SoundBuffer ou Music) il est simplement dans les classes filles.
    Conséquence: nombre de lignes pour gérer tes listes: divisé par deux, et sans répétition de code parce que tu utilises Sfx dans les map, au lieu des classes "natives" de ta bibliothèque.

    D'ailleurs, je dis de moitié, mais je mens: plus, puisque les fonctions "addMusic(1 arg)" et "addMusic(2 arg)" font exactement la même chose, à un nom de fichier près.

    D'ailleurs:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        sf::Music * SoundManager::addMusic(const std::string & nom, const std::string & fichier=std::string())
        {
            ListeMusique::iterator p = listeMusique.find(nom);
            if( p != listeMusique.end() )
                return p->second;
            sf::Music * ptr= new sf::Music;
            listeMusique[nom] = ptr;
            if(!fichier.empty())
                ptr->openFromFile(fichier);
            return ptr;
        }
    Naturellement, tu augmentes le nombre de tes classes (+3). Mais tu réduis la quantité de code réel (moins de maintenance). Et si, demain, tu en as marre de SFML (ce qui pourrait se comprendre, j'avais déjà regardé et noté diverses incohérences - nommage de méthodes/classes, informations inaccessibles mais vitales pour certaines applications... - note qu'avec le son, tu as le même souci: impossible de savoir si c'est initialisé ce qui aurait pu éviter d'utiliser une fonction avec un argument avec valeur par défaut, ce qui diminue la performance inutilement dans ce cas) il te suffit alors d'implémenter de nouvelles classes SfxMusic et SfxSoundBuffer, et ce, sans même nécessairement supprimer le support de la version SFML. Magique
    Pour Irrlicht, la raison est la même: tu ne sais jamais si tu auras besoin ou pas de contourner une limitation de la bibliothèque que tu utilises.

    Après, c'est un avis personnel (et vu ce que j'ai pu voir de diverses lib, j'en changerai pas tout de suite: entre les lib non portables qui brident le code à une seule plate-forme genre MFC, les lib bugguées genre SDL (j'y ai trouvé un bug, l'ai soumis mais aucune réponse), celles ayant des erreurs de conception (wxWidgets avec ses menus, SFML avec ses noms tirés aux dés et des interfaces manquantes, genre pouvoir savoir si une musique à été chargée dans un objet n'aurait pas été un luxe), lib non maintenues... si j'utilise le C++ c'est pour la portabilité du C et la l'orienté objet qui me permettent d'évoluer. Si je me limite pour une librairie, autant utiliser delphi au moins les frameworks y sont natifs. Ca ne m'empêche pas d'être reconnaissant envers leurs auteurs, mais je ne mettrait pas mon code en prison pour autant.).

    Pour l'histoire des énumérations, essaies donc ce code en "mode parano" de gcc (enfin, mingw):
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #include <stdio.h>
     
    enum Essai{one=1, two, three};
     
    int main()
    {
        Essai tmp=one;
        tmp=two;
        printf("%d",tmp);
    }
    Pour info, avec les options "-Weffc++ -pedantic-errors -Wextra -Wall -ansi " ça passe sans même un warning.

    Les énumérations n'ont pas pour rôle de te permettre de déclarer des constantes, pour ça, c'est [codeinline]const int foo=20;[codeinline].
    Le rôle des énumérations, c'est de définir un type dont les valeurs sont définies à l'avance. (J'ai tendance à m'en servir par exemple quand j'ai plusieurs variables dont le rôle est similaire, mais le nombre fixe: je crée un tableau statique, et ce sont les index qui contiennent le noms des variables: ça me permet d'utiliser des boucles pour accéder à toutes. Mais chacun peut s'en servir comme il veut.)
    Tu remarqueras d'ailleurs que si dans le programme ci-dessus tu mets tmp=2; ça ne compilera pas. Ca permet simplement d'éviter de mettre une mauvaise valeur, ce qui est un avantage non négligeable comparé aux "#define FOO 3" et autres "const unsigned char 3;"

    Pour ce qui est des namespace, mon utilisation personnelle (sûrement pas optimale, j'ai encore du mal à les utiliser) c'est pour chaque module, ou plutôt bibliothèques de mon application, mais pas pour les exécutables ou les plug-ins.

    Dans le cas d'autorealm, par exemple, j'ai 4 modules différents plus les plugins: gui, renderEngine, pluginEngine, menuEngine.
    Ce n'est pas encore fait, mais je compte utiliser un namespace pour chacun des "engine" (pour le moment, il n'y a que renderEngine, parce que j'avais une collision avec wxWidgets).
    Pourquoi uniquement les moteurs?
    Parce que le module gui est l'application elle-même, il y a très peu de chances qu'elle soit réutilisable, alors ça ne vaut pas le coup de m'embêter avec.
    Et pour les plugin, si je fais un namespace à chaque fois, j'ai pas fini, vu que ça risque de rapidement monter à une quantité impressionnante (le autorealm d'origine comporte un nombre de fonctionnalités impressionnant et comme je compte me baser sur les plugin...). D'ailleurs, idem que pour l'application principale, il y a peu de chances qu'ils soient utilisables dans une autre application, et encore moins qu'il y ait une collision, vu le faible nombre de noms qu'ils utilisent (2, en fait xD)
    Les moteurs, eux, en revanche, je pourrai très bien les réutiliser pour d'autres applications (ce que je compte bien faire d'ailleurs). En fait, ce sont des librairies, donc j'ai (je vais, pour la plupart) protégé leurs nommages.

    Après, comme je t'ai dis, c'est une question de style, ça ne se discute pas vraiment. Mieux vaut trop de namespace que pas du tout, au final, ça alourdit la lecture mais ça a le mérite de ne pas avoir de trucs genre "FooBar déjà définie dans <librairie externe que tu utilises>:<fichier>:<ligne>"

    Et pour finir, la traduction, ne t'embête pas avec ça si tu penses ne pas savoir faire. Devoir maintenir deux versions d'un même langage prends énormément de temps (rien que maintenir une seule version n'est pas bénin après tout) donc bon...

  8. #88
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Tu aimes vraiment les pavés^^

    Je comprend un peu mieux ce que tu veux dire pour l'encapsulation.
    Mais pour Irrlicht, j'ai quand même peur d'avoir un nombre impressionnant d'interfaces à créer...


    Citation Envoyé par Freem Voir le message
    Les énumérations n'ont pas pour rôle de te permettre de déclarer des constantes, pour ça, c'est [codeinline]const int foo=20;[codeinline].
    Le rôle des énumérations, c'est de définir un type dont les valeurs sont définies à l'avance.
    Le rôle des énumérations est d'énumérer.
    Faire des constantes avec const int x = 4; pour 20 valeurs allant de 0 à 19 c'est un code tout bonnement dégueulasse. Tu fait comment si tu as besoin de décaler des valeurs?
    Avec enum tu es sûr de ne pas faire d'erreur et c'est beaucoup plus rapide.

    Les énumérations permettent en premier lieu de déclarer des constantes, c'est leur premier objectif.
    Après le typage (?) a été un rajout du C++.
    En C on peut définir un type pour un enum mais ce dernier pouvait contenir n'importe quelle valeurs.

  9. #89
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Citation Envoyé par Neckara Voir le message
    Tu aimes vraiment les pavés^^
    Le pire, c'est que je relis pour essayer d'en enlever, et que j'ai jamais réussi à faire de dissert de plus de 2 pages en français
    J'imagine que c'est parce j'ai toujours tendance à être le plus exhaustif possible.

    Citation Envoyé par Neckara Voir le message
    Je comprend un peu mieux ce que tu veux dire pour l'encapsulation.
    Mais pour Irrlicht, j'ai quand même peur d'avoir un nombre impressionnant d'interfaces à créer...
    Bah, volontairement ou pas, tu le feras:
    Tu vas sûrement avoir une classe Personnage et une classe ObjetAnime, lesquels agrègeront sûrement un (au moins) objet de type SpriteAnime, qui lui-même agrègera des objets de type Sprite, qui, enfin, encapsulera le mécanisme d'image de Irrlicht. Par exemple.

    L'important à retenir, c'est juste que quand tu copies/colles du code pour ne changer qu'un type, une valeur, un appel de fonction... c'est que tu peux factoriser le code que tu as dupliqué (type => template, valeur => fonction, appel de fonction => callback ou méthodes virtuelles).

    Citation Envoyé par Neckara Voir le message
    Le rôle des énumérations est d'énumérer.
    Faire des constantes avec const int x = 4; pour 20 valeurs allant de 0 à 19 c'est un code tout bonnement dégueulasse. Tu fait comment si tu as besoin de décaler des valeurs?
    Avec enum tu es sûr de ne pas faire d'erreur et c'est beaucoup plus rapide.

    Les énumérations permettent en premier lieu de déclarer des constantes, c'est leur premier objectif.
    Pas tout a fait.
    Pousse ton raisonnement sur les énumérations un peu plus loin:
    Tu énumères les possibilités de quoi? Généralement, d'une liste finie de choix, correspondant à un concept.
    Exemple:
    Je fais un programme pour un marchand de fruits. Celui-ci vends:
    _ banane
    _ pomme
    _ poire
    _ fraise
    _ raisin
    Si je définis des entiers constants, c'est que j'ai le droit de dire int monFruit=20;. Ca ne te choques pas toi?
    Même si ça ne te choques pas, que va-t-il se passer si tu relies chaque fruit à un traitement spécial? (comme tu as fais dans ton code, via des tableaux de pointeurs de fonction, par exemple)
    Réponse:j'accède a une zone mémoire inconnue, en pensant que c'est l'adresse d'une fonction... comportement indéterminé donc.

    Et au niveau conception, même si le vin est tiré des fruits, vingt n'a rien à voir avec le raisin
    Au final, il serait plus juste de dire: Fruit monFruit=raisin;. Du coup, le compilateur C++ me protégeras des dépassements de tableaux et des valeurs non traitées par mon switch (l'usage que je fais des enum est toujours lié à ces choses, perso).

    D'ailleurs, C++11 à renforcé la sécurité (une histoire de portabilité du code, a ce qu'il semble), parce qu'avant on pouvait convertir une énum en int (mais pas l'inverse). Maintenant c'est impossible (si on choisit de faire ainsi du moins).

    Au final:
    _ banane est une des valeurs que peut prendre le type fruit -> banane=>constante
    _ 20 est une des valeurs que peut prendre le type int -> 20=> constante
    _ PI est le nom de la valeur 3.14 que peut prendre le type double -> PI=>constante

    Citation Envoyé par Neckara Voir le message
    Après le typage (?) a été un rajout du C++.
    En C on peut définir un type pour un enum mais ce dernier pouvait contenir n'importe quelle valeurs.
    Ca fait TRES longtemps que je n'ai pas fait de C, donc tu as peut-être raison.
    Mais, de toute façon, je pensais que tu faisais un programme en C++, pas en C?
    Le C++ à effectivement un typage beaucoup plus fort que le langage C, et moi, j'aime beaucoup ce point: ça me permet d'être un peu plus distrait quand je programme, j'ai le compilo qui passe derrière moi pour m'indiquer certaines erreurs bêtes que je fait.

  10. #90
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Bah, volontairement ou pas, tu le feras:
    Tu vas sûrement avoir une classe Personnage et une classe ObjetAnime, lesquels agrègeront sûrement un (au moins) objet de type SpriteAnime, qui lui-même agrègera des objets de type Sprite, qui, enfin, encapsulera le mécanisme d'image de Irrlicht. Par exemple.
    Je pense qu'on verra ça quand on commencera l'UML^^


    Citation Envoyé par Freem Voir le message
    Pas tout a fait.
    Pousse ton raisonnement sur les énumérations un peu plus loin:
    Tu énumères les possibilités de quoi? Généralement, d'une liste finie de choix, correspondant à un concept.
    Exemple:
    Je fais un programme pour un marchand de fruits. Celui-ci vends:
    _ banane
    _ pomme
    _ poire
    _ fraise
    _ raisin
    Si je définis des entiers constants, c'est que j'ai le droit de dire int monFruit=20;. Ca ne te choques pas toi?
    Même si ça ne te choques pas, que va-t-il se passer si tu relies chaque fruit à un traitement spécial? (comme tu as fais dans ton code, via des tableaux de pointeurs de fonction, par exemple)
    Réponse:j'accède a une zone mémoire inconnue, en pensant que c'est l'adresse d'une fonction... comportement indéterminé donc.
    Je ne Je peux très bien faire :
    Code :
    1
    2
    3
    namespace Banane { enum{ Min, France = 0, Antille, Inconnu, Max}; }
    namespace Pomme { enum{Min = Banane::Max, SweetAppleAcres = Banane::Max,  AppleJack, Max}; }
    const int fruitMax = Pomme::Max;
    Ainsi je peux donc très facilement ajouter plusieurs types de fruits sans trop me perdre. C'est bien plus facile d'utiliser Banane::France que de rechercher dans les 3600 propositions de constantes que va proposer le compilateur.
    Ensuite, il n'y a pas moyen d'entrer une valeur qui fasse planter puisqu'on vérifie par rapport à la valeur fruitMax qu'on est bien dans le bon interval.
    Si je dois utiliser des constantes, bonjour les dégâts


    Citation Envoyé par Freem Voir le message
    Au final, il serait plus juste de dire: Fruit monFruit=raisin;. Du coup, le compilateur C++ me protégeras des dépassements de tableaux et des valeurs non traitées par mon switch (l'usage que je fais des enum est toujours lié à ces choses, perso).
    Dans ce cas là je ferias surtout :
    Code :
    1
    2
    namespace NFruit{  enum Fruit{raisin}; //pas besoin de typedef en C++ non?}
    Fruit monFruit = NFruit::raisin
    ça évite aussi de devoir se casser la tête si on a deux énumération avec une même constante.

    Citation Envoyé par Freem Voir le message
    D'ailleurs, C++11 à renforcé la sécurité (une histoire de portabilité du code, a ce qu'il semble), parce qu'avant on pouvait convertir une énum en int (mais pas l'inverse). Maintenant c'est impossible (si on choisit de faire ainsi du moins).
    Je ne pense pas que tous les compilateurs prennent encore bien en charge le C++11. Sinon je trouve que les modifications fait par le C++11 au niveau des enums sont pas mal du tout.
    Mais je ne pense pas qu'on puisse faire ce que je faisait avec les bananes et les pommes avec un seul enum.


    Citation Envoyé par Freem Voir le message
    Ca fait TRES longtemps que je n'ai pas fait de C, donc tu as peut-être raison.
    Mais, de toute façon, je pensais que tu faisais un programme en C++, pas en C?
    C'était surtout pour t'expliquer que le typage n'était pas le but premier des enums

  11. #91
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Citation Envoyé par Neckara Voir le message
    Je pense qu'on verra ça quand on commencera l'UML^^
    Effectivement, ça semble logique


    Désolé de te dire ça, mais j'ai vraiment l'impression que tu te mélanges les pinceaux pour ce qui est de l'usage des enum...
    Je vais commencer par 2 bouts de code, le premier en rapport avec mon exemple de fruits, le second en rapport avec ton projet, et je vais conclure sur la définition de wikipedia, si tu me le permets.

    Pour les fruits:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    enum Localisation {Min, France = 0, Antille, Inconnu, Max};
     
    struct Banane
    {
      Localisation loc;
    };
    struct Pomme
    {
      enum Variete {Min, SweetAppleAcres = 0,  AppleJack, Max} variete;
      Localisation loc;
    };
    struct Poire
    {
      enum Variete {Min, Williams = 0,  Concorde, Max} variete;
      Localisation loc;
    };
    Ainsi, tu ne te casses pas la tête avec 36000 constantes.

    Bon, je te passe toute l'explication, pour prendre un cas concret (ça tombe bien, tu as un projet au code accessible )

    Voici une énumération définie dans le fichier Projet/Communs/Param.h ligne 116 :
    Code :
    1
    2
    3
    4
    5
     
    namespace DROITS
        {
            enum{ACCES, SUPERADMIN, MODERATEUR, TECHNICIEN, ANNONCE, AJOUTER_JOUEUR};
        }
    A ce que j'ai pu lire, les classes l'utilisant sont:
    _ InfoJoueur
    _ Traitement
    _ Client
    _ Admin
    Client, Admin et Traitement se contentent de l'utiliser, en accédant à une propriété de InfoJoueur (mon propos ne se rapporte qu'a l'usage du namespace naturellement. La duplication de code aurait aussi pu être évitée mais ce n'est pas le sujet).
    Vu que ce n'est utilisé réellement que par InfoJoueur, ceci:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        class InfoJoueur
        {
        public:
            enum DROITS{ACCES, SUPERADMIN, MODERATEUR, TECHNICIEN, ANNONCE, AJOUTER_JOUEUR};
            InfoJoueur(..., ..., const DROITS droits,..., ..., ..., ...);
        private :
            DROITS droits;
    ...
        };
    Aurait été plus clair, tout en évitant les risques de collision, vu que le nom réel du type est InfoJoueur:ROITS.

    Accessoirement, tu gagnerais de la rapidité de compilation à chaque fois que tu modifies une énumération.

    Citation Envoyé par Neckara Voir le message
    C'était surtout pour t'expliquer que le typage n'était pas le but premier des enums
    La, pour le coup, vu que je n'arrive pas à te convaincre, je vais utiliser ce qu'on appelle un argument d'autorité, ou une référence: http://fr.wikipedia.org/wiki/Type_énuméré

    Tout cela étant dis, à relire l'usage que tu as fait de cette enum précise (jouer sur les bits), je pense que tu t'es trompé sur un autre point: tu as les bit-field:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct DROITS
    {
        unsigned ACCES:1;
        unsigned SUPERADMIN:1;
        unsigned MODERATEUR:1;
        unsigned TECHNICIEN:1;
        unsigned ANNONCE:1;
        unsigned AJOUTER_JOUEUR:1;
    };
    PS: plutôt que de vérifier à l'exécution à chaque fois la validité d'une valeur, il est plus efficace d'utiliser la type safety. Et au pire, utiliser assert() pour être sûr lors du debug

  12. #92
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Pour les fruits:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    enum Localisation {Min, France = 0, Antille, Inconnu, Max};
     
    struct Banane
    {
      Localisation loc;
    };
    struct Pomme
    {
      enum Variete {Min, SweetAppleAcres = 0,  AppleJack, Max} variete;
      Localisation loc;
    };
    struct Poire
    {
      enum Variete {Min, Williams = 0,  Concorde, Max} variete;
      Localisation loc;
    };
    Ainsi, tu ne te casses pas la tête avec 36000 constantes.
    Ce n'était qu'un exemple vite fait.
    Le but était de dire que j'ai par exemple 100 constantes (pour un tableau de fonctions par exemple).
    Un seul enum regroupant 100 constantes ça fait mal quand même
    Il vaut donc mieux faire plusieurs enums dans plusieurs namespaces pour trier un peu.
    Pour les fruits, c'est comme si je décidait d'avoir un identifiant unique par variété de fruit et de regrouper ces identifiants par types de fruits.
    Exemple d'utilisation :
    Code :
    1
    2
    3
    4
    5
    6
    class Livraison
    {
               IdVariete variete;
               unsigned int quantite;
               char date[50];
    };
    Si en plus, tu ne fait pas ça qu'avec les fruits, mais que tu le fait avec des meubles, de la vaisselle, bref tout le contenu d'une grande surface.
    Chaque produit a besoin d'un identifiant unique.
    Tu utilises des structs, mais si tu ne dois pas instancier cette structure, ne vaut-il pas mieux utiliser des namespaces ?

    Citation Envoyé par Freem Voir le message
    Voici une énumération définie dans le fichier Projet/Communs/Param.h ligne 116 :
    Code :
    1
    2
    3
    4
    5
     
    namespace DROITS
        {
            enum{ACCES, SUPERADMIN, MODERATEUR, TECHNICIEN, ANNONCE, AJOUTER_JOUEUR};
        }
    A ce que j'ai pu lire, les classes l'utilisant sont:
    _ InfoJoueur
    _ Traitement
    _ Client
    _ Admin
    Client, Admin et Traitement se contentent de l'utiliser, en accédant à une propriété de InfoJoueur (mon propos ne se rapporte qu'a l'usage du namespace naturellement. La duplication de code aurait aussi pu être évitée mais ce n'est pas le sujet).
    Vu que ce n'est utilisé réellement que par InfoJoueur, ceci:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        class InfoJoueur
        {
        public:
            enum DROITS{ACCES, SUPERADMIN, MODERATEUR, TECHNICIEN, ANNONCE, AJOUTER_JOUEUR};
            InfoJoueur(..., ..., const DROITS droits,..., ..., ..., ...);
        private :
            DROITS droits;
    ...
        };
    Aurait été plus clair, tout en évitant les risques de collision, vu que le nom réel du type est InfoJoueur:ROITS.
    Là je veux bien^^

    Citation Envoyé par Freem Voir le message
    Accessoirement, tu gagnerais de la rapidité de compilation à chaque fois que tu modifies une énumération.
    Qu'entends-tu par là?

    Citation Envoyé par Freem Voir le message
    Tout cela étant dis, à relire l'usage que tu as fait de cette enum précise (jouer sur les bits), je pense que tu t'es trompé sur un autre point: tu as les bit-field:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    struct DROITS
    {
        unsigned ACCES:1;
        unsigned SUPERADMIN:1;
        unsigned MODERATEUR:1;
        unsigned TECHNICIEN:1;
        unsigned ANNONCE:1;
        unsigned AJOUTER_JOUEUR:1;
    };
    Oui, quand j'avais écris le code, je ne connaissait pas encore les bits fields. D'ailleurs ça sera bien plus pratique que ce que j'avais fait^^

    Citation Envoyé par Freem Voir le message
    PS: plutôt que de vérifier à l'exécution à chaque fois la validité d'une valeur, il est plus efficace d'utiliser la type safety. Et au pire, utiliser assert() pour être sûr lors du debug
    Je ne suis pas contre donner un type aux énumérations, les points où je ne suis pas d'accord c'est quand tu dis de remplacer les :
    Code :
    1
    2
    namespace X
    { enum{...}; }
    par : [codeinline]enum X{...};[codeinline] j'ai besoin de conserver le namespace pour "m'y retrouver" dans toutes les constantes.
    Et l'autre point, c'est pour les enums que j'utilise pour mon tableau de pointeur de fonctions.
    Si je n'en fait plus qu'un, ça risque de devenir assez compliqué...

    EDIT : on va peut-être continuer par MP?
    Je crois qu'on flood un peu^^
    En soit ce n'est pas grave, pour l'instant on ne recrute pas trop et je pense refaire un sujet quand on aura fini le cahier de charges.

  13. #93
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Citation Envoyé par Neckara Voir le message
    Le but était de dire que j'ai par exemple 100 constantes (pour un tableau de fonctions par exemple).
    [...]
    Pour les fruits, c'est comme si je décidait d'avoir un identifiant unique par variété de fruit et de regrouper ces identifiants par types de fruits.
    [...]
    Tu utilises des structs, mais si tu ne dois pas instancier cette structure, ne vaut-il pas mieux utiliser des namespaces ?
    Ton exemple viens de le montrer: en général, une énumération s'accompagne de plusieurs choses:
    _ un comportement spécifique selon la valeur des instances de l'énumération
    _ d'autres propriétés telles qu'une quantité (pour reprendre l'exemple classique de l'inventaire), des couleurs, ...

    En reprenant ton exemple de fruits et de meubles, voici une idée pour te passer des enum:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class ID
    {
    long m_id;  // pour ne pas manquer de place, mais bon...
    ... // code pour assurer l'unicité des ID
    };
     
    Singleton //juste pour éviter d'avoir plusieurs listes
    {
    std::map<ID,Objet *> noms;
    ... //code pour rendre le singleton unique
    };
     
    class Objet
    {
    ID identifiant;
    };
    En fonction de la granularité souhaitée, tu peux créer une arborescence aussi complexe que tu le souhaites: tu peux faire une classe Fruit héritant de Objet, avec une classe Banane héritant de Fruit.
    Ou si tu peux te passer de la description précise de Banane (parce que le comportement est le même que celui de fraise, ou de chaise, par exemple, en fonction du cahier des charges) te contenter de mettre juste le mot "banane" dans un string (bien qu'en général, je préfère les fruits de mer dans les string )
    D'ailleurs, ce n'est pas valable que pour le nom, mais pour toutes les propriétés (genre type: fruit ou meuble?) : si tu n'as pas un comportement spécifique qui dépende de la propriété, rien n'empêche de le mettre dans une variable. Au final, tant que tu as ton ID unique...

    Au niveau des avantages, en voici une petite liste:
    _ plus besoin de tableau fixe à maintenir (listeMap[id]=new Objet();listeMap[id].trucmuche(); sera plus simple, il suffit de surcharger les opérateurs "[]" et "." du singleton)
    _ plus besoin d'énumérations (les noms possibles étant obligatoirement des classes héritant de Objet)
    _ comportement dynamique: tu peux ajouter une classe à ton programme, tu auras nettement moins de code où répercuter les modifications (ce qui implique moins de compilation à faire, mais aussi une simplicité de maintenance)

    Niveau inconvénients (parce qu'on ne convainc pas en faisant croire qu'une solution est parfaite):
    _ l'implémentation avec une map, c'est bien sûr un certain temps pour la recherche d'une occurrence. Ca peut être compensé par l'usage des itérateurs ou d'un autre conteneur cela dis.
    _ ID prendra quelques cycles supplémentaires à chaque instanciation et prendra un peu plus de place selon l'implémentation (moi, j'ai tendance à préférer garder la trace de la valeur de la prochaine occurrence, ça prend sizeof(m_id) octets en plus.)

    Citation Envoyé par Neckara Voir le message
    Qu'entends-tu par là?
    J'entends par là que tout le monde connaît la rapidité légendaire de compilation du C++ (irony inside) y compris les fan de ce langage (dont je pense faire partie, d'ailleurs).

    L'une des cause de la lenteur, c'est que l'on doit parser tous les en-têtes. Certains compilateurs ont un cache qui permet d'éviter de le refaire à chaque fois, mais pas tous (il y a aussi la technique des en-têtes pré-compilés d'ailleurs).
    Bien entendu, dès lors que l'on doit modifier un header, il faut re-compiler tous les fichiers .c ou .cpp qui l'incluent, que ce soit directement ou pas, et ça peut prendre du temps, surtout avec les template.
    Du coup, certains ont créé des idiomes pour avoir un header ne contenant strictement que l'interface publique, et ainsi pouvoir jouer avec les "détails d'implémentation" à leur guise en ne compilant que le .cpp sous-jacent. Je trouve personnellement cette pratique un poil extrémiste, mais bon...

    Au final, une façon très simple d'optimiser les temps de compilation, c'est de n'inclure que les informations utiles.
    Pour ça, utiliser ce qu'on appelle les "forward declaration", cad, mettre "class MachinChose;" dans les header quand on utilise que des références et pointeurs, et inclure le fichier .h correspondant dans le cpp. (Note: ça résout aussi certains problème d'inclusion bouclée).
    Dans ton cas, tu as un énorme fichier central qui contiens une pléthore de choses sans réel rapport les unes avec les autres, ces mêmes choses étant en plus uniquement utilisées par un jeu de classes bien précis.
    A chaque fois que tu le modifies, tu dois donc recompiler chaque .cpp qui l'inclue, que ce soit directement ou pas.

    Donc, plutôt que d'utiliser les namespace, je te conseillerais de commencer par utiliser les déclarations imbriquées, c'est à dire de déclarer tes enum à l'intérieur de la classe qui en instancie une (dans la zone publique, naturellement, puisque d'autres auront peut-être besoin de tester les valeurs). Si jamais ton enum est instanciée par plusieurs classes, créer un header contenant cette enum, qui peut alors effectivement appartenir à un namespace... sauf que je doute que ça arrive si souvent que ça.
    Pour la coup, cette technique te supprimera aussi des namespace, puisque le namespace sera le nom de la classe utilisatrice.
    Pour le coup, ça résout aussi ton souci de 36000 membres d'enum à trier à chaque fois.

    Citation Envoyé par Neckara Voir le message
    Je ne suis pas contre donner un type aux énumérations, les points où je ne suis pas d'accord c'est quand tu dis de remplacer les :
    Code :
    1
    2
    namespace X
    { enum{...}; }
    par : [codeinline]enum X{...};[codeinline] j'ai besoin de conserver le namespace pour "m'y retrouver" dans toutes les constantes.
    Et l'autre point, c'est pour les enums que j'utilise pour mon tableau de pointeur de fonctions.
    Si je n'en fait plus qu'un, ça risque de devenir assez compliqué...
    Comme j'ai dit plus haut, imbriquer les déclarations de tes énumérations dans les classes qui s'en servent réellement permettra d'avoir le même effet qu'un namespace, tout en ayant un code plus lisible (pas besoin de naviguer entre 10K fichiers de 50k lignes pour savoir à quoi sert tel ou tel truc).

    Pour ton tableau de callbacks, je te conseille plutôt de regarder ceci.
    Le principe, en gros, c'est qu'une classe possède une référence (ou un pointeur) sur une interface (classe abstraite) qui ne possède qu'une fonction. Pour avoir un comportement, tu crées une classe fille de l'interface, qui implémente la fonction d'entrée. Le résultat est que tu peux changer le comportement d'une classe à l'exécution de ton programme, (ce qui est habituellement l'intérêt des callbacks) sans re-compiler la dite classe (puisque qu'elle n'a eu aucune modification, au final).
    En cogitant un peu dessus, je pense que ça te permettra de faire sauter pas mal de tableaux codés en dur (et il y a moyen d'aller un peu plus loin, via un mécanisme de plugin, mais ce n'est pas le sujet je pense)

    Tu pourras remarquer (ou pas) que j'ai une tendance à préférer éviter les codes "en dur".
    Pourquoi?
    Simplement parce que ça implique à chaque fois des répercussions dans de potentielles innombrables portions de code, et qu'on en oublie donc quasi-systématiquement. Utiliser des fichiers de conf est plus long à l'exécution, mais uniquement au chargement initial.
    Ca enlève aussi une certaine facilité pour créer du code générique, et empêche pas mal de réutilisabilité du code.

    Citation Envoyé par Neckara Voir le message
    EDIT : on va peut-être continuer par MP?
    Je crois qu'on flood un peu^^
    En soit ce n'est pas grave, pour l'instant on ne recrute pas trop et je pense refaire un sujet quand on aura fini le cahier de charges.
    Pas vraiment du flood, juste du hors-sujet.
    Il faudrait plutôt demander à quelqu'un de splitter le sujet, parce qu'effectivement, ça a viré à l'architecture logicielle, la.

  14. #94
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Ton exemple viens de le montrer: en général, une énumération s'accompagne de plusieurs choses:
    _ un comportement spécifique selon la valeur des instances de l'énumération
    _ d'autres propriétés telles qu'une quantité (pour reprendre l'exemple classique de l'inventaire), des couleurs, ...
    Mais pour mon tableau de fonction, ce n'est pas le cas. Et ça ne choque pas mon prof de C++ non plus.

    Citation Envoyé par Freem Voir le message
    En reprenant ton exemple de fruits et de meubles, voici une idée pour te passer des enum:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    class ID
    {
    long m_id;  // pour ne pas manquer de place, mais bon...
    ... // code pour assurer l'unicité des ID
    };
     
    Singleton //juste pour éviter d'avoir plusieurs listes
    {
    std::map<ID,Objet *> noms;
    ... //code pour rendre le singleton unique
    };
     
    class Objet
    {
    ID identifiant;
    };
    En fonction de la granularité souhaitée, tu peux créer une arborescence aussi complexe que tu le souhaites: tu peux faire une classe Fruit héritant de Objet, avec une classe Banane héritant de Fruit.
    Ou si tu peux te passer de la description précise de Banane (parce que le comportement est le même que celui de fraise, ou de chaise, par exemple, en fonction du cahier des charges) te contenter de mettre juste le mot "banane" dans un string (bien qu'en général, je préfère les fruits de mer dans les string )
    D'ailleurs, ce n'est pas valable que pour le nom, mais pour toutes les propriétés (genre type: fruit ou meuble?) : si tu n'as pas un comportement spécifique qui dépende de la propriété, rien n'empêche de le mettre dans une variable. Au final, tant que tu as ton ID unique...
    Mais l'id est l'id du type, mettre un code pour garantir l'unicité d'un id ne me semble pas super...

    Citation Envoyé par Freem Voir le message
    Au niveau des avantages, en voici une petite liste:
    _ plus besoin de tableau fixe à maintenir (listeMap[id]=new Objet();listeMap[id].trucmuche(); sera plus simple, il suffit de surcharger les opérateurs "[]" et "." du singleton)
    _ plus besoin d'énumérations (les noms possibles étant obligatoirement des classes héritant de Objet)
    _ comportement dynamique: tu peux ajouter une classe à ton programme, tu auras nettement moins de code où répercuter les modifications (ce qui implique moins de compilation à faire, mais aussi une simplicité de maintenance)
    Je ne suis pas vraiment convaincu. Et pour mon tableau de fonction cela ne me semble pas vraiment approprié.

    Citation Envoyé par Freem Voir le message
    Au final, une façon très simple d'optimiser les temps de compilation, c'est de n'inclure que les informations utiles.
    Pour ça, utiliser ce qu'on appelle les "forward declaration", cad, mettre "class MachinChose;" dans les header quand on utilise que des références et pointeurs, et inclure le fichier .h correspondant dans le cpp. (Note: ça résout aussi certains problème d'inclusion bouclée).
    Dans ton cas, tu as un énorme fichier central qui contiens une pléthore de choses sans réel rapport les unes avec les autres, ces mêmes choses étant en plus uniquement utilisées par un jeu de classes bien précis.
    A chaque fois que tu le modifies, tu dois donc recompiler chaque .cpp qui l'inclue, que ce soit directement ou pas.
    Oui, notre prof de C++ (encore lui ) nous a un peu parlé de cela la semaine dernière.

    Citation Envoyé par Freem Voir le message
    Donc, plutôt que d'utiliser les namespace, je te conseillerais de commencer par utiliser les déclarations imbriquées, c'est à dire de déclarer tes enum à l'intérieur de la classe qui en instancie une (dans la zone publique, naturellement, puisque d'autres auront peut-être besoin de tester les valeurs). Si jamais ton enum est instanciée par plusieurs classes, créer un header contenant cette enum, qui peut alors effectivement appartenir à un namespace... sauf que je doute que ça arrive si souvent que ça.
    Pour la coup, cette technique te supprimera aussi des namespace, puisque le namespace sera le nom de la classe utilisatrice.
    Pour le coup, ça résout aussi ton souci de 36000 membres d'enum à trier à chaque fois.
    Oui je pense que je vais essayer de faire cela au maximum.


    Citation Envoyé par Freem Voir le message
    Tu pourras remarquer (ou pas) que j'ai une tendance à préférer éviter les codes "en dur".
    Pourquoi?
    Simplement parce que ça implique à chaque fois des répercussions dans de potentielles innombrables portions de code, et qu'on en oublie donc quasi-systématiquement. Utiliser des fichiers de conf est plus long à l'exécution, mais uniquement au chargement initial.
    Ca enlève aussi une certaine facilité pour créer du code générique, et empêche pas mal de réutilisabilité du code.
    Pour le tableau de fonction, il n'est utilisé qu'une seule fois donc bon^^.
    Après je ne pense pas utiliser cela pour autre chose.

    Ensuite, il faut que je prenne le temps de réfléchir un peu plus^^


    Sinon si ça t'intéresse de nous aider à écrire le cahier des charges et/ou à faire par la suite la modélisation UML... plutôt que de contredire le pauvre petit Neckara

  15. #95
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Citation Envoyé par Neckara Voir le message
    Mais pour mon tableau de fonction, ce n'est pas le cas. Et ça ne choque pas mon prof de C++ non plus.
    Je ne vais pas m'étendre sur l'utilisation des arguments d'autorité en général, et encore pire pour ceux qui concernent un prof, vu que ces praticiens m'ont plus souvent déçu qu'impressionné (toutes matières confondues hein).
    Je ne suis pas méprisant, c'est juste que j'ai perdu l'habitude de penser que les profs ont forcément raison (j'ai vu plus d'une erreur dans les propos de ceux que j'ai eus, et même récemment plus d'une immondice dans la bouche d'un particulièrement inculte... sisi, inculte lui va bien à celui-la, et je pèse mes mots.).

    Citation Envoyé par Neckara Voir le message
    Mais l'id est l'id du type, mettre un code pour garantir l'unicité d'un id ne me semble pas super...

    Je ne suis pas vraiment convaincu. Et pour mon tableau de fonction cela ne me semble pas vraiment approprié.
    Tout dépend effectivement de l'usage de ton tableau.
    Si tu es sûr qu'il n'aura pas besoin d'évoluer, ou juste rarement, un tableau en dur est la meilleure solution: rapide et réactif.
    Cela étant dit, utiliser une enum pour faire un alias d'index ne me semble pas vraiment approprié, encore pire pour l'idée de mettre cet alias dans un namespace.
    Au pire, si ton tableau n'est utilisé que dans un seul endroit, rien n'empêche de mettre la déclaration de l'enum dans ce même endroit, pour éviter d'embrouiller tout le code.

    Pour ce qui est de l'histoire d'ID lié à un type, j'ai fait une confusion, mea culpa. (La raison est juste qu'il m'arrive de me mélanger les pinceaux avec autorealm)

    Après, à voir selon les usages que tu faits, mais j'admets qu'avoir vu plus de namespace dans un seul fichier que dans ma vie m'a fait bizarre

    Je ne dis pas qu'ils sont tous incorrects, mais que la plupart ne sont probablement pas justifiés, et ont un effet contraire à celui recherché à la base: rendre le code plus lisible.
    Après l'architecture de ton programme, si j'y ai fouiné 2H, c'est un grand max, et 2H ne suffisent sûrement pas à s'approprier un programme.

    Citation Envoyé par Neckara Voir le message
    Sinon si ça t'intéresse de nous aider à écrire le cahier des charges et/ou à faire par la suite la modélisation UML... plutôt que de contredire le pauvre petit Neckara
    Les cahiers des charges, je n'ai aucune expérience dans leur élaborations, et pour l'architecture logicielle, même si j'ai pas mal amélioré mes connaissances cette dernière année, je suis encore loin d'être calé (il y a encore pas mal de design pattern dont je vois mal l'intérêt, par exemple)

    Mais à part ça, pourquoi pas.
    Cela dis, si je commence à m'impliquer réellement, ne compte pas sur moi pour ne pas contredire, j'adore poser des questions que les gens préfèrent éluder, et je suis pas très réputé pour dire blanc quand je pense noir (cependant, j'argumente quand je contredis, c'est déjà ça)
    Te voila prévenu

  16. #96
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Citation Envoyé par Freem Voir le message
    Je ne vais pas m'étendre sur l'utilisation des arguments d'autorité en général, et encore pire pour ceux qui concernent un prof, vu que ces praticiens m'ont plus souvent déçu qu'impressionné (toutes matières confondues hein).
    Je ne suis pas méprisant, c'est juste que j'ai perdu l'habitude de penser que les profs ont forcément raison (j'ai vu plus d'une erreur dans les propos de ceux que j'ai eus, et même récemment plus d'une immondice dans la bouche d'un particulièrement inculte... sisi, inculte lui va bien à celui-la, et je pèse mes mots.).
    Je sais, j'ai d'ailleurs fait l'expérience qui proposait en solution un code dont le résultat est indéterminé (effets de bord dans les paramètre d'un fonctions) et qui n'en démordait pas en disant qu'il y a la théorie et la pratique et que là ça marche. (aller, un de plus ça ne fera pas de mal : )
    Mais le prof, en plus d'être très sympathique semble savoir ce qu'il fait^^
    Comme j'ai un peu d'avance en TP, il me donne quelques conseils sur le code et sa lisibilité.
    Je ne voulais pas utiliser un argument d'autorité pour dire que "tu as torts parce que lui, il s'y connait plus mieux bien" mais pour te montrer qu’apparemment ça ne choque pas tout le monde^^


    Citation Envoyé par Freem Voir le message
    Tout dépend effectivement de l'usage de ton tableau.
    Si tu es sûr qu'il n'aura pas besoin d'évoluer, ou juste rarement, un tableau en dur est la meilleure solution: rapide et réactif.
    Cela étant dit, utiliser une enum pour faire un alias d'index ne me semble pas vraiment approprié, encore pire pour l'idée de mettre cet alias dans un namespace.
    Au pire, si ton tableau n'est utilisé que dans un seul endroit, rien n'empêche de mettre la déclaration de l'enum dans ce même endroit, pour éviter d'embrouiller tout le code.
    Le tableau évoluera surtout au début, le temps d'ajouter toutes les fonctions de traitements mais sinon le tableau sera assez stable.
    Par contre si je ne met pas d'enum pour les indices de tableaux, que mettre ? Si je met des constantes en dur ça me semble être la pire des solutions
    Les enums doivent être connus par toutes les fonctions/méthodes souhaitant envoyer un paquet. La valeur de l'enum est mis au début du paquet (après un cast préalable). Le serveur récupère le paquet, regarde la valeur mis au début et fait :
    Code :
    1
    2
    3
    4
    if(valeurLue >= NbFonctions)
           tableauFonction[valeurLue]( args )
    else
            ;//erreur
    Donc j'ai besoin de connaître les enums un peu partout même si je n'utilise le tableau qu'une seule fois.

    Citation Envoyé par Freem Voir le message
    Mais à part ça, pourquoi pas.
    Cela dis, si je commence à m'impliquer réellement, ne compte pas sur moi pour ne pas contredire, j'adore poser des questions que les gens préfèrent éluder, et je suis pas très réputé pour dire blanc quand je pense noir (cependant, j'argumente quand je contredis, c'est déjà ça)
    Te voila prévenu
    Je n'ai pas besoin de personnes qui pensent comme moi.
    Avoir une personne avec une opinion différente permet d'aller au bout de nos idées et de peser le pour et le contre.
    Même si j'aurais le dernier mot, ça permet toujours de développer l'idée, de corriger quelques failles etc.
    Préfères-tu que je te contacte via MP ou via skype (denmig_neckara)?

  17. #97
    Expert Confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    décembre 2008
    Messages
    805
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : décembre 2008
    Messages : 805
    Points : 2 650
    Points
    2 650

    Par défaut

    Je vois ce que tu veux dire, pour ce qui est du prof

    Pour ton tableau, il faut voir exactement quel est son rôle, après.
    En revanche, si tu utilises une enum nommée (attention, pseudo-code à venir), ton test "if valeur > maxTableau then erreur else tableau[valeur]" peut devenir inutile via une fonction du style:

    enum Comportement{....};

    inline void (*)(argtype1,arg2,...) getCallback(Comportement index)
    {
    static void(*tableau[](argtype1,arg2,...) ){func1, func2};
    return tableau[index];
    }

    Du coup, vérifier que tu es "dans les clous" n'est plus important, SI ton enum est correctement synchronisée.

    Pour le contact, envoies-moi un mp pour qu'on s'échanger nos mails, je n'ai plus installé skype depuis... pas mal de temps

  18. #98
    screetch
    Invité(e)

    Par défaut

    excusez moi de le dire, mais cette discussion est devenue proprement barbante, compare au sujet inital et a l'etat du projet, savoir si il faut des enum dans un namespace ou des enums en dehors d'un namespace ca ne fera pas avancer le schmilblick d'un projet qui stagne un peu.
    Et puis j'ai envie de dire, neckara il fait comme il veut; Freem, pourquoi tu tiens absolument a changer sa facon de coder? je veux dire, un ou deux messages pour expliquer les avantages, ca va, la on en est a 10 messages pour tenter de convaincre de coder comme toi et pas comme lui. C'est de l'integrisme programmationnel ca non?
    vive la liberte d'expression informatique
    si neckara se rend compte a un moment que son code a des desavantages il se rappelera de tes messages.

    et si on parlait du jeu?

  19. #99
    Expert Confirmé Sénior


    Homme Profil pro Denis
    Étudiant
    Inscrit en
    décembre 2011
    Messages
    5 003
    Détails du profil
    Informations personnelles :
    Nom : Homme Denis
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : décembre 2011
    Messages : 5 003
    Points : 14 900
    Points
    14 900

    Par défaut

    Le rôle exact du tableau est d'appeler la bonne fonction permettant de traiter les données reçues sans devoir passer par de grands switchs successifs.

    Mais je ne peux pas utiliser un seul enum nommé sans me perdre dans toutes les constantes.
    Il est bien plus facile de distinguer plusieurs catégories de fonctions de traitements. Mais il me faut un identifiant unique pour chaque fonction.
    Bien sûr avec une seule indentation, je peux m'y retrouvé un peu dans mon enum mais ceci ne va pas être pratique pour définir non seulement les noms des constantes (vu qu'on aura pas de namespace donc impossible de réutiliser les mêmes noms) mais aussi pour les retrouver avec l'auto-complétion de l'IDE (ce qui est tout de même très pratique).

    (Je t'envoie un MP ce soir)

    EDIT : je n'avais pas vu la réponse de Screetch

  20. #100
    Expert Confirmé Sénior

    Homme Profil pro Emmanuel Deloget
    Développeur informatique
    Inscrit en
    septembre 2007
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Nom : Homme Emmanuel Deloget
    Âge : 38
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : septembre 2007
    Messages : 1 894
    Points : 4 448
    Points
    4 448

    Par défaut

    Citation Envoyé par Neckara Voir le message
    On veut sécuriser l’envoi du mot de passe pour éviter qu'il voyage en clair sur le réseau.
    Et une fois la connexion TCP mis en place, il n'est pas possible d'usurper l'identité d'un ordi?
    Si.

    Il faut comprendre que bien que tu utilises TCP (mode connecté), celui-ci fonctionne au dessus de IP - et IP est à la base un protocole de type datagram (mode non connecté ; en fait, le headers UDP ne spécifie guère plus que le sports sources et destination en plus du header IP); Du coup, une attaque de type "man in the middle" permet de couper la machine source du réseau et de prendre sa place une fois la connexion établie.

    Ce qui rends l'attaque un peu plus difficile, c'est qu'il faut être sur le même sous-réseau que la machine attaquée, et se comporter vis-a-vis d'elle comme une gateway ou un proxy. Sur un réseau public, ça veut dire qu'il faut être soit entre la machine source et le routeur internet (si le lien est direct, on peut provoquer ce cas en installant un programme sur la machine source, à l'insu de l'utilisateur), soit il faut être quelque part sur le réseau de l'opérateur - là, c'est plus compliqué, parce que les opérateurs font tout pour éviter ce type de hack. Ceci dit, "compliqué" ne veux pas dire impossible même si, en pratique, c'est la première solution qui sera employée (installation d'un trojan sur le poste ciblé).

    TCP n'est qu'une simulation d'un protocole connecté au dessus de IP - il n'offre donc pas nécessairement les garanties que tu cherches. Du coup, ça peut être utile de crypter l'intégralité des communications - pas en utilisant RSA tout du long - ça n'aurait pas de sens, et ça permettrait en outre à quelqu'un d'analyser le traffic et d'avoir plein de vecteurs de tests pour essayer de casser les clefs public/privées.

    On utilise RSA pour encrypter une communication bidirectionnelles ou les deux parties se mettent d'accord sur une clef utilisée dans un algo de cryptage symétrique (perso, j'aime bien blowfish : il est rapide, et pas si courant que ça). Une fois la clef acceptée par les deux parties, l'algo symétrique est utilisé pendant un temps - puis on renouvelle l'opération plus tard (par exemple 30 minutes après). De manière a faire tourner les clefs.

    Pour éviter une attaque "Man in the Middle", les échanges en RSA sont signés par le serveur (ce qui implique que le programme connaisse la clef publique du serveur AVANT toute communication - sans quoi, un tiers peut se faire passer pour le serveur et jouer le rôle de proxy).

    Le protocole serait alors :
    (RSAs = crypté avec la clef publique du serveur ; il faut la clef privée du serveur pour décrypter le message)
    (RSAc = crypté avec la clef publique du client ; il faut la clef privée du client pour décrypter le message)
    (la signature n'est pas dans le message crypté en RSAc ; elle est calcuée sur le message crypté lui-même)

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
       CLIENT                                 SERVEUR
    ========================================================================
     
    ask_auth          -----(clair)----->
    + RSA pub
     
                      <-----(RSAc)------  ask_auth_rep + signature
     
    auth_login        ------(RSAs)----->
    + hash(password)
     
                      <-----(RSAc)------  auth_login_rep + clef blowfish
                                         + signature
     
    start_session     ----(blowfish)--->
     
                      <---(blowfish)----  start_session_ok
    A partir de là, l'attaquant est déjà bien ennuyé. Même s'il a vu passer les messages en provenance du client, et connait donc sa clef publique, il ne peut passe faire passer pour le serveur et répondre à sa place (car le test de signature (calcul d'un hash crypté avec la clef privée du serveur, qui peut être alors décrypté par la clef publique et comparé au hash calculé par le client) va échouer). Il ne peut pas non plus décoder le paquet contenant la clef blowfish, puisqu'il lui fait la clef privée du client. Du coup, il ne pourra pas se mettre au milieu des communications blowfish.

    Vis a vis du serveur, il ne peut pas se faire passer pour le client, puisqu'il est incapable d'intercepter le login/password envoyé par le client. Il peut empêcher le client de se connecter en changeant la clef publique par la sienne, mais du coup, il ne pourra pas à la fois ré-encrypter le message envoyé par le serveur avec la clef publique du client et garantir que la signature ne changera pas.

    Citation Envoyé par Neckara Voir le message
    Si je les ai écris moi-même c'est que je n'ai pas réussi à trouver une petite librairie portable simple d'utilisation et d'installation qui me convenait.
    Meh ? OpenSSL ? TropicSSL ?

    Citation Envoyé par Neckara Voir le message
    Mais si tu connais une bonne bibliothèque pour faire du SHA-251 (ou un SHA-2 plus petit) ainsi que du RSA, je suis preneurs.
    OpenSSL. Cf. http://cpp.developpez.com/telecharge...ish-de-OpenSSL

    Ce petit bout de code a pour avantage de te laisser gérer le protocole de communication, et ne fournit que les services de cryptage/décryptage. J'ai réimplémenté sha-256 sous la forme qui est C++ compliant (c'est à dire correctement encapsulé ; tu n'as qu'une fonction à appeler). Le code est relativement rapide et semble être correct.

    Citation Envoyé par Neckara Voir le message
    On m'a conseillé OpenSSL mais niveau tutoriel/exemple pas facile a trouvé et en plus pour windows, il faut la compiler...
    J'avais essayer avec une personne qui travaille dans la programmation et on a pas réussi car il nous manquaient des programmes comme make etc...
    Pour simplifier le travail : http://www.openssl.org/related/binaries.html
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •