Vers un workflow pour des applications shiny prod-ready — 2/2

Deuxième partie de la transcription de la conférence que j’ai donnée lors de la session poster de la rstudio::conf(2019).

Lire la première partie ici.

Construire des applications Shiny prod-ready, étape par étape

Etape 1: Design

Ne vous précipitez pas dans le code. C’est tentant, parce que c’est ce que nous aimons faire et ce à quoi nous sommes bons. Mais avant d’entrer dans un « coding marathon », prenez le temps de réfléchir à l’application et à la façon dont elle sera déployée et utilisée. Prenez un stylo et un morceau de papier et dessinez l’application. Parlez-en avec les gens qui utiliseront le produit final, juste pour déchiffrer ce dont ils ont réellement besoin. Prenez un moment pour parler avec le service informatique.

Voici quelques exemples de questions que vous pouvez poser :

  • « Qui sont les utilisateurs finaux de l’application ? » — Ceci vous aidera à savoir si les utilisateurs ont des connaissances techniques ou non, et ce qu’ils visent à réaliser avec l’application.
  • « Est-ce qu’ils utiliseront l’app souvent? » — Les détails du design et de l’interface utilisateur de l’application que vous utilisez chaque jour sont plus importants que lorsque l’application est utilisée une fois par mois.
  • « De quel niveau de complexité et de personnalisation les utilisateurs ont-ils vraiment besoin ? » – Les rédacteurs de cahier des charges veulent parfois plus de fonctionnalités que ce dont les utilisateurs ont réellement besoin.
  • « Quel niveau d’interactivité voulez-vous et dans quelle mesure est-il central ? » – Les gens adorent les graphiques interactifs et aiment quand les choses se synchronisent automatiquement les unes avec les autres. Pourtant, cela peut rendre l’application plus lente, sans gain significatif. Par exemple, être réactif à une selectInput() ou une sliderInput() peut conduire à trop de calculs : peut-être que l’utilisateur ne réussira pas à choisir la bonne entrée la première, deuxième ou troisième fois… Alors laissez-le faire son choix, et ajouter un bouton.
  • « Quelle est l’importance de la rapidité de l’application ? » – Devriez-vous passer beaucoup de temps à optimiser les petites choses ?
  • etc.

Poser des questions, prendre des notes et dessiner l’application vous aidera à avoir une bonne idée de ce qui est attendu et de ce que vous devez faire maintenant.

Étape 2: Prototype

J’aime partir sur le principe de « UI first ». Pour deux raisons principales :

Une fois l’interface utilisateur définie, il n’y a pas d' »implémentation surprise ». Une fois que nous sommes d’accord sur les éléments qu’il y a dans l’application, il n’y a pas de soudain « oh l’application doit faire ça et ça maintenant ».

Une interface utilisateur prédéfinie permet à chaque personne impliquée dans le développement de savoir sur quelle partie de l’application elle travaille. En d’autres termes, lorsque vous commencez à travailler sur le backend, il est beaucoup plus facile de travailler sur une pièce que vous pouvez identifier et intégrer visuellement dans un scénario d’application.

Alors oui, passez du temps à écrire un prototype en lorem ipsum. Et bonne nouvelle, nous avons un outil pour vous : il s’appelle {shinipsum}. Le but principal de ce paquet est de créer des éléments aléatoires brillants qui peuvent être utilisés pour dessiner une interface utilisateur, sans avoir à travailler sur le backend.

Ainsi, une fois que vous avez un brouillon de votre application sur une feuille de papier, vous pouvez passer à l’étape « ipsum-UI » : construire le front-end de l’application, et le remplir d’éléments aléatoires Shiny, avec des fonctions comme random_ggplot() ou random_DT().

Un autre paquet qui peut être utilisé pour cela est {fakir}. Ce package est conçu pour créer de fausses de données, principalement à des fins pédagogiques, mais il peut être utilisé pour insérer des données dans un prototype Shiny.

Étape 3: Build

Maintenant que l’interface utilisateur et les fonctionnalités sont définies, il est temps de travailler sur le backend 🎉

Cette partie est assez standard – tout le monde peut maintenant travailler sur l’implémentation des fonctions qui traitent les entrées de l’application, dans leurs propres modules. Comme l’interface utilisateur, les fonctionnalités et les modules ont été définis dans les étapes précédentes, tout le monde (enfin, en théorie) sait sur quoi il faut travailler.

Et aussi, comme nous l’avons déjà dit, il ne devrait pas y avoir d' »implémentation surprise », car l’application a été bien définie auparavant.

Étape 4: Secure

Sécuriser votre application signifie deux choses : tester et verrouiller l’environnement.

Tout d’abord, assurez-vous d’inclure des tests tout au long du processus de dev – tout comme n’importe quel autre code R. Comme l’application est contenue dans un package, vous pouvez utiliser des outils de test standard pour tester la logique métier – comme indiqué dans la première partie, il est important de séparer les fonctions et l’algorithmique en backend de l’interface utilisateur. Cela signifie que ces fonctions de backend peuvent être exécutées en dehors de l’application. Et oui, s’ils peuvent fonctionner en dehors de l’application, ils peuvent être testés de manière standard, en utilisant {testthat}.

Quand il s’agit de tester le front, vous pouvez essayer le paquet {shinytest} de RStudio, si vous avez besoin de vous assurer qu’il n’y a pas de régression visuelle tout au long du développement du projet. {shinyloadtest}, d’autre part, teste le comportement d’une application lorsqu’un, deux, trois, vingt, vingt, cent utilisateurs se connectent à l’application, et vous donne un rapport visuel sur la connexion et le temps de réponse de chaque session.

