IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

Comment ne pas avoir accès au méthode d'un include dans un include ?


Sujet :

C++

  1. #1
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut Comment ne pas avoir accès au méthode d'un include dans un include ?
    Mon problème est simple :

    J'ai 3 classes static A, B et C.

    A include B qui include C et j'aimerais que dans le code de A je ne puisse pas appeler C::foo().

    Comment faire ?
    Est-ce que l'utilisation de namespace est une bonne solution ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    - 3 classes static ?
    - si A inclue B qui inclue C, A inclue C
    - si A inclue C, A a accès à C
    - les namespace sont là pour délimiter/ranger le code

    Ton truc ressemble plus à un foutoir d'architecture.
    - pourquoi A inclue B ?
    - pourquoi B inclue C ?

    - si A manipule un B, il n'en a rien à faire de C
    - que B manipule un C en interne, n'intéresse pas A
    - que fait C::foo public s'il doit pas être appelé ?
    - pourquoi ne pas simplement éviter d'appeler C::foo ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut
    Bah C::foo() est en public pour que B puisse y accéder.

    En gros C c'est ma classe Database, A c'est ma classe Algorithm et B ma class Database_manager.

    Avant ma classe Algothim utilisait directement ma Database::write() mais ce n'est pas bon et c'est pour cela que je passe par ma classe Database_manager pour évite les appels à la base de données n'importe comment.
    Mais là, vu que Database_manager include Database, je peux toujours directement appeler les fonctions de Database dans la classe Algothim et je voudrais que cela ne soit pas possible.

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Bah C::foo() est en public pour que B puisse y accéder.
    Toi, t'as pas vécu les années Dorothée et la "Force de l'amitié".

    Déjà, si tout n'était pas statique, t'aurais beaucoup moins problèmes.

    Si C n'est pas "statique", et bin A pourrait se brosser pour accéder au membre "C" de la classe "B".

    "Database_manager", c'est un nom pourri, ça veut rien dire.
    Utilisez des noms corrects, ça simplifiera grandement la maintenance.

    Si vous faites une "vraie" DAL, vous faites ça dans une librairie à part, donc avec un seul .h public qui ne déclare que les choses utilisables par le code client de la librairie.

    Le problème n'est pas technique, mais c'est un problème de conception/architecture.

  5. #5
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut
    Citation Envoyé par bacelar
    Si vous faites une "vraie" DAL,
    Tu veux pas plutôt dire DLL ? Et puis de toute façon je vais pas créer plusieurs libraire alors qu'il s'agit du même projet avec du code non-réutilisable.

    Citation Envoyé par bacelar
    Déjà, si tout n'était pas statique, t'aurais beaucoup moins problèmes.
    J'ai pas besoin de créer d'objet donc pourquoi ne pas même en static ? Je vais pas mettre des singletons partout ! Et puis un singleton ne règlerais pas le problème car je pourrais quand même faire C::instance()->foo()

    Citation Envoyé par bacelar
    "Database_manager", c'est un nom pourri, ça veut rien dire.
    Il s'agit de ma classe qui s'occupe d'effectuer les requête SQL grâce à la classe Database et de retourné directement les variables ou objets au reste du code. Je savais pas comment la nommé.
    Mais partout ou j'ai accès à Database_manager j'ai aussi accès à Database et c'est pas bon.

    Bah, je vais créer un namespace private_database que je n'appellerais que dans database_manager et ça sera très bien comme ça

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    https://en.wikipedia.org/wiki/Data_access_layer
    Citation Envoyé par Matthieu76 Voir le message
    J'ai pas besoin de créer d'objet donc pourquoi ne pas même en static ? Je vais pas mettre des singletons partout ! Et puis un singleton ne règlerais pas le problème car je pourrais quand même faire C::instance()->foo()


    Il s'agit de ma classe qui s'occupe d'effectuer les requête SQL grâce à la classe Database et de retourné directement les variables ou objets au reste du code. Je savais pas comment la nommé.
    Mais partout ou j'ai accès à Database_manager j'ai aussi accès à Database et c'est pas bon.

    Bah, je vais créer un namespace private_database que je n'appellerais que dans database_manager et ça sera très bien comme ça
    Et tu pourras toujours faire private_database::C::foo() donc déplacer le pb te suffit ?

    Pas besoin de créer un objet database ? Quid de la connection ? T'en crées une nouvelle pour chaque requête ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Citation Envoyé par Matthieu76 Voir le message
    Tu veux pas plutôt dire DLL ?
    Pourquoi pas faire une DAL dans une DLL, cela renforcera le réutilibilité, la facilité d'évolution et de testabilité.
    Vous pouvez aussi en faire une simple LIB pour la réutilibilité.

    Citation Envoyé par Matthieu76 Voir le message
    Et puis de toute façon je vais pas créer plusieurs libraire alors qu'il s'agit du même projet avec du code non-réutilisable.
    Avec cette attitude, vous ne réutiliserez jamais rien.
    Si vous n'êtes pas capable de le faire dans des cas simples, n'essayez même pas dans des "vrais cas".

    Vous faites une usine à gaz (des static de classe dans tout les coins) pour faire "comme les vrais" mais quand on dit que c'est pas comme ça, vous dite, "je vais pas me prendre la tête, je garde mon usine à gaz", c'est débile, supprimez directement cette usine à gaz.

    Citation Envoyé par Matthieu76 Voir le message
    J'ai pas besoin de créer d'objet donc pourquoi ne pas même en static ?
    Pas besoin de faire des statiques/globales déguisées, quand un simple champ dans une classe fait largement l'affaire.

    Citation Envoyé par Matthieu76 Voir le message
    Je vais pas mettre des singletons partout ! Et puis un singleton ne règlerais pas le problème car je pourrais quand même faire C::instance()->foo()
    Les singletons, c'est pas pour faire des globales déguisées à la con, si pas besoin, on n'utilise pas. Et on en a rarement "juste besoin", c'est toute une architecture (IoC, mocking, etc...) qui peuvent ÉVENTUELLEMENT en avoir besoin.
    C'est un argumentaire "homme de paille", faudrait pas nous prendre pour des perdreaux de l'année.

    Citation Envoyé par Matthieu76 Voir le message
    Il s'agit de ma classe qui s'occupe d'effectuer les requête SQL grâce à la classe Database et de retourné directement les variables ou objets au reste du code.
    C'est pas clair, et ça n'a rien à voir avec une "gestion" de base de données.
    Quand une classe n'a pas de rôle PRÉCIS, elle dégage.

    Citation Envoyé par Matthieu76 Voir le message
    Je savais pas comment la nommé.
    Preuve que vous n'avez pas assez réfléchi votre conception.

    Citation Envoyé par Matthieu76 Voir le message
    Mais partout ou j'ai accès à Database_manager j'ai aussi accès à Database et c'est pas bon.
    Vous avez accès à "Database" parce que "Database" est publiquement déclarer dans un .h, c'est pas arrivé par hasard, bordel.
    Si vous n'en voulez pas, comment se fait-il que vous avez sciemment foutu cette classe dans un .h qui est là pour ne donner que le strict nécessaire.
    C'est ubuesque !!!

    Citation Envoyé par Matthieu76 Voir le message
    Bah, je vais créer un namespace private_database que je n'appellerais que dans database_manager et ça sera très bien comme ça
    C'est bien, les namespaces sont là pour structurer le code, mais faudrait quand même réfléchir 2 minutes à l'ensemble des namespaces, à leur fonction, et donc à leur noms.
    Parce que "private_database", comme nom, c'est tout pourri.

    Si vos classes ne servent qu'à rendre votre code imbitable, SUPPRIMEZ-LES !!!

  8. #8
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut
    Citation Envoyé par bacelar
    Vous avez accès à "Database" parce que "Database" est publiquement déclarer dans un .h, c'est pas arrivé par hasard, bordel.
    Bah je suis bien obligé de déclarer ma classe en public dans database.h sinon je ne peux pas l'utiliser dans database_magager.h ?

    Un exemple sera plus parlant :

    database.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class Database
    {
        private :
            //...
     
        public :
            static string execute_request_sql(string request);
            //...
    }
    database_manager.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #inculde <database.h>
    public class Database_manager
    {
        private :
            //...
     
        public :
            static obj get_obj(string request)
            {
                 return  Obj.string_to_obj(database::execute_request_sql("SELECT * FROM obj"));
            }
        //...
    }

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    - Si la classe n'a que des méthodes static, autant en faire un namespace
    - Si la classe n'a pas d'instance non dynamique, l'inclure dans l'en-tête ne sert à rien
    - Implémenter dans le .h c'est... moyen

    On tourne en rond sur ton architecture bancale, mais tant que tu voudras pas l'entendre et restera caché derrière, ça mène à rien.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut
    Citation Envoyé par Bousk
    Si la classe n'a que des méthodes static, autant en faire un namespace
    C'est pas faux, même si d'un point de vu POO c'est pas mieux de faire une classe static ?


    Citation Envoyé par Bousk
    Si la classe n'a pas d'instance non dynamique, l'inclure dans l'en-tête ne sert à rien
    Hein ? Si je mets pas #inculde <database.h> j'aurais pas accès à ma class Database. Désolé je comprends pas ce que tu dis


    Citation Envoyé par Bousk
    Implémenter dans le .h c'est... moyen
    Oui, non pardon en faite c'est bien implémenter dans mon .cpp, juste j'avais la flemme de tout écrire.


    Citation Envoyé par Bousk
    On tourne en rond sur ton architecture bancale, mais tant que tu voudras pas l'entendre et restera caché derrière, ça mène à rien.
    Donc du coup, je fais quoi ? J'organise mon code comment ?

  11. #11
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    C'est pas faux, même si d'un point de vu POO c'est pas mieux de faire une classe static ?
    Surement pas.
    On utilise l'outil qui correspond à la situation.
    Si vous avez regroupé un capharnaüm de fonctions qui n'ont pas de lien entre elles, c'est très moyen, voir complètement dégueu.
    Mais un namespace est moins contraignant qu'une classe statique.
    Et si c'est un capharnaüm, c'est pas une classe, point barre.

    Faites un peu de conception, nom d'un chien.
    Votre "Database" mérite largement une classe, et pas une classe statique du tout.
    Jusqu'à preuve du contraire, votre "database_magager" ne sert à rien.
    Utilisez CORRECTEMENT une classe avant d'en ajouter une juste pour faire "beau".
    Donc DÉGAGEZ "database_magager".

    Hein ? Si je mets pas #inculde <database.h> j'aurais pas accès à ma class Database. Désolé je comprends pas ce que tu dis
    Vous n'aurez pas accès à Database DANS le fichier d'en-tête, c'est bien, c'est ce qu'on veut, parce que l'implémentation est dans le fichier .cpp.
    Si vous utilisez un champ de type référence sur "Database" ou pointeur sur "Database", ou que vous en passez un dans la signature des méthodes, une simple "forward definition" de la classe suffit.
    Mais comme je l'ai dit, DÉGAGEZ "database_magager" à la con.

    Si vous ne voulez pas que "Algothim" puisse appeler "Database::write()", bin, vous déclarez la méthode "Database::write()" comme privée, c'est tout, basta.

    Oui, non pardon en faite c'est bien implémenter dans mon .cpp, juste j'avais la flemme de tout écrire.
    Vous devriez utiliser la même flemme pour ne pas inventer des classes superfétatoires à la noix.
    Et mettre le code dans un .h, c'est pas du tout la même chose que le mettre dans le .cpp.

    Donc du coup, je fais quoi ? J'organise mon code comment ?
    Simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
     
    void Algothim::methodeA2Balles()
    {
    ...
        Database db{tousPleinDeParametresALaCon},
     
        auto resultat = db.laMethodePublicQuiFaitleJob(parametreALaCon1,parametreALaCon2);
     
    ...
    /* on fait mumuse avec resultat */
    ...
    }
     
     
     
     
    -----------
    Dans Database.h
    -----------
     
    class Database
    {
        write();
    public :
       Database(TypeTousPleinDeParametresALaCon tousPleinDeParametresALaCon);
     
       TypeValeurRetourDeLaMethodePublicQuiFaitleJob laMethodePublicQuiFaitleJob(TypeParametreALaCon1 parametreALaCon1, TypeParametreALaCon2 parametreALaCon2);
    }

  12. #12
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut C'est mieux comme ça ?
    D'acoord, merci je comprends mieux. En gros, je dois mettre mon #include dans le .cpp plutôt que dans le .h pour ne pas y avoir accès depuis d'autre fichier qui include mon .h. Merci, c'est la répose que j'attendait.

    Pour ce qui est de mon architecture, j'y est réfléchie et ce que je vais faire c'est garder ma classe database tel quel (en enlevant static) et la mettre dans une librairie car elle peut être réutilisé pour tout mes futures projet C++ et je fais faire une nouvel class comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public DatabaseController : private Database
    {
        public :
            TypeValeurRetourDeLaMethodePublicQuiFaitleJob laMethodePublicQuiFaitleJob(TypeParametreALaCon1 parametreALaCon1, TypeParametreALaCon2 parametreALaCon2);
            //...
    }
    Et ma méthode write je la passe en protected.

    Je pense que comme ça c'est vraiment beaucoup mieux.

    Merci à tous

  13. #13
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    En gros, je dois mettre mon #include dans le .cpp plutôt que dans le .h pour ne pas y avoir accès depuis d'autre fichier qui include mon .h.
    Oui.
    Mais attention à bien mettre les includes nécessaires dans le .h pour que d'autres cpp qui UTILISENT la classe puissent s'en servir s'en être obligé d'inclure d'autres .h avant celui de la classe.

    je vais faire c'est garder ma classe database tel quel (en enlevant static)
    Ok

    et la mettre dans une librairie car elle peut être réutilisé pour tout mes futures projet C++
    C'est très bien.

    et je fais faire une nouvel class comme ça :
    Ne multipliez pas les classes inutilement.
    C'est quoi la valeur ajoutée de la classe "DatabaseController" ??? (Controller / Manager, c'est tout aussi flou).

    Et ma méthode write je la passe en protected.
    Si une méthode n'a pas été conçu pour être "overridable", on la met en privée, pas en protected.

    Je pense que comme ça c'est vraiment beaucoup mieux.
    Oui

  14. #14
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut re
    Citation Envoyé par bacelar
    C'est quoi la valeur ajoutée de la classe "DatabaseController" ??? (Controller / Manager, c'est tout aussi flou).
    Bah dans Database il n'y a que des méthodes indépendantes au projet (write(), read(), reset(), etc...) et dans DatabaseController il y des méthodes dependantes au projet tel que :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    string DatabaseController::GetNameOfObj(int id)
    {
        return this.read("SELECT name FROM obj WHERE id =" + to_string(id));[0] // la method read provient de Database
    }
    La fonction read me return une liste de string qui est le résultat de ma requête SQL.

  15. #15
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Erreur patente de conception.

    "write(), read(), reset()" est une API générique qui est bonne pour planquer des détails de conception interne des composants.
    Là, vous vous en servez juste pour obscurcir inutilement l'API de la classe DataBase.
    Quitte à savoir qu'il y a un mécanisme de "CRUD" (CREATE READ UPDATE DELETE) autant que cela soit explicite dans l'API de DataBase.

    J'ai l'impression que vous êtes dans la stratégie de "je bricole un truc sans trop réfléchir et on fait une conception autour de ce bricolage", mais c'est l'inverse qu'il faut faire.
    Vous faites une conception qui facilite l'utilisation des composants par leur code client, puis vous bricolez une implémentation de l'API conçu AVANT.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
     
     
    class Obj
    {
        constexpr std::string tablaName = "obj";
        constexpr std::string colonnesStr = "id, name";
     
        int id;
        std::string name;
     
        Obj(int id_, std::string name_):id(id_),name(name_){}
     
    public :
        static std::list<Obj> getObjs(IDataBase database, std::map<std::string,std::string> criteresAlpha, std::map<std::string,int> criteresNumerique);
     
        std::string GetName();
    }
     
    string Obj::GetName()
    {
        return name;
    }
     
    std::list<Obj> Obj::getObjs(IDataBase database, std::map<std::string,std::string> criteresAlpha, std::map<std::string,int> criteresNumerique)
    {
        std::list<Obj> result;
        auto res = database.select(colonnesStr, tablaName, criteresAlpha, criteresNumerique);
        for(auto& line : res)
        {
            result.add(Obj(StringToInt(line[0]),line[1]);
        }
        return result;
    }
     
    std::vector<std::vector<std::string>> DataBase::select(std::string colonnes, std::string tableName,  std::map<std::string,std::string> criteresAlpha, std::map<std::string,int> criteresNumerique)
    {
    /*construction de la clause WHERE avec criteresAlpha et criteresNumerique*/
        std::string request = "SELECT " +colonnes + " FROM " + tableName " WHERE " + clauseWhereCalculer + (clauseWhereCalculer=="" ? " AND" ! "") +" (1=1)" )
    ...
        return result;
    }
    Fait à l'arrache, avec encore des dépendances à une source de données tabulaire dans la classe "Obj" de votre projet "client" mais on n'est déjà plus obligé d'avoir une source SQL pour implémenter IDataBase.

    C'est quoi la valeur ajoutée de la classe "DatabaseController" ??? (Controller / Manager, c'est tout aussi flou). (BIS)

    De plus, c'est le genre de truc qu'on laisse à un ORM pour pondre ce type de code au kilomètre.

  16. #16
    Membre très actif Avatar de Matthieu76
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Mars 2013
    Messages
    568
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2013
    Messages : 568
    Par défaut
    Ok, je sais que je fais de la merde mais c'est plus simple pour moi si toutes les requêtes SQL sont dans le même fichier de code car cela me permet de pourvoir charger en rame toutes les requêtes puis de ensuite pouvoir juste appeler le résultat sans avoir à effectuer la requête qui prend trop de temps.

    Dans mon cas "DataBaseManager" (nom encore à définir) va appeler beaucoup de requêtes SQL à l'initialisation et comme ça quand je demande une valeur de ma base je la prends directement dans "DataBaseManager" sans appel à la base ce qui accélère beaucoup mon temps de calcul. En gros, database manager est un buffer du résultat de toutes mes requêtes SQL.

    Je sais que je devrais faire mes appels à la database à l'instantiation de mes objets en passant une instance de Database dans le constructeur mais pour moi c'est moins lisible et puis ça me force à refaire tout mon code et c'est chiant, j'ai plus de 5000 lignes de code, je peux pas tout refaire à la main.


    Citation Envoyé par bacelar
    je bricole un truc sans trop réfléchir et on fait une conception autour de ce bricolage
    Évidemment que c'est comme ça, à la base mon projet devait prends moins d'1 an à développer et là j'en suis quasiment à 3 et il n'est toujours pas fini car je rajoute toujours de nouvelles features. Au début il n'y avait même pas de database, les éléments se rajoute au fur et à mesure du projet.

    Et j'espère que tu comprends que je ne peux pas refactorisé la totalité de mon code à chaque fois que je rajoute quelque chose, c'est pour ça que mon projet est comme ça. Je sais que j'aurais dû réfléchir à l'architecture du projet depuis le début mais au début il n'y avait que 3-4 classes et c'était bien puis j'ai rajouté le multi-threading, puis j'ai eu plusieurs fenêtre, j'ai ajouté la base de données puis j'ai passé du code en librairie puis j'ai commencé à recoder mes algo en GPU, etc...

    Du coup je ne vais pas passer 6 mois à tout recorder mais je veux juste un peu mieux ségréguer mon code et séparer la partie affichage de la partie environnement (database et récupération de données diverse) de la partie algorithmique.

  17. #17
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 489
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 489
    Par défaut
    Vous avez la tête dans le guidon et vous allez vous prendre le mur, tôt ou tard.

    Ne soyez pas victime de biais cognitif "aversion à la perte".
    Si votre code est difficilement maintenable et qu'une autre approche réduit drastiquement la charge de travail et simplifie la maintenance, VIREZ LE VIEUX CODE, il a fait son temps.
    Sinon, il va être votre boulet, c'est de la dette technique.

    Si votre code n'est pas trop dégueulasse, le passage d'une approche à une autre sera de simple copier/coller, vous un petit programme de parsing/génération de code.

    Il faut aussi éviter l'approche "big bang" de tout refaire, mais vous pouvez introduire rapidement la nouvelle approche sur de l'extension de l'application, vous avez un avantage direct.

    Ne vous enfermez pas dans une mauvaise solution.

    Si vous voulez continuez avec votre bricolage sur ce que vous avez déjà, faites, mais mettez un truc carré pour le nouveaux code.

    La mise en place d'un ORM ou d'une approche comme la mienne, c'est quelques dizaines de minutes. N'hypothèques pas la maintenance du nouveau code pour si peu.

    Ok, je sais que je fais de la merde
    On ne nait pas avec la science infuse.
    L'erreur est humaine, persévérer est diabolique.

    Dans mon cas "DataBaseManager" (nom encore à définir) va appeler beaucoup de requêtes SQL à l'initialisation et comme ça quand je demande une valeur de ma base je la prends directement dans "DataBaseManager" sans appel à la base ce qui accélère beaucoup mon temps de calcul. En gros, database manager est un buffer du résultat de toutes mes requêtes SQL.
    Ouais, bon, c'est un Cache, pas un "Manager".
    Et comme c'est juste un cache, il n'a pas à s'emmerder avec la base de données.
    Vous utilisez une classe générique de Cache et basta.

    Avec MON implémentation, le cache, c'est trivial :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    MonCache::MonCache(IDataBase database)
    {
        ObjRef = Obj::getObjs(database)
        Obj2Ref = Obj2::getObj2s(database)
        Obj3Ref = Obj3::getObj3s(database)
    }
    {
    Avec ObjRef , Obj2Ref et Obj3Ref des champs de MonCache de type std::list<Obj> std::list<Obj2> et std::list<Obj3>.

    et juste changer un peu la signature de "select" de DataBase :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DataBase::select(std::string colonnes, std::string tableName,  std::map<std::string,std::string> criteresAlpha = std::map<std::string,std::string>(), std::map<std::string,int> criteresNumerique = td::map<std::string,int>())
    La synthèse des requêtes SQL n'est que dans DataBase, la gestion des colonnes de la table n'est que dans la classe correspondante à cette table.
    Simple, facile, univoque et très facile à générer AUTOMATIQUEMENT.

    , j'ai plus de 5000 lignes de code, je peux pas tout refaire à la main.
    5000 lignes, c'est ridiculement petit !!!
    Vous avez largement assez peu de code pour faire un "big bang" !!!

    je peux pas tout refaire à la main.
    Tout le code "à la con" est facilement automatiquement générable. En les ORM ont des outils pour le faire pour vous.

    , les éléments se rajoute au fur et à mesure du projet.
    Il ne faut pas accumuler la dette technique et faire régulièrement du refactoring, donc souvent supprimer de vieux code.

    Et j'espère que tu comprends que je ne peux pas refactorisé la totalité de mon code à chaque fois
    Pas la peine si la conception est modulaire, de base.
    Si elle ne l'ai pas, il faut y tendre assez rapidement pour ne pas galérer de plus en plus.

    Mettez les choses à plat, et avec 5000 lignes, franchement, c'est "big bang" directe, c'est peanuts.

    Mais vous pouvez toujours faire un truc carré pour les nouvelles features et modifier à minima le code existant.
    Mais pas l'inverse, ne faites pas un truc tout tordu juste pour ne pas modifier quelques lignes dans du vieux code tout moisi.

    La première architecture n'est jamais bonne, les attentes du client change, etc...
    Mais il faut prendre le temps de refactorer le code quand c'est nécessaire.
    Il faut que l'architecture soit simple pour quel soient facilement refactorable.
    Vous devez faire simple, et vos classes "Manager" et autres variables globales planqués en champ statiques sont des cordes pour vous pendre.

    Du coup je ne vais pas passer 6 mois à tout recorder
    Non, quelques heures pour voir où couper le vieux code pour le remplacer par du code qui sera majoritairement auto-générable en quelques secondes par un ORM ou une moulinette de quelques lignes.

    mais je veux juste un peu mieux ségréguer mon code et séparer la partie affichage de la partie environnement (database et récupération de données diverse) de la partie algorithmique.
    C'est de très bon objectifs, mais faut le faire correctement, donc plus de manager à la con, de variables globales toutes moisies dans des champs statiques, etc...

    Le code des classes que je vous propose est tellement bête qu'on peut le faire en ayant la tête dans le cul. Preuve que c'est un bon code.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Instal comment ne pas avoir "éditeur inconnu" ?
    Par Ehjoe dans le forum VB.NET
    Réponses: 2
    Dernier message: 27/11/2009, 11h38
  2. [XL-2000] Comment ne pas avoir de bug en ne voulant pas enregistrer un fichier déjà existant
    Par Avinetor dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 05/06/2009, 17h40
  3. Réponses: 2
    Dernier message: 14/11/2008, 18h31
  4. Réponses: 2
    Dernier message: 25/04/2008, 10h43
  5. Réponses: 8
    Dernier message: 27/10/2006, 14h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo