Paradigme MVC, MVVM, organisation de son application

muqaddarmuqaddar Administrateur
mai 2014 modifié dans Objective-C, Swift, C, C++ #1

En mettant à  jour mon application Web (Rails 4.1, Ruby 2.0), je m'aperçois que le concept MVC m'y semble beaucoup plus clair et respecté que dans mon application Cocoa iOS.


 


Il est vrai que sur iOS les VC sont un peu confus, sont-ils plus des vues ou des contrôleurs ?


 


En réfléchissant, j'ai l'impression que j'aurai pu ajouter une série de contrôleurs dans l'appli Cocoa.


 


Dans mon application Rails, j'ai:


- mes modèles Active Record


- mes contrôleurs CRUD (Create, Read, Update, Delete) + des actions AJAX


- mes vues HTML + CSS


 


Dans mon application Cocoa, j'ai:


- mes modèles qui définissent les champs


- les mêmes modèles qui s'occupent aussi du CRUD SQLite : [model save];


- quelques contrôleurs pour faire des requêtes DB


- les VC


- quelques vues persos


 


Là , où je veux en venir c'est que finalement, j'ai en Rails:


- Contrôleur Vins => met à  jour le vin courant avec son modèle :


VinsController => update => [[instance vin]: update]


 


Et en Cocoa, j'ai depuis un VC une "étape" en moins, puisque j'appelle directement le modèle:


- [[Instance vin] update]


et non:


