Bonnes Pratiques "model"

Bonsoir à  tous,



Une question me turlupine :



un objet "Classe" contient une relation to-many vers "Groupe", lui-même ayant une to-many vers "Eleve".



Si une "Classe" est sélectionnée, je dois pouvoir accéder aux élèves de cette classe, quel que soit leur groupe. J'ai donc 3 solutions :



=> je crée une méthode qui énumère les groupes de la classe et ajoute à  un array les élèves au fur et à  mesure afin d'obtenir tous les élèves de la classe (c'est ce que j'ai fait et évidemment ça marche)



=> je crée une relation "directe" Classe to many Eleve, qui sera "redondante" et que je mettrai à  jour à  l'ajout d'un élève dans un groupe.



=> Il y a un autre moyen que je ne connais pas avec coreData qui me fait direct un "raccourci" Classe-Eleve (du genre @machinchose dans le keyPath..)



C'est une question de base, mais j'essaye d'améliorer ma pratique, histoire de faire des appli "propres"...

Réponses

  • AliGatorAliGator Membre, Modérateur
    mai 2012 modifié #2
    Je sais pas pour CoreData à  proprement parler (car jamais utilisé en pratique pour ma part) mais je vois pas en quoi ça changerait les choses que ce soit CoreData ou pas en fait : sache qu'avec le KVC et donc en utilisant un keyPath approprié, tu devrais directement pouvoir récupérer tous les élèves !



    Normalement [uneClasse valueForKeyPath:@groupes.eleves] devrait directement te donner tous les élèves, enfin je pense (à  vérifier dans les faits)
  • Tout à  fait Ali. ça marche.
  • yoannyoann Membre
    Yep, KVC et éventuellement des opérateurs de collection type @distinctUnion pour éviter les doublons.
  • MickMick Membre
    mai 2012 modifié #5
    La concaténation est donc automatique ?!.. Le KVC c'est quand même magique ! l



    Je vais de ce pas essayer tout ça. La petite astuce de Yoann me plaà®t bien... Je vais aller faire un tour dans la doc sur les fameux opérateurs de collection.. (mais où sont-ils ?...)





    Merci de vos réponses. Les gens sont vraiment sympas par ici !
  • MickMick Membre
    Merci. Dans le même genre (toujours dans la couche Model)



    un Eleve a participé à  des Evaluation (property date, coefficient ...) => Eleve to-many Evaluation. Il a donc un ResultEval (la note, l'appréciation ...) Comment gérer les relations ?

    Ce que j'ai fait :



    Evaluation to-many ResultEval to one Eleve

    Eleve to-many ResultEval to one Evaluation



    Du coup, quand je crée une évaluation je dois créer autant de ResultEval que d'élèves et mettre à  jour les relationships. De même, quand j'ajoute un Eleve, je doit créer autant de ResultEval que d'Evaluation.

    Est-ce là  la bonne technique ? Ca marche mais y a-t-il un autre moyen "plus propre" de procéder quand on a ce genre de "double entrée" ? Des bricoles KVC que je ne connais pas ?
  • yoannyoann Membre
    ça me semble bon, un objet élève, un objet évaluation et un objet résultat qui contiens un référence vers l'élève, l'éval et une property note.





    Tu peux éventuellement rajouter une propriété transitant (non sauvegarder) sur ton résultat, une property "notePondérée". Tu code toi même ton accesseur pour cette property qui devra renvoyer la note * le coef (facile, juste de la lecture de keyPath).



    Une fois ce travail fait au niveau du résultat, tu peux utiliser les opérateurs de collection pour faire des sommes et des moyennes sur tous les résultats d'un élève.



    Par contre, je rajouterais un élément supplementaire dans le lot, la matière associé à  l'éval. ça demandera des fetch request plus poussé pour ressortir uniquements les notes d'une matière mais ça te laisse des possibilités pour l'avenir.
  • MickMick Membre
    Je joints l'ébauche du dataModel. Est-ce que c'est "l'esprit" ? Y a-t-il des redondances inutiles ? ...



    Quelques éléments :



    Au cours d'une "période" il y aura des évaluations dans lesquelles des compétences seront testées. Une compétence peut être testée dans plusieurs évaluations au cours de l'année => J'ai donc créé l'entité "ResultCompsEvalsEleves" => (il y en aura NbEleves x NbEvaluations x NbCompetences). J'ai donc la possibilité de faire un "état" des compétences, classé par date etc...



    L'entité ResultEval permet d'avoir la note d'un élève à  une évaluation.



    L'entité CoursEleve permet d'avoir des infos sur le comportement, la présence, etc.. d'un élève durant une heure de cours.



    L'objectif de l'appli est d'être un outil pour le prof, pas trop "usine à  gaz", méga simple à  utiliser, et qui lui permet de visualiser l'évolution de ses élèves.

    Voici donc le "brouillon" du Model

  • yoannyoann Membre
    Il me semble y avoir beaucoup d'entités pour un simple suivit de progression.



    Typiquement, les périodes, est-ce bien nécessaire de les conceptualiser sous forme d'objet ? Une date de passage d'évaluation ainsi qu'un couple de valeur Année scolaire / Trimestre sous forme de simple chaine de caractère ne suffirait-elle pas ? Récupérer les notes d'une période reviendrait à  faire une FetchRequest avec un prédicat forçant la récupération de tel ou tel date.



    Pour les compétences, je ne comprends pas trop l'intérêt, cela étant, sans vrai description fonctionnelle c'est difficile de juger de la chose.
  • Personnellement je pense qu'il n'y a pas nécessité à  élaborer un modèle complet au début du développement d'une application ; les spec peuvent changer, le modèle peut-être adapté en fonction des contraintes techniques, des performances etc...
  • yoannyoann Membre
    'Kubernan' a écrit:


    Personnellement je pense qu'il n'y a pas nécessité à  élaborer un modèle complet au début du développement d'une application ; les spec peuvent changer, le modèle peut-être adapté en fonction des contraintes techniques, des performances etc...




    Je ne suis pas vraiment de cet avis. Quand on arrive au moment où il faut tout refactorer car la base à  été mal pensé c'est une perte de temps énorme...



    Pour ma part, je préfère passer du temps sur l'expression du besoin et la compréhension entière du projet pour savoir réellement quel est le besoin, le reformuler clairement et anticiper les évolutions via un modèle de donnée éventuellement plus complet que nécessaire d'après le besoin primaire. ça demande de passer plus de temps sur le projet, projet qui avancera plus lentement et demandera plus d'investissement de la part du client mais au moins l'application finale sera, à  mon sens, bien plus intéressante.



    Par contre, pour la phase d'étude, je ne travail pas qu'avec du théorique. Ma méthodologie est de travailler par PoC sur différentes méthodes et d'en suite en tirer une architecture viable pour la v1. Quand je présente un concept à  un client au lieu de faire des dessins je fais des applications maquettes.
  • Je me suis mal exprimé sans doute. Je ne disais pas qu'il fallait se passer de specs.



    Pour mon appli en cours de dev, j'ai 17 pages de specs (avec la description du modèle donc) mais j'ai créé mes entités au fur et à  mesure du développement. Et comme je le disais, personnellement, je trouve cela plus efficace particulièrement avec core data qui nécessite parfois de dénormaliser plus que de coutume (dans le sens où ce n'est pas une base de données relationnelles).



    Procédant ainsi ça me laisse un marge de manoeuvre par rapport au papier. Je me suis par exemple rendu compte qu'une de mes approche (concrètement l'enregistrement de certains calculs, genre des sommations périodiques) ne collait pas du tout avec les performances que j'en attendais. Du coup j'ai éliminé certaines entités et décidé de faire dynamiquement les calculs.



    Je sais également que la v1 de mon appli n'aura pas toutes les fonctionnalités utilisateurs décrites dans mes specs, mais pour m'éviter des lourdeurs dans la migration du modèle pour les versions futures, j'ai intégré dans mes entités des données qui me serviront plus tard.



    Sur ce coup là  je bosse tout seul.



    Avec des clients c'est un peu la loterie : "C'est bien, vous avez fait ce que j'ai demandé mais ce n'est pas ce que je veux" :-)
  • MickMick Membre
    mai 2012 modifié #14
    Quelques éléments pour expliquer mes choix :


    Pour les compétences, je ne comprends pas trop l'intérêt




    Au delà  d'une note, nous devons évaluer des compétences au cours de l'année par ex : dans "communiquer" : savoir faire un graphique. Cette compétence pourra être évaluée plusieurs fois dans l'année. L'élève peut avoir "validé" la compétence si il réussi au moins 3 fois dans des contextes différents. Il est donc important de pouvoir avoir un état des compétences à  la fois par élève et au cours de l'année, mais aussi par classe (pour détecter des éventuels problèmes de classe et adapter l'enseignement en conséquence...). C'est pour cela qu'il me faut des "ResultCompEvalEleve" (compliqué !) puisqu'il me faut la validation ou non de telle compétence pour tel élève au cours de telle évaluation.



    Pour les "périodes", j'ai besoin de la chaà®ne de caractère, et en plus les dates peuvent être différentes : (je travaille dans un IUT de temps en temps, et les périodes sont des semestres, alors qu'au lycée c'est en trimestres. Si en plus l'utilisateur est un remplaçant, il peut faire plusieurs établissements dont les dates des conseils de classes peuvent être différentes !). Je ne vois pas trop d'autres solutions.



    Je suis d'accord avec Yoann sur le fait d'anticiper et de faire dès le départ un modèle complet. Il m'est arrivé de galérer un peu au changement de version du xdatamodel (il n'y avait pas de mapping à  l'époque)



    Selon vous, j'abuserais un peu des entités ? C'est moins violent que le Perrier Citron !
  • yoannyoann Membre
    Avec les explications des compétences ça va mieux. À première vue, ça me semble pas mal comme schéma.
  • MickMick Membre
    Ok, j'ai donc a priori pigé l'esprit.



    Dernière petite chose : pour les photos, quelle est la meilleure manière avec CoreData : stocker l'url sous forme d'une string, ou bien stocker l'imageRep directement dans la base ?
  • yoannyoann Membre
    Pour les données, il y a plusieurs écoles... J'en retiens deux principalement :
    • Stocker un ID de fichier unique, l'application étant capable, à  partir de son environnement d'exécution de trouver le point de stockage et de calculer l'URL final (ne jamais stocker l'URL entière sinon c'est la misère en cas de migration de données) .
    • Stocker deux entités pour une image, l'entité image qui contient les metadonnés et qui dispose d'une ref vers une entité ImageData qui ne contient qu'un blob.


    Je suis partisan de la seconde solution pour ma part. Cela permet d'avoir une base entière, c'est plus simple pour gérer les sauvegardes. Par contre ça augmente la taille de la base de donnée et donc les risques de corruption.
  • FKDEVFKDEV Membre
    'Kubernan' a écrit:


    Pour mon appli en cours de dev, j'ai 17 pages de specs (avec la description du modèle donc) mais j'ai créé mes entités au fur et à  mesure du développement. Et comme je le disais, personnellement, je trouve cela plus efficace particulièrement avec core data qui nécessite parfois de dénormaliser plus que de coutume (dans le sens où ce n'est pas une base de données relationnelles).




    C'est particulièrement vrai dans le cas des apps mobiles où un modèle bien pensé, bien normalisé, peut s'avérer catastrophique en terme de performances.



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