SDL ou SFML ? Ne choisissez plus, prenez Gamedev Framework (gf)

Posté par . Édité par palm123 et Benoît Sibaud. Modéré par Pierre Jarillon. Licence CC by-sa
Tags :
61
19
juil.
2016
Jeu

Gamedev Framework (gf) est un framework de développement de jeu vidéo 2D en C++11. Il est basé sur SDL et OpenGL ES 2.0 et s'inspire très largement de l'API du module graphique de SFML avec quelques différences mineures et surtout en ajoutant des fonctionnalités non-présentes dans SFML.

La première version publique 0.1.0 de ce framework est sortie le 14 juillet 2016.

Logo de gf

Gamedev Framework (gf) est publié sous licence zlib/libpng, identique à celle de SDL et SFML.

Sommaire

Dans cette deuxième partie, je vais vous raconter l'histoire de gf, d'où je suis parti et comment j'en suis arrivé à aujourd'hui. Je ne vais pas vous présenter l'API ou les fonctionnalités. Peut-être dans une prochaine dépêche, quand la bibliothèque aura bien mûri. Vous pouvez déjà avoir un aperçu avec la documentation.

Pourquoi et comment ?

Pourquoi avoir fait ce framework ? Dès qu'on veut faire un jeu en C++ sans moteur de jeu complet, on se retrouve très vite face à deux choix : SDL ou SFML. C'est une question récurrente que j'avais déjà posée en 2013, à l'heure où je commençais Akagoria.

Les arguments sont bien connus : SDL est écrite en C, est très portable, avec des API robustes et bien faites, mais assez bas niveau. Il y a bien quelques fonctions pour afficher des choses mais ça reste assez limité. En revanche, SDL est souvent utilisée pour obtenir un contexte OpenGL et la gestion des événements utilisateurs et ensuite, on peut utiliser directement OpenGL. De son côté, SFML est écrite en C++, est un peu plus haut niveau et est surtout assez adapté quand on débute parce qu'elle offre de très bonnes abstractions.

Depuis le début, j'avais choisi SFML pour Akagoria. L'idée de gf est venue des limitations de SFML. Depuis quelques temps, que ce soit pour Akagoria ou pour des game jams, je me retrouvais à devoir refaire quelques classes de bases, toujours les mêmes. J'en ai fait un projet à part : gameskel. Pour certaines parties, l'intégration avec SFML était assez pénible. Par exemple, j'avais des classes pour avoir des vues qui s'adaptent automatiquement au redimensionnement de la fenêtre. Mais impossible de faire uniquement des classes dérivées de sf::View, ce qui aurait été le plus logique et le plus simple. Du coup, j'étais obligé dans certains cas de faire des contorsions pour arriver à faire ce que je voulais. C'était de plus en plus compliqué.

Le déclic est venu quand j'ai parcouru le forum de SFML à propos des nouvelles fonctionnalités. J'ai été complètement ahuri de voir le conservatisme de certains développeurs de SFML. La moindre demande de fonctionnalité est quasi-systématiquement rejetée, y compris des fonctionnalités complètement triviales, avec des arguments limite fallacieux. Par exemple, un utilisateur demande l'ajout d'un sf::Line pour tracer une ligne entre deux points. Les réponses qu'il obtient, c'est qu'il devrait utiliser sf::Rectangle (pas super simple) ou alors recopier le bout de code qui se trouve sur le wiki ou alors utiliser une bibliothèque externe d'un des développeurs de SFML qui contient une ligne. Il y a aussi cet autre utilisateur qui demande à avoir une surcharge de la fonction scale() qui prend normalement deux paramètres: un pour x, un pour y. Sauf que dans 95% des cas, c'est le même paramètre (par exemple, quand on zoome ou qu'on dézoome). Le bout de code à ajouter fait littéralement 3 lignes. Mais non, on lui répond qu'on ne va pas ajouter ce cas trivial. Et il y en a des dizaines comme ça dans le forum. Et puis, il y a ce refrain qui revient comme quoi SFML ne serait qu'un framework multimedia et pas une bibliothèque pour développer des jeux (même si ça représente la quasi-totalité des cas d'utilisation).

À partir de là, je me suis dit que j'allais laisser tomber SFML.

OpenGL et fenêtrage

Ça tombe bien, j'avais envie de m'intéresser à OpenGL. Le choix a donc été vite fait pour ce qui concerne l'API graphique. Après, j'ai un peu tâtonné avant de me décider. En effet, OpenGL seul est inutilisable, il faut avoir un contexte OpenGL et pour ça, il n'y a pas d'API standard, chaque système a sa manière propre de créer un contexte. Sans compter qu'au delà du contexte, il y a toute la gestion des fenêtres et des entrées utilisateurs (clavier, souris, etc).

Là, on a plusieurs solutions. La première, c'est de réinventer la roue carrée, comme SFML et de recoder toute cette couche à la main. Autant dire que cette solution a été très vite évacuée parce que quand je vois la quantité et la complexité du code qu'il y a dans SFML juste pour cette partie, je me dis que c'est un boulot à part entière. Donc, je suis plutôt parti sur une bibliothèque qui fait déjà le boulot.

Mon premier choix s'est porté sur GLFW qui est une bibliothèque portable qui gère toute la partie fenêtre et entrée, et crée un contexte OpenGL. J'ai commencé et j'avais fait pas mal de trucs, ça marchait. Et puis, j'ai arrêté pour une raison simple : la gestion des manettes de jeu. Cette gestion est très aléatoire, dans le sens où pour chaque manette, la correspondance entre les touches et les identifiants ne sont jamais les mêmes.

Mon second choix a alors été SDL. De la même manière, SDL gère toute la partie fenêtre et entrée et crée un contexte OpenGL. De plus, SDL est connue pour avoir une très bonne gestion des manettes. J'ai donc repris une bonne partie de ce que j'avais déjà fait et j'ai tout porté vers SDL. En fait, SDL est beaucoup plus simple à utiliser. GLFW est basée sur des fonctions de rappel pour gérer les entrées utilisateurs et c'est assez pénible.

Au final, je ne regrette absolument pas le choix de SDL, bien au contraire.

OpenGL moderne

Après avoir un contexte OpenGL, il faut utiliser l'API. Mais quelle version ? Mon choix s'est portée sur OpenGL ES 2.0. Pourquoi ?

OpenGL ES 2.0 est une API plutôt vieille (elle date de 2007) et elle est présente quasiment partout des ordinateurs de bureau aux derniers ordiphones. OpenGL ES 3.0 à l'inverse est un peu trop récente (2012). De plus, WebGL est basée sur OpenGL ES 2.0, donc dès qu'on a un navigateur qui gère WebGL, on a un pilote capable de gérer OpenGL ES 2.0, ce qui fait beaucoup de matériel. Ensuite, OpenGL ES 2.0 est la version moderne d'OpenGL, celle où tout passe par un shader. Enfin, pour nous les libristes, Mesa3D prend en charge OpenGL ES 2.0 depuis Mesa 8.0 en 2012 donc même sur une Debian stable, on a ce qu'il faut en terme de pilote.

Alors certes, il manque des fonctionnalités à OpenGL ES 2.0 mais pour faire de la 2D, ça suffit amplement. Et puis, je préfère exploiter complètement la petite API d'OpenGL ES 2.0 plutôt que d'utiliser 50% d'une API plus évoluée. Voici quelques pointeurs vers de la documentation qui m'a été bien utile pour comprendre comment fonctionne OpenGL et la bonne manière de programmer avec OpenGL.

Choix de l'API

Plutôt que de réinventer une API, je suis très vite parti dans l'idée de cloner autant que faire se peut l'API de SFML. Les avantages, c'est qu'il n'y a pas besoin de réfléchir beaucoup au design de l'API, et que pour ceux qui voudraient passer de SFML à gf, l'effort sera très minime (remplacer sf par gf).

L'adaptation n'a pas toujours été de tout repos. SFML utilise de l'OpenGL à papa, c'est-à-dire sans aucun shader. Et donc, il a fallu mettre en place tout l'attirail de base quasiment de zéro. Pour ceux qui se demandent où ça se situe, c'est dans la fonction gf::RenderTarget::draw(). Après cette base, beaucoup de choses étaient semblables et j'ai repris pas mal de code de SFML en modernisant un peu le code (notamment en profitant du fait d'utiliser C++11).

Une des principales différences avec SFML est l'ajout des classes Vector et Matrix complètement génériques. Je me suis inspiré d'un article de Nathan Reed de 2013 qui explique un design à peu près standard pour ce genre de classes. J'ai ajouté tout un tas de fonctions classiques liées à ces classes (souvent des fonctions dont j'avais directement besoin dans la bibliothèque ou que j'avais déjà utilisées par ailleurs). Au final, le fichier Vector.h est un des plus gros fichiers : plus de 1600 lignes.

Portabilité windows

Un challenge que je me suis fixé était la portabilité sur Windows, et plus précisément avec MSVC. En effet, si je veux que ma bibliothèque puisse être utilisée le plus largement possible, il est nécessaire qu'elle soit utilisable sur Windows via Visual Studio. Après un gros effort d'adaptation du code, je n'aurai qu'un constat : quelle plaie !

Il faut être clair Visual Studio et son compilateur sont autant aimés que détestés. Et comme la dernière mouture de Visual Studio (2015) a une version Community gratuite, je me suis lancé. Personnellement, je trouve que le compilateur est mauvais. Pourtant, les développeurs ont annoncé une meilleure prise en charge de C++11, mais dans les faits, ils sont clairement à la traîne. Voici quelques adaptations que j'ai dû faire et que je n'aurais pas dû faire parce que le code d'origine était du code C++11 valide.

