Faire un code propre MVC en Objective-C

Après avoir lu des dizaines de tutoriaux en ligne, et connaissant plusieurs langages, la première chose que je me suis dit c'est qu'ils codent comme des gros dégeulasses en balançant tout dans le AppDelegate.m. Et que pour un gros programme, c'est comme si on faisait tout dans la méthode main (en langage C). C'est immonde.


 


Ma question est donc la suivante (elle est assez générale) : Comment faire un code propre ?


 


Normalement en MVC on balance tout dans le controller qui gère la fenêtre.


Dans vos programmes, la méthode didFinishLaunchingWithOptions est quasiment vide ou pas ?


A quoi vous sert réellement le AppDelegate ?


 


Normalement il ne doit servir qu'à  des actions précisent bien spécifées dans le fichier : Application Terminée, Application a terminée son lancement, etc.

Je me trompe ?


 


Merci de donner votre point de vue, en m'expliquant comment vous catégorisez vos fichiers.


Réponses

  • MalaMala Membre, Modérateur

    Le problème c'est que ceux qui font des tutoriaux sont rarement des gens qui vivent de leurs développements. Donc  la maintenabilité est le moindre de leur besoin.


     


    Perso sous OS X, en règle générale j'ai un contrôleur principal (qui est aussi de manière assez logique le delegate de mon App et de ma fenêtre mère pour un app Desktop). A partir de là , j'ai deux approches  pour structurer:


    - usage de "sous contrôleurs" (hiérarchisés de manière pyramidale si la complexité du projet le justifie)  pour de gros morceaux liés à  la gestion de parties métier bien identifiées. 


    - usage de catégories liées à  mon contrôleur principal pour des morceaux plus simplistes mais pour autant facilement détachables.


     


    Après sous iOS, l'approche peut même être poussée plus loin. La navigation se faisant par le biais de multiples vues, on a souvent un contrôleur par vue avec un contrôleur de navigation qui chapeaute l'ensemble avec un mécanisme du push/pop. Chaque contrôleur se contente alors de gérer les interactions avec la vue qui lui est affectée et le contrôleur de navigation s'occupe de la hiérarchie des vues/contrôleurs. Que les experts iOS me contredisent si j'ai écris une ânerie. 


  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #3

    Dans vos programmes, la méthode didFinishLaunchingWithOptions est quasiment vide ou pas ?

    Je confirme.
     

    A quoi vous sert réellement le AppDelegate ?

    A faire ce pour quoi il a été prévu à  l'origine : juste être le délégué de l'application
     

    Normalement il ne doit servir qu'à  des actions précisent bien spécifées dans le fichier : Application Terminée, Application a terminée son lancement, etc.

    Exactement.
     

    Je me trompe ?

    Non, tu as tout bon :) Les tutos que tu cites et as pu voir sur la toile sont codés comme les pieds (sans doute parce que leur but c'est de te montrer rapidement comment arriver à  un résultat, plutôt que comment le faire proprement.

    Mais rassures-toi, tu as tout résumé et tout bien compris : le vrai MVC, tel qu'on l'utilise dans nos applis de tous les jours, est comme tu le décris : quasiment rien dans le AppDelegate à  part ce qui est nécessaire pour gérer le lancement/la fin de l'appli, ou ce genre de choses, et ce qui est nécessaire pour gérer la fenêtre et ses interactions dans un Controlleur. Je te rassure c'est bien comme ça qu'on fait, contrairement à  ce que semblent montrer tes tutos !
  • CéroceCéroce Membre, Modérateur
    Tu verras, il y a aussi pas mal de gens qui instancient le modèle dans l'AppDelegate, et ensuite qui écrivent:


    MonModele *modele = [UIApplication sharedApplication].delegate.modele;
    Plus crade, tu meurs !
  • jojolebgjojolebg Membre
    juin 2014 modifié #5

    Tu verras, il y a aussi pas mal de gens qui instancient le modèle dans l'AppDelegate, et ensuite qui écrivent:
     

    MonModele *modele = [UIApplication sharedApplication].delegate.modele;
    Plus crade, tu meurs !

     
    Il y a quelques années, quand j'ai commencé le dev iPhone en tant que stagiaire, un collègue m'avait conseillé cette bonne pratique.
    Aujourd'hui les personnes en charge de la maintenance de l'application en souffre énormément. Dès qu'on me prononce le nom de l'application j'ai tout de suite pleins de remords, et je fuis pour pas que je sois son prochain mainteneur.
  • colas_colas_ Membre
    juin 2014 modifié #6

    Du coup, qui instance les classes modèle ? Les view controllers ?


     


    Si le modèle est global, on l'instancie dans le VC global ?


  • AliGatorAliGator Membre, Modérateur
    Si tu utilises CoreData et MagicalRecord, un appel à  [MagicalRecord setupCoredataStack] dans l'AppDelegate ne me gène pas. Et ensuite tu as accès au modèle directement, via des [MaClasseModele MR_findAll] ou autres méthodes de MagicalRecord pour faire directement des requêtes dans ta base CoreData depuis n'importe où.

    Sinon si tu as un modèle à  instancier soit tu fais une sharedInstance pour le manipuler et y accéder de n'importe où, soit tu le passes de proche en proche de VC en VC (il y a débat entre ces 2 solutions, mais dans tous les cas il ne faut pas avoir à  référencer l'AppDelegate depuis les autres classes à  chaque fois que tu as besoin de ton modèle, sinon c'est que ton code est très mal cloisonné)
  • paozpaoz Membre

    Moi pour l'instant mes fichiers sont déclarés comme suit :


     


    - Un dossier Modèle pour mon modèle de données


    - Un dossier Controller pour mes ViewController


     


    Le problème c'est que je me retrouve avec des fichiers qui ne sont pas des ViewController dans ce dossier. Je pense spécifiquement au fichier nommé ProductViewCell que j'ai créé et qui est une partie spécifique du TableViewController qui gère mes "Products"


    Comment ranger ces fichiers de manière plus propre ? Je refléchis encore à  comment nommer ce nouveau dossier franchement.


     


    Et j'ai une question concernant le navigationController. A quoi il sert exactement ?


    Plusieurs objets le mettent en place systématiquement. Comme par exemple quand on ajoute une vue qui contient des onglets.


    Un navigationController est-il obligatoirement le point d'entrée de notre application ?

  • CéroceCéroce Membre, Modérateur

    Moi pour l'instant mes fichiers sont déclarés comme suit :
     
    - Un dossier Modèle pour mon modèle de données
    - Un dossier Controller pour mes ViewController

    Personnellement, j'ai aussi un dossier Vues... 

    Le problème c'est que je me retrouve avec des fichiers qui ne sont pas des ViewController dans ce dossier. Je pense spécifiquement au fichier nommé ProductViewCell que j'ai créé et qui est une partie spécifique du TableViewController qui gère mes "Products"

    Tout ça se discute, et ce n'est pas d'une importance vitale. En gros UITableCellView hérite de UIView, donc c'est une vue. Pourtant, en général, un type de cellule n'est utilisé que dans une seule table; ainsi ça a plus de sens de grouper la cellule avec le TableViewController qui l'utilise.
    Tu verras par la suite que comme les TableViewControllers deviennent vite énormes, la tendance actuelle est de déporter la logique dans la cellule, qui devient alors un contrôleur...
     

    Et j'ai une question concernant le navigationController. A quoi il sert exactement ?

    Il gère une pile de view controllers. Il y a une commande Push pour empiler, et une commande Pop pour dépiler.
    Seul le view controller en haut de la pile apparaà®t. Une UINavigationBar affiche le titre du contrôleur courant et une flèche pour dépiler.

    Plusieurs objets le mettent en place systématiquement. Comme par exemple quand on ajoute une vue qui contient des onglets.
    Un navigationController est-il obligatoirement le point d'entrée de notre application ?

    Non, par exemple, si tu as des onglets (UITabBarController), chaque onglet contient un view controller différent. Il se trouve que ces view controllers sont souvent des navigation controllers, pour permettre de se promener dans l'arborescence de chaque onglet, mais tu auras bien une pile par onglet.
  • samirsamir Membre
    juin 2014 modifié #10

    Et j'ai une question concernant le navigationController. A quoi il sert exactement ?
    Un navigationController est-il obligatoirement le point d'entrée de notre application ?

     
    à  lire absolument :)
    ViewController Programming Guide for iOS
  • paozpaoz Membre

    C'est souvent des questions bidons qu'ont les développeurs qui viennent d'autres langages, mais en réalité ce sont là  ou se situe les différences entre les langages et surtout c'est là  qu'on différencie un projet qui fonctionne, d'un projet optimisé et maitrisé car le développeur sait exactement ce qu'il fait à  n'importe quel moment!


     


    Merci pour le lien samir, je viens de le lire et il est très bien expliqué !


    Donc ca veut dire qu'un NavigationController contient toutes les View dans lesquels il peut naviguer, empilée et qu'on y accède à  partir d'un ObjectIndex (de mémoire).


    Est-ce que c'est quand même fait de manière intelligente, c'est à  dire qu'il ne charge que ce dont il a besoin au moment ou il en a besoin ? Parce que si tout est empilé, ca fait peur au niveau de l'utilisation mémoire :)


     


    Donc Céroce, ton dossier Controller contient tes ViewController, et ton dossier View contient le contenu de tes ViewController, comme par exemple une TableViewCell ?


  • CéroceCéroce Membre, Modérateur

    Donc Céroce, ton dossier Controller contient tes ViewController, et ton dossier View contient le contenu de tes ViewController, comme par exemple une TableViewCell ?

    Non. Je range les TableViewCells avec les UITableViewControllers qui les utilisent.
    Dans le dossier Vues, je mets mes éventuelles sous-classes de UIView et UIControl, qui seront utilisées un peu partout dans l'appli.
  • paozpaoz Membre
    juin 2014 modifié #13


    Tu verras, il y a aussi pas mal de gens qui instancient le modèle dans l'AppDelegate, et ensuite qui écrivent:

     



    MonModele *modele = [UIApplication sharedApplication].delegate.modele;

    Plus crade, tu meurs !

     




    Tu l'instancies ou ton modèle toi ? Dans le controller de la première vue ?


     


    EDIT : C'est pour relancer le débat entre la sharedInstance et le passage à  chaque VC :p


     




    Non. Je range les TableViewCells avec les UITableViewControllers qui les utilisent.

    Dans le dossier Vues, je mets mes éventuelles sous-classes de UIView et UIControl, qui seront utilisées un peu partout dans l'appli.




    Ok merci de ta réponse :)


  • CéroceCéroce Membre, Modérateur

    Tu l'instancies ou ton modèle toi ? Dans le controller de la première vue ?



    Non, dans l'AppDelegate. Puisque c'est lui qui instancie les contrôleurs "racine", alors il y a forcément accès. La différence, c'est que ce sont les contrôleurs qui passent ensuite à  leurs enfants ce dont ils ont besoin (pas forcément tout le modèle). On identifie alors clairement les dépendances entre classes.
Connectez-vous ou Inscrivez-vous pour répondre.