MONA

Bojan Odobasic - Automne 2021

Mandat du projet

Le projet principal de la Maison MONA est la création d'une application mobile qui promeut la découverte de l'art et des espaces culturels montréalais. L'application permet à l'utilisateur de rechercher des oeuvres d'art publiques et de les ajouter à sa collection personnelle en y joignant une photo et une évaluation. Dans le cadre du cours « Projet d'informatique (IFT 3150) » du Département d'informatique et de recherche opérationnelle de l'Université de Montréal, je contribuerai au développement de l'application mobile pour la plateforme iOS. Concrètement, mon mandat pourrait m'amener à :
  • Ajouter la fonctionnalité de badges
  • Implémenter les entrées de type « Patrimoine »
  • Permettre l'utilisateur de modifier les attributs de sa collection personnelle
  • Afficher des informations complémentaires aux oeuvres collectionnées
  • Améliorer certains éléments de l'interface utilisateur dont :
    • Page d'accueil et oeuvre du jour
    • Aperçu des oeuvres collectionnées
    • Réglages de la langue de l'utilisateur
Les tâches seront réévaluées en cours de route selon les priorités du projet et des contraintes liées au framework utilisé ou à l'application serveur. Un étudiant de la session passée, Jean-Marc Prud'homme, travaillera également sur le projet durant l'automne et nous nous partagerons certaines de ces tâches.

Rapports hebdomadaires

Semaine 1 - 1er au 7 septembre

J'ai eu la confirmation que je participerai au projet au début de la semaine. Puisque je savais déjà que je travaillerais sur l'application iOS, j'en ai profité pour mettre à jour ma version de macOS et pour télécharger Xcode. Nous avons fait une première rencontre de groupe le mercredi avec Lena et les deux autres étudiants pour se présenter et s'entendre sur le déroulement général du projet. Ensuite, Jean-Marc m'a fait un survol du code et m'a montré les principales fonctionalités de Xcode. Plus tard dans la semaine, j'ai lu au sujet de la syntaxe de Swift.

Semaine 2 - 8 au 14 septembre

Lena est en vacances cette semaine et j'ai profité du début tranquille de la session pour faire de la formation au sujet de SwiftUI. Jean-Marc a déployé une nouvelle version de l'application sur l'App Store et il m'a montré le processus. Également, j'ai lu le rapport qu'il avait préparé la session passée et je m'en suis inspiré pour débuter la création de mon propre rapport. J'ai déposé la première ébauche de celui-ci sur les serveurs du DIRO.

Semaine 3 - 15 au 21 septembre

Nous avons fait une première réunion en personne à l'université. Celle-ci a surtout porté sur l'état actuel du projet dans son ensemble ainsi que sur l'état des différentes applications. Lena nous a présenté un peu sa vision du projet et ses attentes par rapport à notre mandat. Je dois avouer que je ne suis pas sûr de bien comprendre mon rôle encore... Je demanderai des clarifications à la prochaine rencontre. Lena m'a demandé d'évaluer la faisabilité ainsi que les avantages/incovénients d'incorporer une base de donnée locale à l'application pour sauvegarder l'ensemble des oeuvres. Cette approche est celle qui a été utilisée dans l'application Android, alors que l'application iOS conserve ces informations dans un fichier JSON. J'ai déposé plus bas le fruit de mes recherches. Également, je devais mettre à jour les billets du Github. Cependant, puisque je viens d'arriver dans le projet, je ne savais pas vraiment où on en était rendu. Nous aurons une rencontre avec Jean-Marc la semaine prochaine ce qui me permettra de mieux saisir l'état des choses. Enfin, j'ai poursuivi la formation SwiftUI.

Présentement, l'application est distribuée avec la liste des oeuvres pré-chargée dans un fichier en format JSON. Ce fichier est lu en entier lors de l'ouverture de l'application et la liste est gardée en mémoire. L'utilisateur ne peut pas modifier la liste d'aucune façon et il n'est pas prévu, pour le moment, qu'il puisse le faire. L'emploi d'un fichier JSON pour stocker des données est plus simple à mettre en place qu'une base de données. Cependant, l'approche pourrait se révéler limitante. En effet, une base de données offrirait probablement de meilleure performance si la quantité de données est grande. Dans le contexte actuel, néanmoins, je ne vois pas d'avantages particuliers. Cela pourrait être réévalué si le projet prend une plus grande envergure et que le nombre d'oeuvres augmente de façon importante.

Avantages d'une base de données
  • Gain en performance lors de la recherche si beaucoup de données
  • Simplification de l'écriture des requêtes complexes
  • Diminution des échanges d'information avec le serveur lors des mises-à-jour (si support adéquat du côté serveur)
Désavantages d'une base de données
  • Risque d'incohérence entre la base de données locale et celle sur le serveur
  • Plus complexe à mettre en place initialement
  • Migrations à prévoir lorsque le schéma est modifié

Si une base de données est à implémenter, il faudra également choisir le gestionnaire. Il y a présentement trois choix populaires :

SQLite
Relationnel, bien connu, assez simple d'utilisation.
Realm
Orienté objet, s'arrime bien avec la structure JSON, moderne, simple d'utilisation, bonnes performances.
Core Data
Orienté objet, supporte le relationnel, déjà inclus avec iOS, bonnes performances.
Semaine 4 - 22 au 28 septembre

Rencontre virtuelle pour débuter la semaine avec Lena et Jean-Marc. Nous avons convenu de ne pas faire de base de données locale pour le moment. Nous avons également révisé les différents cas d'utilisation de l'application pour identifier le travail à faire. J'en ai profité pour clarifier mon mandat. Durant la fin de semaine, j'ai participé, avec les autres étudiants, à une des activités organisées par Lena dans le cadre des journées pour la culture. Cela nous a permis de tester les deux applications sur le terrain et d'apprendre au sujet des oeuvres d'art publiques sur le Mont-Royal. J'ai bien apprécié l'expérience. Enfin, j'ai commencé à faire des modifications au code. J'ai amélioré la gestion des oeuvres du jour en assurant que l'oeuvre sélectionnée au hasard n'est pas déjà collectionnée par l'utilisateur et qu'elle ne sera mise-à-jour qu'une seule fois par jour. Cela a pris beaucoup plus de temps que prévu car je ne suis pas encore très à l'aise avec Swift. J'ai dû lire au sujet de Core Data qui est le framework permettant de faire persister les données ainsi qu'au sujet des « optionnals », un type de données particulier dans Swift qui protège contre les références nulles. J'ai testé les modifications et tout semble bien fonctionner. Le code a été déposé sur GitHub.

Objectifs pour la semaine prochaine
  • Mettre à jour la section Mandat de ma page personnelle et ainsi que les billets sur GitHub.
  • Continuer d'améliorer la page d'accueil (Oeuvre du jour) : permettre la prise de photo directement à partir de cette page page, modifier l'apparence des boutons.
  • Regarder l'implémentation des badges dans l'application Android et au niveau du serveur.