La première adaptation, c'est un truc que j'ai mis deux jours à comprendre. Ça se passe au niveau des constructeurs par copie et par déplacement qui sont générés implicitement (ou pas). J'avais dans ma classe un membre de type std::vector<std::unique_ptr<Foo>>. Or, il n'est pas possible de copier ce membre puisqu'il n'est pas possible de copier un std::unique_ptr. Donc, dans ce cas, normalement, le compilateur ne doit pas générer implicitement de constructeur par copie (puisqu'il ne peut pas le faire). Or, MSVC lui le génère. Sauf qu'après, et bien il essaie de l'utiliser et forcément, il sort une erreur : pas de le droit de recopier. L'astuce ici consiste à supprimer explicitement le constructeur par copie (alors que ça ne devrait pas être nécessaire). Deux jours sur cette connerie !

Ensuite, MSVC est connu pour très mal gérer les templates. En effet, il ne fait pas ce qu'on appelle le «two-phase lookup», ce qui a plein de conséquences très désagréables. Mais dans mon cas, il a très mal géré ce qu'on appelle par le doux nom de SFINAE, «Substitution Failure Is Not An Error». En gros, on définit une série de templates et à l'instanciation, le compilateur va essayer toute la série en substituant le type en paramètre par le type réel pour trouver le bon appel. Si le compilateur n'arrive pas à instancier correctement un des templates, ce n'est pas considéré comme une erreur, c'est juste que le type réel n'est pas adapté et donc ce template est éliminé de la liste des appels possibles. Avec MSVC, patatras, on obtient une erreur. Il instancie, ça ne marche pas, mais non, il considère que c'est une erreur. Du coup, il a fallu forcer l'élimination à grand coup de std::enable_if complétement superflus.

Dernier exemple, l'instanciation explicite de template. Avant C++11, quand on avait des classes templates, on pouvait instancier explicitement dans le code source (histoire de générer tout le code à un endroit) mais on ne pouvait pas dire qu'on avait instancié explicitement. Et donc, au final, ça ne servait pas à grand chose. En C++11, cette fonctionnalité a été ajoutée, ça s'appelle extern template. Sauf que pour MSVC, ça ne marche pas bien. Ça ne se marie pas très bien avec les dllimport/dllexport qu'on doit ajouter juste pour MSVC. Et du coup, j'ai fait pareil que dans le code de Chromium, j'ai désactivé les instanciations explicites pour MSVC (et il le vit bien).

Alors ouais, on pourrait me dire que ce sont des cas très particuliers. Mais je ne pense pas avoir fait du code très complexe. J'ai quand même passé une bonne semaine, je pense, à comprendre et corriger toutes les erreurs de compilation de MSVC. J'ai laissé de côté les avertissements (plus de 2000 !).

Un truc assez pénible à gérer avec Windows, c'est qu'il n'y a pas de paquets. Il faut donc tout installer à la main et ensuite, prier pour que ça fonctionne correctement. En particulier quand on utilise CMake. En définissant les bonnes variables d'environnement, on arrive presque à s'en sortir. Mais il reste que trouver les paquets binaires de bibliothèques assez communes est parfois compliqué. Par exemple, pour Freetype, le seul paquet binaire à disposition est en version 2.3.5 (qui date de 2007) alors que Freetype en est à la version 2.6.5. Ça pique.

Intégration continue

C'est la mode, il faut faire de l'intégration continue. Et puis, comme j'avais confiance dans mon code, j'ai tenté le coup.

Dans le monde libre, il existe Travis-CI qui permet à n'importe quel projet libre hébergé sur GitHub de profiter de l'infrastructure et de faire de l'intégration continue. J'avais déjà pu essayer ce service sur un autre projet donc je n'étais pas en terre inconnue. Sauf que depuis que je l'ai testé il y a quelques années, il n'a pas beaucoup évolué, et c'est bien le problème ! Proposer par défaut en 2016 une Ubuntu 12.04 (donc sorti en 2012), même Debian est à la pointe en comparaison. Ha oui, on peut utiliser une Ubuntu 14.04, mais c'est du bêta… Quel est le problème ? He bien les version de paquets ne sont pas du tout à jour. Chez moi, j'ai une Debian stable, ça m'a posé un problème parce qu'il n'y a pas SDL 2.0.4 mais uniquement SDL 2.0.2 (il manque quelques fonctions sympathiques). Mais là, on est sur une autre planète : sur Ubuntu 12.04, il n'y a même pas SDL2, uniquement SDL1. Du coup, j'ai quand même forcé l'utilisation d'Ubuntu 14.04.

Ensuite, il y a eu le problème des versions des compilateurs par défaut. Sur une Ubuntu 14.04, on a droit à GCC 4.8.4… qui ne gère pas complètement C++11. Heureusement, Travis-CI permet d'installer des paquet provenant de ppa, et notamment des paquets de compilateurs récents. Pour GCC, aucun problème. Mais pour Clang, il y avait un problème de vérification et donc impossible d'installer les dernières versions. Pas de souci, Clang 3.5 gère C++11 donc ça passe quand même. Et donc, j'ai trois configurations: GCC 4.9, GCC 5, Clang 3.5. Mais il faut croire que ce problème de vieux compilateurs ne gêne pas que moi.

Après ça, je me suis intéressé à AppVeyor qui est la même chose que Travis-CI mais pour le système Windows. Là, l'infrastructure est plus récente donc pas plus de souci qu'avec mon Visual Studio local. Mais on se retrouve avec le problème des paquets binaires. Parce que là, ça devient funky : il faut, dans le script appelé par l'instance AppVeyor qui va compiler le code, télécharger les paquets binaires et les décompresser et mettre en place toutes les variables d'environnement qui vont bien et appeler CMake. Et surtout invoquer l'esprit de Turing pour que tout fonctionne de manière déterministe. Et après quelques hésitations, ça fonctionne !

Au final, ça vaut quand même le coup de passer du temps à tout bien configurer. Ça permet d'avoir un CMakeLists.txt à peu près portable, d'être sûr qu'on n'introduit pas de régression fatale, d'avoir une recette pour construire la bibliothèque. Et puis, on peut afficher de beaux petits badges pour montrer qu'on a bien fait son boulot.

Documentation

Dernier point que j'aimerais aborder : la documentation. C'est long ! Je pense qu'au final, j'ai dû passer à peu près un tiers du temps total sur l'écriture de la documentation. Déjà, il y a la documentation Doxygen du code. Certes, ça ne suffit pas mais c'est quand même nécessaire. Là aussi, vu que j'ai cloné l'API de SFML, j'ai également cloné une bonne partie de la documentation Doxygen. Maintenant, je ne souhaite pas aller plus loin dans le clonage, en particulier, je pense que je ne clonerai pas les tutoriels de SFML qui sont pourtant d'excellente qualité. J'ai donc entrepris de compléter la documentation Doxygen par des petits articles sur des ensembles de classes. Ce n'est pas fini mais ça avance petit à petit. L'idée, c'est aussi de commencer par faire des trucs simples et rapides et de les compléter au fur et à mesure, en fonction des retours.

L'objectif à terme, c'est d'avoir une documentation assez complète mais vivante. Et surtout accessible aux néophytes, comme par exemple mes étudiants.

Et maintenant ?

Avant la version 1.0, il y a encore du travail. Comme déjà dit, j'aimerais compléter la documentation au mieux. Puis, j'aimerais ajouter des fonctionnalités. J'ai déjà quelques idées, et j'ai fait un peu de prospection et il y a des trucs que j'aimerais bien essayer. Mais ça, ça sera pour une prochaine fois. Et puis surtout, je vais porter Akagoria sur ce framework, histoire de ne pas faire un framework pour faire un framework. Et pour utiliser toutes ces magnifiques fonctionnalités !

  • # Ça tombe bien, je n'étais convaincu ni par la SDL, ni par la SFML

    Posté par . Évalué à 6.

    La SDL n'est pas en C++ (quand on code en C++, c'est gênant) et le mainteneur de la SFML est toujours hyper frileux pour mettre à jour la lib en fonction des nouveautés (je crois qu'il n'a même pas incorporé les nouveautés du C++11).

    Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

  • # articulation avec OpenFL

    Posté par (page perso) . Évalué à 5.

    Et comment ça s'articule avec OpenFL citée récemment ?

    • [^] # Re: articulation avec OpenFL

      Posté par . Évalué à 3.

      Ça ne s'articule pas, c'est complètement indépendant. Le seul point commun que je vois est que ça s'appuie sur SDL2, mais bon, c'est très maigre.

      • [^] # Re: articulation avec OpenFL

        Posté par (page perso) . Évalué à 1.

        Si je comprend bien c'est plus un concurrent à OpenFL avec la portabilité en moins. Pas de crossplateform vers HTML5, Consoles, etc…

        • [^] # Re: articulation avec OpenFL

          Posté par . Évalué à 2.

          On peut voir ça comme ça. Pour l'instant, ça se destine plutôt à des jeux qui visent le bureau (Windows, Linux, etc). Et je ne me sens pas du tout en concurrence avec OpenFL, le public développeur cible n'est pas le même je pense.

        • [^] # Re: articulation avec OpenFL

          Posté par . Évalué à 1.

          D'un autre côté vu le nombres de titres sous Linux et HTML5, ça ne changera pas grand chose. J'ai l'impression que les applications sont majoritairement sous Android, beaucoup moins sous iOS et flash, encore moins de windows, et les binaires dispo pour Linux se comptent sur les doigts de la main. Est-ce qu'il y a des problèmes de portabilité pour que ça ne soit pas systématiquement sur toutes ces plateformes ou bien est-ce que c'est un choix des auteurs/éditeurs ?

          Comme en plus tous ces jeux semblent fermés, on a peu de chance de les voir débarquer sous Linux, à part via émulateur Android.

          Flash dans le navigateur => c'est vraiment pas prudent en terme de sécurité.

  • # Je n'aime pas la SFML

    Posté par (page perso) . Évalué à 6.

    Très bon choix pour SDL.

    Je n'aime pas la SFML pour plusieurs raisons :

    1. Le développeur utilise du C++ d'un autre âge, pas d'exception, pas de RAII, pas de C++11. Portabilité ? Non merci, C++11 a déjà 5 ans.

    2. J'ai eu un souci de rendu sur FreeBSD (sur Windows ça fonctionnait), tout ce que l'auteur a su me répondre était "aucune idée".

    3. Je suis l'auteur du support du joystick dans SFML, lorsque j'ai proposé le patch, j'ai bien précisé qu'il s'agissait de FreeBSD mais l'auteur a vraiment voulu merger le code avec Linux. Heureusement après plusieurs mails, il a finalement bien voulu ne pas mélanger le code FreeBSD et Linux.

    Hâte de voir ton framework du coup :)

    l'azerty est ce que subversion est aux SCMs

    • [^] # Re: Je n'aime pas la SFML

      Posté par . Évalué à 3.

      pas d'exception

      Ça, ça ne va pas changer, je déteste les exceptions en C++. Et je ne vois pas bien où je pourrais en mettre.

      pas de RAII

      En interne, il y a quelques classes qui utilisent RAII. Maintenant, où est-ce que tu en verrais dans l'API publique ?

      • [^] # Re: Je n'aime pas la SFML

        Posté par (page perso) . Évalué à 9.

        Ça, ça ne va pas changer, je déteste les exceptions en C++. Et je ne vois pas bien où je pourrais en mettre.

        Bienvenue en 1989 :/

        En interne, il y a quelques classes qui utilisent RAII. Maintenant, où est-ce que tu en verrais dans l'API publique ?

        Je déteste vraiment avoir ce genre de code :

        Music m;
        if (!m.loadFromFile("foo")) {
            // gestion de l'erreur 
        }

        Cela signifie que toutes tes fonctions membres vont devoir vérifier que l'état de l'objet Music est bien ouvert et fonctionnel. Alors qu'un constructeur qui throw rend tout simplement impossible d'utiliser l'objet. Certains vont dire que c'est une hérésie de lever une exception dans un constructeur, mais c'est tout simplement la bonne méthode.

        Avec un constructeur qui throw je sais que mon objet sera valide tout au long de sa vie.

        Music m("foo.ogg");
        
        // Par buffer (vector, array), etc
        Music m(buffer.begin(), buffer.end());
        
        // Stream?
        std::istream customstream
        Music m(customstream);

        J'ai regardé rapidement ton projet, pour le ResourcesManager, tu pourrais retourner des std::unique_ptr plutôt que des pointeurs bruts. Ça marquera complètement l'ownership et tu pourras toujours retourner un std::unique_ptr null si l'objet n'est pas trouvé :)

        l'azerty est ce que subversion est aux SCMs

        • [^] # Re: Je n'aime pas la SFML

          Posté par . Évalué à 5.

          Sur les exceptions, je crois qu'on ne sera pas d'accord. Déjà, tu parles de lancer une exception mais jamais de la rattraper. Si tu ne la rattrapes jamais, autant mettre un bon vieux assert ou un abort et on n'en parle plus. Si tu la rattrape, j'aimerais bien savoir où : si c'est pas très loin, utiliser une exception ne sert à rien par rapport à un code de retour ou un booléen pour gérer un truc immédiat; si c'est très loin, alors tu ne peux rien faire de vraiment très sérieux à part quitter le programme.

          J'ai regardé rapidement ton projet, pour le ResourcesManager, tu pourrais retourner des std::unique_ptr plutôt que des pointeurs bruts. Ça marquera complètement l'ownership et tu pourras toujours retourner un std::unique_ptr null si l'objet n'est pas trouvé :)

          Houla non, malheureux ! Justement, l'intérêt du RessourceManager, c'est que c'est lui qui a la responsabilité du pointeur, il ne doit absolument pas la donner à l'utilisateur ! Ça lui permet de maintenir un cache des ressources et donc, de ne pas charger des choses en plusieurs exemplaires inutilement.

          • [^] # Re: Je n'aime pas la SFML

            Posté par (page perso) . Évalué à 1.

            si c'est pas très loin, utiliser une exception ne sert à rien par rapport à un code de retour ou un booléen pour gérer un truc immédiat; si c'est très loin, alors tu ne peux rien faire de vraiment très sérieux à part quitter le programme.

            Donc tu préfère ce genre de code ?

            int c()
            {
               if (!some_failure)
                   return -1;
               return 123;
            }
            
            int b()
            {
                int result_c;
            
                if ((result_c = c()) < 0)
                    return result_c;
            
                return result_c * 456;
            }
            
            int main()
            {
                int value = b();
            
                if (value < 0)
                    // code d'erreur, je suis obligé d'utiliser une seconde fonction pour récupérer une erreur "humaine"
                    std::cout << "code d'erreur: " << value << std::endl;
                else
                    std::cout << value << std::endl;
            }

            Plutôt que :

            int c()
            {
                if (a_failure)
                    throw std::runtime_error("error...");
            
                return 123;
            }
            
            int b()
            {
                return c() * 456;
            }
            
            int main()
            {
                try {
                    std::cout << b() << std::endl;
                } catch (const std::exception &ex) {
                    std::cerr << ex.what() << std::endl;
                }
            }

            l'azerty est ce que subversion est aux SCMs

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à 5.

              Non, je préfère :

              int c()
              {
                  assert(!a_failure);
                  return 123;
              }
              
              int b()
              {
                  return c() * 456;
              }
              
              int main()
              {
                  std::cout << b() << std::endl;
              }
              • [^] # Re: Je n'aime pas la SFML

                Posté par . Évalué à 3.

                Les assert, c'est bien joli, mais ça ne fait pas de contrôle d'erreur. Là, si il y a un souci, c'est le crash direct, et ça, pour l'utilisateur, c'est rédhibitoire.
                Mieux vaut un mode dégradé, ou si pas possible un message explicatif clair.

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 5.

                  Entre mon assert et l'exemple avec exception plus haut, il n'y a aucune différence, ça crashe le programme. Et je suis d'accord, c'est rédhibitoire. Maintenant, c'est aussi pour ça que je préfère des codes de retour explicite.

                  Ceci dit, les assert ont une utilité pour vérifier que tout se passe correctement, sous-entendu si ce n'est pas le cas, c'est une erreur de programmation qui doit être corrigée.

                  • [^] # Re: Je n'aime pas la SFML

                    Posté par (page perso) . Évalué à 5.

                    Pour moi les assert étaient un moyen de débogage qui sont supprimés lors de la compilation en mode release. Ça a changé ?

                    Python 3 - Apprendre à programmer en Python avec PyZo et Jupyter Notebook → https://www.dunod.com/sciences-techniques/python-3

              • [^] # Re: Je n'aime pas la SFML

                Posté par (page perso) . Évalué à 4.

                assert c'est pour des erreurs de développement. Pas des erreurs au runtime.

                l'azerty est ce que subversion est aux SCMs

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 5.

                  Je redis : dans le cas où le seul try/catch est dans main, ça ne fait aucune différence : arrêt immédiat pour l'utilisateur. Donc je repose ma question, où est-ce qu'on rattrape l'exception ?

                  • [^] # Re: Je n'aime pas la SFML

                    Posté par . Évalué à 10.

                    De mon expérience de développeur java. Ton exception contient les informations pertinentes. Tu attrape l'exception là où c'est pertinent. C'est ton abstraction qui rend logique le lieux où tu récupère l'exception. Tu la laisse traverser toutes les couches qui ne peuvent plus fonctionner et tu la récupère là où :

                    • tu sais comment réagir à l'erreur (changer un paramètre et réessayer, passer ton application en mode offline, stocker tes données sur disque,…) ;
                    • tu peux informer l'utilisateur du problème. Il n'est pas pensable dans un jeu un chouia grand publique d'avoir une application qui s'arrête à la limite de générer un coredump sans la moindre info.

                    Donc non il n'y a pas de réponse toute faite du genre « tu la catch ligne 25 du fichier toto.cpp ».

                    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                    • [^] # Re: Je n'aime pas la SFML

                      Posté par . Évalué à 4.

                      De mon expérience de développeur java

                      Les exceptions en C++ n'ont à peu près rien à voir avec les exceptions en Java, hormis le principe général. Déjà, le fait qu'en C++, elles ne soient pas déclarées dans le prototype de la fonction rend leur utilisation très pénible, contrairement à Java. Ensuite, beaucoup de projets C++ découragent l'utilisation des exceptions, parce que, sur certaines architectures, elles ont un coût non-négligeable.

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par . Évalué à 5.

                        Les exceptions en C++ n'ont à peu près rien à voir avec les exceptions en Java, hormis le principe général.

                        Oui mais comme ta question fait partie du principe générale, je me permet d'y répondre.

                        Déjà, le fait qu'en C++, elles ne soient pas déclarées dans le prototype de la fonction rend leur utilisation très pénible, contrairement à Java.

                        J'étais persuadé que l'on pouvait le faire sans que ce soit obligatoire (les exceptions ne sont pas vérifiées) et je viens de découvrir que c'est déprécié. C'est bien dommage au moins pour pouvoir s'en servir dans des analyse statique de code.

                        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par (page perso) . Évalué à 9.

                        https://isocpp.org/wiki/faq/exceptions#why-exceptions

                        “But exceptions are expensive!” Not really. Modern C++ implementations reduce the overhead of using exceptions to a few percent (say, 3%) and that’s compared to no error handling. Writing code with error-return codes and tests is not free either. As a rule of thumb, exception handling is extremely cheap when you don’t throw an exception. It costs nothing on some implementations. All the cost is incurred when you throw an exception: that is, “normal code” is faster than code using error-return codes and tests. You incur cost only when you have an error.

                        l'azerty est ce que subversion est aux SCMs

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par (page perso) . Évalué à 3.

                          ça rend juste le binaire final 25% plus gros

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par . Évalué à 3.

                          Oui les exceptions doivent être utilisées pour des causes "exceptionnelles" :)

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par (page perso) . Évalué à 2. Dernière modification le 21/07/16 à 15:43.

                            http://www.boost.org/doc/libs/1_52_0/libs/graph/example/astar-cities.cpp

                            struct found_goal {}; // exception for termination
                            
                            // visitor that terminates when we find the goal
                            template <class Vertex>
                            class astar_goal_visitor : public boost::default_astar_visitor
                            {
                              public:
                                astar_goal_visitor(Vertex goal) : m_goal(goal) {}
                                template <class Graph>
                                void examine_vertex(Vertex u, Graph& g) {
                                  if(u == m_goal)
                                    throw found_goal();
                                }
                              private:
                                Vertex m_goal;
                            };

                            http://devnewton.bci.im

                            • [^] # Re: Je n'aime pas la SFML

                              Posté par . Évalué à 1.

                              Si les gars qui font boost s'y connaissaient en C++, ça se saurait !

                              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                            • [^] # Re: Je n'aime pas la SFML

                              Posté par . Évalué à 5.

                              OMG!

                              C'est une manière d'implémenter le Pattern visiteur parmi tant d'autres!

                              Hmm du coup c'est le code client qui doit faire le catch?
                              Je comprends pourquoi on pourrait vouloir le faire comme ça (early exit) maisje ne peux m'empêcher de trouver ça bizarre. Je suppose que ça doit être encore une question d'exception vs. check sur les result codes.

                              Voir http://joeduffyblog.com/2016/02/07/the-error-model pour une discussion très intéressante sur le sujet.

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par (page perso) . Évalué à 2.

                        Les exceptions en C++ n'ont à peu près rien à voir avec les exceptions en Java, hormis le principe général. Déjà, le fait qu'en C++, elles ne soient pas déclarées dans le prototype de la fonction rend leur utilisation très pénible, contrairement à Java.

                        Il y a un ensemble des types pouvant être levé comme exception par une fonction. Par défaut, cet ensemble est "ouvert sur tout type". Mais il est possible de spécifier cet ensemble.

                        http://en.cppreference.com/w/cpp/language/except_spec

                        En C++, les "options" par défaut vont "toujours" dans le sens de la simplicité et des performances optimales. À prendre avec des pincettes :)

                        En l'occurrence, spécifier l'ensemble des types d'exceptions pouvant être levées implique la mise en place d'un mécanisme supplémentaire. Java impose toutes sortes de ce genre de mécanismes (introspection et autres) alors qu'en C++ le développeur "choisi".

                        Une autre alternative est de préciser les exceptions pouvant être levées dans la documentation de la fonction.

                    • [^] # Re: Je n'aime pas la SFML

                      Posté par . Évalué à 2. Dernière modification le 21/07/16 à 22:26.

                      En quoi, au final, les exceptions apportent-elles quelque chose à la gestion d'erreur ?

                      La gestion du problème n'est pas résolue, elle est changée (pourquoi pas?) et même amplifiée puisqu'il faut maintenant gérer du code qui ne s’exécute potentiellement plus en ligne droite de haut en bas mais aussi en traviole.
                      Gérer des classes d'exception. Trimballer le contexte de l'erreur jusqu'au lieu de correction.

                      La dernière chose qui me vient à l'esprit pour gérer une erreur, c'est bien du code spaghetti.

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par . Évalué à 4.

                        Trimballer le contexte de l'erreur jusqu'au lieu de correction.

                        Ce problème me paraît encore plus prégnant avec la gestion d'erreur par result code.

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par . Évalué à -2.

                          Et bien, on est obligé de gérer l'erreur là où elle s'est produite, ou dans une couche très proche.
                          Je persiste à penser ceci : si le concept qu'on veut programmer oblige de régler l'erreur dans des blocs supérieurs éloignés, alors ce concept est mauvais.

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par . Évalué à 4.

                            si le concept qu'on veut programmer oblige de régler l'erreur dans des blocs supérieurs éloignés, alors ce concept est mauvais.

                            Il ne l'oblige pas.

                            "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par . Évalué à 7.

                            Et bien, on est obligé de gérer l'erreur là où elle s'est produite, ou dans une couche très proche.

                            Pas du tout, il y a pleins de programmes qui propagent les codes d'erreur jusqu'à la fonction main.

                            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par . Évalué à 4.

                        En quoi, au final, les exceptions apportent-elles quelque chose à la gestion d'erreur ?

                        De la sémantique, éviter de se répéter partout…

                        La dernière chose qui me vient à l'esprit pour gérer une erreur, c'est bien du code spaghetti.

                        C'est pourtant à cause du code spahetti des return codes + vérifs partout qu'on a inventé les exceptions…

                        "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par . Évalué à 2.

                          Du code spaghetti pour réparer du code spaghetti, donc :D

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par . Évalué à 2.

                            Du code spaghetti pour réparer du code spaghetti, donc :D

                            Non, avec les exceptions, en plus de pouvoir utiliser les héritages pour les classes d’exception, le try est définie dans un bloc clairement identifier, rien à voir avec un systhème de goto ou de if sur une profondeurs de dix appels.

                            Une classe définie une erreur, elle peut throw l’exception dans n’importe quelle méthode, sous méthode sans compliqué son code avec des if. À l’utilisateur de récupérer l’exception.

                            Sinon comme proposé on peut avoir une méthode sans exception :

                            retCode fct_no_except(...)
                            {
                                retCode = rc = NO_ERROR;
                                try {
                                   ftc(...)
                                } catch (Erreur e) {
                                    rc = e.getCodeNumber();
                                } catch (...)
                                {
                                    rc = UNKNOWN_ERROR;
                                }
                                return rc;
                            }
                            • [^] # Re: Je n'aime pas la SFML

                              Posté par . Évalué à 5.

                              À l’utilisateur de récupérer l’exception.

                              Ça, ça finit toujours en exception non-rattrapée et qui finit dans main

                              • [^] # Re: Je n'aime pas la SFML

                                Posté par . Évalué à 9.

                                Ça dépend quel soin est donné au "polissage" du logiciel.

                                Je travaille sur un logiciel d'annuaire LDAP (OpenDJ pour ne pas le nommer) sur lequel on fait très attention à fournir de bons messages d'erreurs (qu'est-ce qui s'est passé, qu'est-ce que l'administrateur peut faire pour corriger le problème) et je peux te dire que la gestion d'erreur occupe un bon pourcentage des lignes de code.

                                Bien gérer les erreurs est une politique de développement de ce logiciel.

                                Si le développeur s'en fout, peu importe la méthode de gestion d'erreur, ça finira mal.

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par (page perso) . Évalué à 5.

                        En quoi, au final, les exceptions apportent-elles quelque chose à la gestion d'erreur ?

                        En C++, ou bien en programmation de manière générale ?

                        Trimballer le contexte de l'erreur jusqu'au lieu de correction.

                        Avec les exceptions tu peux traiter tout de suite, comme avec les codes d'erreurs, lorsque c'est pertinent.
                        Tu peux aussi traiter plus loin (et regrouper les traitements d'erreur plutôt que les multiplier) lorsque c'est pertinent (et le 'trimballage' de contexte sera plus facile, car le langage t'aide).

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par . Évalué à 0.

                          En C++, ou bien en programmation de manière générale ?
                          En C++, pour commencer, je ne voudrais pas faire de trop grandes généralités sur des langages que je ne connais pas.
                          Même si je pense que de manière générale les exceptions devraient rester des outils spécifiques utilisés quand nécessaire, et ne pas être des outils généraux utilisés quand possible.

                          Avec les exceptions tu peux traiter tout de suite, comme avec les codes d'erreurs, lorsque c'est pertinent.
                          Tu peux aussi traiter plus loin (et regrouper les traitements d'erreur plutôt que les multiplier) lorsque c'est pertinent (et le 'trimballage' de contexte sera plus facile, car le langage t'aide).

                          En théorie, sûrement. Mais dans les faits ? Est-ce toujours possible de traiter dans les couches supérieures ?
                          Il faut identifier quelles valeurs seront nécessaires à la correction, où elles ont encore un sens, faire attention à leur durée de vie, …
                          Des problèmes supplémentaires à résoudre, qui peuvent pousser à modifier l'architecture du programme pour la plier autour des erreurs. Faire de la "programmation orientée erreur".
                          Je ne peux pas m'empêcher de me sentir coupable quand je dois le faire :(

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par . Évalué à 7.

                            Il faut identifier quelles valeurs seront nécessaires à la correction, où elles ont encore un sens, faire attention à leur durée de vie, …
                            Des problèmes supplémentaires à résoudre, qui peuvent pousser à modifier l'architecture du programme pour la plier autour des erreurs. Faire de la "programmation orientée erreur".

                            C'est purement théorique. Faut arrêter d'avoir la tête dans le guidon et de faire des grandes affirmations sur les malheurs d'une solution tout ça parce qu'on ne l'aime pas ou la maitrise pas ou la connaît pas.

                            Quand tu écris une fonction, tu défini tes paramètres, ta (ou tes) sorties et la manière dont tu sort une erreur s'il est possible que tu plante. La réflexion est la même que tu envoie un code d'erreur, que tu utilise un bidule fonctionnel Option/Either ou que tu lève une exception. Rien de plus rien de moins. Si tu arrive à renvoyer une erreur via un code d'erreur tu devrait réussir à le faire avec une exception ne t'en fais pas trop ;)

                            La difficulté n'est pas dans le fait d'envoyer une erreur, mais dans la manière dont on la gère. Oui il peut paraître compliqué de gérer les exceptions (sans utiliser une solution moche comme beaucoup le font avec un traitement à tous les étages et un rethrow), mais tu as précisément la même problématique avec toutes les façons de gérer les erreurs. Oui il faut réfléchir à où c'est pertinent de récupérer ton erreur,. Oui ça peut donner l'impression de passer son temps à gérer des erreurs, mais un problème aussi complexe ne se gère pas en un coup de cuillère à pot.


                            Un point très pratique en C++, c'est que les exceptions normalisent tes erreurs. Si tu as une méthode qui retourne un entier et dont l'ensemble des entiers est une valeur acceptable, retourner une erreur va te demander soit d'enrober ton retour (avec un Optional par exemple) soit d'utiliser une variable globale (à la errno). Devoir jongler entre tester -1, 0, NULL, un objet encapsulant, ne rend pas pas les choses plus simples.

                            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par (page perso) . Évalué à 7.

                            En C++, pour commencer, je ne voudrais pas faire de trop grandes généralités sur des langages que je ne connais pas.

                            OK. Mais prenons Ada, qui est relativement proche de C++ (impératif, orienté objet, typage statique fort…), et qui est réputé pour être utilisé dans des systèmes critiques. Et bien il propose aussi des exceptions.

                            Et comme des tas d'autres langages sérieux (Ocaml, Haskell, Erlang…), en plus des langages plus mainstream (Java, C#, Python…), proposent aussi des exceptions, on peut quand même largement douter du fait que ça n'apporte rien aux codes d'erreurs classiques (voire des mécanisme plus sophistiqués comme le pattern matching).

                            Est-ce toujours possible de traiter dans les couches supérieures ?

                            Mauvaise question.
                            Si il est intelligent de traiter l'erreur 3 appels de fonctions en amont, alors les exceptions te permettent de faire ça avec peu de code boilerplate. Mais de la même manière que tu coopères avec la fonction qui te renvoie un code d'erreur (en traitant ce code), tu coopères avec du code qui peut soulever des exceptions (en mettant des handlers là où c'est pertinent). Les exceptions n'ont pas la prétention de régler le problème des erreurs, mais de permettre d'écrire (quand ça a du sens) du code plus simple/court/robuste.

                            Personne n'a dit que les exceptions étaient un outil magique qu'il fallait saupoudrer sur ton code, et hop ton code gère les erreurs correctement. Non c'est un outil avec des avantages et des défauts, et qui peut être mal utilisé comme tous les outils.

              • [^] # Re: Je n'aime pas la SFML

                Posté par . Évalué à 3.

                Tu compile tes livrables en gardant les assertions ?
                La bonne pratique ce n'est pas de les garder uniquement en debug/développement ?

                En C++ quelle est la différence entre ton code et :

                int c()
                {
                    if (a_failure) throw new std::runtime_error("error...")
                    return 123;
                }
                
                int b()
                {
                    return c() * 456;
                }
                
                int main()
                {
                    std::cout << b() << std::endl;
                }

                Mis à part que l'un donne la possibilité à l'utilisateur de c() de gérer l'erreur.

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: Je n'aime pas la SFML

                  Posté par (page perso) . Évalué à 4.

                  Moi je dirais qu'avec une fonction assert maison (qu'on pourrait appeler internal_error()), t'as au moins la chance de pouvoir recuperer la pile d'appel et l'afficher à l'utilisateur, ou la sauver quelque part, alors que si tu throw une exception c'est la croix et la bannière pour recuperer sa pile d'appel au niveau du catch

                • [^] # Re: Je n'aime pas la SFML

                  Posté par (page perso) . Évalué à 7.

                      if (a_failure) throw new std::runtime_error("error...")
                      return 123;

                  Houlala, attention !

                  Il est levé là un pointeur vers une exception !
                  Et où sera le delete ?

                  Non non, la bonne écriture est :

                      if (a_failure) throw std::runtime_error("error...");
                  
                      return 123;

                  (il manquait également le ;)

                  Et finalement, lorsqu'un if tient sur une ligne, laisser ensuite une ligne vide favorise une bonne lecture.

            • [^] # Re: Je n'aime pas la SFML

              Posté par (page perso) . Évalué à 5.

              Je suis un développeur C plutôt que C++, mais j'essaie de te répondre objectivement.

              Exception ou code de retour, la difficulté de gestion des erreurs reste la même, où la gère-t-on et quelles actions complémentaires faut-il réaliser : souvent une action au sein de l'api (réinitialisation ressources) et une plus globale (compteur d'erreur, etc….).

              Mais dans le second cas le retour de fonction 'auto-documente' une gestion des codes d'erreur (tiens il y a un retour, est-ce que je dois les gérer ?), alors qu'avec un try/catch c'est beaucoup moins évident (il faut documenter je crois…, ou rencontrer au moins une fois l'erreur) pour l'intégration.

              Et je me demande si le débogage du try/catch est aussi simple qu'avec un code de retour.

              Mais surtout, j'ai trop souvent vu des personnes utiliser des try/catch sous prétexte que c'est nouveau pour finalement les gérer comme des return, et là question lisibilité : c'est zéro !

              Au final ce n'est pas un argument d'abandonner une API pour cette gestion d'erreur, s'il y en a une et qu'elle est correctement documentée pour l'intégration il faut l'utiliser.

        • [^] # Re: Je n'aime pas la SFML

          Posté par . Évalué à 6.

          Moi, les exceptions, j'en prêchais l'usage avant, à tort et à travers.

          Depuis, je me suis aperçu que:

          • c'est pas portable, potentiellement d'une version à l'autre d'un même compilo. Je parle de l'ABI. Ça, c'est le truc qui m'a fait cesser de les utiliser.
          • ça bloat mon code, quand je veux réellement traiter toutes les erreurs, et bien plus que des séries de ifs construites correctement. J'utilise de l'objet, juste, j'évite maintenant les exceptions.
          • ça «booste» le binaire de ~10%. Un binaire de 10Mio fera en moyenne 11Mio à cause du code lié aux exceptions qui est du code principalement mort puisque, en effet, exécuté que si une exception est lancée. Bien plus lourd que des ifs donc. Ce boost n'est pas nécessairement souhaitable sur tous les matériels.

          Bref, je pense que c'est vraiment un choix des développeurs à l'heure actuelle (pour le C++).
          Par contre, si on joue sans exceptions, il faut dans ce cas faire très attention quand on utilise la STL, qui force quasiment l'usage des exceptions (faire foo.reserve(10);if(foo.capacity()<10){do_that;} avant le moindre push/emplace, notamment). D'un autre côté, au moins, ça force le dev à faire des reserve, et ça fait réfléchir à comment n'en faire qu'une seule fois. Parce que j'ai vu plus d'un soft en C++ être méchamment ralentit par les allocations mémoires pour un oui ou un non.

          • [^] # Re: Je n'aime pas la SFML

            Posté par . Évalué à 1. Dernière modification le 20/07/16 à 06:30.

            Gros plus un. Ça impose des options de compilation à tous les utilisateurs de ta lib, qui ont un impact sur les performances ou l'optimisabilité de ton code bien plus important que ces 10 %..

            Quand à la stl, imposer les exceptions (entre autres), font que c'est rarement utilisé dans les très gros projets.

          • [^] # Re: Je n'aime pas la SFML

            Posté par . Évalué à 3.

            ça bloat mon code, quand je veux réellement traiter toutes les erreurs, et bien plus que des séries de ifs construites correctement. J'utilise de l'objet, juste, j'évite maintenant les exceptions.

            Ce n’est pas normal. Après, il y a des gens qui font cohabiter le pire des deux mondes : des exceptions mais pas de raii. Là on court à la catastrophe.

            Écrire du code exception-safe est plus compliqué, mais normalement pas plus « bloat ». Au contraire, cela tend à simplifier les choses. Et le code est plus robuste.

            En ce qui concerne les perfs, elles sont aujourd’hui excellentes sur le chemin normal (càd l’exception n’est pas levée), en revanche il y a effectivement un surcoût qui peut être non négligeable lorsqu’une exception est levée.

            Sinon, je suis bien désolé de t’apprendre que reserve peut tout à fait lancer std::bad_alloc, et donc que ton test ne sert pas à grand chose (sauf, bien sûr, si tes ajouts ont besoin d’être atomiques, mais ça ne me semblait pas être le propos).

            Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à 2.

              Sinon, je suis bien désolé de t’apprendre que reserve peut tout à fait lancer std::bad_alloc

              Tiens, effectivement, c'est ce qu'indique cppreference maintenant… ce n'était pas le cas quand j'ai vérifié. Il faudrait vraiment que j'arrive à trouver un doc exhaustive sur la STL moi.

              Merci du coup.

        • [^] # Re: Je n'aime pas la SFML

          Posté par . Évalué à 2.

          Cela signifie que toutes tes fonctions membres vont devoir vérifier que l'état de l'objet Music est bien ouvert et fonctionnel. Alors qu'un constructeur qui throw rend tout simplement impossible d'utiliser l'objet.

          OK, mais ensuite ? Qu'est-ce que le programme doit faire pour continuer ?

          Si on s'en tient aux erreurs ayant trait à la programmation pure et pas au système (manque de mémoire, par exemple), qu'est-ce qu'une exception apporte ?
          On est au même point que si le programme avait tout simplement vérifier le contexte avant de procéder à la construction.

          Plus l'échec est tardif dans la construction, plus on va devoir défaire du travail pourtant réussi.
          Au lieu de vérifier avant, on tente en espérant que ça passe, mais dans les deux cas de toute façon il faut gérer 1) l'arrêt (throw, …) et 2) l'échec, donc le système d'exceptions n'apporte rien à part un vocabulaire supplémentaire et des algorithmes qui se déroulent de haut en bas mais aussi en travers.

          C'est assez curieux quand on voit la réputation du switch-break, et plus généralement des return en milieu de bloc.

          • [^] # Re: Je n'aime pas la SFML

            Posté par . Évalué à 5.

            C'est assez curieux quand on voit la réputation du switch-break, et plus généralement des return en milieu de bloc.

            Moi j'aime bien les return en milieu de bloc…

          • [^] # Re: Je n'aime pas la SFML

            Posté par . Évalué à 9.

            Au lieu de vérifier avant, on tente en espérant que ça passe […]

            Oui ! Oui ! Oui ! 1 000 fois oui !

            Tenter de toi-même vérifier une précondition avant de faire l'appel d'une méthode, c'est vraiment casse gueule. Ça veut dire que si la précondition change, il faut la modifier partout où la méthode est appelée, ça veut dire que tu dois toi bien maitriser quels sont les préconditions et comment les vérifier, etc. Tenter de vérifier si la création d'un fichier va fonctionner avant de le créer c'est plus subtile que ça en a l'air (vérifier le dossier, vérifier, les droits (SELinux ? AppArmor ? fs en lecture seule ?…)).

            donc le système d'exceptions n'apporte rien à part un vocabulaire supplémentaire et des algorithmes qui se déroulent de haut en bas mais aussi en travers.

            N'importe quoi… Quand tu traite un cas d'erreur, tu va avoir un branchement dans ton code pour passer de l'état « normal » à l'état « c'est la galère ». C'est pas une question de langage ou d'expressivité de celui-ci.

            Il est rare de pouvoir tout gérer dans ton bloc de gestion d'erreur pour ensuite pouvoir continuer le flow d'exécution.
            Quand tu vois ça : https://github.com/torvalds/linux/blob/c05c2ec96bb8b7310da1055c7b9d786a3ec6dc0c/drivers/media/tuners/m88rs6000t.c#L108
            Je me dis surtout qu'ils aimeraient bien avoir la sémantique du try/catch.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à -1. Dernière modification le 23/07/16 à 02:54.

              Tenter de toi-même vérifier une précondition avant de faire l'appel d'une méthode, c'est vraiment casse gueule. Ça veut dire que si la précondition change, il faut la modifier partout où la méthode est appelée,

              Avec des exceptions, si la précondition change, une exception non prévue sera balancée et donc on est dans la même situation, le nouveau cas d'erreur ne peut pas être géré, ou même attrapé si le circuit de catch est spécifique.

              Et puis, autant un constructeur nécessite une exception pour qu'on puisse faire de la gestion d'erreur sans construction double-phase (avec une méthode init()),
              autant un destructeur ne peut pas lever une exception alors qu'une exception est déjà en cours de remontée, sans provoquer l'arrêt cardiaque du programme, ce qui est un frein certain à l'utilisation autour de destructeurs.
              Cette dualité me laisse assez circonspect vis à vis des exceptions.

              J'ai l'impression que cela montre quelque manques importants dans la conception originale du concept d'exception, institutionnalisé, et cette impression me pousse à me freiner dans cet usage.

              • [^] # Re: Je n'aime pas la SFML

                Posté par . Évalué à 4.

                […] si le circuit de catch est spécifique.

                Ça petit arriver mais c'est très rare. Tu n'est pas sensé avoir une classe d'exception par erreur possible.

                Pour le reste c'est une spécificité de C++. Je ne saurais pas trop quoi en dire.

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: Je n'aime pas la SFML

                Posté par . Évalué à 2.

                En java, l'utilisation des finalizers lors de la destruction par le ramasse miettes est déconseillée. La bonne manière de faire est d'utiliser des blocs finally.

      • [^] # Re: Je n'aime pas la SFML

        Posté par . Évalué à 2.

        Les exceptions, c'est bien quand c'est utile, comme tout le reste. Un des avantages du C++ par rapport au C c'est les références, et quand une méthode ne peut pas retourner de référence sur un objet (parce qu'il n'existe pas, est invalide, etc.), il n'y a pas le choix : il faut lever une exception. Ou alors quand on ne peut pas le construire, comme le souligne mon vdd.

        Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

        • [^] # Re: Je n'aime pas la SFML

          Posté par . Évalué à 3.

          C'est bien un des seuls cas où, effectivement, une exception serait justifiée. Actuellement, dans ce cas, je renvoie un pointeur (et donc un pointeur null si l'objet n'existe pas). Mais la question reste la même : où gérer l'exception ?

          • [^] # Re: Je n'aime pas la SFML

            Posté par . Évalué à 3.

            Je ne suis pas grand connaisseur du C++, mais j'aime bien ton approche. :-)

            En OCaml, on utilise le type polymorphe 'a option = None | Some of 'a (c'est l'équivalent de : un pointeur null ou un pointeur sur un objet de type 'a) pour faire cela. Je préfère également cette approche à celle par gestion des exceptions. La bibliothèque standard à tendance à utiliser des exceptions, là où la version de jane street fournit les fonctions en deux exemplaires : avec exception ou avec un type 'a option en retour.

            J'avais eu une discussion sur le sujet avec Perthmâd (où je l'illustrais par le calcul du prédécesseur sur les entiers naturels, et la façon de gérer le cas n = 0), et selon lui cela correspond à une transformation logique connue sous le nom de Friedman's trick. Moi je le vois comme une façon de rester purement constructif, et d'éviter d'avoir à raisonner par l'absurde.

            Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à 3.

              En C++, on va avoir std::optional en C++17 qui joue exactement le même rôle et qui marche avec toutes les classes, pas uniquement les pointeurs.

              À noter aussi que dans std::filesystem, il y a les deux. Pour chaque fonction, on a une version avec un code de retour (en dernier argument) et une fonction sans code de retour mais qui lève une exception. De cette manière, chacun fait bien comme il veut.

              • [^] # Re: Je n'aime pas la SFML

                Posté par (page perso) . Évalué à 2.

                C’est un peu dommage qu’stp::optional arrive si tard (c’est la façon standard de gérer les erreurs en Rust et bien intégré dans le langage).

                À noter aussi que dans std::filesystem, il y a les deux. Pour chaque fonction, on a une version avec un code de retour (en dernier argument) et une fonction sans code de retour mais qui lève une exception. De cette manière, chacun fait bien comme il veut.

                Faut maintenir deux fois plus de code? Ou c’est juste la fin de la fonction qui change?

                Écrit en Bépo selon l’orthographe de 1990

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 3.

                  C’est un peu dommage qu’stp::optional arrive si tard

                  Il y a boost::optional en attendant.

                  Faut maintenir deux fois plus de code? Ou c’est juste la fin de la fonction qui change?

                  Non, il y a une fonction commune aux deux versions qui est appelée et en fonction envoie une exception ou renvoie un code d'erreur.

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 3.

                  C’est un peu dommage qu’std::optional arrive si tard (c’est la façon standard de gérer les erreurs en Rust et bien intégré dans le langage).

                  optional permet de ne pas renvoyer de valeur si on ne peut pas (le cas typique, c’est str_to_int), mais pas de décrire correctement le problème.

                  Si on peut se permettre d’être stateful (par exemple avec un errno par thread), ça va. Si on ne peut pas, c’est du coup un peu léger.

                  Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à 4.

              En OCaml, on utilise le type polymorphe 'a option = None | Some of 'a (c'est l'équivalent de : un pointeur null ou un pointeur sur un objet de type 'a) pour faire cela. Je préfère également cette approche à celle par gestion des exceptions. La bibliothèque standard à tendance à utiliser des exceptions, là où la version de jane street fournit les fonctions en deux exemplaires : avec exception ou avec un type 'a option en retour.

              La subtilité c'est que ce n'est pas le même langage. Tu ne peux pas utiliser un option en OCaml sans vérifier la présence d'une valeur, alors qu'avec un null… c'est transparent. C'est bien pour ça qu'il y a des langages qui intègrent maintenant des types non nullable.

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Je n'aime pas la SFML

              Posté par . Évalué à 10.

              Oui, c'est ce que fait le Rust qui se veut un successeur du C++. Il tire d'ailleurs explicitement ce comportement des langages fonctionnels. Je tiens à dire que je préfère cette façon de faire aux exceptions, mais je préfère tout de même le système d'exceptions aux return en cascade du C.

              M'enfin de toute façon, plus je gère en C++ (je suis dev C++) plus je trouve ce langage fait à l'arrache et inutilement complexe. J'espère qu'il va vite se faire détrôner en tant que langage compilé de référence pour passer à des paradigmes plus modernes. Pour l'instant je tente d'apprendre le Rust, mais j'ai vraiment du mal.

              Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

              • [^] # Re: Je n'aime pas la SFML

                Posté par . Évalué à 2.

                M'enfin de toute façon, plus je gère en C++ (je suis dev C++) plus je trouve ce langage fait à l'arrache et inutilement complexe. J'espère qu'il va vite se faire détrôner en tant que langage compilé de référence pour passer à des paradigmes plus modernes. Pour l'instant je tente d'apprendre le Rust, mais j'ai vraiment du mal.

                Je suis comme toi (dev c++) et partage entièrement ton point de vu. Nous sommes un peu hors sujet mais en deux mots, peux-tu nous dire ce qui te pose problème avec Rust. Je voudrais m'y mettre. Merci !

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 5.

                  En tant que développeur C++ je pense que le langage n'est pas inutilement complexe dans son état à une date donnée, même si le mélange dans un même code de C++ d'il y a 30 ans avec du C++ d'aujourd'hui est, lui, inutilement complexe.
                  Et que vous pouvez toujours rêver à voir C/C++ remplacé par autre chose encore quelques années…
                  Je lisais les mêmes commentaires dans les années 90. Sur usenet.

                • [^] # Re: Je n'aime pas la SFML

                  Posté par . Évalué à 3.

                  Je me suis mal exprimé : je n'ai pas de problème avec le Rust dans le sens où je n'aime pas certains aspects, j'ai juste du mal à apprendre à coder dans ce langage et à intégrer ses spécificités. Le point majeur sur lequel je bloque (comme beaucoup de monde, je suppose), est le “borrowing” et le “lifetime” des variables. C'est ce qui fait tout l'intérêt du Rust, mais ça oblige vraiment à construire une nouvelle façon de penser.

                  Ah si : un truc que je trouve dommage : le langage se la joue fonctionnel (notamment avec une syntaxe et certains paradigmes hérités des langages fonctionnels) alors qu'en fait, on ne peut PAS coder en fonctionnel avec, pour plusieurs raison. Il n'y a pas de récursion terminale (alors que c'est même implémenté en C !!) ; et on ne peut pas utiliser les fonctions imbriquées comme en OCaml par exemple. On peut utiliser des lambdas à la place, c'est vrai, mais je trouve ça dommage d'un point de vue syntaxique, ça fait moins full fonctionnel.

                  Voici un petit exemple (un peu idiot) qu'on pourrait voir en OCaml, mais qui ne fonctionne pas en Rust :

                  fn fac(nbr: isize) -> isize {
                      let scale = 1; // <- useless
                      fn fac_tailrec(nbr: isize, accumulator: isize) -> isize {
                          match nbr {
                              0 => accumulator,
                              _ => fac_tailrec(nbr - 1, accumulator * nbr * scale) // no tail recursive optimisation
                              // error: can't capture dynamic environment in a fn item;
                              // use the || { ... } closure form instead
                          }
                      }
                      fac_tailrec(nbr, 1)
                  }
                  
                  fn main() {
                      println!("{}", fac(7));
                  }
                  

                  Mais bon, c'est un langage jeune, et je suppose qu'il va finir par se bonifier. Dans l'ensemble, c'est un travail extraordinaire.

                  Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

                  • [^] # Re: Je n'aime pas la SFML

                    Posté par . Évalué à -2.

                    s/bonifier/améliorer

                    bonifier = devenir bon (en plus, c'est super moche comme mot)

                    "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                    • [^] # Re: Je n'aime pas la SFML

                      Posté par . Évalué à 2.

                      1. C'est du pinaillage.
                      2. Les dicos en lignes donnent comme définition : “rendre meilleur”, ce qui est bien ce que je voulais dire.
                      3. Moche/pas moche, c'est assez subjectif pour un mot.

                      Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

                    • [^] # Re: Je n'aime pas la SFML

                      Posté par . Évalué à 3.

                      en plus, c'est super moche comme mot

                      Moi j'aime bien !
                      Par exemple dans des phrases type : "certaines personnes sont comme les bons vins ils se bonifient avec l'âge"

                      kentoc'h mervel eget bezan saotred

                  • [^] # Re: Je n'aime pas la SFML

                    Posté par . Évalué à 1.

                    Le point majeur sur lequel je bloque (comme beaucoup de monde, je suppose), est le “borrowing” et le “lifetime” des variables.

                    Si tu ne comprends pas ça, tu ne peux pas non plus coder en C++ moderne :). Changer de langage n’y changera rien, ce sont les paradigmes que tu dois assimiler.

                    Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0

                    • [^] # Re: Je n'aime pas la SFML

                      Posté par . Évalué à 2.

                      Le concept de durée de vie ne fonctionne pas du tout de la même façon en C++ moderne qu'en Rust. Le concept lui-même est simple, mais les façons dont il est géré en C++ et en Rust n'ont rien à voir. Le C++ n'a pas la sémantique move par défaut, rien que ça c'est une différence majeure qui change complètement la façon dont fonctionnent les deux langages. On peut être très bon en C++ et être dépassé par le Rust (au moins au départ).

                      Ce commentaire est libre de droit, vous pouvez le réutiliser comme bon vous semble.

                      • [^] # Re: Je n'aime pas la SFML

                        Posté par . Évalué à 1.

                        euh, std::unique_ptr, c’est globalement la sémantique par défaut de rust (rust est plus strict car il interdit les dangling references, mais la sémantique générale est la même, pour autant que je sache). Ou alors, je veux bien que tu me détailles plus précisément les différences (je connais assez mal rust, pour ne l’avoir jamais réellement pratiqué, donc je peux passer à côté de subtilités).

                        Il n’y a d’ailleurs à ma connaissance que deux langages d’usage généraliste qui ont cette sémantique : rust et C++ :). Ce sont des langages assez proches, les créateurs de Rust s’étant beaucoup inspirés de ce qu’ils aimaient en C++ (en sabrant par contre toute la partie « historique » qu’ils n’aimaient pas, ou des choix qui engendraient une complexité trop importante).

                        Mes commentaires sont en wtfpl. Une licence sur les commentaires, sérieux ? o_0

                        • [^] # Re: Je n'aime pas la SFML

                          Posté par . Évalué à 1. Dernière modification le 21/07/16 à 21:39.

                          Comment Rust peut interdire les "dangling references" ?

                          • [^] # Re: Je n'aime pas la SFML

                            Posté par (page perso) . Évalué à 3.

                            Parce que, contrairement à C++, Rust définit explicitement dans le langage la notion d'ownership, de borrowing et etc, et donc qu'il peut analyser et garantir qu'il n'y a pas de dangling reference (c'est un programme mal-formé du point de vue de la sémantique de Rust).

                            Cf l'overwiew de LWN https://lwn.net/Articles/547145/

      • [^] # De l’utilité des exceptions.

        Posté par (page perso) . Évalué à 8. Dernière modification le 20/07/16 à 15:01.

        pas d'exception

        Ça, ça ne va pas changer, je déteste les exceptions en C++. Et je ne vois pas bien où je pourrais en mettre.

        J'ai un jour dû écrire un logiciel en C de haute disponibilité, qui devait tourner 24h/24, 7j/7, sur un PC industriel équipé d'un watchdog, histoire qu'il reboot automatiquement si mon logiciel devait planter. Du coup, la plupart de mes fonctions comportaient pléthore de if dont l'unique objet était de remonter à la fonction appelante les erreurs détectées dans les fonctions appelées. Je trouvais que cela rendait le programme presque illisible, car il était difficile de distinguer parmi tous ces if lesquels étaient 'algorithmiques', et lesquels étaient dédiés à la gestion d'erreurs.

        Pour améliorer cela, j'ai implémenté en C, en m'appuyant sur la bibliothèque setjmp, un mécanisme, sous forme d'un jeu de macros, dont je me suis rendu compte plus tard qu'il s'apparentait aux exceptions C++, que je ne connaissais pas à l'époque. D'ailleurs, quand je suis passé au C++, j'ai réimplémenté ces mêmes macros en m'appuyant sur les exceptions, au lieu de la bibliothèque setjmp. J'utilise toujours ces macros pour la gestion des erreurs, et, bien que, par défaut, elles s'appuient sur les exceptions C++, on peut, à l'aide d'une option de compilation, basculer sur la bibliothèque setjmp, pour une utilisation dans un environnement où les exceptions ne seraient pas disponibles.

        Quand ma production consistait essentiellement en utilitaires en ligne de commande, l'exception était interceptée grosso-modo dans le main pour afficher un message d'erreur. Par contre, depuis que j'écris des daemon, l'exception est interceptée à la fonction racine du thread dans lequel elle est lancée, pour afficher un message d'erreur dans un log, voire relayer ce message au client, avant de terminer le thread en question. Mais le thread principal continue toujours de tourner, ainsi que les autres threads, prêts à répondre aux requêtes des différents clients.

        Pour les interfaces graphiques, l'exception est interceptée dans la boucle de gestion des événements. Par exemple, si l'utilisateur valide un formulaire en oubliant de remplir un champ obligatoire, une exception est lancée qui remonte jusqu'à cette boucle, affiche un message signalant la nécessité de remplir le champs oublié, et ensuite laisse tout loisir à l'utilisateur de remplir le champ en question, comme s'il ne s'était rien passé.

        En ce qui me concerne, les exceptions (ou la setjmp en C) facilitent grandement le développement de logiciels…

        Freelance en ingénierie informatique.

        • [^] # Re: De l’utilité des exceptions.

          Posté par (page perso) . Évalué à 1. Dernière modification le 21/07/16 à 10:33.

          Si on est obligé de faire en C, il y a e4c qui n'est pas trop mal.

          l'azerty est ce que subversion est aux SCMs

        • [^] # Re: De l’utilité des exceptions.

          Posté par . Évalué à 5.

          Par exemple, si l'utilisateur valide un formulaire en oubliant de remplir un champ obligatoire, une exception est lancée qui remonte jusqu'à cette boucle, affiche un message signalant la nécessité de remplir le champs oublié, et ensuite laisse tout loisir à l'utilisateur de remplir le champ en question, comme s'il ne s'était rien passé.

          Ici, l'erreur (le champ de formulaire vide) est attendue.
          Étant donné que le champ de formulaire attend les données venant de l'extérieur, le fait qu'il soit vide fait partie de sa définition.
          Cela ne dénote pas un échec irrécupérable, gênant l'intégrité du programme.

          Utiliser une exception pour gérer un chemin normal de l'algorithme est une pratique à la salubrité très douteuse.

          • [^] # Re: De l’utilité des exceptions.

            Posté par (page perso) . Évalué à 1.

            De ce que je sais, les exceptions ont été conçues pour faciliter la gestion des erreurs, quelles qu'elles soient. Je ne vois pas en quoi la nature de l'erreur change quoi que ce soit, d'autant plus lorsqu'elle est basée sur ces notions d'attendu/inattendu, pour autant qu'il y ai une définition précise et univoque des ces notions. En outre, la nature d'une même erreur peut varier selon le contexte. Reprenons l'exemple ci-dessus, en supposant que l'interface soit une interface Web. On peut envisager que, lors de la validation du formulaire, avant son envoi, un script JS soit exécuté pour vérifier si le champ est bien rempli, et n'envoyer le formulaire qu'à cette condition, ou, sinon, signaler à l'utilisateur qu'il lui faut remplir ce champ. Au niveau du code C++, le contenu du champ ne peut, théoriquement, jamais être vide, mais c'est une bonne pratique que de le vérifier tout de même, on ne sait jamais. Du coup, si cette erreur se produit tout de même (il peut y avoir un bug dans le code JS), erreur attendue ou inattendue ?

            Freelance en ingénierie informatique.

            • [^] # Re: De l’utilité des exceptions.

              Posté par . Évalué à 6.

              De ce que je sais, les exceptions ont été conçues pour faciliter la gestion des erreurs, quelles qu'elles soient.

              Non, elles sont faites pour gérer les cas exceptionnels. C'est marqué dessus.

              quick summary for why, generally, it's an anti-pattern:
              - Exceptions are, in essence, sophisticated GOTO statements
              - Programming with exceptions therefore leads to more difficult to read, and understand code
              - Most languages have existing control structures designed to solve your problems without the use of exceptions
              - Arguments for efficiency tend to be moot for modern compilers, which tend to optimize with the assumption that exceptions are not used for control flow.

              http://programmers.stackexchange.com/questions/189222/are-exceptions-as-control-flow-considered-a-serious-antipattern-if-so-why

              "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: De l’utilité des exceptions.

                Posté par (page perso) . Évalué à 2. Dernière modification le 24/07/16 à 17:35.

                Je ne vois pas ce à quoi le terme dessus fait référence, et, quant au lien, je ne vois rien dans la biographie de l'auteur qui donne le moindre poids à ses écrits en général, et ces écrits en particulier. Par contre, j'ai trouvé ceci, dont B. Stroustrup lui-même est l'un des auteurs. Je pense que les deux premiers paragraphes de l'introduction sont on ne peut plus clairs quant à l'usage pour lesquels les exceptions C++ ont été conçues…

                Freelance en ingénierie informatique.

                • [^] # Re: De l’utilité des exceptions.

                  Posté par . Évalué à 4.

                  Depuis 1989, date du papier, on a un peu plus d'expérience sur l'utilisation des exceptions. Et parmi toutes les entreprises qui utilisent C++, de grands pans refusent les exceptions dont toute l'industrie des jeux vidéos (puisqu'on en parle), et des petites PME du genre Google qui doit avoir une des plus grosses bases de code en C++ au monde.

                  • [^] # Re: De l’utilité des exceptions.

                    Posté par (page perso) . Évalué à 2.

                    Le document sur le site de Stroustrup visait simplement à établir, de manière indiscutable je crois, ce pour quoi les exceptions C++ ont été conçues. Maintenant, faut-il ou non les utiliser, c'est un autre débat.

                    Je veux bien croire que, dans certains domaines, comme ceux des jeux vidéos, de l'embarqué, du développement de drivers, etc. il y ai des contraintes qui poussent à éviter les exceptions, mais ce qui est vrai pour ces domaines-ci ne l'est pas forcément pour les autres, les contraintes n'étant pas les mêmes…

                    Quand au lien Google, ma compréhension de l'anglais est certainement perfectible, mais il me semble quand même qu'ils écrivent (traduction très libre) :

                    • que les avantages des exceptions C++ l'emportent sur leurs inconvénients,
                    • qu'ils n'utilisent pas les exceptions C++ pour leur nouveaux projets parce qu'ils ont beaucoup de code ne s'appuyant pas sur les exceptions et que :
                      • mélanger code avec/code sans exceptions est problématiques,
                      • réécrire le code sans exceptions pour le rendre tolérant aux exceptions est trop coûteux,
                    • que s'ils recodaient tout from scratch, ils utiliseraient probablement les exceptions…

                    Donc, au final, ça m'a plutôt l'air d'un plaidoyer en faveur des exceptions C++

                    Freelance en ingénierie informatique.

                    • [^] # Re: De l’utilité des exceptions.

                      Posté par . Évalué à 3.

                      clang et LLVM n'utilisent pas les exceptions.

                    • [^] # Re: De l’utilité des exceptions.

                      Posté par . Évalué à 6.

                      Dans les "Contre" :

                      The availability of exceptions may encourage developers to throw them when they are not appropriate or recover from them when it's not safe to do so. For example, invalid user input should not cause exceptions to be thrown. We would need to make the style guide even longer to document these restrictions!

                      Ce paragraphe-là est spécialement pour vous :)

                  • [^] # Re: De l’utilité des exceptions.

                    Posté par (page perso) . Évalué à 2.

                    dont toute l'industrie des jeux vidéos

                    Je fais une nuance: toute la partie de l'industrie qui utilisent encore le C++ (surtout les gros studios qui font des jeux techniquement très ambitieux). Une grande partie de l'industrie est passée à des langages plus hauts niveaux, comme Unity+C# (j'ai quand même regardé rapidement et il semble bien que leur API parle d'exceptions, comme ici).

                    • [^] # Re: De l’utilité des exceptions.

                      Posté par . Évalué à 3.

                      Une grande partie de l'industrie est passée à des langages plus hauts niveaux, comme Unity+C# (j'ai quand même regardé rapidement et il semble bien que leur API parle d'exceptions, comme ici).

                      Deux choses. Premièrement, dire qu'une partie de l'industrie est passée à Unity+C#, c'est un peu trop fort je pense. Il y a probablement autant de jeux sous Linux que de jeux commercialement viable fait avec Unity. En revanche, si on parle en termes de projet à peine commencé, là oui Unity est devant tout le monde. Deuxièmement, d'aucuns diraient que le C# de Unity, c'est très différent du C#, et qu'à part cette Exception, il n'y a pas d'autres traces. Ce qui pourrait s'expliquer par le fait que le cœur de Unity est écrit en C++ et que le C# ne sert qu'à faire du scripting et que les deux systèmes d'exception ne doivent pas collaborer très bien.

                      • [^] # Re: De l’utilité des exceptions.

                        Posté par (page perso) . Évalué à 5.

                        Il y a probablement autant de jeux sous Linux que de jeux commercialement viable fait avec Unity.

                        Dans la mesure où Unity cible aussi Linux (enfin GNU/Linux/x-86(-64) et Android, ça ne reste que du proprio), et que donc on a des jeux Linux utilisant Unity (certains viables, d'autres non), et des jeux Unity ne ciblant pas Linux (certains viables, d'autres non), je ne comprends pas l’intérêt de cette comparaison (d'autant qu'elle sort d'un chapeau, mais passons).

                        Premièrement, dire qu'une partie de l'industrie est passée à Unity+C#, c'est un peu trop fort je pense

                        Au vue du nombre de très bon jeux de ces dernières années faits avec Unity, tu ne dirais pas qu'une certaines partie de l'industrie (quand bien même ça ne serait que 25%, sachant qu'il y d'autres frameworks populaires) l'utilise ?! C'est quoi, de la méthode Coué ?

                        http://unity3d.com/showcase/gallery

                        Firewatch, Monument valley, Kerbal space program, Cities Skyline, Pillars of Eternity, Ori and the blind forest, Grow home, Besiege, Never Alone, The long dark, Dungeon of the Endless. Voila ma petite sélection personnelle des jeux de ces dernières années avec des critiques excellentes. Je rêverais d'avoir ces jeux en libre (et je serais prêt à payer cher).

                        Oui la techno est sûrement utilisée pour plein de petits jeux pas finis, vue qu'elle est populaire ; mais ça me semble être plutôt un argument en sa faveur (parce que c'est comme si tu disais que gf n'est utilisé par aucun mauvais jeu professionnel, donc que ça prouve que c'est génial). D'autant qu'il y a pas mal de très bons jeux qui au final sont faits par des non-programmeurs (à la base) grâce à ce genre de framework qui ont abaissé la barrière d'entrée technique.

                • [^] # Re: De l’utilité des exceptions.

                  Posté par . Évalué à 4.

                  Je ne vois pas ce à quoi le terme dessus fait référence, et, quant au lien, je ne vois rien dans la biographie de l'auteur qui donne le moindre poids à ses écrits en général, et ces écrits en particulier.

                  Paf ! Argument d'autorité… Ok…

                  Bye !

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

              • [^] # Re: De l’utilité des exceptions.

                Posté par . Évalué à 7.

                J'aime beaucoup l'un des arguments :

                Exceptions are, in essence, sophisticated GOTO statements

                C'est le cas de toutes les structures de contrôle.

                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                • [^] # Re: De l’utilité des exceptions.

                  Posté par . Évalué à 2. Dernière modification le 25/07/16 à 20:46.

                  Ah.

                  Je vais utiliser des goto partout alors. Si c'est exactement pareil, j'vois pas l'intérêt de faire autrement…

                  "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

                  • [^] # Re: De l’utilité des exceptions.

                    Posté par . Évalué à 1. Dernière modification le 26/07/16 à 02:53.

                    Attention à ne pas confondre langage et implémentation ! Dans d'autres langages que le c++ (Ocaml p.e.), les exceptions ne sont pas uniquement faites pour être "exceptionnelles" et permettent effectivement de faire un saut à la longjmp sans dérouler la pile d'appel, c'est-à-dire sans pénalité au niveau des perfs. On peut donc effectivement les voir en une sorte de goto glorifié.

                    Bref, si les exceptions en c++ n'étaient pas aussi pénalisantes qu'elles ne le sont, il ne resterait vraisemblablement aucune (bonne) raison de ne pas les utiliser afin de "remonter plusieurs niveaux d'appel sans devoir encombrer chaque niveau de tests pour savoir s'il faut remonter directement au niveau supérieur". En ce sens, l'exemple tiré de boost plus haut me semble une parfaite illustration d'un bon usage des exceptions, au même titre que tout autre code de recherche récursive.

          • [^] # Re: De l’utilité des exceptions.

            Posté par . Évalué à 4.

            Utiliser une exception pour gérer un chemin normal de l'algorithme est une pratique à la salubrité très douteuse.

            Oui, ça s'appelle utiliser les exceptions pour contrôler le déroulement du programme, et c'est très mal (on ne sait plus si c'est une erreur attendue ou non, on génère des exceptions partout, le code est plus difficile à lire).

            "Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)

    • [^] # Re: Je n'aime pas la SFML

      Posté par . Évalué à 1.

      Pour ton point 1, je suis curieux : si je ne veux absolument pas d'exception, ou de C++11, encore moins de RAII ou rtti, puis-je linker avec avec une librairie qui utilise ces features?

      Puis-je linker avec du code C, compilé avec une vrai compilateur C?

      • [^] # Re: Je n'aime pas la SFML

        Posté par . Évalué à 3.

        Oui, tant que les méthodes et les exceptions ne «sortent» pas de la lib. C'est pour ça qu'un certain nombre de lib C++ utilisent une conception en sablier (hourglass) pour l'interface publique: c'est le meilleur moyen de permettre à un autre langage (entres autres) d'utiliser la lib sans devoir implémenter un wrapper.
        Pour la RTTI, je ne vois pas comment ça peut sortir, c'est un détail interne.

  • # Conteneurs

    Posté par . Évalué à 4.

    Pourquoi avoir implémenter tes propres conteneurs plutôt qu'utiliser ceux de la stl ou d'une bibliothèque comme eigen ? Tu a créé des ponts entre certains ?

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Conteneurs

      Posté par . Évalué à 4.

      Pourquoi avoir implémenter tes propres conteneurs plutôt qu'utiliser ceux de la stl ou d'une bibliothèque comme eigen ?

      Quels conteneurs ? Vector ? Ça n'a rien à voir avec std::vector. Et eigen est une très bonne bibliothèque mais un peu trop vaste pour un framework de jeu. Quite à avoir une dépendance externe, j'aurais choisi glm mais avoir le minimum de dépendance est aussi un avantage.

      Tu a créé des ponts entre certains ?

      J'ai fait tout ce que je pouvais pour que ça soit facile d'importer et d'exporter les données pour ce genre de bibliothèque. En particulier, prendre en paramètre un pointeur sur les données et fournir un pointeur sur les données.

      • [^] # Re: Conteneurs

        Posté par . Évalué à 3. Dernière modification le 19/07/16 à 14:54.

        Vector ? Ça n'a rien à voir avec std::vector

        Je ne sais pas lire rapidement les 1600 lignes de ta classe Vector elle fait quoi du coup ?

        En particulier, prendre en paramètre un pointeur sur les données et fournir un pointeur sur les données.

        Un pointeur ou un itérateur ?

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: Conteneurs

          Posté par . Évalué à 3.

          Je ne sais pas lire rapidement les 1600 lignes de ta classe Vector elle fait quoi du coup ?

          C'est un vecteur au sens mathématique, un truc avec des coordonnées (2D, 3D et 4D principalement). Tandis que le std::vector est un tableau dynamique.

          Un pointeur ou un itérateur ?

          Un pointeur. Plus pratique pour échanger avec du C. Et un pointeur est un itérateur (mais l'inverse est faux).

          • [^] # Re: Conteneurs

            Posté par . Évalué à 4.

            Un pointeur ou un itérateur ?

            Un pointeur. Plus pratique pour échanger avec du C. Et un pointeur est un itérateur (mais l'inverse est faux).

            Le pointeur donne un accès direct à ton implémentation. Si pour une raison ou une autre tu as besoin que tes données ne soient pas continues, tu aura des soucis.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

            • [^] # Re: Conteneurs

              Posté par . Évalué à 3.

              Pour les classe de type vecteur mathématique, l'usage est de fournir un pointeur sur les données qui doivent être contiguës. Par exemple: dans eigen ou dans glm. Outre le fait d'assurer l'interopérabilité avec les autres bibliothèques du même genre, ça permet aussi d'utiliser directement les fonctions OpenGL qui attendent des données contiguës.

          • [^] # Re: Conteneurs

            Posté par (page perso) . Évalué à 2.

            La classe vector s’appelle comme ça car elle correspond aussi à la définition d’un vecteur mathématique (y a-t-il d’autres types de vecteurs?), tant que le vecteur contient des nombres réels en tout cas.

            Écrit en Bépo selon l’orthographe de 1990

            • [^] # Re: Conteneurs

              Posté par (page perso) . Évalué à 4.

              y a-t-il d’autres types de vecteurs?

              En mathématiques un vecteur est un élément d'un Espace vectoriel. Il se trouve que très souvent on utilise les cas particuliers que sont ℝ² ("couple de nombres") ou ℝ³ ("triplet de nombres"), mais tu peux tout à fait construire des espaces vectoriels où les éléments sont de nature différente, comme des fonctions par exemple.

            • [^] # Re: Conteneurs

              Posté par . Évalué à 2.

              La classe vector s’appelle comme ça car elle correspond aussi à la définition d’un vecteur mathématique

              std::vector et le Vector de rewind contiennent les mêmes données: un tableau de nombres contigüe en mémoire, dans les deux cas ce sont bien les données d'un vecteur au sens mathématique, sauf que les méthodes portées par l'objet n'ont rien à voir:

              ici de quoi agrandir et rétrecir un conteneur de données (collection, container, choisis le vocabulaire que tu veux) ayant la complexité algorithmique d'un tableau dynamique:
              http://en.cppreference.com/w/cpp/container/vector

              ici les produits vectoriels, normes (euclidienne, Manhattan, etc.) et autres opérations qu'on attends pour manipuler des vecteurs au sens géométriques:
              https://github.com/GamedevFramework/gf/blob/master/include/gf/Vector.h

              vecteur mathématique (y a-t-il d’autres types de vecteurs?)

              bah rien qu'en maths on ne les manipule pas exactement pareil quand on fait de la géométrie ou de l'algèbre linéaire (même si on peut les identifier et passer de l'un à l'autre)
              et quand on programme, par delà la topologie des octets en mémoire, les opérations qu'on peut faire (méthodes et opérateurs) changent beaucoup et justifient assez largement, si je peux me permettre, de ne pas utiliser std::vector pour faire de la géométrie

              et, de façon plus déterminante encore, quand tu sors du monde du c++ pour aller dans le monde du rendering graphique, pouvoir directement caster ton template en float[] ou unsigned[] et savoir que son sizeof sera exactement le même a une certaine valeur, du coup tu ne veux pas d'un tableau dynamique mais bien d'un tableau statique

        • [^] # Re: Conteneurs

          Posté par . Évalué à 3.

          Je ne sais pas lire rapidement les 1600 lignes de ta classe Vector elle fait quoi du coup ?

          T'aurais dû c'est pas bien long, il suffit de ne lire que les noms des méthodes, extrait:

          T manhattanDistance(const Vector<T, N>& lhs, const Vector<T, N>& rhs) {
          T euclideanDistance(const Vector<T, N>& lhs, const Vector<T, N>& rhs) {
          T chebyshevDistance(const Vector<T, N>& lhs, const Vector<T, N>& rhs) {
          * @brief Component-wise multiplication and assignment
          Vector<T, N>& operator*=(Vector<T, N>& lhs, const Vector<U, N>& rhs) {
          * @brief Component-wise logical or operator
          Vector<bool, N> operator||(const Vector<bool, N>& lhs, const Vector<bool, N>& rhs) {

          Bref rien à voir avec ça:
          http://en.cppreference.com/w/cpp/container/vector

          (à part le nom)

  • # Pourquoi pas un scenegraph?

    Posté par (page perso) . Évalué à 3.

    gf semble être une API de dessin, c'est bien, mais moins utile qu'un scenegraph pour faire des jeux: par exemple on doit se taper le z ordering…

    http://devnewton.bci.im

    • [^] # Re: Pourquoi pas un scenegraph?

      Posté par . Évalué à 2.

      Oui et non.

      C'est un peu plus qu'une API de dessin. Mais après, ça n'impose pas vraiment de structure comme pourrait le faire un moteur de jeu. Ceci dit, il est tout à fait possible d'avoir des classes pour fournir un scenegraph, je crois qu'il y a tout ce qu'il faut. Ça se fera peut-être dans le futur.

      En attendant, il y a la classe gf::Entity qui permet d'ordonner les entités (via la classe gf::EntityContainer et donc d'avoir du z ordering. C'est basique mais ça marche bien (je l'utilise systématiquement dans mes jeux).

      • [^] # Re: Pourquoi pas un scenegraph?

        Posté par (page perso) . Évalué à 2.

        Autre chose, pour des jeux 2D pourquoi passer par OpenGl et pas par les fonctions de la SDL?

        http://devnewton.bci.im

        • [^] # Re: Pourquoi pas un scenegraph?

          Posté par . Évalué à 2.

          Autre chose, pour des jeux 2D pourquoi passer par OpenGl et pas par les fonctions de la SDL?

          Les fonctions 2D de la SDL sont assez limitées et sont des fonctions en C. Je pense offrir bien plus de fonctionnalités et en orienté objet. De plus, j'ai une meilleure maîtrise du code bas niveau OpenGL en passant directement par OpenGL et donc, je peux optimiser certaines opérations.

  • # Fork ?

    Posté par . Évalué à 6.

    Si j'ai bien compris, gf expose une API plus ou moins compatible avec SFML. D'autre part son implémentation repose sur du code SFML que tu as modernisé, notamment en passant à C++11, et en basant la partie OpenGL sur SDL.

    Par contre je ne comprends pas trop ta démarche pour arriver à ce résultat. Pourquoi ne pas avoir simplement forké SFML, pour y ajouter les bouts d'API dont tu avais besoin ? Cela ne t'aurait pas non plus empêché de moderniser le code.

    • [^] # Re: Fork ?

      Posté par . Évalué à 5.

      Par contre je ne comprends pas trop ta démarche pour arriver à ce résultat. Pourquoi ne pas avoir simplement forké SFML, pour y ajouter les bouts d'API dont tu avais besoin ? Cela ne t'aurait pas non plus empêché de moderniser le code.

      Parce qu'au départ, ce n'était pas clair que j'allais reprendre l'API de SFML. Mais au fur et à mesure, en y réfléchissant, je me suis dit que c'était une bonne solution. Mais du coup, il était trop tard, et j'ai préféré rester sur mon code plutôt que de repartir d'un fork.

      Note bien aussi que gf ne clone que l'API graphique de SFML. SFML contient aussi un module réseau et un module audio que je n'ai pas du tout repris. Ils sont assez indépendants et peuvent être utilisés conjointement avec gf. Sur ces deux modules, je n'aurais rien apporté du tout tandis que sur le module graphique, je pense avoir apporté suffisamment pour que ça soit considéré comme plus qu'un fork.

      • [^] # Re: Fork ?

        Posté par . Évalué à 1.

        En fait la question du fork aurait pu se poser quand tu t'es rendu compte que SFML était incomplet par rapport à tes besoins, avant que tu ne décides de laisser tomber SFML. Enfin, moi je me serai posé la question, après je ne sais pas du tout si ça aurait été une bonne solution.

        Ceci dit, je trouve ça vraiment cool que tu aies développé ton propre framework !

        • [^] # Re: Fork ?

          Posté par . Évalué à 6.

          En fait la question du fork aurait pu se poser quand tu t'es rendu compte que SFML était incomplet par rapport à tes besoins, avant que tu ne décides de laisser tomber SFML. Enfin, moi je me serai posé la question, après je ne sais pas du tout si ça aurait été une bonne solution.

          Disons que quand j'utilise une bibliothèque et qu'il me manque des choses, mon premier réflexe n'est pas de forker mais de compléter autant que je peux. Parce que maintenir quelques classes supplémentaires et maintenir un fork, ce n'est pas vraiment le même travail ni la même philosophie. Les classes supplémentaires, tous ceux qui utilisent la bibliothèque de base peuvent les utiliser. Tandis qu'un fork impose un choix à l'utilisateur.

  • # Thor, bindings et compilation

    Posté par . Évalué à 2. Dernière modification le 20/07/16 à 23:41.

    Bonsoir,

    Trois points totalement indépendants :

    Tu reproches à la SFML un certain conservatisme. Est-ce que passer par Thor ne permettrait pas de compléter la SFML sans devoir forker ou créer une bibliothèque alternative ?

    Sinon, une grosse force de la SFML, c'est la grande quantité de bindings pour d'autres langages. Tu sembles très porté sur le C++, mais as-tu tout de même ne serait-ce que regarder la possibilité de faire un port pour d'autres langages ? Parce qu'une bibliothèque, ce n'est pas que du code et une API, c'est aussi tout le reste autour, dont de la doc, des tutoriels (tu sembles l'avoir pris en compte, c'est bien (et assez rare)), des ports vers d'autres langages…

    Sinon (bis), j'ai essayé de compiler, étape assez indispensable. Le cmake n'a pas reconnu que j'utilisais une version trop vieille de boost (1.54, contre 1.55 mini demandé). Malheureusement, même avec toutes les dépendances listées installées dans les bonnes versions, j'ai un message d'erreur que je ne parviens pas à interpréter :

    [  7%] Building CXX object library/CMakeFiles/gf0.dir/Matrix.cc.o
    In file included from /home/etienne/Bin/bibliothèques/gf/library/Matrix.cc:21:0:
    /home/etienne/Bin/bibliothèques/gf/include/gf/Matrix.h:673:48: error: redeclaration ‘MatrixType gf::v1::identity() [with MatrixType = gf::v1::Matrix<float, 3ul, 3ul>]’ differs in ‘constexpr’
       GF_API constexpr Matrix3f identity<Matrix3f>() {
                                                    ^
    /home/etienne/Bin/bibliothèques/gf/include/gf/Matrix.h:652:14: error: from previous declaration ‘MatrixType gf::v1::identity() [with MatrixType = gf::v1::Matrix<float, 3ul, 3ul>]’
       MatrixType identity() {
                  ^
    library/CMakeFiles/gf0.dir/build.make:254: recipe for target 'library/CMakeFiles/gf0.dir/Matrix.cc.o' failed
    make[2]: *** [library/CMakeFiles/gf0.dir/Matrix.cc.o] Error 1
    CMakeFiles/Makefile2:117: recipe for target 'library/CMakeFiles/gf0.dir/all' failed
    make[1]: *** [library/CMakeFiles/gf0.dir/all] Error 2
    Makefile:127: recipe for target 'all' failed
    make: *** [all] Error 2
    [1]    25892 exit 2     make

    Quelqu'un a réussi à compiler ? Mon système est
    Linux pc-ordi 4.1.27-24-default #1 SMP PREEMPT Mon Jun 27 13:32:57 UTC 2016 (4ffbe0a) x86_64 x86_64 x86_64 GNU/Linux (opensuse 42).

    • [^] # Re: Thor, bindings et compilation

      Posté par . Évalué à 1.

      Il semble qu'il utilise gcc 5, et comme constexpr a évolué avec cette version, le problème vient sûrement de ta version de gcc.

    • [^] # Re: Thor, bindings et compilation

      Posté par . Évalué à 3.

      Tu utilises quelle version de GCC ?

      Il faut que je regarde de plus près parce que mon code n'est peut-être pas valide (c'est ce que semble dire le message d'erreur). Je vais essayer de corriger ça assez vite.

      • [^] # Re: Thor, bindings et compilation

        Posté par . Évalué à 2.

        Normalement, la 5.3.

        (Note : Ce n'est pas impossible que ce soit la 4.8, mais sauf erreur, j'ai mis la version récente par défaut, et cmake me disait bien avoir trouvé la 5.3)

        • [^] # Re: Thor, bindings et compilation

          Posté par . Évalué à 4.

          J'ai modifié mon code pour enlever cette spécialisation (je m'en servais pour initialiser RenderStates) et je l'ai remplacé par une autre fonction avec un nom différent pour garder le constexpr.

          J'ai pushé dans la branche develop si tu veux tester.

    • [^] # Re: Thor, bindings et compilation

      Posté par . Évalué à 4.

      Je réponds sur le début de ton message.

      Est-ce que passer par Thor ne permettrait pas de compléter la SFML sans devoir forker ou créer une bibliothèque alternative ?

      Thor, c'est un peu comme les classes que j'avais fait au début, ça vient en plus avec tous les avantages et inconvénients (une dépendance de plus). Mais si les classes de Thor étaient si bien, pourquoi ne pas les avoir intégrées dans SFML directement ? C'est ça que je ne comprends pas. En l'occurrence, dans Thor, il y a pas mal de fonctionnalités que j'ai aussi dans mes classes ou que j'ai mis dans gf. C'est donc qu'il y a bien un besoin et donc, ça devrait être directement dans SFML. Et du coup, c'est directement dans gf.

      Tu sembles très porté sur le C++, mais as-tu tout de même ne serait-ce que regarder la possibilité de faire un port pour d'autres langages ?

      Pour les bindings, il faut déjà avoir une API relativement stable. Or, pour l'instant, rien n'est stable, tout peut bouger. Après la version 1.0, on verra.

  • # et vulkan

    Posté par . Évalué à -1.

    là-dedans ?

    • [^] # Re: et vulkan

      Posté par . Évalué à 3.

      Vulkan vient de sortir, il est disponible à peu près nulle part. Dans les arguments pour le choix de OpenGL ES 2, j'ai précisé qu'il était suffisamment vieux pour être présent quasiment partout. C'est un critère important.

      • [^] # Re: et vulkan

        Posté par . Évalué à 1.

        Tu serais intéressé pour venir parler de tout ça au Capitole du Libre :)

        • [^] # Re: et vulkan

          Posté par . Évalué à 2.

          Houla, il faut que je vois si c'est techniquement possible. J'habite un peu à l'autre bout de la France :)

  • # Commentaire supprimé

    Posté par . Évalué à -1. Dernière modification le 28/07/16 à 14:46.

    Ce commentaire a été supprimé par l'équipe de modération.

    • [^] # spam & escroquerie

      Posté par . Évalué à 1. Dernière modification le 28/07/16 à 14:52.

      Supprimer ses commentaires n'est pas suffisant, Quelqu'un sait-il comment demander a google (qui semble détenir blogspot.com|.be) de supprimer son blog pour escroquerie?

      Donation Bitcoin : 1N8QGrhJGWdZNQNSspm3rSGjtXaXv9Ngat

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.