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

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

 C++ Discussion :

Concernant la propreté...


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2010
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2010
    Messages : 33
    Par défaut Concernant la propreté...
    Bonjour,

    Je suis actuellement en train de développer un moteur 3D basique en C++. N'ayant jamais attaqué un projet de cette taille (et ayant apprit à coder pas très proprement car j'étudie à Epitech et suis obligé de me taper leur norme idiote :/), j'essaye de faire ça le plus proprement possible, mais mes maigres connaissances en la matière me font me poser plein de questions. Voici les principales :

    1) Une classe par .h/.cpp, c'est ce que j'applique. Est ce que je mérite de me faire lapider pour ça, ou est ce propre et standard?

    2) Que pensez vous des long long int? Peuvent-ils poser des problèmes de compatibilité à l'exécution du programme dans certains environnements, ou n'est ce juste que certains compilateurs qui ont du mal avec? Peuvent-ils être utilisés proprement ou sont-ils à bannir de nos programmes?

    3)Pour stocker les différentes données de mon programme, j'utilise une arborescence à base de structure et de classes. Cette arborescence est accessible par un pointeur unique sur une structure et donne donc accès à la totalité des données du programme (non encapsulée dans les classes bien entendu).
    Je la donne en exemple pour que ça soit plus clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    struct     mainData
    {
    int         drawParamsMask;
    VideoParams *videoParams;
    Mesh        *Models;
    Map         *Materials;
    ...ect
    };
    Bon, en réalité, elle est bien plus complexe, mais je la simplifie pour l'exemple. Donc à partir de ça, je me demandais si il était une bonne idée de rendre le pointeur sur la structure mainData global (non pas taper! ), car à mon sens cela permet de disposer de tous les avantages d'une globale tout en limitant les inconvénients qu'elles causent : seul un pointeur de 4octet sera global, ce qui n'est pas très lourd à faire passer aux fonctions et limite donc la perte de perfs, mais j'aurais pourtant accès à toutes les données de mon programme partout et à tout moment. Bon, j'imagine que je dois me tromper et qu'en fait c'est crade comme il faut, mais j'aimerais en être certain et en avoir l'explication le cas échéant. (Pour ma défense, je n'ai jamais utilisé de globales jusqu'à maintenant et les ais toujours fuies comme la peste, non je dis ça parce que je tiens à mon image quand même )

    Voilà, c'est tout pour le moment, mais c'est déjà beaucoup je le sais, et c'est pour ça que je dis un grand merci (en avance) à ceux qui auront lu mon message ainsi qu'à ceux qui pourront éclairer ma lanterne en y répondant.

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    1/ Pas nécessairement, l'important c'est que le fichier ne contienne pas tout et n'importe quoi, mais si, par exemple, tu as une classe qui est un complement d'un autre, il n'est pas nécessaire des les éclater, tu peux très bien les mettre ensemble.

    Regardes les headers de bibliothèques connues (comme boost), tu verras qu'ils ne mettent pas toujours une seule classe par header (http://www.boost.org/doc/libs/1_45_0...c/headers.html par exemple)

    2/ C'est standard, mais il est possible que certains compilo ne les prenne pas en compte ...

    3/ En c++, struct == class, la différence tient dans l'accessibilité et l'héritage par défaut (privé pour class et publique pour struct).

    Pour la suite de la question, plutôt que de plagier je te renvoy à cet article : http://blog.emmanueldeloget.com/inde...ables-globales je ne pense pas que ta variable global respecte ces 3 points

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par RT222 Voir le message
    Bonjour,

    Je suis actuellement en train de développer un moteur 3D basique en C++. N'ayant jamais attaqué un projet de cette taille (et ayant apprit à coder pas très proprement car j'étudie à Epitech et suis obligé de me taper leur norme idiote :/), j'essaye de faire ça le plus proprement possible, mais mes maigres connaissances en la matière me font me poser plein de questions. Voici les principales :
    La norme d'Epitech n'est pas idiote, crois moi. Et puis Nicolas ne serait pas content d'entendre ça Ca ne veut pas dire que c'est la norme de toutes les normes. C'est juste la norme Epit{a,tech}.

    Citation Envoyé par RT222 Voir le message
    1) Une classe par .h/.cpp, c'est ce que j'applique. Est ce que je mérite de me faire lapider pour ça, ou est ce propre et standard?
    C'est tout à fait propre.

    Citation Envoyé par RT222 Voir le message
    2) Que pensez vous des long long int? Peuvent-ils poser des problèmes de compatibilité à l'exécution du programme dans certains environnements, ou n'est ce juste que certains compilateurs qui ont du mal avec? Peuvent-ils être utilisés proprement ou sont-ils à bannir de nos programmes?
    Le long long int n'a pas d'existence en C++. Pas avant la normalisation finale de C++0x.

    Citation Envoyé par RT222 Voir le message
    3)Pour stocker les différentes données de mon programme, j'utilise une arborescence à base de structure et de classes. Cette arborescence est accessible par un pointeur unique sur une structure et donne donc accès à la totalité des données du programme (non encapsulée dans les classes bien entendu).
    Ah ? Et pourquoi ?
    Citation Envoyé par RT222 Voir le message
    Je la donne en exemple pour que ça soit plus clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    struct     mainData
    {
    int         drawParamsMask;
    VideoParams *videoParams;
    Mesh        *Models;
    Map         *Materials;
    ...ect
    };
    Bon, en réalité, elle est bien plus complexe, mais je la simplifie pour l'exemple. Donc à partir de ça, je me demandais si il était une bonne idée de rendre le pointeur sur la structure mainData global (non pas taper! ), car à mon sens cela permet de disposer de tous les avantages d'une globale tout en limitant les inconvénients qu'elles causent : seul un pointeur de 4octet sera global, ce qui n'est pas très lourd à faire passer aux fonctions et limite donc la perte de perfs, mais j'aurais pourtant accès à toutes les données de mon programme partout et à tout moment. Bon, j'imagine que je dois me tromper et qu'en fait c'est crade comme il faut, mais j'aimerais en être certain et en avoir l'explication le cas échéant. (Pour ma défense, je n'ai jamais utilisé de globales jusqu'à maintenant et les ais toujours fuies comme la peste, non je dis ça parce que je tiens à mon image quand même )
    C'est très sale, je confirme. Ce n'est pas une question de perf (damned, tu ne sais même pas si ton pointeur va être passé dans un registre ou sur la pile !). Il ne s'agit pas d'avoir 4 octets ou 8 ou 12 ou même 4 MB en global (ce qui n'a pas de sens), mais des symboles accessibles partout. C'est ça qui est sale, parce que ça veut dire que ton code ne sera pas réentrant, et qu'il ne sera pas protégé en cas d'utilisation concurentielle des informations (dans des threads). Et ça démontre un gros problème d'architecture. Les globales n'offrent pas d'avantage - elles ont principalement des inconvénients.

    Vu que tu n'est pas clair sur le sujet, je te conseille amicalement mais fermement de ne jamais utiliser de globale dans ton code. Tu pourras en utiliser à partir du moment ou tu auras une compréhension complète des raisons pour lesquelles tu ne dois pas le faire. Je sais, c'est paradoxal.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

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

  4. #4
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2010
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2010
    Messages : 33
    Par défaut
    La norme d'Epitech n'est pas idiote, crois moi. Et puis Nicolas ne serait pas content d'entendre ça Ca ne veut pas dire que c'est la norme de toutes les normes. C'est juste la norme Epit{a,tech}.
    Je suis d'accord pour dire qu'elle est bien conçue pour les nouveaux élèves qui, arrivés en piscine, ont tendance à coder des put_nbr de 6 fonctions de plus de 20 lignes. Elle pousse à l'économie de code et donc indirectement d'opérations effectuées, ce qui n'est pas un mal. Mais autant ceci vaut pour les débutants, autant lorsque l'on commence à acquérir un minimum de compétences et que l'on attaque des projets plus consistants, cette norme est une plaie à suivre, particulièrement la limite absolue de 25 lignes par fonctions.

    Pourquoi 25 lignes piles? Je sais que le découpage fonctionnel est très important dans un programme, seulement imposé comme ça, c'est juste une plaie et ça rend plus sale les codes, d'autant plus que pas mal de raccourcis sont interdits : déclaration de plusieurs variables de même type sur une seule ligne, initialisation de ces variables lors de leur déclaration... Combien de fois j'ai été obligé de tricher à mort sur une fonction, en utilisant des raccourcis d'écriture très peu clair à lire, mais plus courts à écrire, pour tenir à tout prix cette limite et éviter ainsi un découpage inutile? Pourquoi suis je obligé bien souvent de morceler des fonctions, alors que leur action était linéaire et ne nécessitait absolument pas de découpage?

    Je ne suis pas convaincu non plus par l'interdiction totale (et non expliquée d'ailleurs des for et des switch (et pourquoi les ternaires sont-ils autorisés eux?). Ne pas les employer n'est pas en soi un problème, là où ça gêne à mon sens, c'est qu'ils sont utilisés dans de très nombreux programmes et que leur non connaissance peut gêner à la compréhension de codes en dehors d'Epitech (bien que cette lacune soit comblée en quelques minutes, mais bon...). L'école prend aussi le parti de nous décourager à utiliser les commentaires, alors que j'ai toujours lu que bien commenter son code est capital.

    Et pour finir, les globales sont autorisées dans la norme (qui se contente de les déconseiller). J'ai bien sûr un très grand respect pour Nicolas Sadirac, et j'admire ce qu'il a fait et ce qu'il est capable de faire, mais cela ne m'empêche pas de pester contre la norme d'Epitech (qu'il n'a sans doute pas écrite lui même d'ailleurs) que je trouve, pour les raisons citées ci-dessus, fort mal conçue (bien qu'elle ait certaines qualités, je ne le nie pas non plus).

    Ceci dit, il s'agit là d'un avis de débutant, et peut être ais-je tort de penser ainsi, mais cette norme m'a pour le moment tellement posée de problèmes que je ne peux m'empêcher de lui vouer une certaine haine.

    3)Pour stocker les différentes données de mon programme, j'utilise une arborescence à base de structure et de classes. Cette arborescence est accessible par un pointeur unique sur une structure et donne donc accès à la totalité des données du programme (non encapsulée dans les classes bien entendu).
    Ah ? Et pourquoi ?
    Oh non, ne me dis pas qu'il ne faut pas faire comme ça, j'adore procéder ainsi. Je précise que je n'y met pas tout bien entendu, l'idée n'est en aucun cas de ne plus avoir de variables locales aux fonctions (ce qui serait très moche je le sais ). Par donnée, j'entends tout ce qui a un rapport avec la configuration du programme et les objets qui y ont été chargés.

    Voici la véritable structure que j'utilise, ça sera plus clair. C'est encore en chantier donc il manque plein de trucs, je précise :

    Main_Structure_Data.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    #pragma once
     
    namespace		mdt
    {
     
    	struct		videoParams
    	{
    		short int		screenWidthMax;
    		short int		screenWidth;
    		short int		screenHeightMax;
    		short int		screenHeight;
    		short int		refreshRateMax;
    		short int		refreshRate;
    		short int		fpsMax;
    	};
     
    	// Déclarations anticipées
    	class		Mesh;
    	class		DiffuseMap;
    	class		SpecularMap;
    	class		NormalMap;
    	class		OcclusionMap;
    	class		EnvironMap;
    	class		Skeleton;
    	class		Animation;
    	class		Camera;
     
     
    	struct	MainData
    	{
    		videoParams		*videoParams;
    		Mesh			*models;
    		DiffuseMap		*diffusesMaps;
    		SpecularMap		*specularsMaps;
    		NormalMap		*normalsMaps;
    		OcclusionMap		*OcclusionsMaps;
    		EnvironMap		*EnvironnementalsMaps;
    		Skeleton		*skeletons;
    		Animation		*animations
    		Camera			*cameras;
    		int			drawParams; // masque de bit, voir définitions dans 3D_Draw.h
    	};
     
    }
    Je trouvais cette manière de procéder très pratique et efficace car, ayant besoin de stocker et parfois de faire transiter un grand nombre de paramètres entre les fonctions (bon pas en l'état actuel, mais ça va venir), tout était rassemblé en un seul et unique pointeur qu'il me suffit de passer à une fonction pour avoir accès à toutes les données. En plus d'être pratique, il me semblait que c'était plus léger que de passer des tonnes de paramètres en entrée. En prime, cela me permet d'avoir facilement accès à l'intégralité des données de mon programme (paramètres et contenu), et de pouvoir plus facilement suivre sa configuration et tout ce qui a été chargé en mémoire. Enfin c'est ce que je croyais, si j'ai tort, je serais ravi de le savoir. Loin de moi l'idée de vouloir coder salement.

    3/ En c++, struct == class, la différence tient dans l'accessibilité et l'héritage par défaut (privé pour class et publique pour struct).

    Pour la suite de la question, plutôt que de plagier je te renvoy à cet article : http://blog.emmanueldeloget.com/inde...ables-globales je ne pense pas que ta variable global respecte ces 3 points
    Merci pour le lien, très intéressant à lire. Ma structure respecte clairement le premier point, puisqu'elle est créée au démarrage du programme, et détruite uniquement à sa sortie. Je ne sais pas si elle respecte le deuxième point, sachant que même si son contenu change, la structure vers laquelle pointe le pointeur, ainsi que le pointeur lui même restent les mêmes du début à la fin. Quant au troisième point, effectivement il ne me semble pas du tout respecté. ^^

    C'est très sale, je confirme. Ce n'est pas une question de perf (damned, tu ne sais même pas si ton pointeur va être passé dans un registre ou sur la pile !). Il ne s'agit pas d'avoir 4 octets ou 8 ou 12 ou même 4 MB en global (ce qui n'a pas de sens), mais des symboles accessibles partout. C'est ça qui est sale, parce que ça veut dire que ton code ne sera pas réentrant, et qu'il ne sera pas protégé en cas d'utilisation concurentielle des informations (dans des threads). Et ça démontre un gros problème d'architecture. Les globales n'offrent pas d'avantage - elles ont principalement des inconvénients.

    Vu que tu n'est pas clair sur le sujet, je te conseille amicalement mais fermement de ne jamais utiliser de globale dans ton code. Tu pourras en utiliser à partir du moment ou tu auras une compréhension complète des raisons pour lesquelles tu ne dois pas le faire. Je sais, c'est paradoxal.
    Ok ok, je me rends et suivrais donc ton conseil avisé. Point de globales dans mon programme.


    Un grand merci à vous deux, vous m'avez grandement aidé.

  5. #5
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut, et bienvenue sur le forum
    Citation Envoyé par RT222 Voir le message
    Je suis d'accord pour dire qu'elle est bien conçue pour les nouveaux élèves qui, arrivés en piscine, ont tendance à coder des put_nbr de 6 fonctions de plus de 20 lignes. Elle pousse à l'économie de code et donc indirectement d'opérations effectuées, ce qui n'est pas un mal. Mais autant ceci vaut pour les débutants, autant lorsque l'on commence à acquérir un minimum de compétences et que l'on attaque des projets plus consistants, cette norme est une plaie à suivre, particulièrement la limite absolue de 25 lignes par fonctions.

    Pourquoi 25 lignes piles?
    A mon avis, c'est essentiellement historique:

    A l'époque où windows et son système de fenêtrage n'était encore qu'un doux rêve, les moniteurs affichaient... 25 lignes de 80 colonnes.

    La limite des 80 colonnes et des 25 lignes permettait donc de s'assurer:
    • qu' il n'y aurait pas de passage à la ligne pour afficher une ligne unique de code
    • que l'ensemble de la fonction serait affichable à l'écran, sans risquer de voir les premières lignes "mangées" par le manque de place.

    D'ailleurs, on croise aussi souvent des conseils qui préconisent de se limiter à 50 lignes (2* la hauteur de l'écran)... Mais c'est tout autant arbitraire, et cela commence à faire des fonctions pour le moins importantes
    Je sais que le découpage fonctionnel est très important
    Oh que oui, c'est vachement important... peut être même plus que ce que tu ne pourrais le croire pour l'instant
    dans un programme, seulement imposé comme ça, c'est juste une plaie et ça rend plus sale les codes, d'autant plus que pas mal de raccourcis sont interdits : déclaration de plusieurs variables de même type sur une seule ligne, initialisation de ces variables lors de leur déclaration... Combien de fois j'ai été obligé de tricher à mort sur une fonction, en utilisant des raccourcis d'écriture très peu clair à lire, mais plus courts à écrire, pour tenir à tout prix cette limite et éviter ainsi un découpage inutile? Pourquoi suis je obligé bien souvent de morceler des fonctions, alors que leur action était linéaire et ne nécessitait absolument pas de découpage?
    Peut être en demandais tu simplement trop à tes fonctions

    Il est vraiment rare que j'atteigne les 25 lignes dans une fonction, même en déclarant chaque variable dans une ligne...

    Mais ce qui importe surtout, c'est d'essayer de suivre le principe de la responsabilité unique: chaque fonction ne devrait faire qu'une seule chose, mais devrait la faire correctement

    Je ne suis pas convaincu non plus par l'interdiction totale (et non expliquée d'ailleurs des for et des switch (et pourquoi les ternaires sont-ils autorisés eux?).
    Ca, par contre, cela me semble effectivement aberrant...
    Ne pas les employer n'est pas en soi un problème, là où ça gêne à mon sens, c'est qu'ils sont utilisés dans de très nombreux programmes et que leur non connaissance peut gêner à la compréhension de codes en dehors d'Epitech (bien que cette lacune soit comblée en quelques minutes, mais bon...).
    Tout à fait... la connaissance des boucles (de tous les types de boucles) et des tests (de tous les types de tests) reste quand même la base de la programmation structurée...
    L'école prend aussi le parti de nous décourager à utiliser les commentaires, alors que j'ai toujours lu que bien commenter son code est capital.
    Il y a à boire et à manger sur ce point:

    Un code correctement écrit ne devrait, en effet, pas nécessiter de commentaires.

    Par contre, il est vrai qu'un commentaire utile est souvent appréciable. Encore faut il qu'il soit effectivement utile, et qu'il ne vienne pas rajouter une couche sur ce que le code permet de comprendre.

    Un commentaire proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    i++; // on ajoute un à i
    n'a en effet aucun intérêt, mais si un commentaire mets les invariants en évidence ou précise la logique qui est suivie (ou du moins qui doit etre suivie) par le code présente malgré tout un intérêt majeur
    Et pour finir, les globales sont autorisées dans la norme (qui se contente de les déconseiller).
    En fait, c'est le cas à peu près partout:

    On peut te donner une quantité inimaginable d'arguments contre les variables globales, mais tu restes malgré tout seul maître de ton code, et il peut toujours arriver un moment où... une variable globale sera la "moins mauvaise solution".

    Mais Emmanuel a bien raison de dire qu'il est préférable d'attendre de savoir pourquoi tu dois t'en priver avant de décider de les utiliser
    J'ai bien sûr un très grand respect pour Nicolas Sadirac, et j'admire ce qu'il a fait et ce qu'il est capable de faire, mais cela ne m'empêche pas de pester contre la norme d'Epitech (qu'il n'a sans doute pas écrite lui même d'ailleurs) que je trouve, pour les raisons citées ci-dessus, fort mal conçue (bien qu'elle ait certaines qualités, je ne le nie pas non plus).
    Le problème de ce genre de "norme" est qu'elles sont rarement mises à jour, et ne prennent donc que rarement l'évolution de l'état de l'art en compte.

    Et, comme on oublie régulièrement de préciser l'année où elles ont été mises au point, on en arrive régulièrement à remarquer que certaines règles sont en désaccord total avec ce que l'état de l'art nous conseille
    Ceci dit, il s'agit là d'un avis de débutant, et peut être ais-je tort de penser ainsi, mais cette norme m'a pour le moment tellement posée de problèmes que je ne peux m'empêcher de lui vouer une certaine haine.
    On peut le comprendre, mais il faut te dire que les "règles de codage", pour bizarres ou perfectibles qu'elles puissent paraitre, sont malgré tout indispensables pour s'assurer la cohérence du code dans un projet d'importance.
    Oh non, ne me dis pas qu'il ne faut pas faire comme ça, j'adore procéder ainsi. Je précise que je n'y met pas tout bien entendu, l'idée n'est en aucun cas de ne plus avoir de variables locales aux fonctions (ce qui serait très moche je le sais ). Par donnée, j'entends tout ce qui a un rapport avec la configuration du programme et les objets qui y ont été chargés.
    Mais pourquoi ne pas utiliser une variable classique et veiller à ce qu'elle soit accessible par les objets qui en ont réellement besoin

    La liste des objets qui en ont besoin de doit, malgré tout, pas être *si* importante que cela

    Voici la véritable structure que j'utilise, ça sera plus clair. C'est encore en chantier donc il manque plein de trucs, je précise :

    Main_Structure_Data.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
     
    #pragma once
     
    namespace		mdt
    {
     
    	struct		videoParams
    	{
    		short int		screenWidthMax;
    		short int		screenWidth;
    		short int		screenHeightMax;
    		short int		screenHeight;
    		short int		refreshRateMax;
    		short int		refreshRate;
    		short int		fpsMax;
    	};
     
    	// Déclarations anticipées
    	class		Mesh;
    	class		DiffuseMap;
    	class		SpecularMap;
    	class		NormalMap;
    	class		OcclusionMap;
    	class		EnvironMap;
    	class		Skeleton;
    	class		Animation;
    	class		Camera;
     
     
    	struct	MainData
    	{
    		videoParams		*videoParams;
    		Mesh			*models;
    		DiffuseMap		*diffusesMaps;
    		SpecularMap		*specularsMaps;
    		NormalMap		*normalsMaps;
    		OcclusionMap		*OcclusionsMaps;
    		EnvironMap		*EnvironnementalsMaps;
    		Skeleton		*skeletons;
    		Animation		*animations
    		Camera			*cameras;
    		int			drawParams; // masque de bit, voir définitions dans 3D_Draw.h
    	};
     
    }
    Alors, réfléchissons un peu...:

    VideoParams est un ensemble de données qui n'est réellement intéressant que pour la partie "affichage" de ton programme (on pourrait d'ailleurs en dire sans doute autant pour camera (dont j'imagine qu'elle permet de sélectionner le type de vue), et d'animations).

    Les autres données de MainData semblent essentiellement nécessaires à la partie "métier", même s'il parait évident qu'il sera nécessaire de les passer à la partie affichage
    Je trouvais cette manière de procéder très pratique et efficace car, ayant besoin de stocker et parfois de faire transiter un grand nombre de paramètres entre les fonctions (bon pas en l'état actuel, mais ça va venir), tout était rassemblé en un seul et unique pointeur qu'il me suffit de passer à une fonction pour avoir accès à toutes les données. En plus d'être pratique, il me semblait que c'était plus léger que de passer des tonnes de paramètres en entrée. En prime, cela me permet d'avoir facilement accès à l'intégralité des données de mon programme (paramètres et contenu), et de pouvoir plus facilement suivre sa configuration et tout ce qui a été chargé en mémoire. Enfin c'est ce que je croyais, si j'ai tort, je serais ravi de le savoir. Loin de moi l'idée de vouloir coder salement.
    Tu dois, encore une fois, veiller à respecter au mieux la règle de la responsabilité unique.

    Il est, surement, possible de regrouper certaines de ces données dans des structures / classes clairement déterminées, mais il faut, malgré tout veiller à ne pas transmettre trop de choses inutiles

    De plus, si tu code en C++, tu devrais surtout t'intéresser aux services que tu attends de la part de tes objets. Ils te permettront fatalement de déterminer quelles données seront nécessaires pour leur permettre de rendre le service attendu


    Merci pour le lien, très intéressant à lire. Ma structure respecte clairement le premier point, puisqu'elle est créée au démarrage du programme, et détruite uniquement à sa sortie.
    Mais alors, pourquoi la déclarer en variable globale, et non comme une variable locale à la fonction main
    Je ne sais pas si elle respecte le deuxième point, sachant que même si son contenu change, la structure vers laquelle pointe le pointeur, ainsi que le pointeur lui même restent les mêmes du début à la fin.
    c'est le problème des variables globales: n'importe quoi peut y accéder depuis n'importe où et en faire n'importe quoi...

    Si tu crées ta variable de type MainData ne serait-ce que dans la fonction main (et que tu en fais donc bel et bien une variable locale) (à défaut de revoir l'ensemble de l'analyse), les seules fonctions qui pourront accéder à tout ou partie de son contenu seront celles... auxquelles tu transmettra les informations sous la forme de paramètres
    Ok ok, je me rends et suivrais donc ton conseil avisé. Point de globales dans mon programme.
    voila une sage décision
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2010
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2010
    Messages : 33
    Par défaut
    Salut, et bienvenue sur le forum
    Merci.

    A l'époque où windows et son système de fenêtrage n'était encore qu'un doux rêve, les moniteurs affichaient... 25 lignes de 80 colonnes.
    Aaaahhh, d'accord. Ce sont justement les limites exactes imposées par la norme d'Epitech. Je suis content car j'en connais la raison maintenant et me coucherais moins bête. ^^

    Pour le reste de la norme, je suis content de voir que je n'ai pas dit que des bêtises et n'ai donc pas complètement tort en pestant contre. Mais je reste bien conscient que je n'ai pas complètement raison non plus, la faute à mon manque d'expérience dans le domaine. Il faut que je garde en tête que la norme ne me veut pas que du mal.

    Peut être en demandais tu simplement trop à tes fonctions

    Il est vraiment rare que j'atteigne les 25 lignes dans une fonction, même en déclarant chaque variable dans une ligne...

    Mais ce qui importe surtout, c'est d'essayer de suivre le principe de la responsabilité unique: chaque fonction ne devrait faire qu'une seule chose, mais devrait la faire correctement
    Tu dois, encore une fois, veiller à respecter au mieux la règle de la responsabilité unique.

    Il est, surement, possible de regrouper certaines de ces données dans des structures / classes clairement déterminées, mais il faut, malgré tout veiller à ne pas transmettre trop de choses inutiles

    De plus, si tu code en C++, tu devrais surtout t'intéresser aux services que tu attends de la part de tes objets. Ils te permettront fatalement de déterminer quelles données seront nécessaires pour leur permettre de rendre le service attendu
    Je crois avoir compris quelque chose de très important grâce à toi. J'avais apparemment mal interprété le principe de la généricité, et toujours eu tendance à vouloir faire des fonctions polyvalentes, ce qui est bien différent. Je vais donc m'atteler à corriger ce problème et donc à revoir en bonne partie la structure de mon code actuelle (pas de soucis, je n'en suis qu'à la partie design pour le moment, ça ne sera donc pas trop dur). Pour commencer plus de MainData, je commence enfin à me rendre compte en quoi son utilisation est absurde, d'autant plus que j'ai plein d'autres moyens de passer mes données aux fonctions qui en ont besoin de manière claire, aisée, et sans rien surcharger. Responsabilité unique... je ne l'oublierais pas.


    Un grand merci pour cette réponse de très grande qualité qui m'amène à revoir les choses sous un nouvel angle. J'étais perdu avant de venir ici, et même si je le reste quand même pas mal, je pense enfin avancer dans le bon sens. Et ça, c'est motivant.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par RT222 Voir le message
    Aaaahhh, d'accord. Ce sont justement les limites exactes imposées par la norme d'Epitech. Je suis content car j'en connais la raison maintenant et me coucherais moins bête. ^^
    A l'époque, ce genre de limite avait une raison d'être... Certains langages imposaient d'ailleurs la limite des 80 colonnes de manière structurelle (le COBOL par exemple )

    Mais, maintenant, ces limites sont souvent gardées "par habitude" plus qu'autre chose
    Pour le reste de la norme, je suis content de voir que je n'ai pas dit que des bêtises et n'ai donc pas complètement tort en pestant contre. Mais je reste bien conscient que je n'ai pas complètement raison non plus, la faute à mon manque d'expérience dans le domaine. Il faut que je garde en tête que la norme ne me veut pas que du mal.
    Au contraire, elle ne te veut que du bien et tend à te faciliter au mieux l'écriture et, surtout, la relecture de ton code.

    N'oublie pas qu'un code est lu / analysé beaucoup plus souvent qu'il n'est écrit
    Je crois avoir compris quelque chose de très important grâce à toi. J'avais apparemment mal interprété le principe de la généricité, et toujours eu tendance à vouloir faire des fonctions polyvalentes, ce qui est bien différent. Je vais donc m'atteler à corriger ce problème et donc à revoir en bonne partie la structure de mon code actuelle (pas de soucis, je n'en suis qu'à la partie design pour le moment, ça ne sera donc pas trop dur). Pour commencer plus de MainData, je commence enfin à me rendre compte en quoi son utilisation est absurde, d'autant plus que j'ai plein d'autres moyens de passer mes données aux fonctions qui en ont besoin de manière claire, aisée, et sans rien surcharger. Responsabilité unique... je ne l'oublierais pas.
    Ce qui importe quand tu détermine ce que fait une fonction, c'est de te rappeler qu'elle agit comme une "entité indivisible" qui, bien qu'elle puisse s'arrêter si certaines conditions ne sont pas respectées, s'exécutera dans son intégralité lorsque l'on rentre dedans.

    Tu dois donc veiller à ce que la logique qui la compose n'ait qu'un but unique

    A titre d'exemple, on pourrait dire que la fonction main vaut souvent la peine d'être limitée à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        type val = initialize();
        run(&val);
        finalize(&val);
        return 0;
    }
    ou, si tu travaille en Orienté objet, tu auras sans doute un ou plusieurs objets qui "chapeautent le tout", et elle prendrait alors une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    int main()
    {
        Type_1 obj; // RAII inside: initialisation de l'objet à la création
        Type_2 obj2(&obj); //idem
         obj.run();
        return 0;
    } // La destruction des objets libère les ressources
    chaque fonction (ou constructeur dans le deuxième cas) appelant un certain nombre de fonctions (éventuellement de constructeurs d'autres types) effectuant une partie bien déterminée de la tâche en cours
    Un grand merci pour cette réponse de très grande qualité
    De rien
    qui m'amène à revoir les choses sous un nouvel angle. J'étais perdu avant de venir ici, et même si je le reste quand même pas mal, je pense enfin avancer dans le bon sens. Et ça, c'est motivant.
    c'était le but
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par RT222 Voir le message
    Merci.
    Aaaahhh, d'accord. Ce sont justement les limites exactes imposées par la norme d'Epitech. Je suis content car j'en connais la raison maintenant et me coucherais moins bête. ^^
    Étonnamment, ces limites continuent d'avoir du sens.

    Pour la limite à 25 lignes, c'est relativement simple d'en saisir la portée : elle oblige à rendre son code modulaire et à penser correctement le découpage en fonction. Pour un maximum de lisibilité, il faut trouver un bon équilibre entre longueur maximale de fonction et nombre de fonctions. S'il ne sert à rien d'avoir 100,000 fonctions d'une ligne, avoir 10,000 fonctions de 10 lignes sera certainement plus gérable que d'avoir 100 fonctions de 1000 lignes. La complexité du code (calculée par une métrique genre McCabe) sera aussi nettement affectée par cette limite - pour le plus grand bonheur du relecteur.

    La limite à 80 caractères par ligne peut sembler étrange vu nos écrans : un IDE classique va te permettre d'afficher entre 140 et 200 caractères par lignes, donc pourquoi se limiter à 80 ?

    Et bien, d'une part, pour faciliter la lecture. Une ligne longue est souvent complexe à lire - il y a plein de paramètres, plein de choses à comprendre, etc.

    D'autre part, et ceux qui programment dans le monde du libre vont comprendre tout de suite, il est quelque fois nécessaire de partager le code suivant des moyens moins classiques qu'un simple envoi de fichier vers un serveur SVN. On peut le coller dans des forums, ou envoyer une fonction par mail ou par news (est-ce que c'est encore un moyen de communication utilisé à Epit{a,ech} ?). Hors, ces moyens de partage du code sont souvent beaucoup plus limités que votre EDI : le mail va couper le code à 72 ou 80 caractères (idem pour les news), et la boite "code" du forum n'est guère avantageuse à ce niveau. Du coup, s'assurer que la longueur de chaque ligne ne va pas faire qu'elle sera découpée avec une violence extrême conserve un intérêt à ce niveau.

    Si on prends les projets open source emblématique, on voit que la taille maximale des lignes est bien souvent aux alentours de 80 caractères - pour ces raisons (le code open source étant souvent partagé sur des mailing lists, sous forme de snippets ou de patchs).

    Nicolas n'est pas bête du tout - même si bien souvent, il n'explique pas les raisons qui motivent ces décisions (le mieux que tu pourras entendre de lui, c'est "cherche". Ce qui n'est pas forcément plus mal).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

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

Discussions similaires

  1. Curiosité concernant le réseau sous mandrake 9.2
    Par R3iTt0R dans le forum Réseau
    Réponses: 4
    Dernier message: 04/06/2004, 11h57
  2. Question concernant l'API "WaitforSingleObject
    Par Drooxy dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 29/03/2003, 07h26
  3. Concerne les graphes
    Par mcr dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 12/11/2002, 11h02
  4. [TASM] Problème concernant l'instruction LGDT
    Par Ninkosen dans le forum Assembleur
    Réponses: 3
    Dernier message: 15/07/2002, 19h09
  5. Renseignement concernant MulDiv
    Par bastien dans le forum C++Builder
    Réponses: 2
    Dernier message: 17/06/2002, 10h22

Partager

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