Semaine 5 - 29 septembre au 5 octobre

Rencontre de début de semaine en personne. Nous avons discuté d'améliorations à apporter à l'interface utilisateur. Il y a des modifications à faire dans la fenêtre des oeuvres collectionnées. En particulier, l'ordre d'affichage des informations est à inverser et il faudra permettre à l'utilisateur d'ouvrir sa photo afin qu'il puisse la zoomer et la voir sous une autre orientation. Nous avons discuté aussi de nouvelles fonctionnalités. Suite à l'activité de la fin de semaine passée, il nous apparaît de plus en plus important de permettre la modification de la photo d'une oeuvre collectionnée. Une bouton sur cette même fenêtre pourrait être ajouté afin de recommencer la prise de photo. Cependant, il n'est pas clair pour le moment si l'application serveur permet de gérer cela. Également, Lena aimerait que suite à l'ajout d'une oeuvre à la collection, qu'un lien s'affiche pour permettre d'obtenir davantage d'informations sur celle-ci. Ces données sont probablement protégées par un droit d'auteur donc on ne pourrait pas simplement les ajouter à notre base de données. Ceci nécessite des modifications au niveau serveur avant de pouvoir être intégré aux l'applications mobiles. Les billets du Github ont été mis-à-jour suite à ces nouvelles demandes. Niveau programmation, j'ai refait le code de la semaine passée. Jean-Marc m'a suggéré d'utiliser les « UserDefaults » plutôt que Core Data pour retenir les données. Le code est beaucoup moins complexe de cette manière et ne requiert pas l'utilisation d'une base de données qui au final ne contenait qu'une seule ligne... Pour l'amélioration de la page d'accueil, j'ai décidé d'attendre un peu car je n'ai pas d'iPhone présentement pour faire les tests et le simulateur ne permet pas d'utiliser les fonctions de caméra. Une librairie nommée « iCimulator » permet d'ajouter cette fonctionnalité mais je n'ai pas réussi à la faire fonctionner. Je réessayerai plus tard. Enfin, j'ai regardé le code du serveur ainsi que de l'application Android pour comprendre le fonctionnement actuel des badges. J'ai consigné mes découvertes plus bas. J'ai découvert quelques bugs qui ont été rapportés à Ming qui s'occupe de cette application.

Objectifs pour la semaine prochaine
  • Retenter l'installation de « iCimulator »
  • Permettre le changement de la langue directement dans l'application

Application serveur
La définition des badges est conservée du côté de serveur. Il s'agit d'une liste de badges existants avec une description incluant les conditions d'obtention. Cette approche a été favorisée afin d'uniformiser les badges entre les différentes plateformes. Un fichier CSV sur le serveur contient les définitions. Une « job » Laravel permet d'importer les données de ce fichier dans la table de Badges de la base de données. L'API contient une route (/api/badges) qui retourne le contenu de cette table. Le serveur ne s'occupe pas de vérifier les conditions d'obtention des badges et ne conserve pas un historique des badges obtenus par les utilisateurs.
Application Android
La liste des badges existants est enregistré dans une base de données (com.maison.mona.data). Un champ « isCollected » précise si le badge a été obtenu. Des entités ont été créées pour les badges et les conditions d'obtention (arguments requis et optionnels) dans com.maison.mona.entity. Un convertisseur fait le lien entre le JSON obtenu du serveur et les entités. Un adaptateur fait quant à lui le lien entre la base de données et les icônes des badges. Parmi les fragments (com.maison.mona.fragments), on retrouve :
  • BadgeDetailFragment : affiche les détails d'un badge. Une fonction s'occupe de faire le décompte des oeuvres collectionnées pour établir où en est l'utilisateur par rapport à l'objectif.
  • OeuvreRatingFragment : s'occupe de recueillir les notes des utilisateurs pour une oeuvre. Après que ce soit fait, il y a une vérification des conditions d'obtention des badges en faisant encore un décompte de toutes les oeuvres collectionnées.
L'implémentation de la vérification des conditions d'obtention des badges est « hard-coded » dans l'application, en fonction du type d'argument requis et optionnel associé au badge.

Semaine 6 - 6 au 12 octobre

Rencontre virtuelle cette semaine. Lena nous mentionne que le tutoriel a été mis-à-jour par Zuzanna et qu'il faudrait l'intégrer rapidement à l'application. Jean-Marc m'a déjà fait part de son intention de le faire cette semaine. Nous avons discuté des problèmes d'envoi des photos du côté serveur. Il semblerait qu'un mauvais lien symbolique empêchait le serveur de récupérer les photos. Celui-ci a été corrigé. Par contre, Thomas ne semble pas convaincu que tous les problèmes étaient causés par cela. Nous avons remarqué que les photos de l'activité des journées de la culture sont arrivées en retard et qu'il en manquait une partie. Puisque l'application iOS tente un renvoi des photos à la prochaine ouverture, je crois que cela explique le délai de réception. Certains utilisateurs n'ont probablement pas rouvert leur application depuis, ce qui explique aussi qu'il manque des photos. J'ai tenté de mon côté d'envoyer une photo et celle-ci s'est rendue sur le serveur. Je ne constate donc aucun problème additionnel avec l'envoi des photos dans l'application iOS actuellement. Nous resterons à l'affût. Thomas mentionne aussi que certains envois se sont fait avec une photo null. Lena reconnaît l'identificateur des utilisateurs concernés et va les contacter pour vérifier s'ils utilisent la dernière version de l'application et s'ils éprouvent des problèmes avec celle-ci. Pour ma part, j'ai réussi à installer « iCimulator » à l'aide des « CocoaPods ». Cela me permettra de faire des tests avec la caméra en attendant que je mette la main sur un iPhone. J'ai ajouté une fonctionnalité permettant de changer la langue d'affichage directement dans l'application. Avant les modifications, la langue de l'application était déterminée par celle du système. Nous n'avions qu'à fournir des traductions pour les textes, et le système se chargeait d'afficher le tout dans la bonne langue. Cependant, puisque nous n'offrons que le français et l'anglais, un utilisateur avec une autre langue d'affichage au niveau système se faisait imposer la langue par défaut. Il pourra maintenant sélectionner celle qui lui convient le plus. Pour ce faire, j'injecte la langue que l'utilisateur a sélectionné (ou la langue de son appareil s'il n'a rien sélectionné) dans l'environnement de l'application. Cependant, cela complexifie un peu notre travail car le système ne s'occupe plus de traduire automatiquement tout le texte. Par exemple, j'ai dû recréer quelques composants fournis par le système moi-même (bouton « Précédent » et « Picker »). Il reste néanmoins quelques textes qui ne pourront pas être traduits (par exemple, la mention « Légal » sur la carte).

