Bonnes pratiques pour les projets statistiques

Formation à la DESE

Romain Avouac, Thomas Faria, Lino Galiana, Tom Seimandi

29 Septembre 2022 et 3 octobre 2022

Introduction

La notion de bonnes pratiques

  • Origine : communauté des développeurs logiciels
  • Constats :
    • le “code est plus souvent lu qu’écrit” (Guido Van Rossum)
    • la maintenance d’un code est très coûteuse
  • Conséquence : ensemble de règles informelles, conventionnellement acceptées comme produisant des logiciels fiables, évolutifs et maintenables

Pourquoi s’intéresser aux bonnes pratiques ?


L’activité du statisticien / datascientist tend à se rapprocher de celle du développeur :

  • projets intenses en code
  • projets collaboratifs et de grande envergure
  • complexification des données et donc des infrastructures
  • déploiement d’applications pour valoriser les analyses

Bonnes pratiques et reproductibilité

Source : Peng R., Reproducible Research in Computational Science, Science (2011)

  • Une reproductibilité parfaite est coûteuse

  • Git est un standard atteignable et efficient

Bonnes pratiques et reproductibilité

  • Les journaux académiques sont de plus en plus exigeants sur la reproductibilité (notamment AEA et @AeaData)

Le contrôle de version : pourquoi faire ?

1️⃣ Archiver son code proprement

pour en finir avec ça :

1️⃣ Archiver son code proprement

ou ça :

1️⃣ Archiver son code proprement

ou encore ça :

prior <- read_csv(prior_path)
prior <- prior %>%
    select(id, proba_inter, proba_build, proba_rfl) %>%
    separate(id, into = c('nidt', 'grid_id'), sep = ":") %>%
    group_by(nidt) %>%
    mutate(
        proba_build = proba_build/sum(proba_build),
        proba_rfl = proba_rfl/sum(proba_rfl),
        ) %>%
    unite(col = "id", nidt, grid_id, sep = ":")

# Test
# prior_test <- prior %>%
#    mutate(
#        proba_inter = round(proba_inter, 4)
#        proba_build = round(proba_build, 4)
#        proba_rfl = round(proba_rfl, 4)
#    )

write_csv(prior_round, "~/prior.csv")

1️⃣ Archiver son code proprement

Pour arriver à ça :

Source : ThinkR

2️⃣ Voyager dans le temps (de votre projet)

3️⃣ Une collaboration simplifiée et efficace

Un modèle distribué

Source : specbee.com

3️⃣ Une collaboration simplifiée et efficace

Qui permet l’expérimentation en toute sécurité

Source : lutece.paris.fr

3️⃣ Une collaboration simplifiée et efficace

Quel que soit l’environnement de travail

3️⃣ Une collaboration simplifiée et efficace

Avec des outils pour faciliter la collaboration

4️⃣ Partager son code à un public large

Une vitrine pour vous

En résumé

  • Construire et naviguer à travers l’historique de son projet
  • La collaboration rendue simple et efficace
  • Améliorer la reproductibilité de ses projets
  • Améliorer la visibilité de ses projets

Le contrôle de version avec Git

⚠️ Git est complexe

L’utilisation de Git nécessite certaines notions préalables:

  • Fonctionnement d’un filesystem
  • Connaissance basique du terminal Linux
  • Potentiellement, un grand nombre de commandes

Source : Ici

⚠️ Git est complexe

Mais

  • L’usage quotidien n’implique que quelques commandes
  • Enormément de ressources disponibles sur internet
  • Des interfaces visuelles (ex: RStudio, Sublime Merge, VS Code) qui facilitent l’apprentissage
  • Un petit investissement individuel pour de gros gains collectifs

Concepts

Git, GitHub, GitLab… quelles différences ?

  • Git est un logiciel ;
  • Utilisation en ligne de commandes
  • Différentes interfaces graphiques (RStudio, VS Code…)

Concepts

Git, GitHub, GitLab… quelles différences ?

  • GitHub et GitLab sont des forges logicielles
  • Forge: espace d’archivage de code
  • Des fonctionalités supplémentaires : réseau social du code

Tip

  • GitHub : utilisation pour les projets open-source
  • GitLab : utilisation pour les projets internes

Concepts

Dépôt local / dépôt distant (remote)

Source : Collaborative work with R

Concepts

Workflow (version littéraire) :

  • On travaille sur un dépôt local en éditant des fichiers
  • On dit à Git que ces fichiers doivent être suivis (staging area)
  • On valide les modifications faites en local (commit)
  • On soumet les modifications (push) après avoir récupéré la version collective (pull)