Un autre outil que j’aime utiliser est Katalon Studio. Ce n’est pas lié à R, et peut être utilisé avec n’importe quel type d’application web. Son fonctionnement est très simple : il ouvre votre navigateur où s’exécute l’application Shiny, et enregistre tout ce qui se passe. Une fois que vous arrêtez l’enregistrement, vous pouvez relancer l’application et elle rejouera tous les événements qu’elle a enregistrés. Et bien sûr, vous pouvez spécifier votre propre scénario, définir vos propres événements, etc. L’outil n’est pas si simple de prime abord, mais une fois que vous avez une bonne compréhension de son fonctionnement, c’est un outil très puissant.

Deuxièmement, sécuriser votre application signifie qu’elle peut être déployée à nouveau à tout moment dans le futur – en d’autres termes, vous devez vous assurer d’avoir une bonne maîtrise de la version R requise et des versions des paquets nécessaires pour exécuter votre application. Cela signifie que vous devez être conscient que la mise à niveau d’un paquet peut casser votre application – donc, fournissez un environnement qui peut empêcher votre application de casser quand un paquet est mis à jour. Pour cela, il y a, bien sûr, Docker, des outils spécifiques à R comme {packrat}, ou le déploiement de dépôts CRAN personnalisés ou de gestionnaires de paquets.

Étape 5: Déploiement

Les outils de déploiement ne font pas l’objet de ce billet de blog donc je n’en parlerai pas en détail (souvenez-vous, nous parlons de construire 😉), mais nos deux outils de choix sont Docker & ShinyProxy, et RStudio Connect.

Introduction à {golem}

Ok, ça fait beaucoup de choses à incorporer. Existe-t-il un outil qui peut nous aider à simplifier ce flux de travail ? Bien sûr que si, et il s’appelle {golem}, et vous pouvez le retrouver là : https://github.com/ThinkR-open/golem/

{golem} est un paquet R qui implémente un cadre de travail prédéfinie pour la création d’applications Shiny prêtes pour la production.

Tout commence par un projet RStudio, qui contient une configuration prédéfinie pour construire votre application. L’idée est qu’avec {golem}, vous n’avez pas besoin de vous concentrer sur la base de votre application, et vous pouvez passer votre temps à réfléchir à ce que vous voulez faire, pas à la façon de le faire. Il s’appuie sur le processus de travail que nous avons développé chez ThinkR et tente de rassembler en un seul endroit les fonctions et les outils que nous avons développés, en interne, pour créer des applications conçues pour la production.

Lorsque vous ouvrez un projet golem, vous commencerez par un fichier d’historique de développement, qui contient une série de fonctions qui vous guideront tout au long du processus de démarrage, de construction et de déploiement de votre application. Le package nouvellement créé contient également un app_ui.R et app_server.R en attente d’être rempli, et une fonction run_app() qui va lancer votre application. Tout nouveau module peut être ajouté avec golem::add_module(), une fonction qui crée un nouveau fichier avec le squelette nécessaire pour un module. Comme je l’ai dit, vous n’avez pas besoin de penser aux choses techniques 😉

Vous pouvez également trouver une série d’outils relatifs à l’interface utilisateur, au serveur et aux produits, des fonctions pour créer des scripts de déploiement et d’autres choses intéressantes. Consultez le fichier README pour plus d’informations.

Les outils

Package avec {golem}

Nous pensons que les applications Shiny Apps doivent être mises dans un package. Pourquoi ? Parce que cela permet de les documenter, de les tester et de les installer dans plusieurs environnements.

Pensez à votre dernière application Shiny qui n’était pas dans un paquet. C’est une app.R, peut-être avec un dossier que vous sourcez et qui contient des fonctions (disons dans un dossier R/). Peut-être que vous avez écrit quelques méta-informations (appelons ça une DESCRIPTION), et quelques tests que vous avez mis dans un dossier test. De plus, comme vous voulez être sûr de bien faire les choses, vous avez mis de la documentation dans vos fonctions. Vous voyez où je veux en venir ? Oui, vous avez écrit un paquet R.

Git

Pas besoin de s’étendre : on ne travaille pas sur un projet de dev sans versionning.

Shiny modules

Les modules Shiny sont des outils cruciaux lorsqu’il s’agit de construire de grosses applications : ils permettent de collaborer, de diviser le travail en plusieurs parties, ils facilitent les tests, et ils permettent de faire la mise en place des nouvelles fonctions plus facilement.

Prototypeavec {shinipsum} et {fakir}

Ces deux outils vous permettent de prototyper une application Shiny et d’aller « UI first ». En savoir plus :

CI and testing

Les tests sont essentiels pour assurer la survie à long terme de votre application. Le paquet {testthat} peut être utilisé pour tester le côté « logique métier » de votre application, tandis que les fonctionnalités de l’application peuvent être testées avec des paquets comme {shinytest}, ou des logiciels comme Katalon.

Deploy

Docker, Shiny Proxy, RStudio Connect… Ne vous contentez pas de mettre votre application sur le serveur et de la laisser vivre sa vie. Utilisez des outils spécialement conçus pour le déploiement et la mise à l’échelle des applications. Mais ce sera le sujet d’un autre billet de blog 

Vous voulez en savoir plus ? Gardez un oeil sur notre bookdown “Building Big Shiny Apps — A Workflow“!