Objectifs pour la semaine prochaine
  • Mise-à-jour du site web de la Maison Mona (activité de groupe)
  • Élaborer une ébauche de plan pour l'implémentation des badges

Semaine 7 - 13 au 19 octobre

Rencontre virtuelle avec Jean-Marc. Nous avons surtout fait une mise au point par rapport aux priorités de l'application iOS. Nous avons convenu de faire deux « milestones » ou « releases » d'ici la fin de la session. Le premier « milestone » portera sur des corrections UI/UX, soit l'amélioration de la page d'accueil, de l'affichage des oeuvres et de la fenêtre de filtrage/tri. Les deux premières corrections seront effectuées par moi, alors que la dernière le sera par Jean-Marc. Nous prévoyons déployer ces corrections le 10 novembre. Le deuxième « milestone » ajoutera les fonctionnalité de badges et de changement de langue. Je serai responsable de faire l'implémentation et le déploiement de ces nouvelles fonctionnalités. Parallèlement, Jean-Marc fera l'ajout des données de type patrimoine à titre de test, sans déploiement. Le tout devra être complété pour le 15 décembre. J'apprécie qu'on clarifie les tâches de cette manière. Enfin, j'ai présenté la fonctionnalité de modification de langue que j'avais codé la semaine passée. Nous avons cependant réalisé que cela allait à l'encontre des lignes directrices d'Apple. Il est préférable de rediriger les utilisateurs vers le panneau de configuration d'iOS plutôt que de gérer cela à même l'application. Puisque je n'avais pas encore fusionné mon code à la branche principale du GitHub, je vais mettre cela de côté pour le moment et je vais faire les modifications nécessaires pour le mois de décembre. Plus tard dans la semaine, j'ai mis sur papier mon ébauche de plan pour l'implémentation des badges que je présente plus bas. Pour ce qui est de l'activité de groupe de modification du site web de la Maison Mona, elle a été remise à plus tard dans la semaine.

Objectifs pour la semaine prochaine
  • Mise-à-jour du site web de la Maison Mona (activité de groupe)
  • Terminer l'amélioration de la page d'accueil (Oeuvre du jour) : permettre la prise de photo directement à partir de cette page page, modifier l'apparence des boutons.
  • Débuter l'implémentation des badges

Il faudra implémenter les éléments suivants :
BadgeModel
La liste de badges sera conservée dans un fichier JSON et sera distribuée avec l'application, tout commes les oeuvres actuellement. Une structure modèle répliquera les champs du fichier JSON. Les conditions d'obtention (arguments requis et optionnels) seront dans une structure séparée ou dans une énumération. Je conserverai également une référence vers les icônes des badges sous forme d'énumération. Il faudra également créer un BadgesDataService pour décoder le fichier JSON.
Badge (entitée Core Data)
Tous les badges existants seront ajoutés à la base de données locale (Core Data). En effet, puisqu'il faudra garder une trace de l'avancement de l'obtention de chaque badge, il sera plus efficace de procéder ainsi. Cette entité aura un champ id (identique à celui du JSON) de type entier et requis, artworksLeft (nombre d'oeuvres manquantes pour l'obtention) de type entier positif et requis et dateObtained (date d'obtention du badge) de type date et optionnel.
updateBadgeTable
Cette fonction sera exécutée à chaque ouverture de l'application. Elle permettra d'ajouter des nouveaux badges dans la base de donnée et de les octroyer à l'utilisateur si nécessaire. La fonction vérifiera tout d'abord si le nombre de badge dans la base de données est égale au nombre de badges dans le fichier JSON. Si oui, la fonctionne termine. Si non, pour chaque badge manquant, elle ajoutera une entrée dans la base de données locales après avoir calculer le nombre d'oeuvre déjà collectionnée admissibles pour le badge. Dans le cas où le nombre d'oeuvres manquantes est égal à zéro, une alerte avertira l'utilisateur qu'il a obtenu un ou des nouveaux badges.
checkForBadge
Cette fonction se retrouvera dans BadgeViewModel. Elle sera exécutée à chaque fois qu'une oeuvre est collectionnée. Elle permettra de vérifier si des badges doivent être octroyés à l'utilisateur suite à l'ajout de cette nouvelle oeuvre à sa collection. Pour chaque badge existant, la fonction vérifiera si l'oeuvre correspond aux conditions d'obtention. Si oui, le champ artworksLeft de ce badge sera décrémenté de un. Si le champ devient alors égal à zéro, une alerte avertira l'utilisateur qu'il a obtenu un ou des nouveaux badges.
De plus, il faudra créer l'interface qui affiche les badges dans la page collection. La page de collection affichera les badges par le même mécanisme qu'elle affiche les oeuvres. Il sera adapté cependant pour accepter le BadgeModel. Il sera nécessaire de croiser les données du fichier JSON ainsi que celles dans la base de données locales afin d'afficher la liste des badges existants, marquer ceux qui ont été obtenus et indiquer le nombre d'oeuvres manquantes pour les autres. Cela sera facilité par le BadgesDataService déjà discuté ainsi que par les fonctions de base de Core Data. Enfin, il ne manquera que BadgeView pour gérer l'affichage des badges individuels.

Semaine 8 - 20 au 26 octobre

Pas de rencontre formelle cette semaine car nous avons eu l'activité de groupe de mise-à-jour du site web de la Maison Mona. J'ai personnellement travaillé sur la page Application. J'ai ajouté un carrousel qui présente le tutoriel de l'application. J'ai également mis à jour les captures d'écrans et les textes explicatifs. Du côté de l'application iOS, j'ai avancé l'amélioration de la page d'accueil (oeuvre du jour). J'ai modifié le comportement du bouton « Photographier » pour qu'il ouvre la caméra directement. J'ai modifié également la couleur du bouton « Cibler » pour qu'il soit en harmonie avec le reste des couleurs de l'application. Pour ce qui est du bouton « Afficher sur la carte », nous voulions qu'il affiche un aperçu de la localisation de l'oeuvre du jour au lieu d'une image générique. Cependant, je constate qu'il a peu d'options de personnalisation. En outre, il n'est pas possible de modifier les couleurs de la carte. Je demanderai l'avis de Lena avant de l'implémenter. Enfin, j'ai reçu de la part de Zuzanna les « mockups » de l'interface souhaitée pour les badges. Puisque la page « Collection » est la porte d'entrée et qu'il y avait des modifications majeures à faire, j'ai commencé par cela. Un aperçu de la nouvelle page est disponible ici. Le bouton « Badges » sera désactivé lors du déploiement de la version de mi-novembre. Je n'ai pas eu le temps de faire davantage pour les badges puisque j'ai des examens et travaux de mi-session à venir.

Objectifs pour la semaine prochaine
  • Terminer le bouton « Afficher sur la carte » sur la page d'accueil (oeuvre du jour)
  • Poursuivre l'implémentation des badges
Semaine 9 - 27 octobre au 2 novembre

