CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

Question ouverte sur un design pattern

tbop2
tbop2
Niveau 10
15 juin 2011 à 15:03:01

Bonjour, (question c++)

La question me semblait triviale et pourtant je bloque sur une solution definitive acceptable.

J'ai une classe qui comporte n attributs de type float, ils sont tous logiquement independants les uns des autres et non, a nouvel ordre, aucune raison d'etre refactorer comme autre choses que des floats.

J'ai une autre classe qui joue le role de ClassCollector.

Voila le probleme : Je voudrais UNE methode publique Class GetClosestClassFrom(....... value) qui me renverrait l'objet dont la valeur de l'attribut sous-entendu demande est la plus proche de value.
Probleme comment minimiser la redondance et avoir une solution elegante ?

Ma seule solution trouvee jusqu'a ce jour pour avoir un resultat dynamique esthetique et d'envoyer un flag supplementaire pour preciser l'attribut referent. Mais a ce moment la pour aller au bout de l'optimisation dynamique je ne vois d'autre solution que de refactorer tous ces attributs float dans une map<AttributeEnum, float> ou un tableau de float bien ordonnee mais un peu plus risky.

On aurait alors une seule methode avec cette tronche

Class GetClosestFrom(float value, AttributeEnum attribute)

Dans laquelle on gettera dynamiquement le bon attribute avec un float GetAttribute(AttributeEnum attribute) pour chaque objet parcouru.

