Débat Objective-C 2.0

AliGatorAliGator Membre, Modérateur
05:28 modifié dans Actualités #1
Quoi tu n'aimes pas les @property/@synthetize ?
Et les foreach ?

Bon pour le Garbage Collector, je suis d'accord, ça va avec les bouses ^^
«1345

Réponses

  • schlumschlum Membre
    05:28 modifié #2
    dans 1228940251:

    Quoi tu n'aimes pas les @property/@synthetize ?
    Et les foreach ?

    Bon pour le Garbage Collector, je suis d'accord, ça va avec les bouses ^^


    Bah les propriétés ça ne sert à  rien... Quand on programme c'est pas construire les accesseurs qui prennent le plus de temps.
    C'est de la politique du tout cru dans la bouche à  la Java. Et surtout, ça amène cette espèce de syntaxe en "." que j'abhorre dans ce contexte.
    Le "foreach", pareil... une espère de truc à  la PHP qui ne sert pas à  grand chose.
  • AliGatorAliGator Membre, Modérateur
    05:28 modifié #3
    Moi j'aime bien le @synthetize non pas seulement pour éviter d'avoir à  créer les accesseurs (certes ça prend pas tant des masses de temps mais c'est quand même ça de gagné, et c'est pas rien, c'est comme si tu dénigrais l'autocomplétion ou les text-macros, le cumul des petits temps gagnés finit par être considérable)

    Après la syntaxe avec le "." moi ça me dérange pas mais je comprend que ça puisse dérouter. Mais rien ne t'empêche de t'en passer :P
    Le foreach c'est pareil ça permet de faire des "fast-enumerations", il parait que c'est plus rapide qu'un for ou même qu'un NSEnumerator, perso je pense jamais à  les utiliser ^^
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #4
    Les propriétés, selon moi, apporte une très bonne réponse à  ce que je hais le plus en Java, bien sûr en Cocoa il y a déjà  le KVC mais cette technique explicite un peu plus les accesseurs et surtout la manière d'accéder et avec quels noms...
    Ce que je hais le plus en java c'est le concept des beans qui t'oblige littéralement à  définir une variable d'instance et les accesseurs setIvar() et getIvar() correspondant, ça fait des lignes de codes inutiles répétitives même avec un générateur, et surtout ça gêne la vue !
    Toute technique permettant de réduire le nombre de lignes de codes sans changer le fonctionnement de ce dernier est bonne à  prendre.

    Pour la syntaxe avec . j'ai un sentiment mitigé, ça fait un peu double emploie avec le . qui est normalement réservé aux structures (et non au pointeur de structure comme le sont les objets ObjC), et ça masque aussi le fait qu'il s'agisse bien d'un message.
    Cependant, d'un autre côté, ça permet de faire de la vérification de type à  la compilation, ça réduit le nombre de crochets qui peuvent nuire à  la lisibilité du code, mais aussi ça permet de faire la différence entre un message normal et un accesseur, ça permet de voire qu'on veut une variable d'instance, et non pas envoyer un simple message.

    Pour le foreach, je trouve ça assez utile, ça permet encore une fois de simplifier la syntaxe ce qui n'est jamais négligeable, mais aussi Apple a implémenté ça sous forme de "hack" permettant de réduire le nombre d'envoie de messages à  la structure principale, un message peut récupérer une dizaine d'objets, permettre à  l'utilisateur d'itérer dans ces objets et ensuite récupérer la dizaine suivante, ce qui induit forcément une vitesse de la boucle accrue.

    Cependant, le foreach sera bientôt dépassé par les merveilleux et ô combien puissants blocks ! Permettant à  l'implémenteur de la structure à  itérer de concevoir la boucle la plus efficace possible et de simplement passer les objets itérés au block de code passé en paramètre. Réduisant ainsi au maximum l'influence de l'itération sur l'exécution de la boucle, avec ça seul le code de l'utilisateur sera à  blâmer en cas de ralentissement. :D
  • schlumschlum Membre
    05:28 modifié #5
    dans 1228955535:

    Les propriétés, selon moi, apporte une très bonne réponse à  ce que je hais le plus en Java, bien sûr en Cocoa il y a déjà  le KVC mais cette technique explicite un peu plus les accesseurs et surtout la manière d'accéder et avec quels noms...
    Ce que je hais le plus en java c'est le concept des beans qui t'oblige littéralement à  définir une variable d'instance et les accesseurs setIvar() et getIvar() correspondant, ça fait des lignes de codes inutiles répétitives même avec un générateur, et surtout ça gêne la vue !
    Toute technique permettant de réduire le nombre de lignes de codes sans changer le fonctionnement de ce dernier est bonne à  prendre.


    C'est pas Java, c'est relatif à  tout langage objet, et ça s'appelle l'encapsulation  :P
    Les accesseurs, ce sont de toutes petites fonctions de 2/3 lignes qu'on case dans un coin, flaguées avec un pragma mark ; et en général on ne fait que les accesseurs dont on a besoin ! (sinon, on ruine l'encapsulation  :o)
    Par ailleurs, un accesseur peut gérer plusieurs variables d'un coup, que ça soit en lecture ou en écriture, et selon la logique du programme.

    Avec leurs trucs de propriétés, synthethize, de . et cie, on ne s'y retrouve plus, c'est une vraie cacophonie !
  • AliGatorAliGator Membre, Modérateur
    05:28 modifié #6
    Non je suis plutôt de l'avis de psychoh13 sur ce coup, désolé schlum :P
    En plus le coup des accesseurs dont parle psychoh13 c'est propre à  Beans dans le sens ou oui c'est de l'encapsulation, mais c'est obligatoire pour faire de ta classe un Beans, même pour les plus simplistes des variables d'instance.
    Et quand tu commences à  avoir genre 20 ou 30 variables d'instances, ben un entre 200 à  300 lignes minimum (un getter + un setter fait au minimum 10 lignes en tout, et encore quand il est pas thread-safe et tout car dans ce cas c'est plus) à  écrire...
    Alors qu'un [tt]@synthetize var1, var2, var3, var4, var5, ...[/tt] ça prend une à  3 lignes (si on ne veut pas tout mettre sur la même ligne histoire de répartir un peu) et ça pollue quand même vachement moins le code :P

    Par contre ce que je reproche aux @properties d'un autre côté c'est d'avoir à  les déclarer comme variables d'instances (ce qui n'est plus le cas dans le Runtime 64 bits d'ailleurs, dommage que ça ne le soit pas avec le Runtime 32 bits) parce que quitte à  faciliter la déclaration combinée des ivars, getters et setters, ça aurait été bien de tout faire en une ligne plutôt que "type mavar" + "@property(...) type mavar".





    Tiens sinon j'ai du mal à  comprendre comment les futurs blocks introduits dans le dernier gcc et la LLVM peuvent accélérer les boucles, dans les faits, enfin sous le capot ?

    PS : Les admins, un split du sujet pour créer un thread à  part, genre "débat sur Objective-C 2.0" ?
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #7
    dans 1228957387:

    C'est pas Java, c'est relatif à  tout langage objet, et ça s'appelle l'encapsulation  :P
    Les accesseurs, ce sont de toutes petites fonctions de 2/3 lignes qu'on case dans un coin, flaguées avec un pragma mark ; et en général on ne fait que les accesseurs dont on a besoin ! (sinon, on ruine l'encapsulation  :o)
    Par ailleurs, un accesseur peut gérer plusieurs variables d'un coup, que ça soit en lecture ou en écriture, et selon la logique du programme.

    Avec leurs trucs de propriétés, synthethize, de . et cie, on ne s'y retrouve plus, c'est une vraie cacophonie !


    Deux trois lignes de code c'est énorme pour quelque chose qu'on peut facilement générer automatiquement. L'encapsulation, bien sûr c'est important, et c'est inhérent aux langages objets ; cependant, créer des accesseurs pour le simple plaisir d'avoir des accesseurs est idiot.
    Ce qui m'énerve en Java, C# ou même C++, c'est de voir ce genre de truc :

    private String variable;<br />public String getVariable()<br />{<br /> &nbsp; &nbsp;return variable;<br />}<br /><br />public void setVariable(String v)<br />{<br /> &nbsp; &nbsp;variable = v;<br />}
    


    Quand je vois ça je me dis "autant mettre public String variable; et on en parle plus" ça fait autant et avec le dispatching des méthodes en moins !
    Personnellement, je code beaucoup dans divers langages, je me passerais bien d'avoir à  écrire toutes ces lignes de code répétitives qui prennent de la place et gêne beaucoup la lisibilité !

    Le système KVC de Cocoa a l'avantage de donner aux objets des implémentations par défaut pour les variables d'instance auxquelles ont autorise l'accès, ce que fait @property/@synthesize, et si on veut avoir un accesseur spécifique, genre le nom complet d'une personne qui est en fait l'association de la variable prénom et de la variable nom, on crée un accesseur personnalisé. Mais ce genre d'accesseur personnalisé représente, alors pour être gentil 10 à  20% de la masse des acceseurs... Si je peux me passer d'écrire tout ce code inutile, je dis pas de problème, même avec un générateur d'accesseur aussi bon soit-il.
    Et puis l'avantage de @synthesize par rapport à  KVC c'est que tu n'as pas la recherche dynamique de la variable d'instance, ou de son accesseur, à  faire, ce qui réduit considérablement le temps de récupération...


    ça me rappelle une vidéo d'un mec java-addict qui avait découvert le python, là  où toutes les variables d'instance sont publics, pas de problème si bien sûr on assume qu'on est tous des adultes consentants, bon toujours est-il que la manière d'accéder à  une ivar en python est la même qu'en passant par un accesseur, et d'ailleurs c'est exactement le même nom, il suffit de fournir une implémentation de l'accesseur dans le cas où ce ne serait pas un simple ivar = value ou return ivar, et l'utilisation de l'accesseur se fait de façon transparente, comme KVC et @synthesize, et ce genre de trucs n'est vraiment pas négligeable.

    Et encore une fois ce n'est pas par flemmardise, c'est surtout parce que, comme l'a dit ce mec, le code est plus souvent lu que écrit, donc il vaut mieux toujours rendre son code le plus lisible possible, c'est d'ailleurs pour ça que les noms des méthodes ObjC sont si longs, c'est simplement pour construire des phrases lisibles par un être humain...



    @AliGator: Le truc pour le coup du 64 bits, à  mon avis la raison pour laquelle ils ne l'ont pas fait en 32 c'est simplement parce que le système doit bientôt passer en full-64 et que les 32 bits seront obsolète, à  mon avis ils ont voulu "repartir" à  zéro.
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #8
    dans 1228958161:
    Tiens sinon j'ai du mal à  comprendre comment les futurs blocks introduits dans le dernier gcc et la LLVM peuvent accélérer les boucles, dans les faits, enfin sous le capot ?


    Je vais prendre l'exemple le plus frappant, à  mon humble avis, celui des dictionnaire.
    Quand tu veux itérer dans un dictionnaire tu dois toujours le faire en deux étapes, tu dois itérer dans les clés et récupérer les valeurs correspondantes aux clés, avec la nouvelle boucle foreach ça donne ça :

    for(id key in dict)<br />{<br />&nbsp; &nbsp; id obj = [dict objectForKey: key];<br />&nbsp; &nbsp; // code utilisant la clé et sa valeur<br />&nbsp; &nbsp; NSLog(@&quot;dict[%@] = %@&quot;, key, value);<br />}
    


    Comme ça, ça à  l'air simple, efficace et rapide, mais il n'en est rien, certe le foreach accélère l'itération des clés, mais il n'est pas capable d'accélérer la récupération des valeurs qui doit rester une initiative de l'utilisateur.
    Quand tu récupères la valeur grâce à  sa clé, il va chercher dans une table de hashage la bonne case, bien sûr une table de hashage est faite pour être très rapide, mais il n'empêche que ce n'est pas un accès direct, qu'il demande un hashage et qu'en plus il nécessite au moins le message objectForKey: tous ces facteurs alourdissent la boucle ; bien sûr ça dépend de la taille du dictionnaire, plus il y a de valeurs plus c'est lent.

    Maintenant, voici la version avec un block:

    [dict iterateKeysAndValuesUsingBlock: ^(id key, id value, BOOL *stop)<br />{<br />&nbsp; &nbsp; NSLog(@&quot;dict[%@] = %@&quot;, key, value);<br />}];<br />
    


    Ce qu'on voit ici, c'est qu'on donne à  une méthode de la classe un block de code qu'on va lui demander d'utiliser pour chaque élément du dictionnaire. D'une certaine manière, on "change" l'implémentation de la méthode en lui donnant un morceau de code qui sera exécuté dans la boucle implémentée par le développeur de la classe.

    Le truc c'est que iterateKeysAndValuesUsingBlock: a un accès DIRECT à  la structure interne du dictionnaire, nous on n'a qu'un accès indirect grâce à  objectForKey:, ce qui fait qu'on va laisser à  l'implémenteur de la classe le soin de concevoir la boucle la plus efficace possible (et je fais confiance à  Apple pour ça) pour récupérer, et c'est ça qui est important, EN MàŠME TEMPS, à  la fois la clé et la valeur qui y correspond.

    Tout ce que l'utilisateur aura donc à  faire c'est de fournir un code permettant de traiter ce couple clé/valeur sans avoir à  se soucier de la boucle elle-même. La méthode nous garantit qu'elle va envoyer à  notre block les objets qu'on veut, et nous, nous faisons les traitements qu'on veut.
    Et puis, quand bien même l'algorithme implémenté dans la méthode ne serait pas aussi efficace que le foreach, ne pas avoir à  se soucier de concevoir correctement la boucle et de n'avoir à  se soucier que de la gestion des données elles-mêmes est un avantage certain !
    Les blocks permettent aux implementeurs d'écrire des algorithmes à  la fois optimisés ET flexibles et aux utilisateurs de se concentrer sur l'essentiel de leur boulot c'est-à -dire le traitement des données.
  • schlumschlum Membre
    05:28 modifié #9
    Bah, pas convaincu...
    Dire que ça gêne la lisibilité c'est de la mauvaise foi  :P ils sont tous rassemblés à  la fin de la classe, ça ne gêne rien du tout  :)

    Et pour le debug, comment on fait pour savoir à  quel moment telle variable d'instance passe à  telle valeur buguée ? On mets le point d'arrêt sur le @synthetize ?  ???

    Et c'est quoi cette histoire de haricots  :o Depuis quand il faut définir un setter et un getter pour toutes les variables d'instance ?  ???
    La logique objet c'est justement d'avoir le moins d'accesseurs possible au profit de traitements internes !
    Sinon effectivement, on met tout en public et basta...  :o
  • schlumschlum Membre
    05:28 modifié #10
    dans 1228959478:

    [dict iterateKeysAndValuesUsingBlock: ^(id key, id value, BOOL *stop)<br />{<br />&nbsp; &nbsp; NSLog(@&quot;dict[%@] = %@&quot;, key, value);<br />}];<br />
    



    Et on s'approche de plus en plus du PHP... À quand la version Objective-C PHP ?  :P

    Ce qu'on perd de vue, c'est qu'un dictionnaire n'est pas fait pour être itéré comme ceci (pour la bonne raison déjà  qu'on ne peut garantir l'ordre)... Si on veut itérer quelque chose, les tableaux sont là  pour ça !
    À qui ça viendrait à  l'idée (quand on est dans son état normal  :)) de prendre un dictionnaire et de lire un par un les mots, puis leur définition (et ce dans le désordre en plus...) ?  :P
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #11
    Les beans sont des inepties inventées par java pour java, et dont les java-addict raffole, ce sont en général des classes de stockages dont le code est à  99% prévisibles, et l'exigence c'est que toutes les variables d'instance d'un beans doivent avoir un getter/setter correspondant...

    Sinon, la logique objet c'est surtout de pouvoir avoir les données et les traitements sur les données dans un même paquet, mais pour les classes de models sont faites en général pour stocker les données et doivent donc permettre l'accès à  la plupart de leurs variables d'instances.

    Sinon le débogage n'est certe pas facilité avec les @synthesize, mais les bindings rendaient déjà  la tâche pas facile, cependant, étant donné qu'en général les trucs auto-générés sont efficaces et sans bogues, et bien ça réduit fortement les endroits qui génèrent des bogues dans ce que t'as écrit.
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #12
    dans 1228960002:

    Et on s'approche de plus en plus du PHP... À quand la version Objective-C PHP ?  :P

    Ce qu'on perd de vue, c'est qu'un dictionnaire n'est pas fait pour être itéré comme ceci (pour la bonne raison déjà  qu'on ne peut garantir l'ordre)... Si on veut itérer quelque chose, les tableaux sont là  pour ça !
    À qui ça viendrait à  l'idée (quand on est dans son état normal  :)) de prendre un dictionnaire et de lire un par un les mots, puis leur définition (et ce dans le désordre en plus...) ?  :P


    Les blocks cherchent entre autre à  remplacer les callbacks sous forme de pointeurs de fonctions, ce genre de conception est loin d'être réservé à  PHP, qui d'ailleurs, soit dit en passant, n'a implémenté les closures (synonyme de blocks) que très tard (version 4 voire même 5 minimum), ce genre de syntaxe se rapproche plus de javascript.

    Pour ce qui est d'itérer un dictionnaire... Bien sûr que si qu'on a parfois besoin d'itérer toutes les clés du dictionnaire, par exemple dans le cas où le dictionnaire représente une liste de paramètres.
    Par exemple, NSAttributedString, tu peux passer une liste de style à  appliquer, et pour chaque clé tu associes une valeur, genre couleur du texte, taille du texte, police du texte. Tu vas itérer dans le dictionnaire pour savoir quels sont les paramètres à  mettre en place, et l'avantage c'est que tu n'as pas à  te taper la récupération de toutes les clés que tu as définies. Genre l'utilisateur ne donne que les paramètres de couleur et de taille, tu n'as pas à  vérifier qu'il n'ait pas aussi ajouter le type de police la couleur de remplissage, l'épaisseur des caractères, etc.

    Et justement, un dictionnaire n'est pas ordonné, tu te fiches totalement de l'ordre dans lequel tu recevras les clés/valeurs, le block n'implique en aucun cas que tu recevras les valeurs, il implique juste que tu les recevras et t'as pas besoin d'en savoir plus.

    Si tu veux de l'ordre quand tu itères, c'est le NSArray, si tu veux associer une clé et une valeur sans te soucier de l'ordre c'est le dictionnaire, si tu veux juste un ensemble de valeur, c'est le NSSet, mais dans tous ces cas tu dois pouvoir faire une itération et selon le type un ordre est garanti ou pas...

    Autre chose, les blocks permettent aussi plus de généricité quant aux types des variables itérer, par exemple, on ne peut pas utiliser le foreach ou le NSEnumerator pour boucler sur les caractères d'une string ou sur les caractères d'un NSCharacterSet, on est obligé d'utiliser des for et while avec index manuel.
  • schlumschlum Membre
    05:28 modifié #13
    dans 1228960128:

    Les beans sont des inepties inventées par java pour java, et dont les java-addict raffole, ce sont en général des classes de stockages dont le code est à  99% prévisibles, et l'exigence c'est que toutes les variables d'instance d'un beans doivent avoir un getter/setter correspondant...


    :crackboom:- Je suis bien content de ne pas faire de Java  :P

    Sinon, la logique objet c'est surtout de pouvoir avoir les données et les traitements sur les données dans un même paquet, mais pour les classes de models sont faites en général pour stocker les données et doivent donc permettre l'accès à  la plupart de leurs variables d'instances.


    " la plupart ", je ne suis pas d'accord... justement le but c'est d'y avoir accès le moins possible. Quand je rentre dans une voiture, je veux pouvoir avoir accès au volant, aux vitesses et à  l'ouverture du réservoir pour mettre de l'essence (je simplifie), pas à  l'injection du carburateur, l'arbre des vitesses, chaque rouage du moteur, le circuit de refroidissement, les durites etc.

    Sinon le débogage n'est certe pas facilité avec les @synthesize, mais les bindings rendaient déjà  la tâche pas facile, cependant, étant donné qu'en général les trucs auto-générés sont efficaces et sans bogues, et bien ça réduit fortement les endroits qui génèrent des bogues dans ce que t'as écrit.


    Ben si je balance un mauvais truc au dessus et que je veux savoir quand, le synthetize n'est pas en cause du bug, et je suis pourtant obligé de mettre le point d'arrêt dans le setter  ???
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #14
    dans 1228960827:
    Sinon, la logique objet c'est surtout de pouvoir avoir les données et les traitements sur les données dans un même paquet, mais pour les classes de models sont faites en général pour stocker les données et doivent donc permettre l'accès à  la plupart de leurs variables d'instances.


    " la plupart ", je ne suis pas d'accord... justement le but c'est d'y avoir accès le moins possible. Quand je rentre dans une voiture, je veux pouvoir avoir accès au volant, aux vitesses et à  l'ouverture du réservoir pour mettre de l'essence (je simplifie), pas à  l'injection du carburateur, l'arbre des vitesses, chaque rouage du moteur, le circuit de refroidissement, les durites etc. [/quote]

    Le truc là , c'est que ton analogie ne tient pas, tu parles du controlleur, je parle du modèle, si on voulait garder
    dans 1228960827:
    Ben si je balance un mauvais truc au dessus et que je veux savoir quand, le synthetize n'est pas en cause du bug, et je suis pourtant obligé de mettre le point d'arrêt dans le setter  ???


    Bah tu regardes dans le code où tu utilises l'accesseur...
  • schlumschlum Membre
    05:28 modifié #15
    dans 1228960686:

    Par exemple, NSAttributedString, tu peux passer une liste de style à  appliquer, et pour chaque clé tu associes une valeur, genre couleur du texte, taille du texte, police du texte. Tu vas itérer dans le dictionnaire pour savoir quels sont les paramètres à  mettre en place, et l'avantage c'est que tu n'as pas à  te taper la récupération de toutes les clés que tu as définies. Genre l'utilisateur ne donne que les paramètres de couleur et de taille, tu n'as pas à  vérifier qu'il n'ait pas aussi ajouter le type de police la couleur de remplissage, l'épaisseur des caractères, etc.


    Euh... ça m'étonnerait que NSAttributedString itère sa liste de style. À mon avis il va plutôt les chercher un par un au moment où il en a besoin, et si le style est absent, il prend la valeur par défaut (d'où l'utilité d'un dictionnaire et pas d'un array justement !) ???
    Ex :
    // ... Préparation du dessin de la chaà®ne dans un contexte graphique<br />NSColor *c = [styles valueForKey: NSForegroundColorAttributeName];<br />if(c==nil)<br /> &nbsp; &nbsp;[[NSColor blackColor] set];<br />else<br /> &nbsp; &nbsp;[c set];<br />// ... On continue ...
    

  • schlumschlum Membre
    05:28 modifié #16
    dans 1228961197:
    Le truc là , c'est que ton analogie ne tient pas, tu parles du controlleur, je parle du modèle, si on voulait garder


    ???
    Je parle de classes en général... Un objet qui fait des traitements internes et a quelques entrées / sorties (les accesseurs)
  • schlumschlum Membre
    05:28 modifié #17
    dans 1228961197:

    dans 1228960827:
    Ben si je balance un mauvais truc au dessus et que je veux savoir quand, le synthetize n'est pas en cause du bug, et je suis pourtant obligé de mettre le point d'arrêt dans le setter  ???


    Bah tu regardes dans le code où tu utilises l'accesseur...


    Si c'est à  50 endroits dans le code, je suis pas sorti de l'auberge quoi  ;D
    Condamné à  installer 50 breakpoints conditionnels, la plaie  :P
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #18
    dans 1228961357:
    Euh... ça m'étonnerait que NSAttributedString itère sa liste de style. À mon avis il va plutôt les chercher un par un au moment où il en a besoin, et si le style est absent, il prend la valeur par défaut (d'où l'utilité d'un dictionnaire et pas d'un array justement !) ???
    Ex :
    // ... Préparation du dessin de la chaà®ne dans un contexte graphique<br />NSColor *c = [styles valueForKey: NSForegroundColorAttributeName];<br />if(c==nil)<br /> &nbsp; &nbsp;[[NSColor blackColor] set];<br />else<br /> &nbsp; &nbsp;[c set];<br />// ... On continue ...
    




    Non, justement pour des raisons d'efficacité, NSAttributedString doit avoir récupérer tous les paramètres donnés par l'utilisateur et les avoir insérer dans une structure locale beaucoup plus efficace et adaptée que le simple dictionnaire et ce AVANT d'avoir à  afficher quelque chose, et surtout dans le cas de NSAttributedString qui n'est pas modifiable et qui donc n'a pas besoin de revérifier systématiquement quels sont les paramètres passés par l'utilisateur lors de l'affichage du texte.

    Bien sûr qu'il y a des valeurs par défaut, et c'est justement pour ça qu'itérer dans le dictionnaire est bien, et quand on parle d'itérer ça ne veut pas forcément dire qu'on veut un ordre ou qu'on utilise des index, ici les index sont des clés plus faciles à  lire...
    Donc pour ce qui est des valeurs par défaut, tu vas justement itérer dans le dictionnaire pour savoir quelles sont les valeurs que l'utilisateur souhaite modifier, et ainsi tu vas regarder la totalité de son dictionnaire et récupérer les valeurs qui correspondent.

    Comme quand tu vas commander ton ordi sur l'Apple Store, tu vas indiquer à  l'Apple Store que tu veux 4 Go de RAM, un processeur de 2,8 GHz et un écran 24"...
    C'est beaucoup plus rapide de voir quelles sont les modifications apportées par l'utilisateur que de regarder pour chaque options disponibles lesquelles ont été spécifiées par l'utilisateur. Au lieu d'avoir à  tester 12 clés et ne voir que 3 modifications, tu ne testes que 3 clés.
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #19
    dans 1228961558:
    Si c'est à  50 endroits dans le code, je suis pas sorti de l'auberge quoi  ;D
    Condamné à  installer 50 breakpoints conditionnels, la plaie  :P


    Et mettre un breakpoint sur @synthesize ça marche...  :P
    Quand tu exécutes tu peux voir "self" avec l'ancienne valeur dans ses ivars et "_value" qui est la future valeur de l'ivar. ;)
  • schlumschlum Membre
    05:28 modifié #20
    dans 1228962093:

    Non, justement pour des raisons d'efficacité, NSAttributedString doit avoir récupérer tous les paramètres donnés par l'utilisateur et les avoir insérer dans une structure locale beaucoup plus efficace et adaptée que le simple dictionnaire et ce AVANT d'avoir à  afficher quelque chose, et surtout dans le cas de NSAttributedString qui n'est pas modifiable et qui donc n'a pas besoin de revérifier systématiquement quels sont les paramètres passés par l'utilisateur lors de l'affichage du texte.


    Alors si ça fonctionne comme ça, quel intérêt d'un NSDictionary plutôt qu'un NSArray de paires ?  ???
    Le NSArray serait encore plus performant  :o
  • schlumschlum Membre
    05:28 modifié #21
    dans 1228962382:

    dans 1228961558:
    Si c'est à  50 endroits dans le code, je suis pas sorti de l'auberge quoi  ;D
    Condamné à  installer 50 breakpoints conditionnels, la plaie  :P


    Et mettre un breakpoint sur @synthesize ça marche...  :P
    Quand tu exécutes tu peux voir "self" avec l'ancienne valeur dans ses ivars et "_value" qui est la future valeur de l'ivar. ;)


    Pas trop cons sur le coup alors  :o
  • psychoh13psychoh13 Mothership Developer Membre
    décembre 2008 modifié #22
    dans 1228962622:
    Alors si ça fonctionne comme ça, quel intérêt d'un NSDictionary plutôt qu'un NSArray de paires ?  ???
    Le NSArray serait encore plus performant  :o


    Déjà  parce que les dictionnaires gèrent déjà  les paires, là  t'aurais soit besoin d'une nouvelle classe d'association et en plus tes valeurs devraient être ordonnées, hors tu ne veux pas ça avec un dictionnaire.

    Le principe du dictionnaire c'est un ensemble de valeurs identifiées par des clés, après tu as deux approches, soit ça contient des "modifications" auquel cas tu vas regarder toutes les "nouvelles" valeurs contenues dans le dictionnaire, soit tu cherches la valeur d'une clé spécifique, dans les deux cas, l'utilisation d'un dictionnaire plutôt que d'un array est bien plus efficace.
    Et d'autant plus dans le cas d'un dictionnaire modifiable, quand tu as un array, si tu retires ou ajoutes une valeur, l'ordre est chamboulé, les index des autres valeurs changent, alors que le dictionnaire, n'étant pas ordonné, l'ajout ou la suppression de valeur ne fait que changer le nombre de valeur qu'il y a dans le dictionnaire, mais pas l'ordre puisqu'il n'y en a pas.

    Et puis les blocks sont aussi très bien dans l'itération (cette fois-ci ordonnée donc) d'un NSArray, avec ce type de block : void (^iter)(int idx, id obj, BOOL *stop) tu bénéficies de l'avantage du for( ; ; ) tranditionnel c'est-à -dire la présence d'un index de facto, et tu bénéficies de l'optimisation de l'implémentation de la boucle comme dans le cas d'un foreach.

    Puis t'as plein d'autres utilisations que j'énumère dans un autre sujet.
  • schlumschlum Membre
    décembre 2008 modifié #23
    Que pour les classes NSMutableString, le dictionnaire d'attributs soit " listé ", je n'y crois pas une seconde... ça serait dramatique niveau perfs.

    - Je récupère le premier couple clé - valeur
    - Je fais 50 comparaisons de NSString pour savoir à  quel champ de ma structure optimisée correspond la clé
    ... (x20)
    (à  moins qu'il y ait un autre NSDictionary qui donne la correspondance, pour avoir une situation bien absurde  ;D)

    Ben oui... recevoir dans le désordre, t'as l'air de dire que c'est sensass', mais on fait quoi pour trouver efficacement la correspondance de la clé ? :P
    ça montre bien que les NSDictionary ne sont pas faits pour ça  ???

    Alors que dans l'autre sens, ça justifie pleinement l'utilisation d'un NSDictionary :
    - Je veux remplir le champ de ma structure optimisée correspondant à  la couleur
    - [attributes objectForKey: NSForegroundColorAttributeName]
    ...
  • 05:28 modifié #24
    Schlum serait-il un conservateur ?  ;D
  • schlumschlum Membre
    05:28 modifié #25
    dans 1228987989:

    Schlum serait-il un conservateur ?  ;D


    J'aime bien avoir la main mise sur tous les éléments de mon programme, donc effectivement ça passe par plusieurs choses plus ou moins " conservatrices ".
    - Ne pas utiliser les bindings
    - Ne pas utiliser les properties
    - Ne pas abuser de la flexibilité de Cocoa avec des trucs du genre "respondsToSelector"
    - Ne pas utiliser les trucs trop high-level et abstraits genre CoreData
    - Ne surtouuuuuut pas utiliser de Garbage Collector !
    ...
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #26
    dans 1228968810:

    Que pour les classes NSMutableString, le dictionnaire d'attributs soit " listé ", je n'y crois pas une seconde... ça serait dramatique niveau perfs.

    - Je récupère le premier couple clé - valeur
    - Je fais 50 comparaisons de NSString pour savoir à  quel champ de ma structure optimisée correspond la clé
    ... (x20)
    (à  moins qu'il y ait un autre NSDictionary qui donne la correspondance, pour avoir une situation bien absurde  ;D)


    Je ne vois vraiment pas en quoi la situation serait absurde, les tables de correspondances sont en général très efficaces, mais bon on ne peut pas trop savoir comment ça fonctionne réellement, mais bon il se trouve que dans les sources de GNUStep (qui n'est pas certe l'implémentation d'Apple, ni la meilleure implémentation), ils utilisent un NSArray en internet pour stocker les infos de la NSAttributedString, qui rappelons-le n'est pas en soit destiné à  être dessiné, en effet, cette classe est définie dans Foundation, et une catégorie est ajoutée dans AppKit pour dessiner ces objets.

    dans 1228968810:
    Ben oui... recevoir dans le désordre, t'as l'air de dire que c'est sensass', mais on fait quoi pour trouver efficacement la correspondance de la clé ? :P
    ça montre bien que les NSDictionary ne sont pas faits pour ça  ???

    Alors moi je te te mets au défi de faire respecter aux utilisateurs de ta classe NSAttributedString l'ordre des attributs dans lequel tu voudrais les récupérer pour que ton algo à  toi soit le plus optimisé possible... Bonjour les dégâts.
    OUI, une collection non-ordonné est sensass' quand l'ordre n'est pas important (La Palice) ou même lorsque l'ordre serait gênant, ce qui est le cas ici.
    Comme je l'ai déjà  dit, il sera beaucoup plus efficace de voir quelles sont les clés définis dans un dictionnaire passé par l'utilisateur que de chercher parmi toutes les clés que l'implémenteur rend disponible et de vérifier si elles sont utilisées dans le dictionnaire de l'utilisateur...

    dans 1228968810:
    Alors que dans l'autre sens, ça justifie pleinement l'utilisation d'un NSDictionary :
    - Je veux remplir le champ de ma structure optimisée correspondant à  la couleur
    - [attributes objectForKey: NSForegroundColorAttributeName]
    ...


    Tu vois, personnellement je doute même qu'il stocke les valeurs qui n'ont pas été définies par l'utilisateur, ce serait idiot puisque, si tu as, effectivement, des valeurs par défaut, il sera plus rapide de les recalculer (présence de la valeur dans le flot d'instruction) que d'aller la chercher dans la RAM.


    dans 1228991527:
    J'aime bien avoir la main mise sur tous les éléments de mon programme, donc effectivement ça passe par plusieurs choses plus ou moins " conservatrices ".
    - Ne pas utiliser les bindings
    - Ne pas utiliser les properties
    - Ne pas abuser de la flexibilité de Cocoa avec des trucs du genre "respondsToSelector"
    - Ne pas utiliser les trucs trop high-level et abstraits genre CoreData
    - Ne surtouuuuuut pas utiliser de Garbage Collector !
    ...


    ça pour le coup c'est un comportement anti-programmation objet, sur le GC je suis d'accord, pour l'instant il est trop jeune pour vraiment être plus efficace que le système actuel. Mais ne pas utiliser les autres fonctionnalités parce que tu n'as pas la main-mise dessus est tout simplement débile.
    Le principe fondamental de la programmation objet c'est la modularisation du code, c'est-à -dire de faire du code réutilisable, d'avoir des objets plutôt générique donnant la possibilité de réutiliser ce code à  d'autres endroits et dans d'autres circonstances, tout ce qui peut permettre de ne pas (re)taper du code faire parti intégrante de la programmation objet et devrait être utilisé lorsque la situation le permet...
    Attention, je ne dis pas qu'il faut à  tout prix utilisé les bindings, les properties ou CoreData, je dis que lorsqu'on a le choix entre taper 200 lignes de code ou faire deux liaisons graphiques, il vaut mieux aller vers les liaisons graphiques, parce que réinventer systématiquement la roue est une énorme perte de temps.

    Personnellement, j'étais aussi retissant à  utiliser les bindings, mais étant ouvert d'esprit et curieux, je voulais voir si je ne pouvais pas utiliser les bindings dans un projet à  moi (plutôt qu'uniquement dans le tutoriel), c'était une catastrophe, j'arrivais pas à  voir en quoi les bindings pouvaient m'aider dans mon cas, et en effet ça marchait beaucoup mieux et avec très peu de ligne de code sans bindings... Ici, les bindings étaient plus une tare qu'une réelle avancée...

    Cependant, j'ai commencé à  concevoir une application permettant de gérer des tournois de poker... Et donc là , je me suis penché sur core data et les bindings... Et bien, je peux te dire que ça m'a épargné de longues heures de tapage de codes répétitifs pour arriver à  afficher les données dans une interface graphique attrayante ; ne serait-ce que pour afficher les données d'un seul objet, instance d'une entité, dans l'interface, si je n'avais pas utiliser les bindings j'aurais dû me taper une bonne centaine de lignes toutes pareilles hormis le nom de la variable affectée, bah crois-moi, j'étais aux anges de voir qu'en même pas dix minutes j'avais déjà  fait 3 ou 4 fois ça, en plus d'avoir pu afficher toutes les lignes d'une entité attachées à  l'objet sélectionné par l'utilisateur dans une autre partie de l'interface...

    Alors, c'est un système effrayant parce que tout est masqué et on ne sait pas trop ce qu'il se passe, et aussi il y a une période d'adaptation à  cette technologie qui peut être longue, mais une fois que tu as compris le foncitonnement, ça facilite la vie à  un point tu peux pas savoir...


    PS: demande à  Eaglelouk comme il est content de pouvoir faire des interfaces animés super-rapides sans avoir à  taper du code. :D
  • AliGatorAliGator Membre, Modérateur
    05:28 modifié #27
    dans 1228991527:

    dans 1228987989:

    Schlum serait-il un conservateur ?  ;D


    J'aime bien avoir la main mise sur tous les éléments de mon programme, donc effectivement ça passe par plusieurs choses plus ou moins " conservatrices ".
    - Ne pas utiliser les bindings
    - Ne pas utiliser les properties
    - Ne pas abuser de la flexibilité de Cocoa avec des trucs du genre "respondsToSelector"
    - Ne pas utiliser les trucs trop high-level et abstraits genre CoreData
    - Ne surtouuuuuut pas utiliser de Garbage Collector !
    ...
    Ben c'est qu'on se rejoint presque, je trouve que les bindings sont une idée sympa mais trop obscure (ça peut aller pour les choses simples mais dès que ça se complique on perd le contrôle) donc moi non plus je ne les utilise pas. Pareil pour la flexibilité de Cocoa, c'est une bonne chose mais ne pas en abuser et préférer "coder propre". CoreData je n'ai jamais utilisé (aussi parce que jamais eu l'occasion de m'y mettre), et GarbageCollector, je déteste :D

    Reste les @properties que je trouve très pratiques contrairement à  toi ;) (heu c'est pas toi que je trouve pas pratique, hein c'est toi qui trouve pas pratique les properties loool) mais l'avantage c'est que tu as encore le choix, tu peux les utiliser.... ou pas !
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #28
    dans 1228994004:
    Ben c'est qu'on se rejoint presque, je trouve que les bindings sont une idée sympa mais trop obscure (ça peut aller pour les choses simples mais dès que ça se complique on perd le contrôle)


    Bah justement, c'est ça que vous ne semblez pas comprendre, lol, tu ne vas pas t'amuser à  planter un clou avec un tournevis quand même ? Alors utiliser les bindings dans un cas où ce n'est pas utile est encore plus débile que de chercher à  les éviter à  tout prix. Sans vouloir offenser personne...

    C'est comme le modèle MVC, personne, et surtout pas Apple, ne t'oblige à  l'utiliser, il s'agit d'un design pattern pratique, sur lequel est basé Cocoa, mais si toi il te gêne plus qu'il ne t'aide, il ne faut pas l'utiliser !
  • schlumschlum Membre
    05:28 modifié #29
    dans 1228993698:

    Alors moi je te te mets au défi de faire respecter aux utilisateurs de ta classe NSAttributedString l'ordre des attributs dans lequel tu voudrais les récupérer pour que ton algo à  toi soit le plus optimisé possible... Bonjour les dégâts.
    OUI, une collection non-ordonné est sensass' quand l'ordre n'est pas important (La Palice) ou même lorsque l'ordre serait gênant, ce qui est le cas ici.
    Comme je l'ai déjà  dit, il sera beaucoup plus efficace de voir quelles sont les clés définis dans un dictionnaire passé par l'utilisateur que de chercher parmi toutes les clés que l'implémenteur rend disponible et de vérifier si elles sont utilisées dans le dictionnaire de l'utilisateur...

    Tu vois, personnellement je doute même qu'il stocke les valeurs qui n'ont pas été définies par l'utilisateur, ce serait idiot puisque, si tu as, effectivement, des valeurs par défaut, il sera plus rapide de les recalculer (présence de la valeur dans le flot d'instruction) que d'aller la chercher dans la RAM.


    C'est toi qui parlait de structure interne, je reprenais donc ton modèle  ;)
    Nul besoin de faire respecter aux utilisateurs un ordre puisque la recherche est faite avec une table de hashage  ???
    Par ailleurs, même une table de correspondance ne sera pas capable à  priori de fournir l'emplacement dans la structure ; ou alors on encastre les pointeurs dans une NSValue, et ça devient vraiment glauque...

    Je n'ai pas compris non plus ce que tu voulais dire par " modifications " et " nouvelles valeurs ", et ne vois d'ailleurs toujours pas l'avantage de créer un NSDictionary pour faire du listing (processus qui va créer une table de hashage pour le coup inutile etc.), alors qu'on peut le faire de manière plus rapide avec un array classique. Même si on reçoit dans l'ordre en s'attendant à  recevoir dans le désordre, en quoi c'est gênant, puisque le hasard du désordre aurait pu faire qu'on l'aurait reçu dans l'ordre... ?
  • schlumschlum Membre
    05:28 modifié #30
    dans 1228993698:

    Cependant, j'ai commencé à  concevoir une application permettant de gérer des tournois de poker... Et donc là , je me suis penché sur core data et les bindings... Et bien, je peux te dire que ça m'a épargné de longues heures de tapage de codes répétitifs pour arriver à  afficher les données dans une interface graphique attrayante ; ne serait-ce que pour afficher les données d'un seul objet, instance d'une entité, dans l'interface, si je n'avais pas utiliser les bindings j'aurais dû me taper une bonne centaine de lignes toutes pareilles hormis le nom de la variable affectée, bah crois-moi, j'étais aux anges de voir qu'en même pas dix minutes j'avais déjà  fait 3 ou 4 fois ça, en plus d'avoir pu afficher toutes les lignes d'une entité attachées à  l'objet sélectionné par l'utilisateur dans une autre partie de l'interface...


    C'est à  la mode en ce moment les applications de gestion de tournois de poker dis donc  :)
    C'est ton droit le plus strict d'utiliser les bindings... mais faudra pas venir te plaindre le jour où tu voudras introduire quelque chose à  ce niveau qui dépassera le cadre des bindings et que tu devrais tout casser pour tout recoder  :P

    Le concept " objet " ne doit pas introduire de la rigidité, mais au contraire de la souplesse  ;)
  • psychoh13psychoh13 Mothership Developer Membre
    05:28 modifié #31
    L'itération consiste simplement à  "récupérer" la totalité du contenu d'une collection, dans le cas d'un NSArray tu veux récupérer les valeurs (et donc seulement des valeurs) dans un ordre précis, quitte à  le faire dans le désordre un NSSet est plus rapide...
    Dans le cas d'un dictionnaire, tu veux savoir quelles sont les clés utilisées et quelles sont les valeurs qui leur sont associées : "tiens, ce dictionnaire concurrent définit ces 3 mots avec ces définitions, moi j'ai 4 mots dont 2 sont dans l'autre dictionnaire, et les définitions ne sont pas les mêmes !".

    dans 1228996368:
    C'est à  la mode en ce moment les applications de gestion de tournois de poker dis donc  :)
    C'est ton droit le plus strict d'utiliser les bindings... mais faudra pas venir te plaindre le jour où tu voudras introduire quelque chose à  ce niveau qui dépassera le cadre des bindings et que tu devrais tout casser pour tout recoder  :P

    Le concept " objet " ne doit pas introduire de la rigidité, mais au contraire de la souplesse  ;)


    Bah justement, les bindings sont loins d'être rigide, et comme je l'ai déjà  dit, et donc je le répète, ils ne sont à  utiliser que là  où ils sont appropriés, mais le fait d'avoir à  supprimer un bindings pour taper du code personnalisé n'est pas vraiment gênant, après tout les bindings sont un système permettant de faire rapidement des trucs qu'on aurait mis des heures à  coder, il est plus facile de casser un truc qui a pris 2 minutes à  concevoir qu'une énorme usine à  gaz qui t'as pris 3 jour sà  écrire.
    Car c'est bien ça l'enjeu de la programmation objet, c'est d'éviter que tout soit fait dans un seul bloc, où toutes les lignes de code sont interdépendantes, les bindings sont là  justement pour éviter d'avoir de grosses usines à  gaz totalement rigide. Certes, avec ton usine à  gaz tu sais exactement ce qu'il se passe et où ça se passe, mais mais la proportion de bogues est bien plus grande que dans un code beaucoup plus modulaire, étant donné que tu tapes plus de code tu as plus de chance d'avoir des bogues, autant s'épargner des heures de débogages surtout pour des broutilles répétitives.

    Personnellement, je préfère sous-traiter des actions à  des objets dont c'est le métier plutôt que de m'amuser à  réinventer la roue pour le seul plaisir de dire "Ah le trou dans la chambre à  air c'est MOI QUI L'AI FAIT !".
Connectez-vous ou Inscrivez-vous pour répondre.