Rencontre virtuelle en début de semaine. Nous avons surtout présenté l'état de nos avancements. Lena nous encourage à donner un coup au projet puisque la session avance rapidement. Nous avons discuté longuement des difficultés de l'ajout des données du patrimoine à la base de données sur le serveur. En effet, les données sont souvent présentées comme polygones, mais leur format varie selon les différentes sources. J'ai mentionné qu'il serait préférable de standardiser le tout avant l'ajout dans le serveur et d'éviter de devoir gérer différents formats dans les applications mobiles. Nous constatons cependant que la conversion d'un format à un autre n'est pas triviale et qu'il faudra s'informer davantage à ce sujet. Pour ma part, j'ai discuté avec Lena à propos des limitations des aperçus de la carte pour le bouton de la page d'accueil. Elle est d'accord que je procède malgré tout. Elle me mentionne d'ailleurs qu'il faudra revoir la présentation de l'oeuvre du jour car les utilisateurs ne comprennent pas tous quoi en faire. Nous y avons réfléchi quelques peu, mais nous n'avons rien conclu pour le moment. Plus tard dans la semaine, j'ai fait l'implémentation du bouton avec l'aperçu de la carte sur la page d'accueil. Puisque cela nécessitait davantage de code, j'ai séparé le bouton dans sa propre « View » (DailyArtworkMapPreviewView) et son comportement dans une « ViewModel » (DailyArtworkMapPreviewViewModel). Je me suis heurté à quelques limitations reliées au framework. Premièrement, l'aperçu ne permet pas d'ajouter de « pin » ni d'autres annotations à la carte. J'ai contourné le problème en empilant les éléments désirés du bouton les uns par-dessus les autres et en mettant l'image de la carte en arrière-plan. Deuxièmement, l'aperçu ne se met pas à jour lors du changement vers le mode nuit. Pour le forcer, j'ai dû faire créer deux aperçus simultanément : un pour le mode jour et un pour le mode nuit. L'application se charge ensuite de sélectionner le bon aperçu selon le mode du téléphone. Le tout a été fusionné dans GitHub. J'ai été un peu ralenti cette semaine dû à une mise-à-jour automatique de XCode qui ne fonctionnait pas bien sur mon ordinateur. J'ai dû retourner à la version antérieure. Je n'ai pas eu le temps de travailler davantage sur les badges cette semaine. Vers la fin de la semaine, j'ai préparé mon rapport mi-session qui sera présenté à M. Lapalme mercredi prochain.

Objectifs pour la semaine prochaine
  • Amélioration aux oeuvres collectionées : disposition des éléments et permettre zoom sur la photo
  • Modification de l'affichage de la collection vide
  • Poursuivre l'implémentation des badges
Semaine 10 - 3 au 9 novembre

Rencontre spéciale cette semaine avec M. Lapalme où nous avons présenté l'état d'avancement de nos projets. M. Lapalme était satisfait du travail accompli jusqu'à présent, mais il a émit des réserves par rapport à mes objectifs pour la seconde moitié. Personnellement, je suis confiant en mes capacités de mener les tâches restantes jusqu'au bout. Puisque je ne connaissais rien aux technologies utilisées en début de session, je crois qu'il est normal que l'avancement a été plus lent les premières semaines. J'ai constaté néanmoins que ma vitesse s'est nettement améliorée et j'estime qu'il est toujours réaliste de conserver les mêmes objectifs. En fin de rencontre, j'en ai profité pour clarifier certaines éléments UI avec Lena. En particulier, j'ai constaté que les fonctionnalités de « zoom and pan » des photos ne sont pas offertes nativement par SwiftUI et qu'il faudrait recourir à une librairie externe afin de permettre à l'utilisateur de zoomer une photo de sa collection. Lena préférait qu'on laisse tomber cela pour le moment. Au niveau programmation, j'ai modifié l'interface de la page collection lorsque l'utilisateur n'a aucune oeuvre collectionnée. Le résultat peut être visualisé ici. J'ai également modifié la page qui affiche les informations au sujet d'une oeuvre collectionnée. Il fallait avant tout changer l'ordre d'affichage des éléments ainsi que les dimensions des photos. Puisqu'on voulait avoir le score (les étoiles) à côté du titre de l'oeuvre, j'ai dû l'intégrer au view des informations générales (CollectedArtInfoView) alors que cela allait plutôt avec le view de l'appréciation de l'utilisateur (RatingView). Idéalement, il aurait fallu le mettre dans son propre view mais c'était trop compliqué car la synchronisation de son positionnement avec celui du titre de l'oeuvre aurait alors été problématique. Enfin, j'ai créé une fonction qui permet de formatter les dates inconnues. Le résultat final est disponible ici. Tout est maintenant prêt de mon côté pour la première « milestone ». Je n'ai pas travaillé sur les badges cette semaine (c'est la prochaine « milestone »).

Objectifs pour la semaine prochaine
  • Poursuivre l'implémentation des badges selon le plan
Semaine 11 - 10 au 16 novembre

Rencontre cette semaine en équipe iOS. Jean-Marc et moi avons présenté notre travail en vue de la « release » de novembre. Pour ma part, il y avait seulement quelques ajustements UI mineurs. Jean-Marc, quant à lui, a dû faire clarifier le fonctionnement des filtres, ce qui retardera un peu la « release ». Enfin, nous avons discuté des difficultés rencontrées avec les données de type « patrimoine » sur lesquelles Jean-Marc a travaillé dernièrement. Côté programmation, j'ai procédé immédiatement aux modifications de dernière minute en vue de la « release ». J'ai corrigé certaines traductions et j'ai augmenté la hauteur des photos des oeuvres pour éviter qu'elles ne soient trop rognées lorsqu'elles sont en format portrait. Enfin, avec l'aide de Jean-Marc, j'ai harmonisé les couleurs du mode « nuit ». Nous avons eu de la difficulté avec la couleur de fond des listes car SwiftUI ne permet pas de la modifier. En effet, le fond reste noir, peu importe les options qu'on lui ajoute. La solution trouvée a été de modifier la couleur de fond par défaut de l'application en général. Au niveau des badges, j'ai fait beaucoup de progrès. J'ai ajouté le fichier JSON, créé le BadgeModel qui réplique le JSON ainsi que le BadgeDataService qui fait le « parsing » du JSON. La création du modèle a été compliquée par le fait que le JSON obtenu du serveur n'est pas valide. En effet, les conditions d'obtention des badges (required_args et optional_args) ne sont pas des objets mais de simple strings et ils n'utilisent pas des doubles guillements tel qu'attendu. De plus, chaque propriété est dédoublée inutilement pour les deux langues. J'ai dû créé mon propre décodeur afin d'obtenir un modèle simplifié de cette structure complexe et de faire le double « parsing » pour les conditions d'obtention en remplaçant les caractères non valides. Je crois que le serveur devrait être corrigé pour retourner un JSON valide, mais cela affectera également l'application Android qui fait probablement les mêmes opérations... De plus, j'ai ajouté dans le modèle un champ badgeType qui attribue, à partir des conditions d'obtention, un type particulier au badge (issu d'un enum). Ce type sera utilisé pour aider aux fonctions d'attribution de badge. Ensuite, j'ai créé l'entité Badge pour la base de données CoreData. J'ai modifié le MainDataPublisher pour qu'il s'occupe de peupler la table à l'ouverture de l'application à partir du JSON grâce à la fonction updateBadgeTable. Enfin, j'ai débuté l'interface utilisateur. J'ai créé le BadgeView qui permet d'afficher les détails d'un badge, le BadgeViewModel qui retrouve tous les badges de la table de CoreData et les classe en fonction de leur type. ainsi que le CollectionBadgeView qui affiche les différents types de badges dans un ScrollView spécifique. Il reste encore quelques ajustements cosmétiques à faire, mais l'essentiel est là.

