Si la \term{review} relève des problèmes, alors ceux-cis doivent être adressés.
Dans le cas contraire, les changements de la \term{Merge Request} sont incorporés dans la branche \texttt{develop} et la tâche sur \entity{Jira} marquée comme \textit{Faite}.
\textbf{VSCode}\cite{vscode} est un éditeur de texte utilisé par presque toute l'équipe pour modifier ou naviguer le code.
\textbf{Slack}\cite{slack} est une plateforme de messagerie instantanée,
que l'entreprise préfère aux emails pour la communication indirecte.
\textbf{Jira}\cite{jira} est un logiciel de gestion et de suivi de tickets,
que notre équipe utilise pour suivre les tâches à faire durant la semaine,
quelles tâches sont en cours de développement, prêtes à être revues ou finies,
ainsi que pour garder un \term{backlog} des tâches à faible priorité.
\textbf{Confluence}\cite{confluence} est un logiciel qui permet à l'équipe de regrouper des documentations qui n'ont pas de place claire au sein du code.
\textbf{NX}\cite{nx} est un outil simplifiant la gestion de \og monorepositories \fg (des repositories contenant plusieures applications et librairies).
\textbf{NX} est utilisé pour la repository de l'équipe qui contient Mint Service, Mint Admin et Mood TV.
L'objectif au long terme et de migrer l'ensemble des projets de l'équipe sur cette repository,
car elle permet de facilement réutiliser du code entre les projets et de synchroniser des modifications entre projets.
Typescript permet d'éviter une classe de bugs causés par des valeurs passées à des fonctions attendant un certain type en entrée.
\\
Typescript existe aujourd'hui en tant que langage qui doit être transpilé en javascript avant de pouvoir être utilisé dans Node.JS ou dans un navigateur,
mais certains interpréteurs (comme \textbf{Bun}\cite{bun}) supportent le typescript,
et il existe une initiative pour standardiser un système permettant d'ajouter des types en javascript sans devoir le traduire.
\item[Continuous Integration] En plus de tester le code localement,
le code est aussi compilé et testé sur un serveur via les outils de \entity{GitLab} pour l'intégration continue.
Éxecuter ces tests sur un serveur permet de valider le comportement de l'application à tout moment du projet par rapport à une base commune,
et de s'assurer qu'une combinaison de modifications ne mène pas à un problème.
\item[Linting et formatting] Nous utilisons des outils comme \entity{ESLint} et \entity{Prettier} pour vérifier la consistence
de la forme du code dans les différents projets.
\entity{ESLint} nous permet de mettre en place des règles vérifiées automatiquement,
et qui lorsqu'elles sont suivies diminuent le risque d'avoir du comportement inattendu dans l'application.
\item[Merge Reviews] Avant qu'une modification ne soit incorporée dans la branche commune,
elle doit être vérifiée et validée par un humain.
Cette étape complète celle d'\entity{ESLint}, car certaines règles de style ne peuvent pas être appliquées automatiquement.
La vérification des modifications par un humain permet aussi d'éviter des potentiels bugs ou points de confusion.
\item[Recettes] Pour valider les produits, un serveur de test, le \og lab \fg,
est à disposition pour déployer et tester localement les différents projets.
Cette version déployée localement est ensuite testée par les chefs de projet et d'autres personnes de l'entreprise pour déceller des problèmes qui n'auraient pas été trouvés pendant le développement.
\item[Semantic versioning] Nous utilisons le versionage sémantique pour nos projets et pour les dépendance des projets.
Le versionage sémantique permet d'encoder dans le numéro de version du programme quel type de mise à jour il y a entre deux versions.
Le format du versionage sémantique est \;\texttt{major.minor.patch}, où:
\begin{itemize}
\item Si seulement \texttt{patch} change, alors la mise à jour ne modifie pas la fonctionnalité, mais corrige uniquement des bugs.
\item Si \texttt{minor} ou \texttt{patch} changent, alors la mise à jour ajoute uniquement de la fonctionnalité; faire la mise à jour ne devrait pas casser du code utilisant la librairie en question.
\item Si \texttt{major} change, alors la mise à jour introduit des changements cassants: il faudra alors faire des changements au code utilisant la librairie.
Pour limiter le couplage entre les services, et pour simplifier la réutilisation des services,
NestJS permet de faire de l'\term{injection de dépendances} par \term{constructeur sans défaut}\cite{yang2008empirical} dans les services et dans les controleurs,
On m'a donné en début de stage la tâche d'implémenter un système d'envoi de mail pour \entity{Mint Service}.
Ce système prend la forme de plusieurs librairies, qui doit remplir les conditions suivantes:
\begin{itemize}
\item Il doit être facilement réutilisable dans d'autres projets.
\item Il doit permettre de changer de fournisseur de service pour l'envoi d'emails sans devoir faire de grands changements du côté des utilisateurs de la librairie.
\item Il doit pouvoir envoyer des emails qui s'affichent de la manière voulue sur la majorités des boîtes mail.
\item Il doit pouvoir envoyer des emails contenant des informations sur l'utilisateur; cette étape devra être faite avec le service de \term{templates} d'email sur \entity{Amazon SES}\cite{amazonses}\cite{amazonsestemplate}
J'ai selectionné deux moteurs de recherche et de remplacement de texte (\term{Search and Replace}): \entity{Handlebars}\cite{handlebars} et \entity{Mustache}\cite{mustache}.
Ces deux moteurs opèrent de manière similaire: ils lisent le code source,
et lorsqu'une variable indiquée par les balises \texttt{\{\{} et \texttt{\}\}} est rencontrée,
celle-ci est subtituée par la valeur assignée au nom de cette variable.
\entity{Handlebars} et \entity{Mustache} peuvent tous les deux être utilisés pour implémenter le système de composants voulu,
car ils permettent de définir des variables spéciales, que les deux moteurs appelent \term{partials},
qui peuvent appeler du code javascript arbitraire.
J'ai enfin fait un prototype en \entity{Typescript},
qui transforme un email décrit à partir de composants \entity{Handlebars} ou \entity{Mustache} en du HTML.
Après avoir montré ce prototype à mon chef de projet, nous étions tous les deux d'accord que le moteur \entity{Handlebars}
remplissait mieux nos attentes, en grande partie parce que \entity{Handlebars} permet de passer du code en tant qu'\og enfants \fg,
tandis que \entity{Mustache} requiet de passer par deux composants (un avant et un après le code \og enfant \fg). \figref{hbs1}
\inputfig{hbs1}
Pour le premier projet sur lequel \entity{Mint Service} allait être déployé,
\entity{Amazon SES}\cite{amazonses} allait être utilisé pour faire l'envoi de mails.
\entity{Amazon SES} permet d'envoyer les emails sous format texte et HTML en même temps,
permettant d'avoir des emails facilement lisibles par un lecteur d'écran
ou sur une messagerie configurée pour afficher les mails sans leur mise en forme.
La partie \entity{Handlebars} a donc été étendue pour permettre d'annoter quels parties du code doivent être
placés dans la version texte du mail. [Figures~\ref{hbs2a} et \ref{hbs2b}]
\inputfig{hbs2}
\subsubsection{Implémentation initiale dans Mint-Service}
Une fois que le prototype me donnait des résultats satisfaisants,
j'ai pu passer à l'implémentation au propre du système d'envoi de mails dans \entity{Mint Service}.
\item Les mails sont chargés et sont rendus, puis sont mises en lignes sur \entity{Amazon SES} en tant que \og templates \fg\cite{amazonsestemplate}
\item Les mails sont ensuite envoyés en instructant à \entity{Amazon SES} de faire le rendu et l'envoi d'une des \term{templates} à l'adresse mail voulue, avec les données voulues
\end{enumerate}
J'ai d'abords créé et implémenté une librairie permettant de compiler du code \entity{Handlebars}
ainsi que des composants en format HTML et en format texte, nommée \texttt{handlebars-generator}. Cette librairie ne s'occupe pas du
chargement des fichiers, ni de l'envoi des mails, et est implémentée sans framework,
ce qui permet de la réutiliser dans le futur pour d'autres projets.
Puis, j'ai créé et implémenté une librairie Nest.JS nommée \texttt{mailing-nest} qui s'occupe de:
\begin{itemize}
\item Charger les composants et les emails depuis un dossier donné
\item Transformer ceux-cis avec \texttt{handlebars-generator} en HTML et en texte
\item Mettre en ligne des \term{templates} pour utiliser le service d'envoi d'emails personalisés d'\entity{Amazon}
Avec le système de mail en place, j'ai pu implémenter la première template d'email, qui était celle pour l'envoi d'identifiants au patients.
Très rapidement, j'ai pu voir sur \url{caniemail.com} que la quasi-totalités des fonctionnalités HTML5 modernes n'étaient pas supportés par \entity{Microsoft Outlook},
ce qui nous forcerait à utiliser des \texttt{<table>} dans l'entièreté des emails pour pouvoir supporter \entity{Microsoft Outlook},
qui est à ce jour le 3ème client email le plus utilisé du monde \cite{oberloemailclients}.
Une solution à ce problème est d'utiliser une librairie assurant la compatibilité avec \entity{Outlook}.
J'ai choisi la librairie \entity{MJML}\cite{mjml}, qui utilise un langage ressemblant au html, qui est ensuite compilé en HTML compatible avec \entity{Outlook}:
Après avoir fini l'implémentation du système de mail, j'ai pu l'observer alors qu'il est passé par la vérification de qualité,
des déploiements et recettes sur un serveur local, et enfin des déploiements chez les clients.
Les deux librairies ont vu peu de changements, et ont fonctionné comme voulu.
L'organisation du code au sein de \entity{Mint Service} a pris deux essais pour arriver à un format satisfaisant:
le premier essai plaçait l'envoi des mails dans un service dédié à la gestion des utilisateurs (\texttt{GuestModule}),
mais il s'averrait qu'il fallait assez de code pour préparer les informations des mails qu'il était préférable de déplacer la logique d'envoi des mails dans un module à part, \texttt{MintMailingModule}.
Malgré \entity{MJML} et le système de composants, écrire des templates d'emails reste plus compliqué à écrire que du code React:
\begin{itemize}
\item La différence de format entre les templates Handlebars/MJML et les composants React fait qu'il est difficile d'appliquer les intuitions valables pour le React lorsqu'on écrit ou réécrit des templates d'emails.
\\
Ceci est en grande partie dû au fonctionnement de MJML,
qui requiet une structure stricte dans le code (\texttt{mj-body}$\rightarrow$\texttt{mj-section}$\rightarrow$\texttt{mj-column}$\rightarrow$ texte).
\\
HTML lui a une structure plus flexible,
permettant d'imbriquer la pluspart des éléments disponibles dans un ordre arbitraire. \cite{mdncontentcategories}
(il faut mixer ensemble deux différents formats handlebars, l'un étant interprété de notre côté, et l'autre étant interprété du côté d'\entityb{Amazon SES}\figref{emailsrchbs}).
car le seul moyen pour accéder aux erreurs d'envoi de mails sur \entityb{Amason SES} est de mettre en place un système
de transfert de messages, puis de l'activer en envoyant les mails avec un paramètre précis.
\end{itemize}
Pour palier à la deuxième difficulté, j'ai décidé vers la fin de mon stage de modifier l'implémentation du système d'envoi de mails,
afin de faire l'entièreté du rendu de notre côté, et d'uniquement utiliser \entity{Amazon SES} pour l'envoi pur des mails.
J'avais également comme but secondaire de rendre ce système plus robuste,
en permettant notamment l'insertion de code pour vérifier la validité des données insérées dans les emails lorsqu'on est dans un environnement de développement.
Les modifications ont été faites dans l'ordre suivant, qui permettait de progressivement appliquer les changements nécessaires:
\begin{enumerate}
\item Suppression de la transformation des balises secondaires (\texttt{[[} et \texttt{]]}) et des options associées
\item Marquage de différents types comme dépréciés, et ajout de types pour l'envoi pur d'emails
\item Dépréciation des méthodes d'envoi d'email via les templates SES (\texttt{sendTemplatedEmail}), et ajout des méthodes pour l'envoi pur d'emails (\texttt{sendEmail})
\item Modification des templates pour ne plus utiliser les balises secondaires
\item Modification de l'application de prévisionage des emails pour utiliser le nouveau format des informations substituées dans les mails
\item Modification de \entity{Mint Service} pour utiliser \texttt{sendEmail} au lieu de \texttt{sendTemplatedEmail}
\item Suppression de \texttt{UploadModule} et de \texttt{sendTemplatedEmail}
\item Suppression des types inutilisés
\end{enumerate}
À la suite de ces modifications, les emails s'affichent de la même manière qu'avant,
et le système d'envoi de mails est désormais plus simple à utiliser
et plus simple à étendre avec différents services d'envoi de mail.
Je n'ai pas pu implémenter le système de validation des données, par soucis de difficulté d'implémentation:
il aurait fallu étendre le système de chargement de composants pour également charger du code Javascript,
et transformer le format des données utilisé par Handlebars en un format facilement vérifiable.
\\
Il est par contre maintenant possible d'écrire dans \entityb{Mint Service} des tests pour s'assurer que la logique de transformation des données reste compatible avec les emails.
À la suite de cette modification,
je pense qu'il est encore possible d'améliorer de différentes manières ce système d'envoi de mails:
\begin{itemize}
\item En ajoutant plus de tests automatisés dans le système, notamment des tests d'intégration
\item En rendant les différents modules plus simples d'utilisation
\item En permettant d'utiliser une syntaxe plus proche de celle de React pour appeler des composants (\texttt{<Composant>} au lieu de \texttt{\{\{>Composant\}\}})
\item En utilisant un système comme \href{https://react.email/}{React Email} ou \href{https://astro.build/}{Astro} pour écrire les templates en Javascript, ce qui permetterait aussi de faire de la vérification des données et des types.
\end{itemize}
\begin{figure}[H]
\includegraphics[width=\textwidth]{mailingnest-2}
\caption{Organisation finale du système d'envoi de mail dans Mint-Service}
\entity{Mood TV} est une application tournant sur les télévisions \og intelligentes \fg produites par \entity{LG}.
Ces télévisions font tourner le système d'exploitation \entity{WebOS}, et la version pour laquelle nous visons l'application utilise \entity{Chrome 53}.
Comme ces télévisions utilisent chrome, notre application peut être programmée entièrement en React,
à condition de s'assurer que le code javascript soit compatible avec cette version de chrome.
Mon travail sur \entity{Mood TV} a été d'optimiser le temps de chargement de la page:
avant, celle-ci prenait environ 10 secondes à charger,
et j'ai été laissé en autonomie pour trouver pourquoi le temps de chargement est si haut et comment le baisser.
\caption{Profil du chargement de la page, avant toute optimisation; annoté}
\label{moodtvbefore}
\end{figure}
On peut séparer le temps de chargement en différentes étapes:
\begin{enumerate}
\item Le chargement initial (en bleu), qui est le moment durant lequel le navigateur télécharge le code javascript,
et durant lequel \entity{webpack} prépare ce code pour reproduire un environnement modulaire moderne.
\item L'hydration \cite{hydration}, qui est une étape du rendu avec React: cette étape du chargement permet à React d'attacher
son arborescence d'état au HTML existant, permettant d'intéragir dans le code React avec les éléments du DOM.
\item La réception des \og catégories \fg, qui consiste au traitement de deux requêtes faites à l'API sur laquelle se trouve le \term{Content Management System}
\item L'envoi de requêtes pour récupérer les informations des films présents dans ces catégories
\\
On peut déjà observer sur cette capture d'écran que cet envoi est en triple, alors qu'il ne devrait n'y avoir qu'une vague.
\item La réception des informations de films, et le traitement du résultat de ces requêtes.
\end{enumerate}
Ensuite, il me fallait un moyen de mesurer de manière précise les performances avant de pouvoir faire des changements.
La solution que j'ai trouvé a été de créer et d'implémenter un protocole d'envoi et de réception de performances: \figref{moodtvperf}
\begin{itemize}
\item La télévision mesure les performances avec l'API javascript \texttt{Performance}\cite{performanceapi},
puis envoie ces valeurs via une requête sur un petit serveur sur mon ordinateur.
\item Ce serveur stoque ensuite toutes les valeurs reçues dans un fichier,
et peut relire de ce fichier si jamais il faut reprendre la mesure de performance.
\item Un programme lit les valeurs du fichier, puis calcule la moyenne, l'écart standard de ces valeurs.
Ce programme peut aussi lire deux fichiers, et comparer les performances entre ceux-cis.
\end{itemize}
\begin{figure}[H]
\includegraphics[width=\textwidth]{moodtvperf}
\caption{Protocole d'envoi et de réception de performances}
\label{moodtvperf}
\end{figure}
Les valeurs obtenues sont sous la forme de listes de nombres, une liste par métrique mesurée.
Soit $(\omega_1, \omega_2, ..., \omega_n)$ une telle liste.
Si on suppose que ces valeurs correspondent à différents résultats d'une même expérience $X$,
alors on peut calculer la moyenne empirique ($\mu^{\star}_n$) et la variance ($(\sigma^{\star}_n)^2$) empirique de ces valeurs de la manière suivante:
J'ai décidé d'utiliser dans mon programme de statistique un test rudimentaire de normalité,
également présent dans la librairie populaire de benchmark pour le langage \entity{Rust} nommée \entity{Criterion}, \cite{criterion}
qui m'a permis de détecter une erreur dans la mesure de donnée (celle-ci mesurait la même donnée plusieures fois).
Ce test de normalité vérifie simplement que plus de 95\% des valeurs mesurée tombent dans l'intervale
$\mu^{\star}\pm\sigma\cdot z_{0.975}$.
Comme $\sigma$ n'est pas connu, je majore $\sigma^{\star}$ par la valeur haute de l'approximation \cite{tapprox} de son intervale de confiance. \figref{normalitytest}
Enfin, on peut utiliser le t-test sur les mesures pour estimer si deux variables aléatoires différentes $X$ et $Y$ diffèrent bien de moyenne. \cite{ttest}
Avec ce test, il est alors possible de déterminer si les performances se sont améliorées ou non.
La fonction pour faire la requête pour une catégorie (\texttt{getItems}) utilisait un \texttt{useCallback} et un cache gêré par React,
ce qui faisait que dès que les informations d'un film était récupéré et stocké dans le cache, React assignait une nouvelle référence à \texttt{getItems},
causant le \texttt{useEffect} responsable pour charger l'ensemble des informations des films à s'éxecuter à nouveau,
et de nouvelles requêtes sont envoyées en conséquence. \figref{fromeffectloop}
Cette librairie est utilisée pour transformer les résultats des requêtes, qui sont sous forme d'objets ordinaires,
en instances de classes proposant des fonctions pour facilement traiter les informations contenues dedans.
Malheureusement, \texttt{class-transformer} ajoute beaucoup de temps de calcul, qui sur le hardware de la télévision connectée,
se traduit en secondes de chargement en plus. \cite{classtransformerbenchmark}
J'ai donc remplacé \texttt{class-transformer} par une transformation manuelle pour les listes de films,
qui copie manuellement les données des films et des catégories en instances de classe.
Avant de faire ce changement, j'ai d'abords écrit des tests unitaires pour vérifier le comportement du système déjà en place.
Puis, j'ai progressivement modifié les fonctions de traitement de requête affectées pour utiliser ma transformation manuelle à la place.
% Les seuls tests présents auparavant étaient des tests d'intégration, qui avaient cassé au fil des mois et qui ne fonctionnent plus ajourd'hui.
% J'ai donc dû nettoyer les tests d'intégration existants pour les faire tourner séparemment des tests unitaires.
\inputfig{perf4}
\subsection{Résultats et rétrospective}
Avec ces optimisations, la page prend désormais entre 4 et 6 secondes pour charger, contre 10 à 15 secondes auparavant.
Le temps d'éxecution sur le processeur de la télévision n'est aussi plus un engorgement,
et on peut voir sur le profil des performances qu'une bonne partie du temps est passé à attendre que les différentes requêtes se finissent. \figref{moodtvafter}
\caption{Profil du chargement de la page, après les optimisations; annoté}
\label{moodtvafter}
\end{figure}
Faire ce travail m'a permis d'avoir une compréhension plus profonde sur différents sujets:
\begin{itemize}
\item Les techniques d'optimisation logicielle (profilage, benchmarking)
\item Le modèle de propagation de mises à jour de React (\texttt{useEffect}, les boucles d'évenements infinies \figref{fromeffectloop})
\item L'optimisation de la taille des bundle javascript
\item L'extraction de données de performances depuis le navigateur (web vitals \cite{webvitals}, \texttt{reportWebVitals} sur Next.JS \cite{nextjsvitals})
\item L'analyse de données de performances (z-test, t-test, intervale de confiance)
J'ai été globalement satisfait du travail que j'ai pu fournir durant ce stage:
les résultats attendus étaient obtenus (le système d'envoi de mail marche encore au moment où j'écris ce rapport, la télévision charge consistemment en moins de 5 secondes, etc.)
et j'ai pu écrire des tests unitaires pour une bonne partie de mon code, ce qui permettra de maintenir sa fonctionnalité dans les années à venir.
\subsection{Appréciation des technologies utilisées}
J'ai eu durant ce stage des sentiments partagés \entity{React}:
D'un côté, je trouve que la programmation avec React souffre de la décision de React à être à mi-chemin entre de la programmation réactive \og fine \fg\cite{reactivity}
et de la gestion manuelle de mise à jour.
J'ai rencontré beaucoup de bugs causés par des effets de bord du système de React,
dont certains qui ne pouvaient qu'être résolus en changeant en profondeur l'organisation de plusieurs composants.
De l'autre côté, le refactor de \entity{Mood TV} pour extraire ses composants et les placer dans une librairie était très agréable,
car j'avais le contrôle sur l'organisation que ces composants allaient avoir, et le résultat était très satisfaisant une fois ces composants agencés ensemble.
J'ai apprécié la programmation autour de \entity{Nest.JS}:
le principe d'inversion de contrôle permet d'écrire du code facilement vérifiable et réutilisable,
ce qui rend la base de code plus agréable à naviguer et utiliser.
J'ai enfin été agréablement surpris par \entity{TypeScript}:
si on active l'ensemble des vérifications du code, alors il y a très peu de chances d'avoir des erreurs de type au runtime.
Le système de type est assez avancé pour pouvoir concevoir des types qui garantissent des invariantes qui auraient été difficiles à garantir dans d'autres langages typés.
Écrire des types avancés en TypeScript est presque un art. \figref{types}
\subsection{Estimation du gain apporté}
Pour donner une estimation du gain que mon travail a apporté à l'entreprise,
j'estime que j'ai contribué à 10\% du code sur l'ensemble des applications dévelopées pour \entity{Moment Care}.
Si on estime ensuite que notre équipe contribue à la moitié de la valeur ajoutée par \entity{Moment Care},
et que \entity{Moment Care} génère environ 200,000€ par an (les bénéfices de l'année 2022 de \entity{Moment Care} étaient de 183,000€),
alors on obtient une fourchette basse du gain que j'ai apporté, qui s'élève à 10,000€/an pour les quelques années à suivre.
Naturellement, ma part de contribution va diminuer, via du code écrit par d'autres personnes dans le futur, et via des refactors de mon code.
Une rapide analyse du code sur la monorepository indique que la demi-vie du code est de 6 mois; \figref{halflife}
ceci donne environ 2.9 années d'espérance à mon code, soit une fourchette basse de 30,000€ de gain sur les années à venir.