diff --git a/Makefile b/Makefile index fd31982..c49066a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ BUILD_DIR=build DOT_FILES=$(wildcard figures/*.dot) +TEX_FILES=$(wildcard figures/*.tex) +PNG_FILES=$(wildcard images/*.png) PDF_FILES=$(DOT_FILES:figures/%.dot=$(BUILD_DIR)/figures/%.pdf) build: $(BUILD_DIR)/report.pdf @@ -11,7 +13,7 @@ $(PDF_FILES):$(BUILD_DIR)/figures/%.pdf: figures/%.dot @mkdir -p $(BUILD_DIR)/figures @dot -Tpdf -o $@ $^ -Nfontname='Source Sans Pro' -$(BUILD_DIR)/report.aux: report.tex references.bib $(PDF_FILES) +$(BUILD_DIR)/report.aux: report.tex $(TEX_FILES) references.bib $(PDF_FILES) @mkdir -p $(BUILD_DIR) @xelatex -interaction=nonstopmode -halt-on-error -shell-escape -output-directory=$(BUILD_DIR) report.tex @@ -25,6 +27,6 @@ $(BUILD_DIR)/report.bbl: $(BUILD_DIR)/report.aux references.bib @cp $(BUILD_DIR)/report.aux $(BUILD_DIR)/report.aux.old @cp references.bib $(BUILD_DIR)/references.bib.old -$(BUILD_DIR)/report.pdf: report.tex $(BUILD_DIR)/report.bbl +$(BUILD_DIR)/report.pdf: report.tex $(TEX_FILES) $(BUILD_DIR)/report.bbl @mkdir -p $(BUILD_DIR) @xelatex -interaction=batchmode -halt-on-error -shell-escape -output-directory=$(BUILD_DIR) report.tex >/dev/null diff --git a/figures/hbs1.tex b/figures/hbs1.tex new file mode 100644 index 0000000..00c30d2 --- /dev/null +++ b/figures/hbs1.tex @@ -0,0 +1,43 @@ +\begin{figure}[H] + \begin{subfigure}[t]{0.45\textwidth} + \begin{lstlisting}[language=hbs, numbers=none, backgroundcolor=\color{bgColor}] +
Hello, world!
+{{>component_end}} + \end{lstlisting} + \caption{Email avec \entity{Mustache}} + \end{subfigure} + \hfill + \begin{subfigure}[t]{0.45\textwidth} + \begin{lstlisting}[language=hbs, numbers=none, backgroundcolor=\color{bgColor}] +{{#>component}} +Hello, world!
+{{/component}} + \end{lstlisting} + \caption{Email avec \entity{Handlebars}} + \end{subfigure} + + \caption{Exemple de définition et d'utilisation d'un composant avec \entity{Handlebars} et \entity{Mustache}} + \label{hbs1} +\end{figure} diff --git a/figures/hbs2.tex b/figures/hbs2.tex new file mode 100644 index 0000000..9ee09b3 --- /dev/null +++ b/figures/hbs2.tex @@ -0,0 +1,17 @@ +\begin{figure}[H] + \includegraphics[width=0.9\textwidth]{hbs2} + \caption{Version HTML d'un email d'exemple} + \label{hbs2a} +\end{figure} + +\begin{figure}[H] + \begin{lstlisting}[language=hbs, numbers=none, backgroundcolor=\color{bgColor}] +Hello, user! + +This is an automated email sent to you, +just to tell you that your favorite animal is: +[ The Giraffe ]( https://wikipedia.com/wiki/Giraffe ) + \end{lstlisting} + \caption{Version texte d'un email d'exemple} + \label{hbs2b} +\end{figure} diff --git a/figures/mailingnest.dot b/figures/mailingnest.dot new file mode 100644 index 0000000..01c385a --- /dev/null +++ b/figures/mailingnest.dot @@ -0,0 +1,84 @@ +digraph nestjs1 { + rankdir=LR; + + subgraph cluster_generator { + { + rank=same + PrintGenerator + TemplateGenerator + } + PrintGenerator -> TemplateGenerator + + label="handlebars-generator" + style="filled" + color="#e0e0f0" + } + + subgraph cluster_mailing_nest { + subgraph cluster_generatormodule { + GeneratorService -> PrintGenerator + label="GeneratorModule" + style="dotted" + } + + subgraph cluster_UploadModule { + { + rank=same + UploadService + AmazonUploadService [color=dimgrey,fontcolor=dimgrey] + } + UploadService -> GeneratorService + UploadService -> AmazonUploadService [color=dimgrey] + label="UploadModule" + style="dotted" + } + + subgraph cluster_SenderModule { + { + rank=same + SenderService + AmazonSenderService [color=dimgrey,fontcolor=dimgrey] + } + SenderService -> AmazonSenderService + label="SenderModule" + style="dotted" + } + + label="mailing-nest" + style="filled" + color="#e0f0e0" + } + + subgraph cluster_mint { + subgraph cluster_MintMailingModule { + MintMailingService -> UploadService + MintMailingService -> SenderService + + label="MintMailingModule" + style="dotted" + } + + subgraph cluster_OrderService { + { + rank=same + OrderService + OrderController [shape=rectangle] + } + OrderController -> OrderService + OrderService -> MintMailingService + + style="dotted" + } + + subgraph cluster_Rest { + Rest [label="..."] + Rest -> MintMailingService + + style="dotted" + } + + label="mint-service" + style="filled" + color="#f0e0e0" + } +} diff --git a/figures/nestjs1.tex b/figures/nestjs1.tex new file mode 100644 index 0000000..33d2f7c --- /dev/null +++ b/figures/nestjs1.tex @@ -0,0 +1,42 @@ + +\begin{figure}[H] + \begin{lstlisting}[style=JavaScript] + export abstract class IChildService { + // ... + } + + @Injectable(IChildService) + export class ChildService implements IChildService { + // ... + } + + @Injectable() + export class ParentService { + private childService: IChildService; + + constructor( + childService: IChildService + ) { + this.childService = IChildService; + } + + // ... + } + + @Module({ + providers: [ + ChildService, + ParentService + ], + exports: [ + ParentService + ] + }) + export class ParentModule {} + \end{lstlisting} + + \centering + \includegraphics{nestjs1} + \caption{Exemple d'injection de dépendances avec NestJS} + \label{nestjs1} +\end{figure} diff --git a/figures/nestjs2.tex b/figures/nestjs2.tex new file mode 100644 index 0000000..4bd74af --- /dev/null +++ b/figures/nestjs2.tex @@ -0,0 +1,29 @@ +\begin{figure}[H] + \begin{lstlisting}[style=JavaScript] + @Injectable() + export class MyService { + constructor( + parentService: ParentService + ) { + // ... + } + } + + @Module({ + imports: [ + // Comme ParentModule exporte ParentService, + // ce service est facilement rendu disponible ici pour MyService: + ParentModule + ], + providers: [ + MyService + ] + }) + export class MyModule {} + \end{lstlisting} + + \centering + \includegraphics{nestjs2} + \caption{Exemple d'import de dépendances avec NestJS (suite de \ref{nestjs1})} + \label{nestjs2} +\end{figure} diff --git a/images/hbs2.png b/images/hbs2.png new file mode 100644 index 0000000..63823d9 Binary files /dev/null and b/images/hbs2.png differ diff --git a/references.bib b/references.bib index 39c1fdb..606b72e 100644 --- a/references.bib +++ b/references.bib @@ -2,7 +2,6 @@ author={Moment}, title={Site de Moment}, howpublished="\url{https://moment.tech/}", - year=2023, note="[En ligne; accédé le 30 Janvier 2023]" } @@ -10,7 +9,6 @@ author={Moment}, title={Moment Care - Un écosystème digital pour votre établissement de santé}, howpublished="\url{https://moment.care/}", - year=2023, note="[En ligne; accédé le 30 Janvier 2023]" } @@ -18,7 +16,6 @@ author={NestJS}, title={NestJS - A progressive Node.JS framework}, howpublished="\url{https://nestjs.com/}", - year=2023, note="[En ligne; accédé le 31 Janvier 2023]" } @@ -47,3 +44,10 @@ month=04, note="[En ligne; accédé le 01 Février 2023]" } + +@misc{amazonses, + author={Amazon Simple Email Service} + howpublished="\url{https://aws.amazon.com/fr/ses/}", + year=2023, + note="[En ligne; accédé le 02 Février 2023]" +} diff --git a/report.tex b/report.tex index 7c638b9..f8fd36a 100644 --- a/report.tex +++ b/report.tex @@ -11,6 +11,7 @@ \usepackage{xcolor} \usepackage{float} \usepackage{cite} +\usepackage{subcaption} \usepackage{hyperref} \hypersetup{ @@ -53,7 +54,14 @@ morestring=[b]" } -\definecolor{bgColor}{rgb}{0.95,0.95,0.92} +\lstdefinelanguage{hbs}{ + morecomment=[s]{\{\{!}{!\}\}}, + commentstyle=\color{purple}\ttfamily, + stringstyle=\color{red}\ttfamily, + morestring=[s]{\{\{}{\}\}}, +} + +\definecolor{bgColor}{rgb}{0.95,0.94,0.92} \lstdefinestyle{JavaScript}{ backgroundcolor=\color{bgColor}, commentstyle=\color{gray}, @@ -74,7 +82,7 @@ language=JavaScript } -\graphicspath{{build/figures/}} +\graphicspath{{build/figures/}{images/}} \newfontfamily{\Tahoma}{Tahoma} \newfontfamily{\SourceSans}{Source Sans Pro} @@ -91,7 +99,8 @@ \newcommand{\entityb}[1]{#1} \newcommand{\person}[2]{#1 #2} \newcommand{\term}[1]{\textit{#1}} -\newcommand{\reffig}[1]{[Figure~\ref{#1}]} +\newcommand{\figref}[1]{[Figure~\ref{#1}]} +\newcommand{\inputfig}[1]{\input{figures/#1}} \title{Rapport de stage ST40 - A2022} \author{Adrien Burgun} @@ -272,10 +281,6 @@ Ce produit est composé d'un serveur, nommé \entity{Flymingo Box}, sur lequel t cliniques d'accéder au même contenu que sur \entity{Mint Digital}. \end{description} - - -\section{Travail réalisé} - Durant ce stage, j'ai surtout travaillé sur les applications suivantes: \begin{itemize} @@ -285,19 +290,19 @@ Durant ce stage, j'ai surtout travaillé sur les applications suivantes: \item Mint TV et Mood TV \end{itemize} -\subsection{Mint Service} +\section{Travail réalisé sur Mint Service} Mint Service est une application construite avec \entity{NestJS}. NestJS est un framework permettant de construire des applications côté serveur en Javascript, et de s'assurer que ces applications soient à la fois sûres, efficaces et flexibles \cite{nestjs}. -\subsubsection{NestJS et organisation du code} +\subsection{NestJS et organisation du code} % TODO: hiérarchiser l'argumentaire NestJS emploie à son coeur les principes de \term{modularité} et d'\term{inversion de contrôle} (\term{IoC}): \\ -L'application est séparée en différents modules, qui eux-mêmes contiennent des \term{services} et des \term{controleurs}. \reffig{nestjs3} +L'application est séparée en différents modules, qui eux-mêmes contiennent des \term{services} et des \term{controleurs}. \figref{nestjs3} \begin{description} \item[Les services] (aussi appelés \term{providers}) contiennent l'implémentation de la logique nécessaire @@ -314,7 +319,7 @@ L'application est séparée en différents modules, qui eux-mêmes contiennent d ainsi que comment NestJS doit construire ces services dans les cas plus complexes. \\ Les modules peuvent exporter un sous-ensemble de leurs services, ce qui permet de rapidement - réutiliser des services en important le module leur étant associé. \reffig{nestjs2} + réutiliser des services en important le module leur étant associé. \figref{nestjs2} \end{description} \begin{figure}[H] @@ -335,7 +340,7 @@ La séparation entre controleurs et services permet d'avoir une claire \term{sé 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, -d'une manière similaire au framework \entity{Spring} en \entity{Java}. \reffig{nestjs1} +d'une manière similaire au framework \entity{Spring} en \entity{Java}. \figref{nestjs1} % TODO: trouver une source % Separation of concerns @@ -345,79 +350,10 @@ Il devient ainsi plus simple avec ce système de modifier différentes parties d Il est aussi plus simple de tester du code organisé de la manière suivante, car les services et les controleurs peuvent être placés dans un environnement isolé et testés individuellement ou collectivement. -\begin{figure} - \begin{lstlisting}[style=JavaScript] - export abstract class IChildService { - // ... - } - - @Injectable(IChildService) - export class ChildService implements IChildService { - // ... - } - - @Injectable() - export class ParentService { - private childService: IChildService; - - constructor( - childService: IChildService - ) { - this.childService = IChildService; - } - - // ... - } - - @Module({ - providers: [ - ChildService, - ParentService - ], - exports: [ - ParentService - ] - }) - export class ParentModule {} - \end{lstlisting} - - \centering - \includegraphics{nestjs1} - \caption{Exemple d'injection de dépendances avec NestJS} - \label{nestjs1} -\end{figure} -\begin{figure} - \begin{lstlisting}[style=JavaScript] - @Injectable() - export class MyService { - constructor( - parentService: ParentService - ) { - // ... - } - } - - @Module({ - imports: [ - // Comme ParentModule exporte ParentService, - // ce service est facilement rendu disponible ici pour MyService: - ParentModule - ], - providers: [ - MyService - ] - }) - export class MyModule {} - \end{lstlisting} - - \centering - \includegraphics{nestjs2} - \caption{Exemple d'import de dépendances avec NestJS (suite de \ref{nestjs1})} - \label{nestjs2} -\end{figure} +\subsection{Système d'envoi de mail} -\subsubsection{Système d'envoi de mail} +\subsubsection{Analyse et prototype} 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: @@ -432,25 +368,71 @@ Ce système prend la forme de plusieurs librairies, qui doit remplir les conditi Mon travail a commencé par l'analyse de différentes solutions permettant d'adresser les deux dernières conditions. -Par le passé, l'entreprise avait déjà utilisé le moteur \entity{handlebars}, +Par le passé, l'entreprise avait déjà utilisé le moteur \entity{Handlebars} \cite{handlebars}, une librairie de recherche et de remplacement de texte, qui permet d'avoir des formes simples de logique, comme des conditions ou des boucles. -Bien que \entity{handlebars} fonctionne bien pour insérer les informations de l'utilisateur dans les mails, +Bien que \entity{Handlebars} fonctionne bien pour insérer les informations de l'utilisateur dans les mails, il ne permet pas de facilement réutiliser du code, qui est souvent complexe afin d'assurer un bon affiche sur les différents programmes de boîte mail. -J'ai donc cherché à avoir un système de \og composants \fg dans la solution choisie: -ces composants doivent pouvoir être appelés avec différentes valeurs en arguments, -et doivent pouvoir appeler d'autres composants, -permettant ainsi de créer des couches d'abstraction afin de plus rapidement résoudre des problèmes, -et de réutiliser ces abstractions dans des nouveaux contextes. +J'ai donc cherché à avoir un système de \og composants \fg dans la solution choisie, afin de pouvoir construire des couches +d'abstraction et de réutiliser facilement le code. Ces composants doivent, plus spécifiquement: + +\begin{itemize} + \item Pouvoir être appelés avec différentes valeurs en arguments + \item Pouvoir appeler d'autres composants +\end{itemize} % TODO: source sur search and replace -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}. +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}. + +J'ai d'abords créé et implémenté une librairie permettant de compiler + +\begin{figure}[H] + \includegraphics[width=\textwidth]{mailingnest} + \caption{Organisation initiale du système d'envoi de mail dans Mint-Service} +\end{figure} \newpage +\section{Annexes} + +\inputfig{nestjs1} +\inputfig{nestjs2} + \bibliographystyle{plain} \bibliography{references}{}