Objectifs pour la semaine prochaine
  • Finir l'interface des badges
  • Ajouter les fonctions qui attribuent les badges
Semaine 12 - 17 au 23 novembre

Pas de rencontre cette semaine. Au niveau programmation, j'ai créé les fonctions d'attribution de badge. Pour simplifier l'implémentation et éviter la répétition de code, j'ai créé dans BadgeModel une fonction applyFor qui prend comme paramètre un modèle d'oeuvre d'art et retourne un booléen pour indiquer si cette oeuvre d'art s'applique pour ce badge. Puisque j'avais déjà créé un champ type pour classifier les différents badge, la décision d'appliquer ou non l'oeuvre au badge est assez triviale. Malheureusement, puisqu'il y a des différences dans l'orthographe des noms de quartier entre le fichier JSON et le fichier des oeuvres, j'ai dû (encore) faire du traitement supplémentaire. J'ai tout regroupé cela dans la fonction init du modèle de badge pour que ce soit facile à corriger lorsque les modifications au niveau du serveur seront faites. Ensuite, au niveau du MainDataPublisher, j'ai créé la fonction addArtworksToUserBadge qui permet essentiellement de décrémenter la valeur du champ artworkLeft d'un badge dans la base de données. J'ai aussi créé la fonction findNumberOfArtworksForBadge qui recherche parmis les oeuvres déjà collectionnées celles qui peuvent s'appliquer à un badge précis. Celle-ci sera appellée lors de l'ajout d'un nouveau badge provenant du fichier JSON afin de tenir compte de la collection pré-existante de l'utilisateur. Enfin, j'ai renommé la fonction updateBadgeTable en checkForNewBadges. Elle s'occupera maintenant, en plus de mettre à jour la table de badges, de conserver une liste des badges qui ont été obtenus suite à la lecture du fichier JSON. Ceci pourra être communiqué à l'utilisateur par un « pop-up ». Finalement, pour ce qui est de l'attribution suite à l'ajout d'une oeuvre dans sa collection, j'ai ajouté la fonction checkForBadges dans CollectedViewModel qui est appellée dans CollectedArtworkView immédiatement après l'envoie des données vers le serveur. Cette fonction itère sur l'ensemble des badges existants et pour chacun des badges non obtenus, elle vérifie si la nouvelle oeuvre s'applique pour ce badge. Si oui, elle appelle la fonction addArtworksToUserBadge pour mettre à jour la table de badges. Si le champ artworksLeft devient égal à 0, le badge est ajouté à une liste qui sera retournée par la fonction afin de communiquer l'information à l'utilisateur via un « pop-up ». L'essentiel du code a été écrit et il ne reste qu'à finaliser l'interface utilisateur. J'ai cependant quelques points à clarifier avec Lena, surtout concernant le « pop-up » et les icônes.

Objectifs pour la semaine prochaine
  • Finir l'interface des badges
  • Tester l'application
Semaine 13 - 24 au 30 novembre

Rencontre en personne à l'université. J'ai fait part de mes préoccupations vis-à-vis la qualité des icônes des badges dans le dossier réseau ainsi que vis-à-vis le format erroné du JSON retourné par l'API des badges. Lena demandera à Zuzanna de corriger les images et Thomas a noté les problèmes du côté du serveur pour correction ultérieure. J'ai pu clarifier aussi ce qui était attendu par rapport au « pop-up » de notification d'obtention de badge. Plus tard dans la semaine, j'ai finalisé l'interface de la collection de badges (disponible ici) ainsi que de la page de détail d'un badge (disponible ici). En plus de retravailler le positionnement des éléments, j'ai créé une barre de progrès personnalisée et j'ai ajouté une fonction de tri pour afficher les badges de quartier en ordre alphabétique. Enfin, j'ai ajouté un bouton dans l'onglet « Autre » qui dirige l'utilisateur vers la page des réglages de l'application Mona au sein du menu de réglages d'iOS. Ceci lui permettra de changer facilement la langue et les autorisations.

Objectifs pour la semaine prochaine
  • Terminer l'interface du « pop-up »
  • Tester l'application
Semaine 14 - 1er au 7 décembre

Pas de rencontre cette semaine. Côté développpement, j'ai créé le « pop-up » de nouveaux badges. Puisqu'il arrive parfois qu'on obtienne plus d'un badge au même moment, je voulais que l'utilisateur puisse tous les voir sur la même notification. Initialement, j'avais implémenté un « PageView » tel que disponible dans UIKit (l'ancien framework d'Apple). Cependant, celui-ci ne s'intégrait pas bien dans le « pop-up ». En effet, pour une raison que je n'explique pas, les interactions avec le « PageView » faisaient apparaître systématiquement la barre de navigation par-dessus le « pop-up », ce qui n'était joli et en cachait une partie. Je me suis rendu compte, par après, que je pouvais obtenir le même effet avec un « TabView » disponible dans SwiftUI directement et ceci a réglé le problème de la barre de navigation. Pour implémenter le « pop-up » en soi, j'ai opté pour l'approche du « ViewModifier ». Ceci permet d'injecter facilement le « pop-up » à n'importe quel niveau dans l'application. Le « ViewModifier » écoute les changements dans le MainDataPublisher et s'affiche par-dessus la vue en cours lorsque le tableau newlyObtainedBadges n'est pas vide. Une nouvelle fonction, setNewlyObtainedBadges, permet de mettre à jour ce tableau. Elle est appellée par les fonctions d'attribution de badges implémentées précédemment. Le « pop-up », quant à lui, appelle également cette fonction pour vider le tableau, ce qui mène à sa disparition de l'écran. Le résultat final est disponible ici. Il ne reste maintenant qu'à tester la fonctionnalité sur de vrais appareils avant de la déployer !

Objectifs pour la semaine prochaine
  • Tester l'application
Semaine 15 - 8 au 14 décembre