- Contrôleur vins] update:[Instance vin


 


Dans le fond, vous penserez p-e que ça ne change pas grand chose et que ça reste du MVC. Que je gagne du code aussi. Pourtant, ne serait-ce pas intéressant d'avoir cette "étape" en plus dans un but de lisibilité, d'uniformité, et également de portage multi-plateforme ?


 


Réponses

  • yoannyoann Membre

    Je ne suis pas certain de comprendre le détail de ton implémentation avec qui fait quoi.


     


    Pour ma part j'ai mes projets toujours organisé de la sorte :


     


    Mon contrôleur de données (TrucDataProvider) en sharedInstance qui m'encapsule toute la gestion de base (CoreData / SQLite) et éventuellement la relation à  un serveur web. Lorsque je fait une requête sur ce contrôleur, il me renvois un objet du modèle totalement autonome.


     


    Donc quand dans mes ViewControllers je récupère un de ces objets du modèle (un NSManagedObject par exemple), je travaille directement dessus.


     


    Il y a effectivement la possibilité de ne pas passer par un objet mais par un dictionnaire avec un ID unique, et le code client du dataProvider travaille avec ces ID et des dico pour lire et mettre à  jour, mais IMHO ça serait se prendre la tête à  ne pas utiliser l'objet pour pas grand chose.


     


    L'intérêt d'une telle solution, c'est qu'il devient très simple de changer le backend de données, il suffit de mettre à  jour la méthode de conversion d'objet modèle en dico.


     


    Mais c'est aussi possible de le faire avec un code qui travaille uniquement avec des objets en faisant en sorte que l'objet X ait toujours la même interface. ça prend un peu plus de temps lors des refactoring mais c'est tout aussi viable et plus propre je trouve.


     


     


    Tout dépend si tu es plus à  l'aide avec la manipulation de données simple (dico) ou de données objets.


  • muqaddarmuqaddar Administrateur
    mai 2014 modifié #3

    Salut yoann,


     


    Je comprends ce que tu fais et que tu travailles directement sur ton objet dans ton VC. C'est mon cas.


    Ma question porte plus sur l'enregistrement des données et l'aspect CRUD.


     


    Comment demandes-tu d'enregistrer ton instance de modèle modifiée ?


     


    Je suppose que tu appelles TrucDataProvider et lui demande d'enregistrer ton modèle modifié.


     


    Alors que moi, c'est mon modèle lui-même qui a ce rôle: [[instance de modèle] update];


    Et en fait, "update" lance ma query SQL pour la modification. Dans tous les cas, elle sera dans mon modèle. (c'est un peu mon Active Record perso)


     


    Par contre, j'aurais pu l'appeler depuis un autre contrôleur intermédiaire, mon CRUD Cocoa en quelque sorte:


    Contrôleur vins] update:[Instance vin


     


    En fait, j'ai déjà  des contrôleurs pour des SELECT correspondant à  ton TrucDataProvider, mais pour le CRUD, c'est le modèle qui gère directement, et non des contrôleurs.


  • yoannyoann Membre

    Dans mon fonctionnement, si c'est mis à  jour sur un objet c'est que c'est la valeur finale. La sauvegarde n'est pas du tout géré par le code client mais par le DataProvider qui va faire ça périodiquement / en fonction d'évènement X ou Y comme le passage en background.


  • muqaddarmuqaddar Administrateur


    Dans mon fonctionnement, si c'est mis à  jour sur un objet c'est que c'est la valeur finale. La sauvegarde n'est pas du tout géré par le code client mais par le DataProvider qui va faire ça périodiquement / en fonction d'évènement X ou Y comme le passage en background.




     


    Tu as 1 seul DataProvider ? J'imagine si tu as 20 modèles à  sauvegarder, ça lui fait faire beaucoup de choses non ?

  • KaroxysKaroxys Membre
    mai 2014 modifié #6

    Bonjour,


     


    Je trouve ce sujet intéressant car on trouve nulle part une architecture type pour les développeurs ... Je trouve ça un peu dommage. J'ai eu l'occasion de parler de mon archi à  un evangelist à  la tech talk de Londres l'an dernier (Décembre). 


     


    Au final, on a pas fait beaucoup de modification et on m'a dit que cette architecture était simple et conviendrait à  la plus part des applications qui sont l'Apps Store (A adapter selon les besoins un peu particuliers)


     


    Mais voilà  ce que j'ai :


     


    -- Models


        --> Domains (Mes objets avec le modèle core data si on l'utilise)


        --> Stores     (Permet de faire soit un enregistrement local ou appels serveur. Généralement j'ai NomAppApiStore [Serveur] et NomAppLocalStore [Pour la gestion locale])


        --> Manager  (Contient toute la magie de l'application, c'est le NomAppManager qui va contenir les update, load etc. Et il va appelé soit le local ou le serveur si on a pas l'information en local etc.)


    -- Screens


        --> Création de group pour classer les écrans 


     


    Dans mon contrôleur, j'ai donc [NomAppManager sharedManager] update]


     


    C'est le manager qui va tout faire et j'ai aucune modification d'object dans mon contrôleur.


     


    Je ne pense pas faire de la même façon que vous et c'est ça que je trouve intéressant :-)


     


    K.


  • muqaddarmuqaddar Administrateur
    mai 2014 modifié #7

    Salut Karoxys,


     


    Ton Architecture ressemble à  celle de Yoann.


    Donc, même question, tu n'as qu'un Manager même si tu as 20 modèles à  gérer en CRUD ? ça lui fait faire beaucoup de choses non ?


  • AlakAlak Membre
    mai 2014 modifié #8

    Personnellement, 


     


    J'ai beaucoup de mal avec le MVC quand je dev une App iOS a cause des VC.


     


    Voici un article sur ce problème ainsi que les Slides du dernier NSMeetup a ce sujet :


     


    https://docs.google.com/presentation/d/1DwR89WLq4gco-BrZew7cdRJKg8tr6xx1cWmOr5-nxck/edit#slide=id.g338d0887c_2_186


    http://natashatherobot.com/breaking-mvc-pattern-models-in-views/


  • FKDEVFKDEV Membre
    mai 2014 modifié #9

    Il faut voir que quand on utilise CoreData, on a un peu moins de code dans la mesure où les requêtes SQL sont construites par les classes fournies par Core Data. On a juste à  manipuler des abstractions comme NSManagedObjectContext, NSFetchRequest et NSPredicate. Et, pour peu qu'on utilise un framework 3rd party type MagicalRecord, on peut même se passer de manipuler certaines de ces classes.


    Donc ton inquiétude sur la quantité de code est à  mon avis justifiée mais elle est compensée par tout ce code déjà  écrit par CoreData et MagicalRecord.


     


     


    Sur mon premier projet avec CoreData, j'y suis allée franco en n'utilisant pas de XXXDataManager.


    C'est-à -dire que dans les XXXViewControllers, je faisais des appels à  NSManagedObjectContext et NSFetchRequest en suivant les exemples fournis pas Apple.


    C'est bien mais on se retrouve avec des accès aux données un peu partout et du coup, j'ai fini par ranger le code dans une catégorie de NSManagedObjectContext (qui est l'objet utilisé pour accéder gérer les requetes dans Core Data).


     


    Dans un second projet, j'ai voulu gérer des accès multi-tâches et des requêtes plus complexes, donc j'ai choisi d'adopter un principe identique à  celui décrit par Yoann :


    J'ai créée un singleton XXXXDataManager me permettant de "ranger" tous les accès à  Core Data. Ce code s'occupe des requêtes et  retourne des objets en prenant en compte le thread dans lequel la demande s'execute (très important avec Core Data).


     


    Ce découpage m'a permis de réutiliser le code du XXXDataManager dans une Webapp sur un serveur OSX avec très peu de modifications. La plupart  des changements étant liés aux chemins d'accès vers la base Core Data qui ne se détermine pas de la même manière sur iOS et OSX.


  • muqaddarmuqaddar Administrateur
    mai 2014 modifié #10

    Intéressant vos retours.


     


    Merci pour les liens Alak.


     


    FKDEV, c'est vrai qu'avec CoreData, c'est un peu différent de mes cas.


    Après, mon problème n'est pas la quantité de code. Je préfère avoir + de code et + de découpage si c'est meilleur pour la lisibilité du projet.


     


    Actuellement, j'ai un mix de tes 2 projets, à  savoir des contrôleurs qui gèrent les requêtes SELECT qui peuvent être complexes. Mais aussi des accès/sauvegarde aux modèles directement depuis les VC. 


     


    Bon, is je comprends bien, de toute façon, il n'y a pas de règle absolue en la matière.


  • AliGatorAliGator Membre, Modérateur
    mai 2014 modifié #11
    Faudra que je prenne un peu plus de temps pour répondre quand je serais posé mais j'ai l'impression que ce que tu recherches ressemble à  un modèle MVVM, qui est une architecture découpée avec un [M]odel, une [V]iew (qui en fait est souvent découpée en une vue et son ViewController qui lui est associé et dédié uniquement pour les interactions UI) et un [V]iew-[M]odel (qui est un peu ce qu'on met sous iOS dans me Controlleur parfois, qui se charge de l'intelligence métier, la logique, etc)


    Je vois des plus élus de gens parler du modèle MVVM et la façon de la mettre en place sur iOS, et le framework Cocoa ne l'interdit pas du tout. En gros il suffit de mettre dans ton UIViewController uniquement ce qui est lié fortement à  l'UI et devra changer si l'UI change, et de prévoir un NSObject (qui sera ton ViewModel) pour la partie interconnexion avec le modèle.


    A mon avis c'est un modèle à  creuser. En tout cas ça semble être plus proche du modèle que tu fais implicitement en RoR, non ?


  • Salut Karoxys,


     


    Ton Architecture ressemble à  celle de Yoann.


    Donc, même question, tu n'as qu'un Manager même si tu as 20 modèles à  gérer en CRUD ? ça lui fait faire beaucoup de choses non ?




     


    Je n'ai pas trop détaillé mais, pour être plus précis, j'ai un manager pour chaque grande fonctionnalité dans une application. Par exemple, si je prend Hollywood Challenge (ma dernière application). J'ai un manager qui va gérer toutes les règles du jeu et qui va également s'occuper de télécharger toutes les images depuis le serveur ou en local si elles sont présentes dans le cache. Et j'ai d'autre manager qui vont me permettre de gérer les in-app par exemple ainsi que d'autre grosse fonctionnalité qui sorte du cadre du jeu en lui même. J'essaye d'avoir des objets simples et que cela ne soit pas trop le bordel. Plus c'est simple mieux c'est :-)


     


    Chaque manager à , dans la plus part des cas, un store api et un store local.


     


    K.

  • samirsamir Membre


    Mon contrôleur de données (TrucDataProvider) en sharedInstance qui m'encapsule toute la gestion de base (CoreData / SQLite) et éventuellement la relation à  un serveur web. Lorsque je fait une requête sur ce contrôleur, il me renvois un objet du modèle totalement autonome.




     


    Dans ce cas ton Provider/Manager dépend de ton modèle de données et ne sera pas réutilisable sans ce dernier. Le mieux à  mopn avis que le provider/manager renvoie des structure de données ( NSDictionnary,...) pour un autre Manager  ( MyModelBuilder) celui la va prendre en entrée la structure renvoyée et construit un modèle objet. Je parle biensur de pattern 'Builder'.

  • muqaddarmuqaddar Administrateur
    mai 2014 modifié #14


    Faudra que je prenne un peu plus de temps pour répondre quand je serais posé mais j'ai l'impression que ce que tu recherches ressemble à  un modèle MVVM, qui est une architecture découpée avec un [M]odel, une [V]iew (qui en fait est souvent découpée en une vue et son ViewController qui lui est associé et dédié uniquement pour les interactions UI) et un [V]iew-[M]odel (qui est un peu ce qu'on met sous iOS dans me Controlleur parfois, qui se charge de l'intelligence métier, la logique, etc)


    Je vois des plus élus de gens parler du modèle MVVM et la façon de la mettre en place sur iOS, et le framework Cocoa ne l'interdit pas du tout. En gros il suffit de mettre dans ton UIViewController uniquement ce qui est lié fortement à  l'UI et devra changer si l'UI change, et de prévoir un NSObject (qui sera ton ViewModel) pour la partie interconnexion avec le modèle.


    A mon avis c'est un modèle à  creuser. En tout cas ça semble être plus proche du modèle que tu fais implicitement en RoR, non ?




     


    Pas franchement. A moins que mon contrôleur CRUD soit ton ViewModel... question de dénomination.


     


    Mais le MVVM est à  étudier de près, d'ailleurs je crois que je l'utilise déjà  dans un VC:


    - mon modèle Vin renvoit le datasource géré dans le VC. C'est très pratique de modifier uniquement le modèle et son datasource et de voir l'UI changer en conséquence sans faire des if (section == 1 et row == 0)


     


    Moi, ce que je recherche est très simple: faire des contrôleurs CRUD pour chaque modèle, comme dans Rails, et qu'on n'appelle pas le modèle directement à  la place pour faire son "auto-sauvegarde". Ces contrôleurs ne servent qu'au CRUD. Je voulais juste savoir si ça servait à  rien, ou bien si ça pouvait être sympa de se baser sur l'archi Rails en Cocoa.


     


    En plus, j'ai déjà  d'autres contrôleurs plus complexes qui font des "megas" requêtes, d'ailleurs 1 s'appelle le "Finder" et c'est un singleton. Mais il ne fait pas de CRUD mais juste du SELECT.


  • AliGatorAliGator Membre, Modérateur
    J'ai du mal à  comprendre ton besoin, mais très certainement parce que j'utilise CoreData pour 99% de mes modèles de données maintenant (et ce même si je n'ai pas besoin de stockage pérenne " il suffit juste de faire un [MagicalRecord setupCoreDataStackInMemoryStore] si on ne veux qu'un modèle non pérenne mais qui reste très facile à  manipuler et a tous les avantages de CoreData).

    En CoreData, on a les NSManagedObjectContext (MOC pour les intimes), et moi je décris souvent ça un peu comme des branches GIT.
    - On a un MOC principal, celui directement relié au PersistantStore. C'est un peu la branche "master" d'un repo GIT.
    - Et puis on peut créer des MOC dont le parent n'est pas un PersistantStore, mais un autre MOC. Donc tu as des MOC fils d'autres MOC, et tu crées ainsi une hiérarchie de MOC. Un peu comme en GIT quand tu crées une branche à  partir du master, et pourquoi pas quand tu crées une branche B à  partir d'une branche A.
    - Quand on fait un "save" sur un MOC, en fait ça correspond à  l'équivalent d'un "merge" en GIT, où tu merge ta branche dans la branche parente. Un "save" sur un MOC ne va faire que sauver/fusionner les modifications de ce MOC sur son MOC parent. Il va s'arrêter là , il ne va pas forcément propager ces modifications jusqu'au PersistantStore.



    Et du coup c'est très pratique. Imagine que tu as ta liste des vins, et qu'à  un moment tu veux afficher une fiche pour éditer un vin. Sauf que l'utilisateur peut finalement décider d'annuler, donc il ne faudra pas que tu sauves les modifications si c'est le cas.

    Pour cela, rien de plus simple : tu te crées une "@property(strong) NSManagedObjectContext* localContext" dans ton VC, et quand tu instancies ce VC, tu passes ton NSManagedObject (ton objet modèle Wine) à  ce VC avant de le pousser (rien de plus classique). Sauf qu'au lieu de manipuler directement l'objet Wine, qui est attaché au MOC principal (on va dire le "master" pour garder l'analogie GIT), tu crées un nouveau MOC "localContext" qui sera fils du contexte "master" (une sorte de "branche" dans mon analogie), et tu vas manipuler le Wine transposé dans ce nouveau contexte.
    - (void)setWine:(Wine*)newWine
    {
    if (!self.localContext)
    {
    // On crée le contexte local, qui sera fils du contexte "master" (= le contexte de l'objet Wine passé)
    self.localContext = [NSManagedObjectContext MR_contextWithParent:newWine.managedObjectContext];
    }
    // Au lieu de stocker dans l'ivar l'objet Wine passé en paramètre, on prend soin de le
    // transposer dans le localContext avant, pour manipuler ce vin dans le contexte local ensuite.
    _wine = [newWine MR_inContext:self.localContext];
    }
    Pourquoi faire ça ? Tout simplement parce qu'ainsi, dans ton VC qui permet d'éditer ce vin, tu peux avoir une TableView par exemple qui affiche tout plein de UITextField, chacun correspondant à  une propriété de ton Wine, et prérempli avec la valeur actuelle. Tu laisses l'utilisateur modifier ces valeurs à  son gré, et dès que le UITextField change de texte tu mets à  jour directement ton objet Wine (ton NSManagedObject).

    Pas besoin d'objet intermédiaire, d'un dictionnaire, ou je ne sais quoi. Même si ta TableView scrolle et que les cellules sont recyclées et disparaissent pour réapparaà®tre, tu afficheras toujours dans le champ la valeur courante de chaque propriété de ton objet Wine local.
    - si l'utilisateur valide avec le bouton "OK", tu as juste à  faire un "save:" sur le MOC et toutes les modifications (nom, cépage, etc) sur le vin seront sauvegardées sur le MOC parent (comme un "merge" de la "branche" sur le "master")
    - MAIS si l'utilisateur annule avec le bouton "Cancel", bah tu dismiss ton VC sans faire de "save:", le localContext part aux oubliettes avec le VC et ses modifications ne sont pas sauvées, et ton contexte principal(ton "master") reste inchangé.




    Conclusion : avec CoreData on a déjà  tout ce qu'il faut pour gérer des cas comme ça, avec des contrôlleurs dédiés qui ne manipulent que des données locales, sans risquer d'impacter les vraies données tant que tu ne lui demandes pas de "merger". On n'appelle pas le modèle pour faire la sauvegarde mais on demande au MOC de faire la sauvegarde.
  • FKDEVFKDEV Membre
    décembre 2015 modifié #16

    Pas franchement. A moins que mon contrôleur CRUD soit ton ViewModel... question de dénomination.




    Le ViewModel est un objet qui adapte le model à  la vue. C'est particulierement utile quand il y a du binding direct pour peupler les vues. Il peut y avoir un objet ViewModel pour chaque objet du Model.

     



    Moi, ce que je recherche est très simple: faire des contrôleurs CRUD pour chaque modèle, comme dans Rails, et qu'on n'appelle pas le modèle directement à  la place pour faire son "auto-sauvegarde". Ces contrôleurs ne servent qu'au CRUD. Je voulais juste savoir si ça servait à  rien, ou bien si ça pouvait être sympa de se baser sur l'archi Rails en Cocoa.



    Si tu penses que c'est bien, fais toi plaisir.


  • muqaddarmuqaddar Administrateur


    J'ai du mal à  comprendre ton besoin, mais très certainement parce que j'utilise CoreData pour 99% de mes modèles de données maintenant (et ce même si je n'ai pas besoin de stockage pérenne " il suffit juste de faire un [MagicalRecord setupCoreDataStackInMemoryStore] si on ne veux qu'un modèle non pérenne mais qui reste très facile à  manipuler et a tous les avantages de CoreData).


    En CoreData, on a les NSManagedObjectContext (MOC pour les intimes), et moi je décris souvent ça un peu comme des branches GIT.

    - On a un MOC principal, celui directement relié au PersistantStore. C'est un peu la branche "master" d'un repo GIT.

    - Et puis on peut créer des MOC dont le parent n'est pas un PersistantStore, mais un autre MOC. Donc tu as des MOC fils d'autres MOC, et tu crées ainsi une hiérarchie de MOC. Un peu comme en GIT quand tu crées une branche à  partir du master, et pourquoi pas quand tu crées une branche B à  partir d'une branche A.

    - Quand on fait un "save" sur un MOC, en fait ça correspond à  l'équivalent d'un "merge" en GIT, où tu merge ta branche dans la branche parente. Un "save" sur un MOC ne va faire que sauver/fusionner les modifications de ce MOC sur son MOC parent. Il va s'arrêter là , il ne va pas forcément propager ces modifications jusqu'au PersistantStore.




    Et du coup c'est très pratique. Imagine que tu as ta liste des vins, et qu'à  un moment tu veux afficher une fiche pour éditer un vin. Sauf que l'utilisateur peut finalement décider d'annuler, donc il ne faudra pas que tu sauves les modifications si c'est le cas.


    Pour cela, rien de plus simple : tu te crées une "@property(strong) NSManagedObjectContext* localContext" dans ton VC, et quand tu instancies ce VC, tu passes ton NSManagedObject (ton objet modèle Wine) à  ce VC avant de le pousser (rien de plus classique). Sauf qu'au lieu de manipuler directement l'objet Wine, qui est attaché au MOC principal (on va dire le "master" pour garder l'analogie GIT), tu crées un nouveau MOC "localContext" qui sera fils du contexte "master" (une sorte de "branche" dans mon analogie), et tu vas manipuler le Wine transposé dans ce nouveau contexte.



    - (void)setWine:(Wine*)newWine
    {
    if (!self.localContext)
    {
    // On crée le contexte local, qui sera fils du contexte "master" (= le contexte de l'objet Wine passé)
    self.localContext = [NSManagedObjectContext MR_contextWithParent:newWine.managedObjectContext];
    }
    // Au lieu de stocker dans l'ivar l'objet Wine passé en paramètre, on prend soin de le
    // transposer dans le localContext avant, pour manipuler ce vin dans le contexte local ensuite.
    _wine = [newWine MR_inContext:self.localContext];
    }

    Pourquoi faire ça ? Tout simplement parce qu'ainsi, dans ton VC qui permet d'éditer ce vin, tu peux avoir une TableView par exemple qui affiche tout plein de UITextField, chacun correspondant à  une propriété de ton Wine, et prérempli avec la valeur actuelle. Tu laisses l'utilisateur modifier ces valeurs à  son gré, et dès que le UITextField change de texte tu mets à  jour directement ton objet Wine (ton NSManagedObject).


    Pas besoin d'objet intermédiaire, d'un dictionnaire, ou je ne sais quoi. Même si ta TableView scrolle et que les cellules sont recyclées et disparaissent pour réapparaà®tre, tu afficheras toujours dans le champ la valeur courante de chaque propriété de ton objet Wine local.

    - si l'utilisateur valide avec le bouton "OK", tu as juste à  faire un "save:" sur le MOC et toutes les modifications (nom, cépage, etc) sur le vin seront sauvegardées sur le MOC parent (comme un "merge" de la "branche" sur le "master")

    - MAIS si l'utilisateur annule avec le bouton "Cancel", bah tu dismiss ton VC sans faire de "save:", le localContext part aux oubliettes avec le VC et ses modifications ne sont pas sauvées, et ton contexte principal(ton "master") reste inchangé.





    Conclusion : avec CoreData on a déjà  tout ce qu'il faut pour gérer des cas comme ça, avec des contrôlleurs dédiés qui ne manipulent que des données locales, sans risquer d'impacter les vraies données tant que tu ne lui demandes pas de "merger". On n'appelle pas le modèle pour faire la sauvegarde mais on demande au MOC de faire la sauvegarde.

     




     


    Merci pour ce cours sur CoreData, même si je ne l'utilise pas. J'ai bien compris ce principe de MOC.


    Ta dernière phrase résume tout: tu viens de confirmer mon idée de "contrôleur CRUD" intermédiaire entre VC et Modèle, ce qui serait mon MOC en quelque sorte.


     


    Encore une fois, tout marche très bien actuellement dans mon app, mais dans ma tête, ce n'est pas assez MVC, même si ça ne veut pas dire grand chose. 


    Et puis si je peux avoir la même archi entre différentes plateformes, je trouve ça plus clair.


     


    Merci Ali et les autres.


    Cette discussion reste ouverte car je la trouve intéressante, comme s'il n'y avait pas de vérité vraie.


     


     




    Le ViewModel est un objet qui adapte le model à  la vue. C'est particulierement utile quand il y a du binding direct pour peupler les vues. Il peut y avoir un objet ViewModel pour objet du Model.




     


    Est-ce qu'un datasource "perso" est un ViewModel ? Quand on y réfléchit, il adapte la vue au modèle.


    Exemple: on peut créer un array de données du modèle dans un certain ordre, et le balancer à  la vue pour qu'elle s'adapte.

  • Bonjour,


    il est difficile de s'intéresser au context de chaque application, mais pour ma part, je vois les applications Coredata un peu à  part dans le sens où le modèle est toujours disponible. Dans beaucoup de circonstances on peu avoir envie d'avoir des sous contrôleurs, car on les a déjà  développé ou par ce que l'on voudrait les utiliser à  nouveau, et ces contrôleurs ne sont pas toujours disponibles simultanément, ce qui implique d'avoir une "machine d'état" qui permet de collecter et de mettre à  disposition les données nécessaires à  l'initialisation des différents contrôleurs qui ne co-éxistent pas en permanence dans les différentes phases de vie de l'application.

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