Recherche parmi toutes les instances d'une classe

FloFlo Membre
23:26 modifié dans API AppKit #1
Bonjour à  tous,

Disons que j'ai une classe C (couche modèle) : C ->> C

Lorsque le constructeur de C est appelé pour créer c, il télécharge des données d (en mode synchrone).

Le problème c'est que ce nouveau c doit aussi créer d'autres c' que l'on initialise aussi à  partir de d. Chaque instance de C ayant un code, je cherche un moyen de savoir si les nouveaux codes contenu dans d n'existe pas déjà  pour ne pas ajouter deux c avec le même code.  ???

J'ai pensé à  plusieurs solution sachant que tous les codes doivent être accessibles par le constructeur de la classe C :
- Une variable de classe dans C contenant les références de toutes les instances
  - Un singleton qui connaà®trait tous les c

Vous en pensez quoi ?  :)

Réponses

  • Philippe49Philippe49 Membre
    août 2009 modifié #2
    Et c'est obligatoire cette imbrication ? Tu ne peux pas télécharger les données d d'abord ?

    dans 1249742664:

    Chaque instance de C ayant un code, je cherche un moyen de savoir si les nouveaux codes contenu dans d n'existe pas déjà  pour ne pas ajouter deux c avec le même code.  ???

    Je ne comprends pas trop cette histoire de code. Le code dont tu parles c'est une partie des données de d et tu veux en quelque sorte partager les données de d entre les différentes instances c ?
  • FloFlo Membre
    août 2009 modifié #3
    Bon je vais arrêter avec mes lettres parce que je suis en train de m'apercevoir que c'est encore moins clair  :)

    En fait je suis sur une petite application de gestion de portefeuille boursier. Les marchés et les actions sont représentés par la même classe "Symbol". Du coup, un "Symbol" peut en contenir d'autres quand il s'agit d'un "Symbol" de marché.

    Quand je souhaite ajouter un "symbol" de marché, le constructeur télécharge d'un coup les données concernant le marché et tous les "Symbol" actions associées. Si les "Symbol" d'actions associées n'existent pas il faut les créer sinon il faut récupérer ceux qui existent et les ajouter. D'où l'importance de pouvoir vérifier si les objets "Symbol" correspondant aux données n'existent pas.

    La recherche s'effectue par le code qui est un attribut NSString de chaque symbol. Ce qu'il me faut c'est juste le moyen le plus "objet" et MVC pour un nouveau "Symbol" de marché de savoir si tous ces "Symbol" action qu'il contient n'existe pas déjà  pour ne pas créer de doublons.

    J'avais deux solutions pour ça :
    - une variable de classe pour la classe "Symbol" contenant les références de toutes les instances
    - un singleton genre SymbolManager accessible par le constructeur de la classe "Symbol" et référençant tous les instance de la classe "Symbol"

    J'ai un peu de mal à  restituer la situation de manière fidèle, désolé  :(
    J'espère avoir été un petit peu plus clair, merci déjà  pour ta réponse   :)
  • Philippe49Philippe49 Membre
    août 2009 modifié #4
    Oui comme cela c'est plus clair. C'est l'initialisation d'un graphe, genre faux arbre permettant à  un noe“ud d'avoir plusieurs pères. Et tu peux avoir trois étages marché -> sous-marché -> action ?

    Je serais tenté par CoreData et les fetch request ...
  • Philippe49Philippe49 Membre
    23:26 modifié #5
    Autrement plus bêtement, les asset ont un identifier, il suffit d'avoir un tableau BOOL V[50000] , et chaque fois qu'un nouvel asset est proposé d'identifier ident, tester V[ident] et le mettre à  YES.
  • FloFlo Membre
    23:26 modifié #6
    C'est vrai qu'avec core data c'est vite réglé mais mon appli est déjà  commencée et ça me prendrais un peu de temps de l'intégrer...

    Dans l'idée si on veut l'exprimer avec core data ça donnerait plutôt ça (voir image)

    Sinon il n'y a que deux niveaux, marché et action exprimés par la même classe.
    Le code de chacun est fournis par le site et est de la forme :
    - UNECHAINE.EXTENSION

    L'idée d'un NSMutableArray en variable de classe référençant toutes les instances de la classe Symbol me plaà®t bien moi, tu en penses quoi ?
  • Philippe49Philippe49 Membre
    août 2009 modifié #7
    En fait je n'ai pas de préférences entre les deux solutions que tu proposes, je pense à  l'optimisation. Je vois mal une variable statique, donc dans le code de la classe, être de capacité extensible (?), donc j'irais plutôt vers une NSMutableArray contrôlée par l'AppDelegate ou un singleton. 
    Si tu envisages plusieurs marchés financiers, cela fait une sacré base de données. Evidemment si il s'agit du portefeuille d'un individu ou d'un groupe d'individu  c'est moins conséquent.
    C'est curieux je vois plus de solutions en C qu'en ObjectiveC, en maintenant trié des tableaux, avec recherche dichotomique. NSMutableArray, NSPointerArray, CFBag, je ne vois pas de collection qui possède la méthode insert:(id)anObject usingSortFunction:(NSInteger (*)(id, id, void *))compare context:(void*)context
  • FloFlo Membre
    23:26 modifié #8

    Je vois mal une variable statique, donc dans le code de la classe, être de capacité extensible (?)


    Il me semblait que c'était possible pourtant non ? Parce que en terme d'accès c'est le plus pratique  ;).

    Sinon le singleton c'est vrai que c'est pas mal non plus  :)


    C'est curieux je vois plus de solutions en C qu'en ObjectiveC, en maintenant trié des tableaux, avec recherche dichotomique. NSMutableArray, NSPointerArray, CFBag, je ne vois pas de collection qui possède la méthode insert:(id)anObject usingSortFunction:(NSInteger (*)(id, id, void *))compare context:(void*)context


    J'ai fais un petit algo d'insertion dichotomique à  un moment, j'avais posé la question sur ce forum et on m'avait répondu que les classe NSArray et NSDictionary étaient bien assez optimisées (ce qui n'est pas faux  ;D)

    Ha oui au passage, qui est le plus rapide en recherche sur un code ivar de type string, NSArray+NSPredicate ou NSDictionary ?
  • Philippe49Philippe49 Membre
    août 2009 modifié #9
    dans 1249825879:


    Je vois mal une variable statique, donc dans le code de la classe, être de capacité extensible (?)


    Il me semblait que c'était possible pourtant non ? Parce que en terme d'accès c'est le plus pratique  ;).

    Possible peut-être, les collections peuvent s'étendre comme des listes chaà®nées dynamiquement, mais c'est au moins bizarre.


    dans 1249825879:

    J'ai fais un petit algo d'insertion dichotomique à  un moment, j'avais posé la question sur ce forum et on m'avait répondu que les classe NSArray et NSDictionary étaient bien assez optimisées (ce qui n'est pas faux  ;D)

    Oui je me souviens de cette discussion, mais la réponse était sur l'insertion d'un objet à  un indice connu.  Je ne sais pas si il existe des tests de rapidité pour les méthodes containsObject: ou  indexOfObject: .

    Si c'est possible en termes de capacité, je comparerais avec un système de tag comme indiqué plus haut.
  • FloFlo Membre
    23:26 modifié #10
    Ok, merci pour tes réponses  :)
  • FloFlo Membre
    23:26 modifié #11
    J'ai trouvé ça sur la doc apple, à  priori, utiliser une variable de classe pour offrir la possibilité aux instances de faire des recherche sur les autres peut se faire :


    Static variables help give the class object more functionality than just
    that of a "factory" producing instances; it can approach being a
    complete and versatile object in its own right. A class object can be
    used to coordinate the instances it creates, dispense instances from
    lists of objects already created
    , or manage other processes essential to
    the application.

    In the case when you need only one object of a
    particular class, you can put all the object's state into static
    variables and use only class methods. This saves the step of allocating
    and initializing an instance.



    J'ai (enfin) retrouvé la partie de la doc (en italique) sur laquel shlum m'avait demandé de me justifier ya un petit moment  :P
  • Philippe49Philippe49 Membre
    août 2009 modifié #12
    Impressionnant tout de même la rapidité dans la recherche par containsObject

    Pour une NSMutableArray de 1 million d'instances, on obtient les comparaisons suivantes

    % gcc essai.m -o pgm -framework Foundation
    % pgm
    Temps de chargement : 0.810794
    Test par containsObject : positif : 0.005012
    Test par le tableau de booléen : positif : 0.000004
    vidage : 0.571266
    %


    Evidemment l'utilisation d'un tableau de booléens est largement plus efficace, mais containsObject: est tout de même impressionnant !

    #import &lt;Foundation/Foundation.h&gt;<br />#define N 1000000 //10000000<br /><br />@interface ClassA : NSObject&nbsp; {<br />	NSUInteger tag;<br />}<br />@property NSUInteger tag; <br />-(id) initWithTag:(NSUInteger) aTag;<br />@end<br /><br />@implementation ClassA<br />@synthesize tag;<br />-(id) initWithTag:(NSUInteger) aTag {<br />	self=[super init];<br />	if(self) {<br />		tag=aTag;<br />	}<br />	return self;<br />}<br />@end<br /><br /><br /><br />int main (int argc, const char * argv&#91;]) {<br />	NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />	NSMutableArray * array=[NSMutableArray array];<br />	ClassA * specialA;<br />	NSUInteger tag;<br />	char isPresent[N]={0}; <br />	<br />	struct timeval tv;<br />	gettimeofday(&amp;tv,0);<br />	unsigned long long t0 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	for(tag=0;tag&lt;N;tag++) {<br />		ClassA * a=[[[ClassA alloc] initWithTag:tag] autorelease];<br />		if(tag==N/2) {<br />			specialA=a;<br />		}<br />		isPresent[tag]=1;<br />		[array addObject:a];<br />	}<br />	gettimeofday(&amp;tv,0);<br />	unsigned long long t1 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	fprintf(stderr,&quot;Temps de chargement : %f&#092;n&quot;,(t1-t0)/(1000.*1000.));	<br /><br />	// Existence de specialA par containsObject:<br />	gettimeofday(&amp;tv,0);<br />	t0 = tv.tv_sec*1000*1000+tv.tv_usec;<br />	BOOL test=[array containsObject:specialA];<br />	gettimeofday(&amp;tv,0);<br />	t1 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	fprintf(stderr,&quot;Test par containsObject : %s : %f&#092;n&quot;,test?&quot;positif&quot;:&quot;negatif&quot;,(t1-t0)/(1000.*1000.));<br /><br />	// Existence de specialA par le tableau de booléens:<br />	gettimeofday(&amp;tv,0);<br />	t0 = tv.tv_sec*1000*1000+tv.tv_usec;<br />	test=isPresent[specialA.tag];<br />	gettimeofday(&amp;tv,0);<br />	t1 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	fprintf(stderr,&quot;Test par le tableau de booléen : %s : %f&#092;n&quot;,test?&quot;positif&quot;:&quot;negatif&quot;,(t1-t0)/(1000.*1000.));<br />	<br />	// vidage<br />	gettimeofday(&amp;tv,0);<br />	t0 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	[pool drain];	<br />	gettimeofday(&amp;tv,0);<br />	t1 = tv.tv_sec*1000*1000+tv.tv_usec;	<br />	fprintf(stderr,&quot;vidage : %f&#092;n&quot;,(t1-t0)/(1000.*1000.));<br />	<br />	return 0;<br />}<br />
    


  • FloFlo Membre
    23:26 modifié #13
    Oui en effet, l'implémentation sous-jacente de NSMutableArray doit vraiment être bien pensée !!  :)

    Sinon j'ai une petite question, si je délègue le travail de recherche d'une instance "Symbol" par son code à  l'appDelegate, le fait qu'une classe du modèle accède au controller n'est pas contraire au MVC ?
  • FloFlo Membre
    23:26 modifié #14
    Genre est-ce choquant de faire (sachant que Symbol est une classe de la couche modèle):

    <br /><br />+ (id) symbolForCode: (NSString *)aCode <br />{<br />&nbsp;  id appDelegate = [NSApp delegate];<br /><br />&nbsp;  if (![appDelegate contains: aCode])<br />&nbsp;  {<br />&nbsp; &nbsp; &nbsp;  Symbol *aSymbol = [[Symbol alloc] init];<br /><br />&nbsp; &nbsp; &nbsp;  // téléchargement des données + ajout des symbols&nbsp; &nbsp; <br /><br />&nbsp; &nbsp; &nbsp;  return [aSymbol autorelease];<br />&nbsp;  }<br /><br />&nbsp;  return nil;<br />}<br /><br />
    

  • Philippe49Philippe49 Membre
    août 2009 modifié #15
    Peut-être faudrait-il qu'un théoricien te donne une réponse.
    Pour ma part, cela ne me choque pas, mieux je trouve cela correct : AppDelegate joue ici un rôle de contrôleur général du model et le fait de décider de ce qui est créé dans le model est pour moi attribué au contrôleur. Le rôle de la couche model, les méthodes qu'elle implémente, concerne plutôt la gestion, les fonctions d'initialisations.
    En gros dans le parallèle qu'on pourrait faire avec une entreprise,
    • Le model est une zone de stockage, de rangement, d'exécution de tâches courantes,
    • Le contrôleur est une zone de décision, de choix/création du modèle, et de connexion/validation  avec la partie clientèle que constitue la view. 
  • mpergandmpergand Membre
    23:26 modifié #16
    dans 1249912465:

    Sinon j'ai une petite question, si je délègue le travail de recherche d'une instance "Symbol" par son code à  l'appDelegate, le fait qu'une classe du modèle accède au controller n'est pas contraire au MVC ?


    Prenons un exemple concret:
    Je fais une recherche (contrôleur) sur une base de données (modèle)  qui me renvoie un nom de personne, mais en fait c'est une référence sur une table externe. J'ai donc 2 possibilités, soit résoudre cette référence externe directement dans le modèle, soit effectuer une deuxième requête au niveau du contrôleur.

    Mais demander au modèle de passer par le contrôleur c'est  B)
  • FloFlo Membre
    23:26 modifié #17

    Mais demander au modèle de passer par le contrôleur c'est  B)


    Hum... c'est bien ce que je pensais.  :-\\

    Merci pour vos réponses, je pense que je vais tester la solution du NSMutableArray en variable de classe, la doc apple n'a pas l'air d'être en désaccord avec cette solution  :)
Connectez-vous ou Inscrivez-vous pour répondre.