Concepts

Workflow (version imagée) :

Source : Git Documentation

Concepts

Workflow (version imagée complète) :

Source : itnext.io

Commandes essentielles


Action Commande
Cloner un projet git clone [url-to-git-repo]
Afficher les changements git status
Retrouver l’URL du dépôt distant git remote -v

Commandes essentielles


Action Commande
Ajouter des changements à l’index de Git Un seul fichier : git add <file-name>
Tous les fichiers déjà indexés : git add -u
Tous les fichiers ⚠️ : git add -A


Warning

La méthode git add -A peut amener à suivre les modifications de fichiers qui ne devraient pas l’être (par exemple, des données).

Il est recommandé de bien réfléchir avant de l’utiliser (ou d’avoir un bon .gitignore)

Commandes essentielles


Action Commande
Faire un commit git commit -m "message"
Pousser les changements locaux (branche master) git push origin master
Récupérer les changements distants (branche master) git pull origin master

Application 0

Préparation de l’environnement de travail

  1. Créer un compte GitHub
  2. Créer un nouveau dépôt public sur GitHub
  3. Générer un token (jeton d’accès) d’authentification
  4. Lancer un service RStudio sur le Datalab
  5. Utiliser un terminal pour activer le stockage des identifiants :
    • git config --global credential.helper store
  6. Cloner le dépôt distant sur votre environnement local (Datalab):
    • FileNew projectVersion ControlGit

Question : qu’est ce qui différencie le projet cloné d’un projet quelconque ?

Application 1

Premiers commits

  1. Créer un dossier 📁 scripts
  2. Y créer les fichiers script1.R et script2.R, chacun contenant quelques commandes R de votre choix
  3. Ajouter ces fichiers à l’index (staging area) de Git en les cochant dans l’interface RStudio
  4. Effectuer un commit, auquel on donnera un message descriptif pertinent
  5. Supprimer le fichier script1.R et modifier le contenu du fichier script2.R
  6. Analyser ce qui se passe lorsque l’on coche ces fichiers dans l’interface RStudio
  7. Effectuer un nouveau commit pour ajouter ces modifications à l’historique

Question : à ce stade, le dépôt du projet sur GitHub (remote) a-t-il été modifié ?

Application 2

Interactions avec le dépôt distant

  1. Effectuer un push pour intégrer les changements locaux au projet distant
  2. Parcourir l’historique du projet sur GitHub
    1. Faire apparaître les différences entre deux versions consécutives du projet
    2. Afficher une version passée du projet
  3. Modifier le fichier README.md via l’interface d’édition web
  4. Faire une modification du projet local, puis commit/push. Que se passe-t-il ?
  5. Faire un pull pour intégrer les changements distants au projet local
  6. Effectuer à nouveau l’étape de push des changements locaux

Question : comment s’assurer que notre projet local est toujours iso au projet distant ?

Bonnes pratiques

Que versionne-t-on ?

  • Essentiellement du code source
  • Pas d’outputs (fichiers .html, .pdf, modèles…)
  • Pas de données, d’informations locales ou sensibles

Note

Pour définir des règles qui évitent de committer tel ou tel fichier, on utilise un fichier nommé .gitignore.

Si on mélange du code et des éléments annexes (output, données…) dans un même dossier, il faut consacrer du temps à ce fichier.

Le site gitignore.io peut vous fournir des modèles.

N’hésitez pas à y ajouter des règles conservatrices (par exemple *.csv), comme cela est expliqué dans la documentation utilitR.

Bonnes pratiques

Format des commits

  • Fréquence
    • Aussi souvent que possible
    • Le lot de modifications doit “faire sens”
  • Messages
    • Courts et informatifs (comme un titre de mail)
    • Décrire le pourquoi plutôt que le comment dans le texte

Application 3

Le fichier .gitignore

Lors de la création du projet via Rstudio un fichier .gitignore a été créé à la racine du projet.

  1. Ajouter le contenu du .gitignore standard R
  2. Exclure également les fichiers de type .pdf et .html
  3. Créer un dossier data à la racine du projet et l’ajouter au .gitignore
  4. Effectuer un commit pour ajouter le fichier .gitignore au projet Git
  5. Vérifier que toutes les règles ajoutées précédemment fonctionnent comme attendu

Question : que se passe-t-il lorsque l’on ajoute au .gitignore des fichiers qui ont déjà été commit sur le projet Git ?

Le travail collaboratif avec Git