Pas de rencontre cette semaine non plus. J'ai testé l'application sur deux appareils physique et aucun problème n'a été détectée avec les nouvelles fonctionnalités. L'application est donc prête pour la soumission à l'App Store. J'ai préparé mon rapport final qui est disponible dans la section du même nom. Le projet sera présenté lundi prochain à Lena, M. Lapalme et M. Famelis. Le support visuel est disponible ici.

Rapport final

Le projet
L'application Mona

La Maison Mona est un organisme sans but lucratif dont la mission consiste à « inviter à des rencontres avec l'art, créer un espace commun pour les échanges, et faire résonner les sens et les sensibilités de chacun·e ». Son projet principal est la création « d'une application mobile gratuite qui promeut la découverte de l'art et des espaces culturels montréalais ». L'application donne accès à une base de données d'oeuvres d'art publiques que l'utilisateur peut consulter au travers d'une liste, d'une carte ou d'une suggestion quotidienne. Elle encourage l'utilisateur à se déplacer pour admirer les oeuvres et à les « collectionner », c'est-à-dire, les prendre en photo en y ajoutant une évaluation personnelle. Ces évaluations fourniront éventuellement à des chercheurs des données leur permettant de comprendre comment la population perçoit et apprécie l'art public.

Mes motivations

J'ai décidé de m'impliquer au sein de ce projet cette session tout d'abord parce que sa mission m'interpelle. J'aime découvrir l'art sous ses nombreuses formes et j'apprécie l'approche qui est tentée par l'application Mona. Une quantité importante d'oeuvres d'art publiques se trouve tout près de nous, mais je trouve qu'elles ne sont pas bien mises en valeur. La Maison Mona participe à la promotion de ces oeuvres, et je suis content d'avoir pu y contribuer.

Mon mandat

Mon mandat dans le cadre du cours « Projet d'informatique (IFT 3150) » portait sur des améliorations à apporter sur l'application iOS. La charge de travail a été partagée avec Jean-Marc Prud'homme, l'étudiant qui a fait avancer l'application durant la session d'été 2021. Ce rapport portera principalement sur les modifications que j'ai effectué, c'est-à-dire :

Description de la solution
Implémentation actuelle

L'application est écrite avec le langage de programmation Swift et utilise le framework SwiftUI. Elle suit le patron de conception MVVM (Model-View-ViewModel). Selon ce patron, le Model est une représentation des données, le View est l'interface visible de l'utilisateur, et le ViewModel contient l'état des données et les opérations associées. Le View est lié directement au ViewModel (il est « observable » dans la terminologie de SwiftUI). Dans la mouture actuelle, les données sont sauvegardées de différentes façons. La base de données d'oeuvres d'art, provenant du serveur de Mona, est distribuée directement dans l'application sous format JSON qui est décodé à l'ouverture. Les données de configuration de l'utilisateur sont sauvegardées dans les UserDefaults (un dictionnaire). Les données sur les oeuvres collectionnées sont enregistrées dans CoreData (la base de données distribuée avec iOS). Toutes les données brutes sont accessibles par les composants de l'application au travers du MainDataPublisher.

Fonctionnalité de badges

Cette fonctionnalité, présente dans l'application Android, permet de récompenser l'utilisateur après avoir collectionné un certain nombre d'oeuvres présentant des caractéristiques communes. Cela encourage la découverte d'oeuvres diverses au travers de la ville. La solution suit le patron de conception MVVM. Les différentes classes et structures concernées sont organisées comme suit :
Diagramme de classes de la fonctionnalité de badges
La liste des badges potentiels a été standardisée et est conservée dans le serveur de Mona. J'ai décidé moi aussi de les distribuer directement dans l'application sous format JSON afin de garder la provenance des données uniforme. Chaque badge dispose également d'une entrée dans CoreData afin de pouvoir suivre facilement la progression de chacun d'entre eux. Les badges du JSON sont associés à un Model nommé BadgeModel, tandis que les entrées de CoreData sont représentées par une entité nommée Badge. Un identificateur unique (id) fait le lien entre ces deux structures. Le décodage des badges à partir du JSON est assuré par une classe nommée BadgeDataService. L'association entre les champs du JSON et ceux du BadgeModel est localisée dans le Model.

Le BadgeDataService est instancié à l'ouverture de l'application par le MainDataPublisher. Le JSON est alors décodé, les Models sont créés et conservés dans un dictionnaire ayant comme clé l'id. L'usage d'un dictionnaire facilite la récupération des données du Model lorsqu'on ne connaît que l'id. L'application charge ensuite les entités de CoreData qui sont conservés dans un tableau. Dans le cas où le nombre d'entités est inférieur au nombre de Models, ce qui arrive la première fois que cette version d'application est lancée ou s'il y a ajout de nouveaux badges dans le JSON, le MainDataPublisher créera les entités nécessaires en vérifiant s'il y a déjà des oeuvres donnant droit au badge. Cette partie est importante afin d'éviter qu'il y ai discordance entre l'état de la collection actuelle et l'état des nouveaux badges.

L'attribution des badges peut aussi avoir lieu après l'ajout d'une oeuvre dans sa collection. Ces opérations sont déclenchées par la View des oeuvres d'art (CollectedArtworkView) et sont localisées dans son ViewModel (CollectedViewModel). La logique permettant de vérifier si une oeuvre d'art donne droit au badge se retrouve plutôt dans le Model du badge. Ceci permet de faire la vérification à différents niveaux de l'interface.

Lorsque des badges sont attribués, le MainDataPublisher garde une référence des entités concernées dans un tableau séparé. Ce tableau est « observé » par le BadgeNotificationViewModifier. Il s'agit d'un ViewModifier, un View particulier de SwiftUI qui peut se « greffer » à une autre vue. Le ViewModifier réagit lorsque le tableau n'est pas vide et recouvre l'écran d'une notification avisant l'obtention de nouveaux badges. Il affiche un aperçu des badges obtenus en créant un View nommé BadgePreviewView pour chacun d'entre eux. La notification est cachée en vidant le tableau. Le ViewModifier est « greffé » au View pricipal (MainView) pour aviser lors des mises-à-jour et au View des oeuvres d'art (CollectedArtworkView) pour aviser lors d'un ajout à sa collection.

L'affichage de la collection de badges se retrouve dans la View CollectionBadgeView. Elle est liée au ViewModel BadgeViewModel qui récupère les données brutes du MainDataPublisher et trie les badges en fonctions de certaines caractéristiques. Pour chacune des entités de badge de CoreData, la View crée une icône donnant un aperçu du badge en question. Ces icônes sont regroupées dans un LazyHGrid et placé dans un ScrollView pour permettre le défilement. Chacune initialise une View naviguable nommée BadgeView qui permet d'affichera davantage de détails sur le badge.

Page d'accueil

