Citation:
j'aimerais un lien ou on apprend bien le c++ si vous en connaisser (zeste de savoir) par exemple .
https://zestedesavoir.com/tutoriels/...-en-c-moderne/
Une version plus avancée en POO peut-être ici :
https://zestedesavoir.com/contenus/b...-en-c-moderne/
Citation:
j'ai appris un peux a droite et gauche sur google et apres tous seul en faisant pas mal d'essais.
Je pense que, malheureusement, quelques-unes de ces sources soient plus o moins frelatés. :aie:
Prenez un peu de temps à désapprendre des choses en lisant attentivement le cours de Zeste de Savoir sur le C++.
Citation:
pour le use case je vois pas par ou commencer , j'ai tous dans ma tete , je vais essayer d'en creer un .
Vous n'avez pas à vous prendre la tête normalement.
Pas besoin d'être exhaustif au départ.
Les cas simples en premier :
- Comportement du système sans action humaine s'il fait à l'extérieur 0°C à 7h, 15°C à 12h, 18°C à 17h ...
- Comportement du système si l'utilisateur appuie sur le bouton "A" quand il fait 0°C dehors et 20°C à l'intérieur
etc...
Vous n'avez pas à savoir comment ça fonctionne mais comment le système est sensé réagir et savoir les paramètres extérieurs pertinents pour le projet.
Citation:
les temporisations sont tres nombreuse dans mon projets ; je connais que celle avec timer(NULL)
C'est un peu limité. :aie:
C'est une brique de base, très très bas niveau. Mais l'avantage, c'est que ça marche tout le temps, mais avec pas grand-chose de fait pour vous aider à l'utiliser "correctement" (cf. usage avec des Framework graphiques, etc...).
Mais maintenant, le C++ (le C semble plus "conservateur" dans le domaine) contient énormément d'outils de bien plus haut niveau, comme "std::async" (https://en.cppreference.com/w/cpp/thread/async.html).
Mais comme tout outil de haut niveau, il faut analyser si c'est tel ou tel outil qui faut prendre en fonction du besoin "réel".
=> Analyser les besoins "concrets" du projet.
En vous lançant directement dans le code, vous risquez de faire des "choix" (ou des non-choix par ignorance) qui hypothèqueront potentiellement grandement la suite du projet.
En utilisant une attente active "while(true){...}", vous réduisez grandement les possibilités d'utiliser des solutions techniques de "haut niveau".
Citation:
pour les "new" c'est pour eviter les fuite de memoires d'apres certain cours en poo.
La réponse de @Obsidian est apparu pendant la rédaction de cette réponse.
Je suis assez d'accord avec, sauf que je suis bien plus circonspect sur la justification de l'usage de pointeurs "nus".
Citation:
j'ai changer les qdebug par cout <<"test"<<endl;
Il faudrait que vous preniez l'habitude d'"être fainéant". :mouarf:
Plutôt que de changer tout votre code à chaque fois qu'on vous indique de changer tel machin ou tel autre, faites en sorte que la modification soit "efficace".
Ici, si vous avez vraiment besoin de trace (Je réitère que pour du débuging "précoce", les points d'arrêt dans un débugueur interactif est bien plus productif), il vaudrait mieux utiliser une MACRO type "TRACE(level,msg)".
Ainsi, vous n'avez qu'à changer l'implémentation de la MACRO pour vous adapter, et préparer un passage vers un "vrai" Framework de trace.
Citation:
Code:
1 2 3 4 5 6
| if (time(NULL) - chrono >= deltaT)
{
chrono = time(NULL);
mainDS18B20.tempExt();
cout << "tempExtLue " << mainDS18B20.tempExtLue << endl;
} |
Ça l'avantage d'être simple, mais, dans ce cadre, comment gérer l'affichage d'une IHM qui demandes des entrées utilisateurs ? Comment gérer des temps de temporisations différentes ? Comment gérer des interactions avec d'autres programmes (IPC), le réseau (perte de connectivité, etc...), des alertes ou alarmes de niveau système, etc ... ? Comment gérer le fait que des périphériques ne répondent pas instantanément ? Comment gérer le fait que des périphériques "push" l'information et n'attendent pas que votre bidule les "poll" ? etc...
=> Analyser le projet avant de faire des "choix". :aie:
En profitant de l'utilisation des getteurs, ce code devrait être bien plus simple :
Code:
1 2 3 4 5 6 7 8
| if (time(NULL) - chrono >= deltaT)
{
chrono = time(NULL);
Temperature temp_ext = mainDS18B20.getTempExt();
TRACE(TRACE_LEVEL_DEBUG,temp_ext);
} |
"getTempExt" appelle "tempExt" si nécessaire.
Citation:
pour les DS18B20 , je le mettait dans les deux ,car j'en avais besoin pour lire le fichier qui contient les relever de temperature sondes par sondes
Le fait "dans avoir besoin" es une très mauvaise justification.
Votre conception doit essayer de modéliser le "réel".
Si vous n'avez qu'un seul "DS18B20", vous ne devriez avoir qu'un objet "DS18B20".
Si vous en avez X, vous devriez avoir que X objets "DS18B20".
Si vous avez besoin du même "DS18B20" dans des instances d'autres objets, vous pouvez toujours "partager" l'accès à celui-ci via des procédés comme les références ou le Design Pattern Singleton.
Si vous avez plusieurs objets "DS18B20" pour le même élément "physique", lequel d'entre eux aura les informations les plus à jour, aura les bons paramètres pour interagir avec le matériel, etc...
Ne choisissez pas une "solution" parce qu'elle semble marcher au début mais choisissez une solution qui "modélise" la "réalité" et qui convient aux besoins que l'analyse du projet à identifier.
Google m'a dit qu'un "termostat", c'est pas la même chose qu'une sonde thermique. :aie:
Soit la sonde thermique est "logiquement" (pas forcément physiquement donc) dans ce que vous modéliser sous le terme de "termostat", et alors votre "SondeThermique" est un champ de la classe "Thermostat".
(J'utilise "SondeThermique" plutôt que "DS18B20" car je pense que des types de sonde thermique sont facilement interchangeable. =>"DS18B20" classe fille de "SondeThermique")
Si c'est des entités disjointes, il ne faut pas faire de la sonde thermique un champ de la classe "Thermostat". Quitte à modéliser comment ils interagissent entre eux dans le code de votre projet.
"Modélisez" le "réel" avant d'essayer de le piloter. :mrgreen:
Citation:
j'ai transformer ce que j'ai fais plus haut , avec une class thermostat.
Votre classe "Thermostat" modélise-t-elle un élément "physique" (couche Data/Hardware) ou est-ce un élément logiciel (couche Métier/Business), produit de votre projet ?
Si c'est le premier cas, faites en sorte que vos objets correspondent à la "réalité", pas à un truc pour vous simplifier la vie.
Citation:
mais avec des news pris sur l'exemple que j'ai trouver sur developpez.net (strategie AI)
Pas tout compris. :aie::aie::aie:
La modification d'implémentation du Design Pattern "Statégie" semble montrer que vous avez assez bien compris l'idée de ce DP.
Mais je ne suis pas sûr que ce soit le bon Design Pattern à suivre dans votre cas. Je vous l'avais proposé comme exemple de DP qui peut grandement simplifier du code, mais il doit être adapté à votre problématique, que vous n'avez toujours pas verbalisez.
Citation:
Code:
1 2 3 4
| time_t rawtime;
const int deltaT = 2;
unsigned long long chrono; |
On évitera de mélanger les constantes et les variables.
On évitera aussi l'utilisation des variables globales. :aie:
Citation:
Code:
1 2
| Thermostat mainThermostat;
DS18B20 mainDS18B20; |
Ok si c'est 2 objets "physiques" disjoints.
Mais si c'est 2 objets "physiques" "liés":
Code:
Thermostat mainThermostat
Si c'est lié, "Thermostat" devrait être en capacité de faire le lien tout seul.
Si "Thermostat" est un objet "logique" et qu'il a besoin d'accéder aux informations d'un objet physique :
Code:
1 2
| DS18B20 mainDS18B20;
Thermostat mainThermostat(mainDS18B20); |
Comme ça, mainThermostat n'aura besoin de personne d'autres pour avoir accès aux informations et piloter le périphérique physique.
Citation:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| while (1)
{
time ( & rawtime);
cout << ctime ( & rawtime) << endl;
if (time(NULL) - chrono >= deltaT)
{
chrono = time(NULL);
mainDS18B20.tempExt();
cout << "tempExtLue " << mainDS18B20.tempExtLue << endl;
}
mainThermostat.lectureTemperatureExt(mainDS18B20.tempExtLue);
mainThermostat.productions();
}
return 0; |
Beaucoup de "bruit" pour rien.
En attendant de connaitre vos réels besoins en "temporisation" :
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
std::tuple<bool, int> getTempo(time_t& chrono) {
{
...
}
....
....
bool fin{ false };
time_t chrono = time(NULL);
...
do{
mainThermostat.tick();
const auto& [fin_, tempo] = getTempo(chrono);
sleep(tempo);
fin = std::move(fin_);
}while (!fin) ;
return 0; |
L'implémentation de la classe "Thermostat" me semble "correct" bien qu'elle ne soit pas thread-safe contrairement au code de votre Github.
Comme le code de votre Github est très lié à Qt, la "thread-safeness" est peut-être important.
Mais dans du code "Console" lié au métier (sans Qt), la "thread-safeness" est vraisemblablement superfétatoire.
Mais il faut structurer votre projet pour maintenir le fait que le code métier n'est pas à être "thread-safeness" quel que soit le choix du Framework d'IHM.
Je ne vois toujours pas l'utilité de cette classe et l'utilisation du DP Stratégie est peut-être "overkill" ou inadapté, non ?
Quelle est la fonction de cette classe ? (Modéliser un objet physique ? Créer des automatisme logicielle ? etc...
-----------------------
Citation:
es-tu au clair sur la notion de « classe » en soi et sur l'héritage en particulier ?
Le changement d'implémentation du Design Pattern Stratégie dans le code qu'il a posté ici semble montrer qu'il a bien progressé sur le sujet. :D
@Obsidian, attention à l'usage de "NULL" qui n'est plus là que pour de la rétrocompatibilité avec le C et l'usage d'API C. En C++ on lui préférera "nullptr".
De plus, l'utilisation de pointeurs "nus" en code C++ "moderne" est plutôt rare, quand il est justifié.
EDIT :
Le fichier "Sans titre_0.pdf" est bien plus qu'un simple cas d'usage.
Il présente plus un schéma d'ensemble qui permet d'avoir d'information sur l'ensemble du projet.
Il y a pas mal de composants physiques (volets, sondes thermiques, compresseurs, vannes etc...).
Je commencerais par mettre en place une couche "hardware", capable de communiquer avec ces composants de manière simple.
Après, j'implémenterai la logique en charge de coordonner ces composants pour atteindre les objectifs du projet (régulations, etc...) : une couche métier.
Après, je mettrais en place une IHM qui afficherait les informations pertinentes, sous une forme lisible pour l'utilisateur "lambda", et des composants d'interaction (boutons, etc...) pour piloter le machin : une couche IHM.