Les bindings: simple ou complexe ?

Faut arrêter les bindings c'est simple. Il faut pas en avoir peur c'est tout.


Il y a pléthore de tutos sur le net pour ça.


Réponses

  • CéroceCéroce Membre, Modérateur


    Faut arrêter les bindings c'est simple. Il faut pas en avoir peur c'est tout.


    Il y a pléthore de tutos sur le net pour ça.




     


    Faut arrêter, les bindings, c'est compliqué. Il faut se limiter à  une utilisation basique.


    Aucun tuto n'approfondit le sujet.



  • Faut arrêter, les bindings, c'est compliqué. Il faut se limiter à  une utilisation basique.


    Aucun tuto n'approfondit le sujet.




    Donne moi un seul exemple concret qui te permet d'avancer une telle chose.


    Pour les tutos c'est vrai qu'il faut assez souvent savoir approfondir soit-même.

  • CéroceCéroce Membre, Modérateur
    décembre 2017 modifié #4

    Oui, voici le premier exemple concret qui me vient à  l'esprit.


     


    On a une liste de formes géométriques, des cercles et des carrés. On doit pouvoir par binding:


    - modifier leur centre


    - modifier leur couleur de remplissage


    - modifier le côté des carrés sélectionnés


    - modifier le rayon des cercles sélectionnés


     


    L'essence du problème est que la liste de formes n'est pas homogène. Si on binde sur la propriété "rayon" du NSArrayController et qu'on y met des carrés, on obtient un superbe plantage du Key-Value Coding pour cause de clef inconnue.


     


    La solution est de parcourir la sélection, voir si toutes les formes ont une propriété "rayon" et seulement là  afficher les textfields qui sont bindés sur "rayon".


     


    C'est loin d'être simple!


  • PyrohPyroh Membre
    décembre 2017 modifié #5

    Bah si, ce cas de figure est simple et sans ligne de code si ce n'est la définition du modèle.


  • PyrohPyroh Membre
    décembre 2017 modifié #6

    Bon allé l'exercice était sympa à  faire. Et rapide aussi. J'ai un peu fignolé l'interface mais en 30 minutes ça tournait correctement.


    Voilà  le seul code lié à  la partie contrôleur :



    class ViewController: NSViewController {
    @objc dynamic var forms: [Form] = []

    override func viewDidLoad() {
    super.viewDidLoad()

    forms = [Square(name: "Square", color: NSColor.red, side: 22),
    Circle(name: "Circle", color: NSColor.blue, radius: 34)
    ]
    }

    @IBAction func addRectangle(_ sender: Any) {
    forms.append(Square(name: "Square", color: NSColor.red, side: 22))
    }

    @IBAction func addCircle(_ sender: Any) {
    forms.append(Circle(name: "Circle", color: NSColor.blue, radius: 34))
    }
    }

    On peut avoir le code ici : 

  • CéroceCéroce Membre, Modérateur
    décembre 2017 modifié #7

    J'avoue que tu as trouvé une solution bien plus simple que la mienne, à  savoir binder la visibilité des StackViews sur selection.radius avec le ValueTransformer NSIsNil.


     


    Comment sait-on qu'on peut faire ça ??? Où se trouve la doc qui dit que le proxy selection renvoie nil si la clef n'existe pas ? En dix ans de bindings, je ne le savais pas, et pourtant j'ai lu et relu les docs.


     


    C'est justement ça qui m'ennuie tant avec les bindings. Il y a un tas de comportements implicites.


    Et d'autres choses qui paraissent faisables ne le sont pas.


  • CéroceCéroce Membre, Modérateur

    Un autre exemple difficile à  implémenter:


    Le modèles contient des formes, disons des cercles. Il ont un centre et une couleur de remplissage. Ils ont tous le même rayon.


    L'exercice consiste à  créer une sous-classe de NSView qui permet de sélectionner les cercles et de les déplacer.


     


    Pour le coup, c'est faisable en lisant la doc, mais c'est très complexe au niveau de la vue, parce qu'il faut gérer les différents états de la sélection dans le NSArrayController.

  • CéroceCéroce Membre, Modérateur

    Une dernière chose que je me refuse à  faire avec les bindings, ce sont les NSOutlineViews. C'est compliqué, et ça impose que le modèle ait une certaine forme. ça peut devenir carrément un cauchemar si on doit gérer le glisser-déposer.


  • klogklog Membre
    décembre 2017 modifié #10


    Une dernière chose que je me refuse à  faire avec les bindings, ce sont les NSOutlineViews. C'est compliqué, et ça impose que le modèle ait une certaine forme. ça peut devenir carrément un cauchemar si on doit gérer le glisser-déposer.




     


    Si je trouve la solution de Pyroh à  ton problème particulièrement élégante, pour le coup, concernant les NSOutlineView, je suis entièrement d'accord avec toi : le binding est un cauchemar.


     


    Et c'est encore pire si on doit raccrocher le tout à  des structures Core Data (et ses NSOrderedSet non directement pris en charge par le binding des NSOutlineView) !


  • PyrohPyroh Membre
    décembre 2017 modifié #11

    Alors comment on sait ça ? Si tu prends en compte que les bindings c'est l'association de deux design patterns principaux : observer et proxy. Tout ça fait que la propriété selection du controller et les fameux arrangedObjects ne sont pas stricto sensu des vrais objets mais des proxies qui ne vont pas répondre spécifiquement de la meÌ‚me manière qu'une sous-classe NSObject standard. 


     


    Dans le cas qui nous intéresse c'est l'implémentation de value(forUndefinedKey:) qui est différente dans le proxy et qui va au choix remonter une exception ou renvoyer un objet de type NSNotApplicableMarker. Si on a mis raisesForNotApplicableKeys aÌ€ false on aura cet objet spécial dans la valeur passée à  la méthode setValue(_:forKeyPath:) du contrôle qui est bound. 


     


    Dans le binding de l'exemple que je donne il y a deux composants vraiment essentiels dans la configuration du binding :


     - Raises For Not Applicable Keys qui doit être décoché sous peine d'exception à  l'exécution.


     - Not Applicable Placeholder nous donne la valeur par défaut du binding si justement la clé n'existe pas. 


     


    Ce qui montre bien que le cas est prévu. En plus il est documenté dans ce magnifique ( :P) document qu'est Bindings Message Flow.


     


    Sinon pour ce qui est de la vue custom le plus difficile va être la gestion interne de la vue avec les events et tout le bordel. Pas le binding en lui meÌ‚me. Malheureusement je ne pense pas avoir le temps de le faire aujourd'hui il me faudrait au moins une bonne heure pour avoir un truc qui marche et encore autant pour le coup de polish.


     


    La NSOutlineView j'en ai déjaÌ€ fait une mais je pense que c'était avec une datasource je dois voir si je retrouve le code si je l'ai archivé pour être suÌ‚r.


     


    J'ajouterai aussi à  l'exemple un colorwell qui réagis un peu mieux aux fameux markers de binding, j'en ai déjaÌ€ écrit un. ça peut être intéressant pour les novices.


  • Allé hop un petit repo GitHub qui va bien : https://github.com/Pyroh/ComplexBindings


  • CéroceCéroce Membre, Modérateur
    décembre 2017 modifié #13

    Dans le binding de l'exemple que je donne il y a deux composants vraiment essentiels dans la configuration du binding :
     - Raises For Not Applicable Keys qui doit être décoché sous peine d'exception à  l'exécution.
     - Not Applicable Placeholder nous donne la valeur par défaut du binding si justement la clé n'existe pas.

    ça a tout l'air d'une astuce, non ? Tu ne trouves pas ça complexe ? Tu ne trouves pas que ça fait appel à  trop de notions ?

    Pour préciser, je ne suis pas anti-bindings, mais mon expérience est qu'ils n'apportent généralement pas de gain de temps, parce qu'on en perd beaucoup au débogage.
  • Non je le vois plus comme deux questions logique : 


     - Est-ce que je me plains si je ne trouve pas ce que je cherche?


     - Qu'est-ce que j'affiche à  la place de me plaindre ?


     


    L'info est dure à  trouver et il faut de l'expérience dans ce domaine précis pour le savoir mais je trouve ça moins contraignant que le boilerplate qui viendrait en lieu place. 


     


    Le lien view <> controller est une saloperie à  mettre en place quelque soit la méthode utilisée. Les bindings ont l'avantage d'être plus simple et plus rapide à  mettre en oeuvre une fois qu'on a compris le truc. Mais il faut le comprendre, pouvoir prendre le temps, se casser les dents un nombre incalculable de fois et lire beaucoup de doc. Pareil pour le debugging une fois que tu sais ce que tu fais tu y recours beaucoup moins souvent.


     


    C'est aussi non-exportable comme knowledge et je sais que ça c'est quelque chose que tu n'aime pas.


     


    Et c'est une composante essentielle du développement macOS. Un développeur macOS sérieux doit maitriser les bindings selon moi...


    Et CoreData mais c'est une autre histoire  :P


  • PyrohPyroh Membre
    décembre 2017 modifié #15

    J'ai implémenté un color well custom qui montre comment on peut répondre aux différents markers. J'ai tout poussé sur le repo.


    Ça intéresse quelqu'un que je creuse un peu plus le sujet ? Avec du code et du bla bla qui l'explique bien suÌ‚r.


     


    Si je suis motivé je ferai une petite vue graphique avec les formes. C'est en gros comme une table view dans l'idée et je vois déjà  comment faire.


  • J'avoue ne rien y comprendre. Bon, je n'ai jamais essayé, cela n'existant pas sous iOS. Une raison pour laquelle Apple n'a pas implémenté les bindings sur son OS mobile ?

  • CéroceCéroce Membre, Modérateur
    décembre 2017 modifié #17

    C'est aussi non-exportable comme knowledge et je sais que ça c'est quelque chose que tu n'aimes pas.

    Peut-être est-ce qui ressort de mes posts, mais ma préférence pour des outils moins spécifiques à  Apple est plus une conséquence qu'un choix.

    Nous pourrions parler de Metal, Core Image, Core Data, mais puisque le sujet est les bindings, je vais dire comment je vois ça.
    Je suis d'accord avec toi quand tu dis que la connexion Vue-Contrôleur est une galère partout et que toute solution technique pour y aider est intéressante. C'est juste que les bindings ne me semblent pas un outil particulièrement probant. Pas seulement parce que c'est basé sur des notions compliquées (franchement, si tu comprends vraiment la gestion des collections en KVC, écris un livre sur le sujet), mal implémentées (KVO), mal documentées, et plus trop supportées par Apple.
    Mais aussi parce que mon expérience m'a démontré qu'il y avait des cas où cette solution ne fonctionne pas (par ex. des limites inhérentes au principe des NSValueTransformers), et surtout que ça devient galère quand le programme grossit.

    Les KVC, KVO et Bindings sont basés sur des chaà®nes de caractères et résolus à  l'exécution. Et les conséquences au quotidien me gavent. J'ai beau avoir une bonne couverture en tests unitaires, je ne suis pas fichu de te dire si l'appli fonctionne sans la lancer et tester tous les cas possibles.
    En effet, il est très possible qu'on binde sur une clef du Modèle qui n'existe plus. C'est ce qui se produit quand on a une appli conséquente, parce que le Modèle change souvent: les clefs sont renommées, disparaissent, passent d'une collection à  une simple valeur, etc. Les facultés limitées pour le refactoring de Xcode n'aident pas.
    Alors certes, tu vas me dire que de toute façon, il faut quand même faire des tests manuels, et que les bugs se resolvent facilement. Mais au final, ce sont des demi-heures perdues qui se cumulent en jours improductifs, et de nouveaux bugs qui réapparaissent sans-cesse.

    Alors que Cocoa était basée sur le dynamisme d'Objective-C, le passage à  Swift destine au statique. Et je vais te dire que même si ça pose de nouveaux problèmes techniques, moi ça me convient, parce que j'en ai marre de jouer au petit singe qui clique sur des boutons.
     
    Au final, je choisis juste les outils qui me paraissent les meilleurs " ou les moins mauvais. J'assume qu'il y a une part subjective dans ces choix.

    Et c'est une composante essentielle du développement macOS. Un développeur macOS sérieux doit maitriser les bindings selon moi...

    Tu vas être surpris, mais je suis d'accord avec toi. Mais c'est parce qu'il n'existe pas d'alternative sérieuse. Peut-être que quelque chose comme RxSwift va s'améliorer. Note que c'est une solution qui m'intéresse parce que quand ça compile, ça marche. Que les concepts de la programmation réactive soient multi-plateformes est un plus, mais avoir le code source davantage.
     

    Et CoreData mais c'est une autre histoire  :P

    Là  pour le coup, je ne suis pas d'accord. Core Data n'a jamais été une bonne ORM. Le principe même des ORM est douteux. Et on dispose d'alternative largement plus crédibles.
    Pour mon dernier développement, j'ai utilisé GRDB, une surcouche à  SQLite écrite en Swift. Comparé à  Core Data, c'est du bonheur.
  • Je partage ton avis, les bindings sont perfectibles en beaucoup de points. Moi j'ai toujours trouvé ça fantastique alors j'ai passé un certain temps à  les étudier, lire sur le sujet, tester et hacker un peu le concept. Parce que j'ai le temps. Le dev iOS/macOS n'est pas mon métier donc je ne cours pas après le temps et la rentabilité est une notion qui n'a pas cours quand on parle de passe temps.


     


    Je comprends que quand tu compte dessus pour bouffer tu ne peux pas passer 4/5 jours à  fouiller juste pour savoir comment ça marche. Dans mon vrai travail je bosse aussi comme ça, y'a une doc et je la suis je ne vais pas commencer à  aller chercher dans les arcanes. Et je ne travaille pas tout seul aussi j'ai des gens avec qui je peux partager l'expérience.


     


    Mais pour le débutant qui code mac en dilettante il a le luxe d'approfondir et se doit d'explorer les bindings si il est un minimum sérieux.


     


    Sinon au passage merci pour GRDB je vais y regarder de beaucoup plus preÌ€s maintenant que je suis en congé, un peu... 


Connectez-vous ou Inscrivez-vous pour répondre.