La page d'accueil a subit quelques modifications discrètes. Tout d'abord, l'algorithme de sélection de l'oeuvre du jour dans CollectedViewModel a été revu. La sélection est toujours aléatoire, mais elle n'incluera plus les oeuvres déjà collectionnées qui les oeuvres ciblées par l'utilisateur. L'oeuvre choisie est sauvegardée dans les UserDefaults, et n'est mise-à-jour qu'une seule fois par jour. Ensuite, le bouton « appareil photo » ouvre maintenant directement la caméra plutôt que d'ouvrir la page de l'oeuvre. Le changement touche le CollectedArtworkView, car il doit détecter que l'utilisateur provient de la page d'accueil et changer son comportement en conséquence. Enfin, la plus grande modification est le bouton de la carte, qui au lieu d'afficher une icône générique, affiche maintenant un aperçu de la localisation de l'oeuvre. La solution développée est emploi également le patron MVVM de façon plus légère. Les différentes classes et structures concernées sont organisées comme suit :
Diagramme de classes de l'aperçu de carte
La View DailyArtworkMapPreviewView bâti le bouton et sélectionne le mode de la carte (jour ou nuit). Son ViewModel DailyArtworkMapPreviewViewModel est responsable de créer l'aperçu. Il récupère l'oeuvre du jour à partir du CollectedViewModel et génère un aperçu distinct pour les deux modes. J'ai utilisé la classe MKMapSnapshotter de MapKit qui permet de charger seulement une portion de carte. Le bouton est finalement intégré au DailyArtworkView.

Page collection et oeuvres collectionnées

La page collection (CollectionView) a été complètement revampée. Elle dispose maintenant d'une en-tête (CollectionHeaderView) qui affiche le nombre d'oeuvres collectionnées, et offre le choix d'afficher sa collection d'oeuvres ou de badges via deux boutons. La collection d'oeuvres (CollectionScrollView) n'a pas été modifiée, mais son interface lorsqu'elle est vide (EmptyCollection) a été améliorée. La collection de badges (CollectionBadgeView) est évidemment nouvelle et a été décrite précédemment. L'affichage d'une oeuvre collectionnée (CollectedArtworkView) a été repensé afin de mettre en valeur la photo de l'utilisateur et son évaluation numérique (les étoiles). La position des informations factuelles de l'oeuvre a été échangée avec les commentaires de l'utilisateur.

Réglages

Initialement, nous voulions permettre à l'utilisateur de modifier la langue et de changer les permissions à même l'application de Mona. Cependant, nous avons réalisé que ce n'était pas l'approche privilégiée par Apple selon ses lignes directrices. Afin d'éviter un refus lors de la soumission vers l'App Store, la solution retenue a été de simplement ajouter un lien vers les réglages système d'iOS où tous ces changements peuvent déjà être faits. Ce lien se retrouve dans la section « Autre » (OthersMainView).

Mode nuit

L'application offrait déjà un mode nuit, mais il y avait plusieurs incongruités et un manque de standardisation dans les couleurs. Jean-Marc et moi avons effectué ensemble les corrections afin d'offrir une expérience plus uniforme et agréable. J'ai porté attention à ce détail lors de tous mes changements à l'interface.

Résultats finaux

Le mandat a été séparé en deux « releases ». La première a été déployée sur l'App Store en novembre. La seconde le sera sous peu. Voici un aperçu des éléments de l'interface sur lesquels j'ai travaillé dans les deux modes supportés par l'application.

Difficultés rencontrées

Je suis arrivé en septembre dans l'équipe avec une idée approximative du travail qui était attendu. Il aura fallu quelques semaines avant de bien clarifier mon mandat. J'ai réussi à réaliser l'ensemble des tâches souhaitées, mais le parcours n'aura certainement pas été sans heurts ! Il y a eu tout d'abord toutes les nouveautés à apprendre. Je n'avais jamais programmé avec Swift et SwiftUI ni même utilisé XCode. Je connaissais à peine la plateforme iOS ! J'ai dû faire beaucoup de formations au mois de septembre afin d'atteindre un niveau minimal d'aisance. J'ai énormément progressé à ce titre durant la session. Ma vitesse de programmation après la relâche n'avait vraiment plus rien à voir avec ce qu'elle était au début.

Malgré cela, j'ai fait quelques erreurs de parcours parce que je me suis lancé dans le codage sans bien connaître mes outils. Par exemple, lors du changement de l'algorithme de sélection de l'oeuvre du jour, j'ai décidé de conserver l'oeuvre choisie dans CoreData qui est le système de base de données intégré à iOS. J'insérais une entrée unique dans une table dédiée, ce qui nécessistait beaucoup de mise en place. Par après, Jean-Marc m'a appris l'existence des UserDefaults qui permettent de péréniser facilement certains paramètres sans devoir passer par une base de données. J'ai fait les corrections et le code s'en ai retrouvé simplifié. De façon similaire, j'ai créé un carrousel pour afficher plusieurs badges dans une notification en utilisant un PageView, un composant de UIKit qui est l'ancien framework UI d'Apple. L'intégration entre les deux frameworks a non seulement été complexe, mais le rendu laissait vraiment à désirer. J'ai réalisé par moi-même un peu plus tard qu'un composant similaire, le TabView, était disponible dans SwiftUI. Celui-ci pouvait être utilisé tel quel et s'affichait à merveille. Enfin, j'ai passé pas mal de temps à implémenter le changement de langue à l'intérieur de l'application pour me rendre compte vers la fin que cela allait à l'encontre de lignes directrices d'Apple. C'était donc du temps mal investi.

Même en s'informant adéquatement, on se retrouve parfois face à des situations hors de notre contrôle. Les gros frameworks utilisés présentent parfois des limites ou des incompatibilités qui n'étaient pas prévus. Par exemple, dans la création de l'aperçu de la carte sur la page d'accueil, la classe MKMapSnapshotter ne permettait d'y ajouter une épingle et ne réagissait pas aux passages du mode jour vers le mode nuit. La première limitation a été réglée en « empilant » l'épingle par-dessus l'aperçu et la seconde, en forçant la création d'un aperçu dans les deux modes et en détectant programmatiquement le mode à utiliser. Parfois, les solutions n'étaient pas trouvées de façon aussi méthodiques. Par exemple, lors de la standardisation des couleurs du mode nuit, nous avons parfois dû y aller à tâtons car les résultats étaient parfois imprévisibles. En particulier, nous avons eu de la difficulté à changer la couleur de fond des listes défilantes sans affecter les couleurs de fond des autres composants. Il s'agissait d'une limitation avec SwiftUI et il fallait chercher les bonnes combinaisons pour obtenir le résultat souhaité.

Enfin, la dernière difficulté a été de réussir à s'approprier la base de code. J'ai pu heureusement compter sur les bons conseils de Jean-Marc pour m'aider lorsque j'étais en difficulté. Néanmoins, il fallait parfois composer avec certains choix passés qui rendaient les modifications plus difficiles. Par exemple, la modification du comportement du bouton « Appareil photo » sur la page d'accueil a été compliquée par le fait que l'ouverture de la caméra est liée à une action de l'utilisateur sur la page d'affichage des oeuvres. Ce choix faisait du sens dans le contexte précédent, mais j'ai dû réfléchir longuement sur l'approche à prendre afin de m'éviter de devoir changer toute la structure associée. Aussi, j'ai eu beaucoup de difficulté à récupérer les informations de l'API des badges. Le format de réponse n'était pas en JSON valide car il utilisait des guillemets non standard. De plus, certains objets à l'intérieur même du JSON était en format String ce qui nécessitait un double décodage. Également, le nom des quartiers n'était pas le même dans cet API que dans celui des oeuvres... J'ai dû faire beaucoup de pré-traitement dans le BadgeModel. Ces problèmes ont été rapportés à Thomas, l'étudiant qui s'occupait du serveur cette session, et seront éventuellement corrigés.

Notions retenues

La participation au projet Mona m'a beaucoup apporté au niveau personnel. Tout d'abord, cela m'a permis de me familiariser avec plusieurs technologies et outils avec lesquels je n'avais jamais travaillé. J'ai appris une nouvelle langue de programmation (Swift), un framework de développement (SwiftUI), un gestionnaire de paquets (CocoaPods), un IDE (Xcode), un système d'exploitation (iOS) et une plateforme de distribution (App Store). Également, j'ai gagné de l'expérience en terme de programmation. En particulier, j'ai pu pratiquer une nouvelle architecture (MVVM), des patrons de conceptions (singleton, observer), la gestion de l'état, les bases de données (CoreDate) et autres structures (JSON). Le langage Swift m'a aussi permis de pratiquer la programmation fonctionnelle (fonction de haut ordre, valeurs optionnelles) et l'usage d'énumérations. Cette expérience aura certainement de l'influence sur mon style de programmation dans le futur, même avec des technologies différentes. De plus, j'ai pu me pratiquer à développer un logiciel complexe en effectuant toutes les étapes du processus : récolter les spécifications, analyser l'état actuel et les besoins, effectuer le design, coder, tester et déployer, et ce en plusieurs itérations. Avec mes erreurs de parcours, je réalise l'importance de bien s'informer et de bien planifier avant de se lancer dans le codage. Je réalise aussi que même si on a bien planifié, il restera toujours des imprévus. La programmation doit être un processus itératif où on doit être vigilant, rester ouvert au changement, être créatif et penser hors de la boîte afin de résoudre les défis. J'en ressors grandi et confiant en mes capacités à programmer quelque chose de plus large et je suis fier du travail accompli cette session.

Vision future

L'application iOS a atteint un bon niveau de maturité. Elle permet de bien remplir son rôle tant pour les utilisateurs que pour les futurs chercheurs. Néanmoins, certaines éléments pourraient être améliorés encore. Je donne ici quelques idées en ordre de priorité (selon moi).

  1. Modification à la collection. L'utilisateur devrait être en mesure de modifier la photo qu'il a prise, ses commentaires et son évaluation. Il devrait aussi pouvoir supprimer une oeuvre. Il s'agit d'une amélioration importante pour améliorer l'expérience de l'utilisateur. Ceci nécessitera des modifications du côté serveur, mais ne devrait pas être trop complexe, et pourrait être fait à court terme.
  2. Affichage d'informations complémentaires. Nous avons discuté de la possibilité d'ajouter des hyperliens sur les oeuvres collectionnées afin de diriger l'utilisateur vers des informations complémentaires. Je trouve l'idée très intéressante, car en l'absence d'un guide, on se retrouve parfois à admirer l'art public sans trop savoir ce qu'on regarde. Après avoir peupler le serveur d'hyperliens, l'ajout dans les applications sera assez facile. Ceci pourrait être fait à court terme.
  3. Fonctions de recherche plus poussées. Il serait intéressant d'offrir des options pour que l'utilisateur puisse rechercher des oeuvres en utilisant des critères plus précis. Certains critères sont déjà présents dans la base de données (catégorie, sous-catégorie...) et d'autres seront ajoutés éventuellement grâce à la fonction de « tags ». Il faudra réfléchir sur la manière qu'on veut présenter les options de recherche ainsi que les résultats afin que ce soit utile et joli. C'est une amélioration à plus moyen terme car il faut peupler la base de donnée, modifier le serveur puis créer une interface mobile et des fonctions de recherche performantes.
  4. Récupération des données à partir des serveurs de Mona. Présentement, les données sur les oeuvres et les badges sont distribuées avec l'application et ne proviennent pas des serveurs de Mona en temps réel. Plusieurs raisons expliquent ce choix (lenteur du serveur, difficulté de récupérer un sous-ensemble de données, champs de la réponse qui changent, identificateurs uniques qui changent également). Néanmoins, je crois qu'il serait préférable à moyen terme que l'application puisse puiser ses données à même le serveur afin que les utilisateurs aient toujours la version la plus à jour de la base de données même si l'application n'est pas à jour. Il faudra tout d'abord s'assurer que les problèmes du serveur ont été réglés. Ensuite, il faudra bien réfléchir à la façon qu'on veut conserver les données (JSON vs base de donnée locale). L'algorithme de synchronisation devra être solide, et tenir compte des changements au niveau de la structure de la réponse. Il faudra aussi s'interroger sur la manière de conserver un mode hors connexion en cas de lenteur ou de non disponibilité du serveur.
  5. Notifier les administrateur des bogues ou erreurs dans la base de données. Il pourrait y avoir dans la section « Autre » un formulaire à remplir si l'utilisateur éprouve des difficultés avec l'application ou la base de données. Le formulaire pourrait envoyer un courriel ou, mieux encore (si possible), un issue dans GitHub. Les données sur l'appareil (type, version de l'application et d'iOS) pourraient être récoltées automatiquement. Ceci aiderait à recevoir des rapports d'erreur plus complets et mieux structurés. Cette amélioration ne devrait pas être trop compliquée et pourrait être faite à court terme.
J'en profite pour faire mention du projet des données de type « Patrimoine » qui est présentement en cours et qui est prioritaire vu le financement obtenu pour sa réalisation. Enfin, nous avions soulevé d'autres idées durant la session que je trouve moins intéressantes personnellement. Le partage sur les réseaux sociaux semble trop contraignant et l'utilisateur peut le faire par lui-même de toute façon. Le mode hors ligne qui bloque complètement le téléchargement et le téléversement me semble futile car l'application utilise peu de données et l'utilisateur peut arrêter la transmission par lui-même (avec le mode avion, par exemple). Les repères (« pin » déposées par l'utilisateur sur la carte pour simuler sa position), présents dans la version Android, risquent d'être mal compris et l'utilisateur peut déjà se déplacer par lui-même sur la carte sans cela.

Ressources

Autres