Outils pour le travail collaboratif

  • L’éco-système Git facilite le travail collaboratif
    • Git : modèle des branches
    • GitHub / GitLab : Issues, Pull Requests, Forks
  • Ces outils ne remplacent pas une bonne définition de l’organisation du travail en équipe
    • Choix d’un workflow
    • Droits d’accès
    • Règles de contribution

Application 4

Synchronisation des dépôts

  1. Se mettre par groupes de 3/4 personnes:
    • Une personne aura la responsabilité d’être mainteneur
    • Deux à trois personnes seront développeurs
  2. Le mainteneur crée un dépôt sur Github. Il/Elle donne des droits au(x) développeur(s) du projet
  3. Créer une copie locale (clone) du projet sur son service RStudio du Datalab
  4. Créer un fichier <votre_nom>-<votre_prenom>.md. Écrire dedans trois phrases de son choix sans ponctuation ni majuscules, puis commit et push les modifications

À ce stade, une seule personne (la plus rapide) devrait ne pas avoir rencontré de rejet du push. C’est normal ! Avant d’accepter une modification, Git vérifie en premier lieu la cohérence de la branche avec le dépôt distant. Le premier ayant fait un push a modifié le dépôt commun ; les autres doivent intégrer ces modifications dans leur version locale (pull) avant d’avoir le droit de proposer un changement.

  1. Pour ceux dont le push a été refusé, effectuer un pull des modifications distantes
  2. Dans RStudio, afficher l’historique du projet et regarder la manière dont ont été intégrées les modifications des collaborateurs
  3. Effectuer à nouveau un push de vos modifications locales
  4. Les derniers membres du groupe devront refaire les étapes précédentes, potentiellement plusieurs fois, pour pouvoir push les modifications locales

Question : que se serait-il passé si les différents membres du groupe avaient effectué leurs modifications sur un seul et même fichier ?

Application 5

Résoudre les conflits

  1. On se place dans la même configuration que dans l’application précédente : un mainteneur et deux/trois développeurs
  2. Le mainteneur modifie le contenu de son fichier, puis commit et push les modifications
  3. Sans faire de pull préalable, les développeurs modifient également le contenu du fichier du mainteneur, puis commit et push les modifications

Le push est rejeté pour la même raison que dans l’application précédente : les dépôts ne sont plus synchronisés, il faut pull les changements distants au préalable. Mais cette fois, le pull est également rejeté : il y a un conflit entre l’historique du projet distant et celui du projet local. Git nous indique qu’il faut résoudre le conflit avant de pouvoir modifier l’historique du projet.

  1. Utiliser l’interface de RStudio pour résoudre le conflit, en choisissant la version du fichier que vous souhaitez conserver, puis commit/push les modifications
  2. Comme dans l’application précédente, seul le développeur le plus rapide parvient à push. Les autres doivent répéter l’opération.

Question : comment limiter au maximum la survenue des conflits d’historique ?

Le modèle des branches

Le modèle des branches

Exemple d’organisation : le GitHub flow

Description plus détaillée : ici

Application 6

Utilisation de branches

  1. Sur le même dépôt local que pour les applications 4 et 5, récupérer les mises à jour de la branche principale du dépôt distant
  2. Créer une branche intitulée <votre_nom>-<votre_prénom>
  3. Effectuer un commit avec les modifications de votre choix, puis pousser les changements sur une nouvelle branche du dépôt distant (git push -u origin <votre_nom>-<votre_prénom>)
  4. Ouvrir une Pull Request (PR) pour proposer d’intégrer vos changements sur la branche principale du dépôt distant
  5. Ouvrir une Issue dans laquelle vous mentionnez la Pull Request précédemment ouverte

Question : quelle organisation pour merge dans la branche principale ?

Application 7

Contribution à un projet open-source

  1. Sur GitHub, faire un fork du dépôt git-exo
  2. Créer une branche intitulée <votre_nom>-<votre_prénom>
  3. Effectuer un commit avec les modifications de votre choix, puis pousser les changements sur votre fork
  4. Ouvrir une Pull Request (PR) pour proposer d’intégrer vos changements sur la branche principale du dépôt git-exo
  5. Ouvrir une Issue dans laquelle vous mentionnez la Pull Request précédemment ouverte

Question : pourquoi, avec un fork, est-il très important de toujours effectuer une Pull Request à partir d’une branche différente de la branche principale ?

Ressources utiles


  • Trouver de l’aide:
    • Pour toute question : le salon Tchap Insee-Git-Gitlab
    • Sollicitez vos collègues utilisateurs de Git !

Merci pour votre attention !