Partage
  • Partager sur Facebook
  • Partager sur Twitter

lister les wifis disponibles et s'y connecter

via l'api wlan en c++

    25 janvier 2018 à 22:29:05

    Très bien, merci beaucoup !

    Je vous tiens au courant de mes avancées !

    Je vais pour l'instant faire la classe mère des exception et une exception interfaceNotFound, j'en ferais d'autres si nécessaire (et ca sera surement nécessaire)

    Ensuite je m'attaquerais à l'utilisation des primitives Win3é (je vous aurais envoyé la dernière version de mon code).

    Aussi, comme je ne gère pas l'exception, je ne dois pas mettre de bloc try, c'est le développeur qui s'en chargera ?

    -
    Edité par raphaeldesaintalbin 25 janvier 2018 à 23:37:09

    • Partager sur Facebook
    • Partager sur Twitter
    "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
      26 janvier 2018 à 10:28:12

      >c'est le développeur qui s'en chargera ?

      Oui.

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        31 janvier 2018 à 0:28:23

        Bonjour !

        Je me demandais, lorsque j'ai récupéré les infos sur les différents réseaux à proximité grâce à WlanEnumInterface(), j'en fait quoi ?

        Je peux pas les afficher sinon on perd le choix de l'affichage, mais il faut bien que l'utilisateur choisisse un réseau en fonction des infos qu'on lui donne dessus...

        Bien à vous,

        Raphael

        • Partager sur Facebook
        • Partager sur Twitter
        "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
          31 janvier 2018 à 12:20:08

          C'est la conception de l'API que va fournir votre librairie/ensemble de classe.

          Vous pouvez, par exemple, fournir une méthode (statique ou pas, c'est fonction de votre conception des classes) qui retourne un ensemble de structure ( un std::vector<MaStructure>) par exemple, avec un champs "nom" et un autre champ "SSID" dans "MaStructure".

          Le code utilisateur pourra faire ce qu'il vaut avec (l'afficher dans une belle fenêtre, etc...).

          Après, il pourra (le code utilisateur) ensuite interagir avec votre librairie via la valeur du "SSID".

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            31 janvier 2018 à 13:17:55

            En effet cette fonction existe mais elle est utilisée directement dans le constructeur de Wlan...

            Il faudrait donc que le constructeur de Wlan soit beaucoup plus vide, que le code client l'appelle, appelle la fonction Interface::creerInterface, affiche les infos puis appelle une fonction sur Wlan, comme Wlan::initialiser() ou le code client passera le SSID, le mot de passe et les interfaces  qu'il a récupéré.

            Ca irait comme solution ?

            • Partager sur Facebook
            • Partager sur Twitter
            "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
              31 janvier 2018 à 14:34:58

              >Interface::creerInterface,

              Comme elle crée pas d'objet "Interface", ce nom est très moyen.

              C'est très important de bien nommer les choses.

              >Wlan::initialiser()

              Ça, c'est un chiffon rouge pour tout programmer OO.

              Sauf utilisation de Design Pattern de création d'objet complexe, un objet doit être totalement opérationnel même juste après l'appel du constructeur.

              Un Wlan est déjà associé à un "SSID", non ?

              Si c'est le cas, il me parait plus simple d'avoir une méthode statique qui renvoie une liste de "NetworkInfo" (le "MaStructure" de mon post précédent), "static std::vector<NetworkInfo> Wlan::GetNetworkInfos()" par exemple.

              Et le constructeur de Wlan pourra prendre un NetworkInfo comme paramètre en entré en plus du login/password, par exemple.

              • Partager sur Facebook
              • Partager sur Twitter
              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                31 janvier 2018 à 16:42:33

                >Comme elle crée pas d'objet "Interface", ce nom est très moyen.

                AHHH !

                J'en ai marre de ces confusions avec un S ou pas !

                c'est Interface::creerInterfaces, qui fait appel au constructeur privé et qui renvoie un tableau de std::unique_ptr sur des "Interface"...

                >Un Wlan est déjà associé à un "SSID", non ?

                Non mais ca va changer !

                > Si c'est le cas, il me parait plus simple d'avoir une méthode statique qui renvoie une liste de "NetworkInfo" (le "MaStructure" de mon post précédent), "static std::vector<NetworkInfo> Wlan::GetNetworkInfos()" par exemple.

                Et le constructeur de Wlan pourra prendre un NetworkInfo comme paramètre en entré en plus du login/password, par exemple.

                Là, vous avez toute mon admiration ;), toujours la bonne solution aux problèmes... Chapeau !

                Merci, je m'y remet de ce pas !

                • Partager sur Facebook
                • Partager sur Twitter
                "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                  31 janvier 2018 à 18:07:54

                  >c'est Interface::creerInterfaces, qui fait appel au constructeur privé

                  Ce n'était pas un problème de "S" ou pas.

                  C'est juste que pour l'utilisateur, il ne cherche pas à créer des interfaces mais à avoir une liste d'information pour l'afficher à l'utilisateur.

                  Moins on rend publique de classe au code utilisateur, plus, en tant que développeur de la librairie, on n'a la possibilité de modifier l'implémentation, sans casser le code utilisateur.

                  Donc, ne rendez public la classe "Interface" que si elle présente des fonctionnalités utiles au code utilisateur.

                  Si c'est juste pour stocker un nom et un SSID, autant utiliser une structure avec ces seules informations (un DTO dans le jargon). Cela découplera le code utilisateur de la classe "Interface".

                  Si vous voulez vraiment donner la liste des objets "Interface", nommé la méthode "... Wlan::GetInterfaces()" (méthode membre d'un objet Wlan) ou "static ... Interface::GetInterfaces()" (méthode statique de la classe Interface).

                  >Non mais ca va changer !

                  Ok, donc Wlan sera un objet (singleton ?) qui servira de portail à la librairie ?

                  Alors il y aura un objet Wlan et des objets "Network" qui seront associés chacun à un SSID, non ?

                  Concevez l'API de votre classe pour le code utilisateur, puis implémenter là.

                  Vous avez déjà un exemple de code utilisateur utilisant votre API pour un cas d'usage "bateau" ?

                  (Il n'a pas besoin d'être compilable)

                  Si oui, montrez le nous pour voir les éventuels défauts de conception.

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                    1 février 2018 à 0:21:10

                    Comme code client je pense que ca va se passer comme ça :

                    infos = Wlan::recupererInterfaces();
                    //l'utilisateur les affiche en fonction de si il est en console, avec Qt etc...
                    std::cout << "sélectionnez le reseau..." << std::endl;
                    std::string SSID;
                    std::cin >> SSID;
                    std::cout << "sélectionnez le mot de passe..." << std::endl;
                    std::string password;
                    std::cin >> password; //ici on imagine que tout se passe en console
                    Wlan wlan(SSID, password); //ici la connexion (récupération des interfaces, création des profils etc...).
                    //il devra aussi avoir une gestion des exceptions

                    Je pense que on est obligé de fournir les infos à l'utilisateur et qu'il se charge de les afficher lui même en fonction de son type de projet, je ne vois pas d'autres solutions...

                    La fonction statique Wlan::recupererInterfaces doit être un bête alias de Interface::créerInterfaces mais comme on cache cette classe à l'utilisateur, on le met dans Wlan.

                    >Si c'est juste pour stocker un nom et un SSID, autant utiliser une structure avec ces seules informations (un DTO dans le jargon). Cela découplera le code utilisateur de la classe "Interface".

                    Même autant utiliser une variable SSID et une variable password non ?

                    > Ok, donc Wlan sera un objet (singleton ?) qui servira de portail à la librairie ?

                    Oui, Wlan gérera la connexion au réseau dès sa construction je pense, à moins que son constructeur ne se contente de préparer l'objet puis on utilisera Wlan::connexion() qui initialisera la connexion.

                    > Alors il y aura un objet Wlan et des objets "Network" qui seront associés chacun à un SSID, non ?

                    Des Interface, oui.

                    • Partager sur Facebook
                    • Partager sur Twitter
                    "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                      1 février 2018 à 10:34:09

                      > fournir les infos à l'utilisateur

                      Si par utilisateur tu entends le développeur de l'application qui utilise la librairie, on est OK.

                      >, je ne vois pas d'autres solutions...

                      Je ne vois pas l'intérêt dans avoir une autre. ;)

                      >La fonction statique Wlan::recupererInterfaces doit être ...

                      Ok, mais les noms en français, en plus avec des accents, ça pique un peu les yeux. ;)

                      Mais ça sera un peu plus qu'un alias car le type retourné par "Wlan::recupererInterfaces" doit être un DTO mais pas "Interface::créerInterfaces".

                      >Même autant utiliser une variable SSID et une variable password non ?

                      "Variable", c'est vague comme description, et SSID est une information "montante" et password une information "descendante". (Généralement, les couches s'empilent de haut en bas sous la forme IHM puis métier puis réseau/date).

                      >Oui, Wlan gérera la connexion au réseau...

                      J'ai du mal avec votre description. Pour moi, pour me "connecter", il me faut un password, donc un objet Wlan serait difficilement un "portail". Ne pas confondre l'objet Wlan et la classe Wlan (qui inclut les statics).

                      "Interface", c'est très différents de "Network", pour moi.

                      P.S.: le code d'exemple me parait OK mais il devrait faire un peu plus, un scénario complet.

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                        2 février 2018 à 11:23:05

                        > Mais ça sera un peu plus qu'un alias car le type retourné par "Wlan::recupererInterfaces" doit être un DTO mais pas "Interface::créerInterfaces".

                        Ce doit être un tableau de DTO, mais pourquoi s'embêter à faire un DTO ?

                        Pour rendre inaccessible les méthodes de Interface ?

                        > "Variable", c'est vague comme description, et SSID est une information "montante" et password une information "descendante".

                        Ca depend : on récupère le SSID mais on l"envoie à un moment aussi.


                        > (Généralement, les couches s'empilent de haut en bas sous la forme IHM puis métier puis réseau/date).

                        Uh o_O

                        J'ai du mal avec votre description. Pour moi, pour me "connecter", il me faut un password, donc unobjetWlan serait difficilement un "portail". Ne pas confondre l'objet Wlan et la classe Wlan (qui inclut les statics).

                        Le password serait passé en paramètre au constructeur de Wlan.
                        Le code client serait donc ça :

                        infos = Wlan::recupererInterfaces();
                        //l'utilisateur les affiche en fonction de si il est en console, avec Qt etc...
                        std::cout << "sélectionnez le reseau..." << std::endl;
                        std::string SSID;
                        std::cin >> SSID;
                        std::cout << "sélectionnez le mot de passe..." << std::endl;
                        std::string password;
                        std::cin >> password; //ici on imagine que tout se passe en console
                        Wlan wlan(SSID, password); //ici la connexion (récupération des interfaces, création des profils etc...).
                        //il devra aussi avoir une gestion des exceptions
                        wlan.connexion() //On lance la connexion ici avec wlanConnect()


                        "Interface", c'est très différents de "Network", pour moi.

                        Ah ? Quelle est la différence ?

                        -
                        Edité par raphaeldesaintalbin 2 février 2018 à 11:27:48

                        • Partager sur Facebook
                        • Partager sur Twitter
                        "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                          2 février 2018 à 12:08:11

                          >Ce doit être un tableau de DTO, mais pourquoi s'embêter à faire un DTO ?

                          Si c'est juste pour stocker un nom et un SSID, autant utiliser une structure avec ces seules informations (un DTO dans le jargon). Cela découplera le code utilisateur de la classe "Interface".(BIS)

                          Par découplage, c'est ne pas lier "Interface" à juste la récupération de simples données à afficher à l'utilisateur.

                          C'est un peu comme renvoyer une liste de numéro de téléphone d'un annuaire et pas un "téléphone".

                          "Interface" dans le contexte d'implémentation a un sens précis mais pour l'utilisateur d'une librairie d'accès à un réseaux, c'est très très flou. Utilisez des noms expressifs pour votre API.

                          >Pour rendre inaccessible les méthodes de Interface ?

                          Pour ne pas compliquer la vie du développeur de l'application qui n'en a rien à faire de ces machins tant que l'utilisateur n'a pas choisi son réseau.

                          >Ca depend : on récupère le SSID mais on l"envoie à un moment aussi.

                          L'IHM pourrait utiliser un indice dans un tableau de DTO plutôt que le SSID que cela ne changerait rien. La source du SSID est le réseau (en bas).

                          >Uh o_O

                          C'est une généralisation du concept de modularité.

                          On conçoit sous forme de modules indépendants pour qu'une modification n'implique pas des modifications dans toute l'application.

                          On regroupe ces modules en couches pour que si, malgré tout, il y a un changement de l'API d'un module, il n'implique que des changements dans une couche.

                          On regroupe les modules en fonction de leur niveau d'abstraction et on conçoit des API entre les couches qui seront les plus stables et étanche possible.

                          Je considère que l'API de votre librairie réseau est une frontière de couche car aucun autre module, autre que ceux que vous allez créer en interne, n'a à savoir comment ça marche à l'intérieur de la librairie.

                          C'est pour ça que j'insiste aussi lourdement sur la conception de l'API et du code des cas d'usage de cette API.

                          Une fois bien conçue, vous aurez les mains libre pour faire ce que vous voulez au niveau de son implémentation (de l'API).


                          Ligne 1, vous récupérez des infos, pas des "Interfaces" donc changez le nom de la méthode.

                          Ligne 9, le concept de "connexion" est complètement flou, même dans les commentaires

                          En fin de ligne 9, on est connecté ou pas ???

                          Ça veut dire quoi "connecté" ? En UDP, il n'y pas de connexion mais on envoie quand même des données.

                          Pourquoi cette ligne 11 ? Si "connexion" est obligatoire pourquoi c'est pas fait dans le constructeur ???


                          >Ah ? Quelle est la différence ?

                          Dans le jargon réseau "Interface" est lié à du hardware comme une carte réseau et un "Network" à la couche 3 du modèle ISO de l'OSI (conception des couches réseaux).

                          Une carte réseau (Interface) peut supporter de l'IPv4(Network) et de l'IPv6(Network).

                          Mais, comme déjà indiqué, "Interface, c'est super flou.


                          Votre cas d'usage n'est toujours pas complet.

                          Et il faut qu'il soit simple et évident pour un utilisateur, d'où l'intérêt de le faire avant l'implémentation, pour ne pas être pollué par des détails d'implémentations.

                          Justifiez cette méthode "connexion", SVP.

                          • Partager sur Facebook
                          • Partager sur Twitter
                          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                            3 février 2018 à 17:53:52

                            km

                            -
                            Edité par raphaeldesaintalbin 3 février 2018 à 18:05:32

                            • Partager sur Facebook
                            • Partager sur Twitter
                            "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                              5 février 2018 à 0:10:11

                              Bonjour, le message précédent était une erreur, et un mystérieux phénomène m’empêche d'éditer ma réponse...

                              Bref, ma réponse, la voici :

                              Bon, tout ça mérite une petite mise au point...

                              > Si c'est juste pour stocker un nom et un SSID, autant utiliser une structure avec ces seules informations (un DTO dans le jargon). Cela découplera le code utilisateur de la classe "Interface".(BIS)

                              Par découplage, c'est ne pas lier "Interface" à juste la récupération de simples données à afficher à l'utilisateur.

                              C'est un peu comme renvoyer une liste de numéro de téléphone d'un annuaire et pas un "téléphone".

                              Ben oui mais on ne doit pas donner que le SSID au client si ?

                              Ca l’intéresse peut être d'avoir des infos plus approfondies (cryptage, MAC...)

                              Dans ce cas la on pourrait presque écrire une fonction (on verra le nom apres) wlan::infosBasiques() et wlan::infosCompletes()...

                              Je vais passer sur les lignes suivantes car trop compliquées, je vais lire des trucs dessus sur internet car actuellement je pige rien...

                              Vous parlez de niveaux d'abstraction et bien c'est extrèmement abstrait pour moi là...

                              > Ligne 1, vous récupérez des infos, pas des "Interfaces" donc changez le nom de la méthode.

                              fait !

                              > Ligne 9, le concept de "connexion" est complètement flou, même dans les commentaires

                              En fin de ligne 9, on est connecté ou pas ???

                              Ça veut dire quoi "connecté" ? En UDP, il n'y pas de connexion mais on envoie quand même des données.

                              Pourquoi cette ligne 11 ? Si "connexion" est obligatoire pourquoi c'est pas fait dans le constructeur ???

                              Alors pour moi, être connecté c'est avoir accès à internet avec le réseau wifi ciblé.

                              Ensuite, je me suis mélangé les pinceaux, normalement, le constructeur doit s'en charger.

                              Mais vous avez dit que

                              "J'ai du mal avec votre description. Pour moi, pour me "connecter", il me faut un password, donc un objet Wlan serait difficilement un "portail". Ne pas confondre l'objet Wlan et la classe Wlan (qui inclut les statics)."

                              Il faudrait donc une autre méthode ou classe ou je ne sais quoi qui s'occupe de lancer la connexion ?

                              Je finis par douter de chacune des utilités de mes classes...

                              > "Dans le jargon réseau "Interface" est lié à du hardware comme une carte réseau et un "Network" à la couche 3 du modèle ISO de l'OSI (conception des couches réseaux).

                              Une carte réseau (Interface) peut supporter de l'IPv4(Network) et de l'IPv6(Network).

                              Mais, comme déjà indiqué, "Interface, c'est super flou."

                              Pfiou, donc maintenant il faut que je change le nom Interface... On pourrait imaginer que la classe s'appellerait "Reseau" tout simplement ?

                              Mais réseau à un autre sens comme vous venez de le dire donc ca devient compliqué... "Wifi" alors ?

                              > Votre cas d'usage n'est toujours pas complet.

                              Et il faut qu'il soit simple et évident pour un utilisateur, d'où l'intérêt de le faire avant l'implémentation, pour ne pas être pollué par des détails d'implémentations.

                              Que manque-t'il ? Le code pour l'utilisateur est super simple !

                              Ensuite pas de justification pour la méthode connexion, enfin il y en avait une pseudo comme dit plus haut mais elle n'est pas bien réglée de cette manière...

                              • Partager sur Facebook
                              • Partager sur Twitter
                              "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                5 février 2018 à 11:18:06

                                >Ben oui mais on ne doit pas donner que le SSID au client si ?

                                Ok, mais le client, que cela soit un simple champ dans une structure DTO ou la valeur de retour d'une méthode getter d'une instance de classe, il a la même info.

                                Mais dans le premier cas, il faut faire toutes les manipulations qu'il lui chante sans que cela puisse foutre le bordel dans ta librairie.

                                Dans l'autre cas, il se retrouve avec un objet "actif" qu'il peut mal utiliser par mégarde et foutre le bordel dans ta librairie.

                                S'il n'y a pas d'avantage à l'utilisation de la seconde approche, évites la.

                                >Ca l’intéresse peut être d'avoir des infos plus approfondies (cryptage, MAC...)

                                Ok, pourquoi ne pas les ajouter aux champs du DTO, et an plus, tu pourra mettre toutes les informations pertinentes et pas uniquement celles liés à l'objet "Interface". L'approche DTO est donc plus souple dans ce cas.

                                > écrire une fonction (on verra le nom apres) wlan::infosBasiques() et wlan::infosCompletes()...

                                Ok, mais pourquoi 2 méthodes?

                                Ça complexifie inutilement le travail de l'utilisateur de la librairie.

                                "wlan::getNetwokInfos()"

                                >je vais lire des trucs dessus sur internet car actuellement je pige rien...

                                Retenez juste que votre librairie doit être une boite noire pour son utilisateur et que vous ne devez pas faire d'assertion sur l'utilisateur de la librairie (comme ne pas utiliser cerr ou cout pour les sorties car l'utilisateur est peut-être un client avec une GUI et donc sans console)

                                >Alors pour moi, être connecté c'est avoir accès à internet avec le réseau wifi ciblé.

                                Ok, alors faite la connexion dans le constructeur d'un objet "Network".

                                >Ensuite, je me suis mélangé les pinceaux, normalement, le constructeur doit s'en charger.

                                Ok, mais le constructeur de quelle classe ? ;)

                                >Je finis par douter de chacune des utilités de mes classes...

                                C'est tout à fait normal, c'est le travail de la conception de savoir quelle classe gardée, supprimée et définir précisément leur rôle respectif.

                                Mes remarques correspondent à ce que vous devez faire pendant la conception pour qu'elle soit utilisable.

                                C'est un travail assez complexe et itératif.

                                Vous devrez forcement revenir plusieurs fois sur cette conception.

                                N'attendez pas d'avoir une conception "parfaite" avant de vous lancer dans l'implémentation.

                                Mais il faut avoir une conception qui tient la route sur les cas d'usages les plus courants avant de vous lancez dans l'implémentation initiale.

                                Donc, si c'est flou pour vous, imaginez pour l'utilisateur de votre librairie. ;)

                                > On pourrait imaginer que la classe s'appellerait "Reseau" tout simplement ?

                                Si c'est plus clair, oui, ça serait une bonne idée.

                                >Mais réseau à un autre sens comme vous venez de le dire donc ca devient compliqué... "Wifi" alors ?

                                Attention, évitez les abus de langage qui mélangent tous les concepts.

                                Utilisez des termes précis et pas les termes four-touts de marketeux.

                                Si vous vous trompez de nom mais que vous avez des définitions précises, votre IDE pourra faire un renommage très facilement.

                                >Que manque-t'il ? Le code pour l'utilisateur est super simple !

                                Simple ? Avec une connexion en plus du constructeur ?

                                Il manque, bin, un peu tout le reste.

                                L'utilisateur de votre librairie, il va pas juste "dire coucou" sur le réseau.

                                Il veut envoyer des messages, créer des flux entre machines, etc...

                                Il faut un cas d'usage, un truc qui sert vraiment à faire quelque chose.

                                >enfin il y en avait une pseudo comme dit plus haut mais elle n'est pas bien réglée de cette manière...

                                C'est tout l'intérêt de faire une conception avant d'y aller bille en tête. ;)

                                Concentrez-vous sur un vrai cas d'usage.

                                Et je poserais les questions qui font mal. ;)

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                  7 février 2018 à 23:45:25

                                  Donc je créé une struct avec toutes les infos principales d'un wifi.

                                  On met une fonction membre de wlan qui renvoie un tableau de ces structures.

                                  Je renomme Interface en Reseau.

                                  > L'utilisateur de votre librairie, il va pas juste "dire coucou" sur le réseau.

                                  Il veut envoyer des messages, créer des flux entre machines, etc...

                                  Ah, j'avais pas prévu ca ! Je pensais au départ faire un truc juste pour se connecter à un réseau !

                                  Mais par contre je sais pas du tout ce que l'utilisateur veut faire d'autre comme ça !

                                  >Concentrez-vous sur un vrai cas d'usage.

                                  Et je poserais les questions qui font mal. ;)

                                  Ok, allons y !

                                  Je m'y met immédiatement !

                                  EDIT : En regardant la doc je retombe sur ca, qui est une liste de ca, pourquoi ne pas directement l'utiliser ?

                                  -
                                  Edité par raphaeldesaintalbin 8 février 2018 à 0:59:26

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                    8 février 2018 à 11:44:22

                                    >Je pensais au départ faire un truc juste pour se connecter à un réseau !

                                    Je n'ai pas de souvenir du sujet de base de ce bien trop long sujet de forum. :-°

                                    Je me souviens juste que tu voulais encapsuler ton code "réseau" dans une API objet.

                                    Pour faire un truc facilement utilisable, il ne faut pas aligner des fonctions les unes après les autres pour ajouter des fonctionnalités.

                                    Il faut concevoir l'API à l'avance pour que l'utilisateur puisse facilement et naturellement si retrouver et utiliser efficacement ce que vous lui offrirez comme service.

                                    "juste pour se connecter à un réseau" me parait assez étrange comme service à offrir.

                                    Essaye de concevoir au moins un service "vraiment" utile à l'utilisateur de ton API et fais en un cas d'usage.

                                    Il faut que tu détermines quelle est l'utilité de ce que tu veux offrir comme service.

                                    Ooups, j'ai revu rapidement le début de thread de messages et maintenant, je comprends mieux le truc.

                                    Désolé.

                                    Votre cas d'usage n'est pas si tronqué que cela.

                                    Mais si je comprends bien, votre tâche principale n'est pas de connecté le réseau Wifi mais d'enregistrer un password avec un SSID, non ?

                                    Rendez l'utilité et l'usage de votre API évidente.

                                    Le "Connect" de l'API Win32 est un détail d'implémentation pour son modèle "asynchrone" assez complexe à utiliser, je trouve.

                                    Concevez une API plus simple, correspondant à l'usage que vous voulez offrir.

                                    C'est pas plutôt un "Register" qu'un "Connect" qu'il faut offrir à vos utilisateurs ?

                                    Vous n'êtes pas obligé d'utiliser des classes si les fonctionnalités que vous voulez offrir ne si prêtes pas.

                                    Une API avec 2 fonctions libres feraient peut-être le job : getWifiNetwoksInfos et registerWifiNetwork, non ?

                                    Ça vous semble OK comme API ?

                                    Après, il faut implémenter ces fonctions, et c'est la qu'est le travail d'implémentation.

                                    >EDIT : En regardant la doc je retombe sur ...

                                    Vous parlez de les utiliser dans votre implémentation de l'API, ou par l'utilisateur/développeur d'application ?

                                    Si c'est pour votre application, pourquoi pas.

                                    Si c'est pour l'utilisateur, c'est une API C extrêmement peu pratique à utiliser en C++, le simple fait d'en faire un wrapping C++ sera déjà une valeur ajoutée non négligeable.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                      9 février 2018 à 16:16:23

                                      Non, je pense que notre modèle de classes est pas mal et puis j'en avais jamais fait donc j'aimerais terminer comme cela.

                                      Et puis j'ai peur que l'on se retrouve à nouveau avec trois fonctions de 400 lignes.

                                      Ensuite, oui je veux aussi enregistrer un profile, c'est de toute façon obligé pour se connecter à un réseau, c'est l'utilité de notre classe profile auquel on passe les infos nécessaires pour éventuellement créer le profil si il n'existe pas ou que l'utilisateur veut écraser l'ancien pour en mettre un nouveau puis récupérer le profil.

                                      Ensuite, je veux utiliser cette structure coté développeur et coté client, ma fonction wlan::getNetworkInfos renverra ce DTO à l'utilisateur pour qu'il l’exploite comme bon lui semble.

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                      "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                        9 février 2018 à 17:05:15

                                        >Non, je pense que notre modèle de classes est pas mal

                                        Vous pouvez nous le rappeler ? :-°

                                        >et puis j'en avais jamais fait donc j'aimerais terminer comme cela.

                                        C'est pas parce que vous avez 2 fonctions libres comme API que vous n'avez pas à utiliser ou concevoir des classes.

                                        Les paramètres et les valeurs de retour de ces fonctions ont de très grandes chances d'être des objets/structures. ;)

                                        Sans compter l'implémentation derrière ces fonctions.

                                        >Et puis j'ai peur que l'on se retrouve à nouveau avec trois fonctions de 400 lignes.

                                        C'est pas parce que vous avez 2 fonctions libres en tant qu'API que vous devez tout coder uniquement dans ces fonctions.

                                        Le code utilisateur ne connait que le haut de l'Iceberg, les 2 fonctions (et le DTO des Infos de réseau).

                                        >Ensuite, oui je veux aussi enregistrer un profile, c'est de toute façon obligé pour se connecter à un réseau,

                                        Mais à quoi cela sert pour l'utilisateur de ta librairie ?

                                        Si ça lui sert à rien, il n'a pas à savoir comment ta librairie fait sa tambouille.

                                        La classe "Profile" serait une classe interne à ta librairie et ne fera pas partie de l'API.

                                        Sinon, comment envisages-tu l'usage du "Profile" par l'utilisateur de ta librairie ?

                                        Je rappelle que l'utilisateur n'a pas à connaitre comment tu te sert d'un profile en interne ni comment s'en servir avec l'API de l'OS que tu utilises en interne de ta librairie.

                                        >c'est l'utilité de notre classe profile auquel on passe les infos nécessaires

                                        Tu as besoin en interne d'une classe "Profile", mais l'utilisateur a-t-il besoin de tous les détails ?

                                        Moi, j'en doute. A la rigueur, un DTO avec des champs simples à initialiser, et avec des valeurs par défauts pertinentes serait simple à utiliser pour l'utilisateur. Si cela a du sens pour l'utilisateur de la librairie (et pas pour son implémenteur ;))

                                        Je ne dis pas qu'il n'y a pas besoin de la classe "Profile", mais doit-elle faire partie de l'API ?

                                        > pour éventuellement créer le profil

                                        Pourquoi pas un DTO que tu passes en paramètre du "registerNetwork" ?

                                        >ou que l'utilisateur veut écraser l'ancien pour en mettre un nouveau puis récupérer le profil.

                                        Montres-nous dans un code le cas d'usage avec l'API que tu envisages.

                                        Attention à ne pas rendre une API complexe juste pour des cas d'usage peu utilisés.

                                        Il faut maintenir les cas d'usage courant simple, quitte à rendre les cas d'usage particuliers un peu plus compliqués à faire.

                                        >Ensuite, je veux utiliser cette structure coté développeur et coté client,

                                        Là, t'as intérêt à justifier cette position complètement psychorigide.

                                        >ma fonction wlan::getNetworkInfos renverra ce DTO à l'utilisateur pour qu'il l’exploite comme bon lui semble.

                                        C'est tout l'intérêt d'envoyer un DTO et non un objet interne de ton implémentation.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                          9 février 2018 à 18:04:48

                                          Non mais la classe profile n'est utilisée qu'en interne !

                                          L'utilisateur passe son ssid dans le constructeur de Wlan et après c'est Wlan qui se charge de récupérer les infos nécessaire à la création du profil et d'utiliser la classe, l'utilisateur n'aura donc pas à connaitre donc pas la classe Profile !

                                          > Pourquoi pas un DTO que tu passes en paramètre du "registerNetwork" ?

                                          Ben car on à pas besoin de cette fonction je pense :-°.

                                          L'utilisateur il veut se connecter mais comme dit plus haut il s'en fout de savoir comment ça marche derrière.

                                          Le constructeur de Wlan appellera directement les fonctions nécessaire chez la classe Profile.

                                          Et je vois pas pourquoi mon idée est psychorigide, pourquoi s’embêter à implémenter un DTO qui sera à très peu de choses près le même truc qui existe déjà ?! 

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                          "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                            9 février 2018 à 19:28:15

                                            > l'utilisateur n'aura donc pas à connaitre donc pas la classe Profile !

                                            Ça c'est cool.

                                            >Ben car on à pas besoin de cette fonction je pense :-°

                                            Ok, alors je comprends pas la phrase :

                                            "ou que l'utilisateur veut écraser l'ancien pour en mettre un nouveau puis récupérer le profil."

                                            >pourquoi s’embêter à implémenter un DTO

                                            Si l'utilisateur n'en a pas l'utilité, oui, ça sert à rien de faire un DTO, mais il doit pas connaitre les classes internes.

                                            Si le code du cas d'usage est le dernier que tu a posté, sans l'appel à la fonction "connexion", pourquoi pas.

                                            C'est juste un peu étrange de rendre un Network "accessible" en appelant un constructeur.

                                            Maintenant, il reste plus qu'à implémenter la fonction statique et le constructeur pour qu'il fasse le travail.

                                            Commences par la fonction statique et poste nous ton code.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                              11 février 2018 à 17:28:38

                                              Je suis en train d'implémenter mon DTO et la fonction Wlan::getNetworkInfos, je vous dirais quand j'aurais fini (ça ne devrait pas pendre beaucoup de temps).
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                                12 février 2018 à 20:21:05

                                                J'allais vous envoyer mon code quand je me suis rendu compte que mon DTO revenait à peu près à la classe Reseau, et que en implémentant ma fonction wlan::getNetworkInfo, ma classe Reseau devenait inutilisée ! Dois-je garder les deux ? les fusionner ?

                                                Pour moi la classe interface n'est pas pratique ni utile et elle peut être supprimée. Qu'en pensez vous ?

                                                En fait, Wlan::getNetworkInfo est un peu la même chose que Reseau:creerReseaux

                                                Je vous met tout de meme le code des classes et structures concernées.

                                                DTO.h

                                                #pragma once
                                                #include <string>
                                                
                                                struct Infos
                                                {
                                                	std::wstring profileName;
                                                	std::string SSID;
                                                	int nbBSSIDs;
                                                	int nbPhyTypes;
                                                	int signalQuality;
                                                	int interfaceNumber;
                                                	bool securityEnabled;
                                                	bool haveProfile;
                                                	GUID interfaceGUID;
                                                	_DOT11_PHY_TYPE phyTypes;
                                                	_DOT11_BSS_TYPE bssTypes;
                                                	_DOT11_AUTH_ALGORITHM authAlgo;
                                                	_DOT11_CIPHER_ALGORITHM cipherAlgo;
                                                
                                                };
                                                

                                                wlan.h

                                                #pragma once
                                                #include <memory>
                                                #include <vector>
                                                #include <iostream>
                                                #include "profil.h"
                                                #include "Reseau.h"
                                                #include "exceptionWlan.h"
                                                #include "DTO.h"
                                                
                                                class Wlan
                                                {
                                                	std::unique_ptr<Profile> profile;
                                                	std::vector<std::unique_ptr<Reseau>> Reseaux;
                                                public:
                                                	Wlan(std::string SSID, std::string password, bool overwriteProfile);
                                                	static std::vector<Infos> Wlan::getNetworkInfos();
                                                	static inline HANDLE Wlan::getHandle();
                                                };

                                                wlan.cpp

                                                #include <Windows.h>
                                                #include <Wlanapi.h>
                                                #include "wlan.h"
                                                
                                                Wlan::Wlan(std::string SSID, std::string password, bool overwriteProfile)
                                                {
                                                	DWORD dwMaxClient(2);  
                                                	DWORD dwCurVersion(0);
                                                	DWORD dwResult;
                                                	HANDLE handle;
                                                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &handle);
                                                	profile = NULL;
                                                	Reseaux = Reseau::creerReseaux(handle);
                                                	for (int i(0); i < (int)Reseaux.size(); i++)
                                                	{
                                                		if (Reseaux[i]->nomReseau == SSID)//si le nom du réseau saisi est trouvé dans la liste on créé un profile
                                                		{
                                                			profile = Profile::createProfile(SSID, password);
                                                			break;
                                                		}
                                                	}
                                                	if (profile == NULL)//si le profil n'est pas créé car le reseau passé en paramètre n'est pas trouvé dans la liste
                                                	{
                                                		throw ReseauNotFound(SSID);
                                                	}
                                                }
                                                
                                                std::vector<Infos> Wlan::getNetworkInfos()
                                                {
                                                	HANDLE handle(Wlan::getHandle());
                                                	PWLAN_INTERFACE_INFO_LIST pIfList;
                                                	DWORD dwResult;
                                                	dwResult = WlanEnumInterfaces(handle, NULL, &pIfList);
                                                	if (dwResult != ERROR_SUCCESS)
                                                	{
                                                		switch (dwResult)
                                                		{
                                                		case ERROR_INVALID_PARAMETER:
                                                			throw InvalidParameter("WlanEnumInterfaces");
                                                			break;
                                                		case ERROR_NOT_ENOUGH_MEMORY:
                                                			throw NotEnoughMemory("WlanEnumInterfaces");
                                                			break;
                                                		case ERROR_INVALID_HANDLE:
                                                			throw InvalidHandle("WlanEnumInterfaces");
                                                			break;
                                                		default:
                                                			throw OtherError("WlanEnumInterfaces", dwResult);
                                                			break;
                                                		}
                                                	}
                                                	PWLAN_AVAILABLE_NETWORK_LIST pBssList;
                                                	std::vector<Infos> listInfos;
                                                	for (int i(0); i < (int)pIfList->dwNumberOfItems; i++)
                                                	{
                                                		dwResult = WlanGetAvailableNetworkList(handle, &pIfList->InterfaceInfo->InterfaceGuid, 0, NULL, &pBssList);
                                                		if (dwResult != ERROR_SUCCESS)
                                                		{
                                                			switch (dwResult)
                                                			{
                                                			case ERROR_INVALID_PARAMETER:
                                                				throw InvalidParameter("WlanGetAvailableNetworkList");
                                                				break;
                                                			case ERROR_NOT_ENOUGH_MEMORY:
                                                				throw NotEnoughMemory("WlanGetAvailableNetworkList");
                                                				break;
                                                			case ERROR_INVALID_HANDLE:
                                                				throw InvalidHandle("WlanGetAvailableNetworkList");
                                                				break;
                                                			default:
                                                				throw OtherError("WlanGetAvailableNetworkList", dwResult);
                                                				break;
                                                			}
                                                		}
                                                		for (int j(0); j < (int)pBssList->dwNumberOfItems; j++)
                                                		{
                                                			Infos infos;
                                                			infos.authAlgo = pBssList->Network[j].dot11DefaultAuthAlgorithm;
                                                			infos.bssTypes = pBssList->Network[j].dot11BssType;
                                                			infos.cipherAlgo = pBssList->Network[j].dot11DefaultCipherAlgorithm;
                                                			infos.haveProfile = (pBssList->Network[j].strProfileName == NULL) ? false : true;
                                                			infos.interfaceGUID = pIfList->InterfaceInfo->InterfaceGuid;
                                                			infos.interfaceNumber = i;
                                                			infos.nbBSSIDs = (int)pBssList->Network[j].uNumberOfBssids;
                                                			infos.nbPhyTypes = (int)pBssList->Network[j].uNumberOfPhyTypes;
                                                			infos.phyTypes = *pBssList->Network[j].dot11PhyTypes;
                                                			if (pBssList->Network[j].strProfileName == NULL)
                                                			{
                                                				infos.profileName = L"";
                                                			}
                                                			else
                                                			{
                                                				infos.profileName = pBssList->Network[j].strProfileName;
                                                			}
                                                			infos.securityEnabled = pBssList->Network[j].bSecurityEnabled;
                                                			infos.signalQuality = pBssList->Network[j].wlanSignalQuality;
                                                			infos.SSID = std::string(reinterpret_cast<const char*>(pBssList->Network[j].dot11Ssid.ucSSID), pBssList->Network[j].dot11Ssid.uSSIDLength);
                                                			listInfos.push_back(infos);
                                                		}
                                                	}
                                                	return listInfos;
                                                }
                                                
                                                HANDLE Wlan::getHandle()
                                                {
                                                	DWORD dwMaxClient(2);
                                                	DWORD dwCurVersion(0);
                                                	DWORD dwResult;
                                                	HANDLE handle;
                                                	dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &handle);
                                                	if (dwResult != ERROR_SUCCESS)
                                                	{
                                                		switch (dwResult)
                                                		{
                                                		case ERROR_INVALID_PARAMETER:
                                                			throw InvalidParameter("WlanOpenHandle");
                                                			break;
                                                		case ERROR_NOT_ENOUGH_MEMORY:
                                                			throw NotEnoughMemory("WlanOpenHandle");
                                                			break;
                                                		default:
                                                			throw OtherError("WlanOpenHandle", dwResult);
                                                			break;
                                                		}
                                                	}
                                                	return handle;
                                                }

                                                reseau.h

                                                #pragma once
                                                #include <Windows.h>
                                                #include <Wlanapi.h>
                                                #include <memory>
                                                #include <string>
                                                #include <vector>
                                                #pragma comment(lib, "wlanapi.lib")
                                                #pragma comment(lib, "ole32.lib")
                                                #include "exceptionWlan.h"
                                                
                                                class Reseau
                                                {
                                                	friend class Wlan;
                                                	Reseau();
                                                	std::string nomReseau;
                                                public:
                                                	static std::vector<std::unique_ptr<Reseau>> creerReseaux(HANDLE handle);
                                                };

                                                reseau.cpp

                                                #include "Reseau.h"
                                                
                                                Reseau::Reseau()
                                                {
                                                }
                                                
                                                std::vector<std::unique_ptr<Reseau>> Reseau::creerReseaux(HANDLE handle)
                                                {
                                                	return std::vector<std::unique_ptr<Reseau>>();
                                                }

                                                -
                                                Edité par raphaeldesaintalbin 12 février 2018 à 21:43:50

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                                  13 février 2018 à 15:48:56

                                                  Bon, la POO, c'est pas naturel. :-°

                                                  DTO, c'est un concept de classe, donc "DTO.h", ça n'a aucun sens.

                                                  La classe "Infos", c'est super mal nommé.

                                                  C'est des infos pour un "Network", cela serait bien mieux nommé "NetworkInfo", sans le "s". DTO.h => NetworkInfo.h

                                                  Les informations (les champs) dans NetworkInfo doivent tout avoir un sens précis pour l'utilisateur de la librairie et pas juste un dépotoir/pense-bête pour votre implémentation.

                                                  Donc on dégage tout ce que ne sert à rien pour l'utilisateur de la librairie.

                                                  #pragma once
                                                  #include <string>
                                                   
                                                  struct NetworkInfo
                                                  {
                                                      std::string SSID;
                                                      int signalQuality;
                                                      bool securityEnabled;
                                                  
                                                      NetworkInfo(std::string SSID_, int signalQuality_, bool securityEnable_):SSID{SSID_},signalQuality{signalQuality_},securityEnabled{securityEnabled_};
                                                  };

                                                  Dans Wlan.h, il y a bien trop d'include.

                                                  Il ne doit inclure dans le .h que ce qui est nécessaire à la compréhension de ce qui est défini dans le .h, pas dans le .cpp.

                                                  La différence entre "Wlan" et "Réseau", c'est pas clair. Un SSID, c'est bien lié à un "Réseau", non ?

                                                  C'est quoi cette liste de "Reseau" dans un "Wlan" ???

                                                  Soit Wlan n'est pas un Réseau et donc il n'a pas de profile ni de SSID, soit c'est un réseau et il n' a pas de liste de "Réseau".

                                                  Il faut que le rôle de Wlan soit clair.

                                                  La notion d'HANDLE n'a aucun sens dans une API objet. C'est de la tambouille interne avec l'API C de Windows.

                                                  Soit Wlan est un réseau:

                                                  #pragma once
                                                  #include <memory>
                                                  #include <vector>
                                                  #include "profil.h"
                                                  #include "NetworkInfo.h"
                                                   
                                                  class Wlan
                                                  {
                                                      std::string SSID;
                                                      std::unique_ptr<Profile> profile;
                                                  public:
                                                      Wlan(const std::string& SSID_, const std::string& password, bool overwriteProfile = false):SSID(SSID_);
                                                      static std::vector<NetworkInfo> Wlan::getNetworkInfos();
                                                  };

                                                  Soit Wlan est un portail, différent d'un réseau :

                                                  #pragma once
                                                  #include <memory>
                                                  #include <vector>
                                                  #include "Reseau.h"
                                                  #include "NetworkInfo.h"
                                                   
                                                  class Wlan
                                                  {
                                                      HANDLE handle = NULL;
                                                      std::vector<std::unique_ptr<Reseau>> Reseaux;
                                                  public:
                                                      Wlan();
                                                      Reseau& creerReseau(const std::string& SSID, const std::string& password, bool overwriteProfile = false);
                                                  
                                                      std::vector<NetworkInfo> Wlan::getNetworkInfos();
                                                  };


                                                  L'"overwriteProfile", je pensais que la gestion des profiles était interne, alors pourquoi avoir un paramètre pour le "gérer" ???

                                                  Si Wlan = Reseau, qui est en charge de libérer l'handle alloué ligne 11 ?

                                                  https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms706610(v=vs.85).aspx

                                                  Il faut que cela soit dans le constructeur.

                                                  Si Wlan est un portail, vous devriez stocker ce HANDLE dans un champ et le libérer dans le destructeur.

                                                  Moi, je vous conseille de faire de Wlan un portail pour facilement gérer l'API C sous-jacente.

                                                  Dans ce cas, votre code du constructeur de Wlan, devra être dispatché (avantageusement) entre le constructeur de Wlan et celui de "Reseau".

                                                  Vous n'aurez plus besoin de cette horrible "getHandle" qui ouvre des handles sans jamais les fermer. Vous utiliseriez à la place le champ "handle" de Wlan, ouvert dans le constructeur, et fermé dans le destructeur.

                                                  Les "#pragma comment(lib,...)", c'est cracra, et ça devrait être dans un en-tête "chapeau" comme celui de Wlan, si c'est une classe "portail'.

                                                  #include <Windows.h>
                                                  #include <memory>
                                                  #include <vector>
                                                  #include <iostream>
                                                  #include "profil.h"
                                                  #include "Reseau.h"
                                                  #include "exceptionWlan.h"
                                                  #include <Wlanapi.h>
                                                  #include "wlan.h"
                                                   
                                                  Wlan::Wlan()
                                                  {
                                                      DWORD dwMaxClient(2); 
                                                      DWORD dwCurVersion(0);
                                                      DWORD dwResult;
                                                      dwResult = WlanOpenHandle(dwMaxClient, NULL, &dwCurVersion, &handle);
                                                  
                                                      if (dwResult != ERROR_SUCCESS)
                                                      {
                                                          switch (dwResult)
                                                          {
                                                          case ERROR_INVALID_PARAMETER:
                                                              throw InvalidParameter("WlanOpenHandle");
                                                              break;
                                                          case ERROR_NOT_ENOUGH_MEMORY:
                                                              throw NotEnoughMemory("WlanOpenHandle");
                                                              break;
                                                          default:
                                                              throw OtherError("WlanOpenHandle", dwResult);
                                                              break;
                                                          }
                                                      }
                                                  }
                                                  
                                                  Wlan::~Wlan()
                                                  {
                                                      dwResult = WlanClodeHandle(handle);
                                                  }
                                                   
                                                  std::vector<Infos> Wlan::getNetworkInfos()
                                                  {
                                                      PWLAN_INTERFACE_INFO_LIST pIfList;
                                                      DWORD dwResult;
                                                      dwResult = WlanEnumInterfaces(handle, NULL, &pIfList);
                                                      if (dwResult != ERROR_SUCCESS)
                                                      {
                                                          switch (dwResult)
                                                          {
                                                          case ERROR_INVALID_PARAMETER:
                                                              throw InvalidParameter("WlanEnumInterfaces");
                                                              break;
                                                          case ERROR_NOT_ENOUGH_MEMORY:
                                                              throw NotEnoughMemory("WlanEnumInterfaces");
                                                              break;
                                                          case ERROR_INVALID_HANDLE:
                                                              throw InvalidHandle("WlanEnumInterfaces");
                                                              break;
                                                          default:
                                                              throw OtherError("WlanEnumInterfaces", dwResult);
                                                              break;
                                                          }
                                                      }
                                                      PWLAN_AVAILABLE_NETWORK_LIST pBssList;
                                                      std::vector<Infos> listInfos;
                                                      for (int i(0); i < (int)pIfList->dwNumberOfItems; i++)
                                                      {
                                                          dwResult = WlanGetAvailableNetworkList(handle, &pIfList->InterfaceInfo->InterfaceGuid, 0, NULL, &pBssList);
                                                          if (dwResult != ERROR_SUCCESS)
                                                          {
                                                              switch (dwResult)
                                                              {
                                                              case ERROR_INVALID_PARAMETER:
                                                                  throw InvalidParameter("WlanGetAvailableNetworkList");
                                                                  break;
                                                              case ERROR_NOT_ENOUGH_MEMORY:
                                                                  throw NotEnoughMemory("WlanGetAvailableNetworkList");
                                                                  break;
                                                              case ERROR_INVALID_HANDLE:
                                                                  throw InvalidHandle("WlanGetAvailableNetworkList");
                                                                  break;
                                                              default:
                                                                  throw OtherError("WlanGetAvailableNetworkList", dwResult);
                                                                  break;
                                                              }
                                                          }
                                                          for (int j(0); j < (int)pBssList->dwNumberOfItems; j++)
                                                          {
                                                              NetworkInfo info(std::string(reinterpret_cast<const char*>(pBssList->Network[j].dot11Ssid.ucSSID), pBssList->Network[j].dot11Ssid.uSSIDLength),pBssList->Network[j].wlanSignalQuality,pBssList->Network[j].bSecurityEnabled);
                                                              listInfos.push_back(info);
                                                          }
                                                      }
                                                      return listInfos;
                                                  }



                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                  Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                    15 février 2018 à 23:03:38

                                                    > Bon, la POO, c'est pas naturel. :-°
                                                    Ouais, c'est la première fois que j'y suis réellement confronté.
                                                    Je change le nom.
                                                    > Les informations (les champs) dans NetworkInfo doivent tout avoir un sens précis pour l'utilisateur de la librairie et pas juste un dépotoir/pense-bête pour votre implémentation.
                                                    Donc on dégage tout ce que ne sert à rien pour l'utilisateur de la librairie.
                                                    Justement, c'est la ou je ne suis pas d'accord avec vous. Ça intéresse peut être l'utilisateur de connaitre le chiffrement de son réseau, quelle interface c'est, si ya un profil etc...
                                                    >Dans Wlan.h, il y a bien trop d'include.
                                                    Il ne doit inclure dans le .h que ce qui est nécessaire à la compréhension de ce qui est défini dans le .h, pas dans le .cpp.
                                                    Ah, merci beaucoup, j'avais du mal avec la répartition des includes, la c'est clair.
                                                    > La différence entre "Wlan" et "Réseau", c'est pas clair. Un SSID, c'est bien lié à un "Réseau", non ?
                                                    C'est quoi cette liste de "Reseau" dans un "Wlan" ???
                                                    Soit Wlan n'est pas un Réseau et donc il n'a pas de profile ni de SSID, soit c'est un réseau et il n' a pas de liste de "Réseau".
                                                    Il faut que le rôle de Wlan soit clair.
                                                    Wlan est un portail qui gère un peu toute mon API, c'est elle qui orchestre tout et qui lie les classes entre elles.
                                                    La liste de Reseau est la pour une raison obscure qui est surement obsolète, je vais aller commenter un peu mon code pour éviter ce genre de truc.
                                                    > La notion d'HANDLE n'a aucun sens dans une API objet. C'est de la tambouille interne avec l'API C de Windows.
                                                    Pas faux, mais je n'ai toujours pas saisi si un même handle peut etre utilisé dans plusieurs fonctions (enfin le type de handle en question) auquel cas en effet on le met dans le constructeur comme dit après.
                                                    Dans votre code ou Wlan est un portail, je ne comprends pas l'interet de la methode creerReseau... Que fait elle ? Elle instancie le tableau de réseaux ?
                                                    Ensuite il faut que je m'occupe de fermer ces handles, c'est vrai je le fais pas j'oublie à chaque fois que la destruction de la fariable ne ferme pas le Handle.
                                                    > Les "#pragma comment(lib,...)", c'est cracra, et ça devrait être dans un en-tête "chapeau" comme celui de Wlan, si c'est une classe "portail'.
                                                    Ben j'ai pas trop le choix si je veux utiliser l'api... Et c'est quoi un en-tête chapeau ? Un header qui contient plein d'includes ? Le header "principal" ?
                                                    PS : désolé la présentation est horrible et sérrée mais je ne sais pas pourquoi mes sauts de lignes ne sont pas pris en compte...

                                                    -
                                                    Edité par raphaeldesaintalbin 15 février 2018 à 23:07:16

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                                      16 février 2018 à 12:12:43

                                                      >Justement, c'est la ou je ne suis pas d'accord avec vous. Ça intéresse peut être l'utilisateur de connaitre le chiffrement de son réseau, quelle interface c'est, si ya un profil etc...

                                                      Alors, il faut le faire de manière cohérente et pas utiliser des types C tout pourris dans votre API C++.

                                                      Et si vous lui donnez des informations, il faut lui donner les outils pour quelles soit utile.

                                                      Vous ne donnez rien pour manager des profiles, alors vous ne lui fournissez pas des informations (car il ne peut rien en faire).

                                                      Ajouter des champs aux DTOs quand on étant les fonctionnalités de la librairie ne pose pas de problème, et simplifie la compatibilité ascendante.

                                                      Les DTOs ne sont pas des dépotoirs d'informations "au cas où".

                                                      Tout ce que vous fournissez à l'utilisateur doit être conçu (pensé, réfléchi) , pas de "au cas où".

                                                      Tous ce que vous fournissez doit être maintenu au long des différentes versions, ajouter un truc moisi et on est dans la dèche.

                                                      >mais je n'ai toujours pas saisi si un même handle peut etre utilisé dans plusieurs fonctions

                                                      Oui, si vous stockez sa valeur quelque-part ailleurs que dans une variable locale à la fonction. Mais attention à bien le fermer à un moment donné, d'où l'utilisation des destructeurs C++ pour simplifier la chose.

                                                      >je ne comprends pas l'interet de la methode creerReseau... Que fait elle ?

                                                      J'ai juste récupéré votre méthode et rectifié le code pour qu'il corresponde au Design Pattern Factory Method comme le suggère son nom.

                                                      Elle fait ce qu'indique son nom, contrairement à votre implémentation.

                                                      Utiliser le Design Pattern Factory Method me dérange pas, et est plus simple a implémenter (les vérifications du moins) qu'un constructeur "classique".

                                                      >Elle instancie le tableau de réseaux ?

                                                      Bin non, elle instancie un Reseau, comme l'indique son nom.

                                                      >Ensuite il faut que je m'occupe de fermer ces handles

                                                      Oui, il le FAUT.

                                                      >c'est vrai je le fais pas j'oublie à chaque fois que la destruction de la fariable ne ferme pas le Handle.

                                                      Les destructeurs sont nos amis.

                                                      >Ben j'ai pas trop le choix si je veux utiliser l'api...

                                                      WHAT ?!?

                                                      Et les propriétés du projet, vous en faites quoi ???

                                                      En plus, il faut toujours un fichier d'en-tête à une librairie ou à un module indépendant d'une librairie, et c'est le seul endroit raisonnable où mettre ce "#pragma comment(lib,...)", le seul.

                                                      Moi, je me sert jamais de "#pragma comment(lib,...)", je trouve que ça prend l'utilisateur de la librairie pour un con et qu'il peut gérer l'emplacement des lib comme il veux.

                                                      > Et c'est quoi un en-tête chapeau ?

                                                      C'est l'en-tête qui regroupe les définitions que l'utilisateur de la lib est en droit de connaitre, mais rien d'autre.

                                                      Si vous avez une classe "Profile" qui ne devrait être utilisé qu'en interne, vous vous arrangez pour qu'elle ne soit pas incluse si l'utilisateur inclus cet en-tête chapeau.

                                                      L'utilisateur ne devrait inclure que cet en-tête pour bénéficier de tout les services que propose la librairie.

                                                      Si Wlan est une espèce de classe portail, l'en-tête de la classe peut servir de fichier d'en-tête chapeau (si cela ne fait pas trop inclure de .h qui ne sont pas en rapport direct avec l'API de la classe Wlan.

                                                      >Un header qui contient plein d'includes ?

                                                      Oui, mais qui ne contient que ce qui est nécessaire à un utilisateur "externe" à la librairie.

                                                      >Le header "principal" ?

                                                      Plutôt celui de l'API offerte par la librairie.

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                        19 février 2018 à 19:54:52

                                                        J'ai bien pris note de vos propositions mais mon ordinateur est actuellement en réparation, je vous répondrais plus précisément des que je l'aurais.

                                                        Veuillez m'excuser,

                                                        Raphaël. 

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                        "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                                          27 février 2018 à 18:28:40

                                                          Bonjour, je n'ai pas encore mon ordinateur mais j'ai bien réfléchi et j'ai pensé qu'il faudrait peut être revoir notre conception.

                                                          Je pense qu'il pourrait être bien de ne laisser que la classe Reseau de disponible à l'utilisateur.

                                                          Elle disposerait d'une fonction publique statique listerReseaux qui renverrait un tableau de réseaux.

                                                          Puis ensuite d'une fonction connect qui ferait que l'utilisateur ne manie qu'une classe, et la classe Wlan est appelée directement dans la méthode Connect.

                                                          Ainsi on s'assure que les bons arguments sont passés à plan car c'est l'API qui s'en charge, pas besoin de conversions en tout genre car à l'intérieur on utilise les structures C natives et l'utilisateur ne passe que le mot de passe et éventuellement un paramètre optionnel overWriteprofile car bien que la gestion des profils soit interne, il faut savoir quoi faire si le profil existe déjà.

                                                          La classe Reseau serait un hybride DTO/classe car ses attributs seront publics mais aurait des méthodes.

                                                          Cordialement,

                                                          Raphael.

                                                          EDIT : Bon la on respecte plus du tout l'encapsulation, ça va pas.

                                                          Ou alors une classe Reseaux qui contient un tableau de DTO Reseau et qui possède un constructeur, une fonction non statique listerReseaux qui renvoie un tableau de Reseau ainsi qu'une fonction Reseaux.connect à laquelle on passe en paramètre SSID et mot de passe.

                                                          -
                                                          Edité par raphaeldesaintalbin 27 février 2018 à 18:34:45

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                          "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte
                                                            27 février 2018 à 20:08:26

                                                            Il vaut mieux plus de classes ayant des définitions claires et un usage simple que peu de classe où on fourretout et n'importe quoi, comme si s'était une dinde.

                                                            Franchement, une classe réseau qui peut être "disconnected" et où il faut faire un appel à la con comme "Connect" pour qu'il passe dans un état "utilisable", moi, je dis NON !!!

                                                            Il est plus simple d'avoir des objets directement opérationnels dès leur création.

                                                            > de ne laisser que la classe Reseau de disponible à l'utilisateur.

                                                            Et le laisser le cloner, avec des informations sur des champs qu'il n'a pas à connaitre, qui peut appeler "Connect" plusieurs fois, etc.. Moi, je sens la fête du slip. o_O

                                                            >Bon la on respecte plus du tout l'encapsulation, ça va pas.

                                                            Bin, j'ai l'impression que la POO commence à entrer. ;)

                                                            >Ainsi on s'assure que les bons arguments sont passés

                                                            C'est un bon objectif, rendre le bon usage de la classe facile et son mauvais difficile.

                                                            Et vous commencez à comprendre que votre premier design n'avait pas ces bonnes caractéristiques.

                                                            >pas besoin de conversions en tout genre car à l'intérieur on utilise les structures C natives

                                                            Si vous réduisez l'utilisation des structures C au strict minimum, mais dans l'implémentation de votre librairie, cela simplifiera son implémentation. On est d'accord, l'utilisateur ne devra jamais voir ces horribles structures C et constantes à 2 balles de l'API Win32.

                                                            >éventuellement un paramètre optionnel overWriteprofile

                                                            Franchement, je ne vois toujours pas pourquoi il devrait s'en soucier. Et si je ne le vois pas, c'est que c'est mal présenté ou inutile. Sans preuve du contraire, supprimez ce détail de l'API.

                                                            > car bien que la gestion des profils soit interne,

                                                            Cela confirme mon analyse.

                                                            > il faut savoir quoi faire si le profil existe déjà.

                                                            Et pourquoi l'utilisateur de votre librairie le serait plus que vous ??? o_O

                                                            >La classe Reseau serait un hybride DTO/classe

                                                            Si la classe sait même pas ce qu'elle est, comment voulez-vous que l'utilisateur puisse s'en servir ?

                                                            Aillez des classes au rôle bien défini et pas des classes chimères mortes-nées et toxiques.

                                                            >car ses attributs seront publics mais aurait des méthodes.

                                                            Description d'une classe mal foutue, on révise sa copie.

                                                            >Ou alors une classe Reseaux qui contient un tableau de DTO Reseau

                                                            Ok, c'est juste renommé "Wlan" en "Reseaux" quoi.

                                                            Le pluriel pour distinguer des classes, ça sent pas bon.

                                                            Soit ce n'est vraiment qu'un regroupement d'objet d'une classe, et alors std::vector<LaClasse> serait bien plus explicite, soit il a des responsabilités supplémentaires et cela doit être indiqué dans le nom de la classe.

                                                            >et qui possède un constructeur

                                                            Si c'est Wlan/Reseaux, Ok, mais il fait savoir de quoi il a besoin, les paramètres du constructeur.

                                                            >une fonction non statique listerReseaux

                                                            Ok, mais c'était déjà le cas de la solution avec un "Wlan" instanciable, non ?

                                                            >qui renvoie un tableau de Reseau

                                                            Non, vos réseaux ne seront pas opérationnels et vous donnez tous les moyens à l'utilisateur de la librairie de faire marcher la loi de Murphy à plein régime.

                                                            Donnez à l'utilisateur tous ce dont il a besoin MAIS UNIQUEMENT CE DONT IL A BESOIN.

                                                            >ainsi qu'une fonction Reseaux.connect

                                                            Toujours la même erreur que la première proposition.

                                                            >à laquelle on passe en paramètre SSID et mot de passe.

                                                            Pourquoi pas comme paramètre du constructeur de la classe Réseau ???

                                                            C'est dur, mais je vais vous donnez un petit tricks, si vous ne voulez pas être forcément "portable".

                                                            Ceux qui ont conçu l'API Win32 que vous cherchez à encapsuler, ils connaissent la POO et cela se voit dans leur API, malgré le fait que l'API soit en C (l'utilisation de handles à la place de pointeur "this", etc...).

                                                            Ce n'est pas par ignorance qu'ils ont utilisé le C, c'est une obligation pour rendre l'API Win32 utilisable par la majorité des autres langages.

                                                            Déjà, essayez de voir le conception OO qu'ils avaient en tête lors de la conception de l'API Win32 et elle ne devrait pas être trop dégueulasse. ;)

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                              7 mars 2018 à 0:26:59

                                                              Bonjour,

                                                              Enfin retour du SAV !

                                                              On s'y remet donc, je me suis rafraîchi la mémoire et je me suis dit que on pourrait prendre uniquement les bons cotés de nos différentes conceptions.

                                                              On reste avec notre DTO Reseau, avec un constructeur privé (important pour après) et une méthode statique dont le prototype serait :

                                                              static std::vector<Reseau> Reseau:listerReseau();

                                                              Ensuite Wlan qui n'a qu'une fonction, son constructeur auquel on passe en argument un Reseau et un mot de passe.

                                                              Ainsi on à des objets fonctionnels à la sortie du constructeur, moins de risque d'erreur dans les arguments car Reseau ne peut être construit "à la main", on peut encore modifier ses attributs mais bon ça limite les risques (je ne pense pas que des accesseurs  avec des attributs privés soient une bonne idée ici, vous en pensez quoi ?)

                                                              De plus on pourra mettre certaines infos de Reseau en private si elles ne sont pas utiles et si on déclare Wlan amie de Reseau on pourra y acceder.

                                                              Ou Reseau amie de Wlan, dans quel sens le faire ?

                                                              Cordialement,

                                                              Raphael

                                                              EDIT : niveau conception, la fonction listerReseaux doit etre une fonction de Wlan ou de Reseau ?

                                                              Si ca appartient à Reseau, c'est une classe, sinon c'est une bête structure.

                                                              -
                                                              Edité par raphaeldesaintalbin 7 mars 2018 à 1:32:46

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter
                                                              "La valeur n'attend point le nombre des années" Le Cid, Pierre Corneille, Don Rodrigue parlant au Comte

                                                              lister les wifis disponibles et s'y connecter

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown