Méthodes de commodité + MVC + Accesseurs
muqaddar
Administrateur
Pour mon application, j'aimerais avoir votre avis sur mes modèles.
J'ai pour habitude de remplir mes variables d'instances par un constructeur de commodité.
Actuellement, je récupère du SQL, et j'ai donc créé ce constructeur :
Or, FMResultSet est un objet (hérité de NSObject) qui contient les données SQL (il a donc été rempli par une reqûete SQL mais je n'ai pas moyen de le remplir sans requête apparemment). C'est parfait pour charger ce qui existe déjà dans la base, mais pas pour créer une instance en vue d'une insertion dans la base (car apparemment ce FMResultSet n'a pas de setters sur les données de son contenu).
J'ai donc créé un autre constructeur de commodité pour charger ce qui provient d'un formulaire avant un nouvel enregistrement.
Ici, on a un dictionnaire qui sera rempli d'objets provenant du formulaire. Ces objets seront chargés dans les iVars de la classe.
1) Est-ce une hérésie d'avoir 2 constructeurs de commodités en MVC ?
2) Je pourrais faire un constructeur avec la liste de toute mes variables (dans le cas du deuxième), mais j'en ai 15 donc je préfère envoyer un dico qui contient tout...
3) Bien sur, je ne pourrais avoir qu'un constructeur avec les 2 arguments FMResultSet ou NSDictionnary et tester nil dessus, mais n'est ce pas moins propre ?
J'ai pour habitude de remplir mes variables d'instances par un constructeur de commodité.
Actuellement, je récupère du SQL, et j'ai donc créé ce constructeur :
- (id)initWithPrimaryKey:(NSUInteger)anId rows:(FMResultSet*)dbRows {<br /> if (self = [super init]) {<br /> <br /> self._id = anId;<br /> <br /> self._name = [[dbRows stringForColumn:@"name"] retain]; <br /><br /> }<br /> return self;<br />}
Or, FMResultSet est un objet (hérité de NSObject) qui contient les données SQL (il a donc été rempli par une reqûete SQL mais je n'ai pas moyen de le remplir sans requête apparemment). C'est parfait pour charger ce qui existe déjà dans la base, mais pas pour créer une instance en vue d'une insertion dans la base (car apparemment ce FMResultSet n'a pas de setters sur les données de son contenu).
J'ai donc créé un autre constructeur de commodité pour charger ce qui provient d'un formulaire avant un nouvel enregistrement.
- (id)initWithPrimaryKey:(NSUInteger)anId dict:(NSDictionary*)aDict {<br /> if (self = [super init]) {<br /> <br /> self._id = anId;<br /> <br /> self._name = [dict objectForKey:@"name"];<br /> }<br /> return self; <br />}
Ici, on a un dictionnaire qui sera rempli d'objets provenant du formulaire. Ces objets seront chargés dans les iVars de la classe.
1) Est-ce une hérésie d'avoir 2 constructeurs de commodités en MVC ?
2) Je pourrais faire un constructeur avec la liste de toute mes variables (dans le cas du deuxième), mais j'en ai 15 donc je préfère envoyer un dico qui contient tout...
3) Bien sur, je ne pourrais avoir qu'un constructeur avec les 2 arguments FMResultSet ou NSDictionnary et tester nil dessus, mais n'est ce pas moins propre ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
stringWithFormat, stringWithContentsOfFile, stringWithString, stringWithCString:encoding: ... tu crois que c'est quoi tout ça ?
Non pour ma part ça ne me choque pas trop comme design... Le seul truc qui pourrait potentiellement paraà®tre gênant c'est de passer un NSDictionary contenant tes valeurs de variables... et encore que c'est acceptable quand même.
L'autre solution est de faire des accesseurs pour chacunes de tes variables (plutôt que de les passer lors de la construction, tu les passes une par une juste après ton appel au constructeur). Mais bon ça veux dire qu'alors tu pourras les modifier après la construction, alors que tu veux peut-être éviter que ça puisse être le cas.
C'est vrai que j'y ai pensé de passer chaque variable... Ainsi j'aurais un "alloc, init" générique puis des appels aux setters comme tu dis. Pourquoi pas.
Il est possible que je veuille les modifier après la construction en tout cas.
Merci Ali.
Euuh les 2 bouts de code que tu nous a copiés ne sont pas des constructeurs de comodité, mais des méthodes d'initialisation d'instance "normales". ???
Les constructeurs de commodité sont des méthodes de classe qui commencent par n'importe quoi sauf alloc, init et copy.
Mais bon, ça ne change pas le problème que c'est tout à fait acceptable d'avoir plusieurs constructeurs (ou plutôt dirons nous plusieurs initialiseurs). Du moment que tu n'en n'appelles qu'une seul, et qu'une fois
(je dis ça parce que j'ai récupéré un projet là où dans le code d'un initWithTruc il y a un appel à [super initWithTruc] + un [self init] (qui est pourtant déjà fait dans le super), ça m'a foutu bien la zone ^^)
Voilà donc au final un vrai constructeur (convenience method) et sa méthode d'initialisation :
Pendant que j'y suis :
ou
ça change quelque chose à la compil ou en consommation processeur/mémoire ?
[tt]_countryId = xx[/tt] ça affecte xx à la variable (locale ou d'instance quelle qu'elle soit) _countryId. Juste une bête affectation comme a=5
[tt]self._countryID = xx[/tt] est traduit par le compilo de la même manière que [tt][self setCountryID:xx][/tt], donc appelle la méthode de setter de la variable. Méthode qui est en réalité souvent autogénérée via le @synthesize, en fait.
Or ce setter est loin de faire une bête affectation (sauf s'il est de type "nonatomic, assign" à la limite), puisqu'il gère le multithreading (sauf si tu mets "nonatomic" en définissant la @property) avec des @synchronize automatiquement, génère les événements de KVO (will/didChangeValue:forKey: ) mais aussi et surtout gère la mémoire (retain du nouvel objet / release de l'ancienne valeur).
Génial, merci de ta réponse.
J'ai bien compris.
Donc c'est très utile dans mon cas.