Voyez vous une autre solution ? (j'en vois plein, mais celle-ce me semble la meilleure... mais quelle lourdeur non ?).

tbop2
tbop2
Niveau 10
15 juin 2011 à 16:28:45

et faut que j'arrete la drogue : "et n'ont, a nouvel ordre, aucune raison d'etre refactores".

Je precise que le n n'est surtout pas dynamique, c'est un n fixe.

chris_27
chris_27
Niveau 10
15 juin 2011 à 16:59:25

Moi, j'ai tout juste compris que tu avais un nombre N fixé de flottants. :(

tbop2
tbop2
Niveau 10
15 juin 2011 à 19:19:58

Ouais la classe ressemble à ça quoi:

class Class
{
private:
float attribute1;
float attribute2;
...
float attributen.

}

Mais mes conclusions m'amènent à penser que je devrais plutôt la faire comme ceci:

class Class
{
public:
enum AttributeEnum
{
...
};

private:
std::map<AttributeEnum, float> mAttributes;

}

Du coup j'ai un code générique pour mon GetClosestDoodTo(5.f, ZeDoodEnum)

Comme ça

///////////////ClassCollector.cpp

Class* ClassCollector::GetClosestDoodTo(float value, AttributeEnum attribute_name)
{
...float global_mini = FLOAT_MAX;
...Class* mini_one = NULL;
...
...for(vector<Class>::iterator it = mDoods.begin() //blabla)
...{
......float current_mini = abs(value - it->GetAttribute(attribute_name));
......
......if(current_mini < global_mini)
......{
.........global_mini = current_mini;
.........mini_one = it;
......}
...}
...
...return mini_one;
...
}

///////////Class.cpp

float Class::GetAttribute(AttributeEnum attribute_name)
{
...return mAttributes[attribute_name];
}

tbop2
tbop2
Niveau 10
15 juin 2011 à 19:22:47

Avec ce code j'évite au maximum la redondance. Mais est-ce vraiment la solution optimale ?

chris_27
chris_27
Niveau 10
15 juin 2011 à 19:43:44

Tu évites la redondance de quoi ?

J'ai déjà pas compris pourquoi un map plutôt qu'un float[], encore moins pourquoi tu n'indexes pas tes N floats avec des entiers directement, et encore moins ce que tu cherches à faire. :(

_skip
_skip
Niveau 10
15 juin 2011 à 20:33:49

Merci,
J'ai aussi du mal à comprendre la démarche et je me demandais si j'étais pas juste complètement con en fait.

Pocolo
Pocolo
Niveau 10
15 juin 2011 à 20:37:08

J'avoue n'avoir compris qu'a moitié aussi. Pas toujours facile de savoir ce qui se passe dans la tête des autres.

tbop2
tbop2
Niveau 10
15 juin 2011 à 21:25:27

Non vous n'êtes pas complètement con du tout c'est moi qui résume mal j'imagine :)

Je vais essayer de vous montrer concrètement le cheminement problème.

J'ai une classe avec n attributs float. Je veux faire une méthode (ou plusieurs) qui fassent exactement la même chose pour chaque attribut. Dans mon cas précis, une méthode qui retourne la classe ayant la valeur la plus proche d'une valeur donnée (pour un attribut donné).
La façon conne serait de faire du copier-coller et de changer les lignes variables à chaque attribut. Ce qui aurait pour conséquence d'avoir un nom spécifique pour chaque méthode. C'est ultra lourd à maintenir et les copier-coller c'est dangereux et moche (redondance !).
La deuxième façon conne serait de passer par un GetAttribute(AttributeEnum) qui renverrait vers un beau grand switch pour déterminer.
La troisième méthode (la mienne), dynamiser un peu plus tout ça en passant par un mapping des attributs. C'est esthétiquement pas très conventionnel (aussi loin que je sache) et cache peut-être des jeux dangereux en aval.

Quelle est votre opinion ?

PS: On peut tout à fait passer par un float il n'y a aucun problème là-dedans, j'essayais juste de rendre ça un peu plus compréhensible à vos yeux mais en terme de performance il FAUT utiliser un float* en fait.

tbop2
tbop2
Niveau 10
15 juin 2011 à 21:26:56
  • La deuxième façon conne serait de passer par un GetAttribute(AttributeEnum) qui renverrait vers un beau grand switch pour déterminer quel est l'attribut demandé.

Si je finis pas mes phrases ça ne vous aidera pas non plus.

tbop2
tbop2
Niveau 10
15 juin 2011 à 21:27:33
  • On peut tout à fait passer par un float*

Bordel.

godrik
godrik
Niveau 30
15 juin 2011 à 22:25:45

un enum peut se caster en entier facilement, si tu ne fais pas de truc bizarre avec les valuere de l'enum, toutes les valeurs sont entre 0 et MAX. Du coup utiliser une map est redondant, un simple tableau suffirait.

note que si tu ajouter un MAX_VALUE a la fin de l'enum tu peux directement definir le tableau comme
float mAttributes[MAX_VALUE];

tbop2
tbop2
Niveau 10
15 juin 2011 à 23:24:56

-> "PS: On peut tout à fait passer par un float* il n'y a aucun problème là-dedans, j'essayais juste de rendre ça un peu plus compréhensible à vos yeux mais en terme de performance il FAUT utiliser un float* en fait."

Sinon godrik qu'en penses tu ? Je me dis finalement qu'il n'y a aucune raison de ne pas employer cette forme exotique de structuration des classes plutôt que celle que l'on m'a toujours apprise. Et en même temps je me dis que tout cela doit bien cacher quelque chose non ?

godrik
godrik
Niveau 30
16 juin 2011 à 00:54:55

mmm, ca m'apprendra a pas tout lire :)

la forme que tu proposes m'a l'air tres bien. Perso, j'aurais certainement fait un truc comme ca.

hyrulink2
hyrulink2
Niveau 7
16 juin 2011 à 13:03:43

Si ton n est vraiment fixe, la solution la plus flexible serait d'utiliser des templates:
template<int N>
class Class
{
public:
float get(int i) {...}
private:
float attrs[N];
};
Le problème ici est qu'on est obligé de tester dans get si i < N

On peut rendre le code un peu plus sûr et plus optimisé si on encapsule l'enum dans une classe, ça donnerai:
struct *Class // remplacer * par le nom de l'enum
{
enum Enum
{
..., // valeur d'enumeration
EndValue // permet d'indiquer la fin de l'enum
};
};

et pour Class:
template<typename T>
{
public:
float get(T::Enum i) {return attrs[i];}
private:
float attrs[T::EndValue];
};
Et la ta classe marche pour les enum qui suivent ce patron et est fortement typée.

Voila, j'ai peut-être répondu totalement à coté de la plaque...

tbop2
tbop2
Niveau 10
16 juin 2011 à 14:17:32

Non mais tu n'es pas a cote de la plaque mais tu as pas mal repete ce que j'avais deja ecrit (ou explicitement sous-entendu (ca a du sens cette phrase ?)). :)

Pas mal le coup de l'enum template sinon !

Sous forums
  • Aide à l'achat Mac
  • Internet
  • Macintosh
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Steam Deck
  • Hardware
La vidéo du moment