forked from HEIG-VD/template-tb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtechnos.tex
222 lines (152 loc) · 21 KB
/
technos.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
Ce chapitre présente les technologies choisies pour le développement de l'application. Elles sont sélectionnées afin de répondre au mieux aux besoins du projet. Des comparaisons entre différentes technologies ayant la même mission sont également effectuées afin de justifier les choix finaux.
\section{Language de programmation}
Il est possible de réaliser une application web comme \gls{beeplace} dans un nombre conséquent de languages différents. Cependant, concernant la partie client de l'application, toutes les possibilités finiront par la même conclusion: le code sera exécuté dans le navigateur et donc dans un environnement \gls{javascript}. En effet, \gls{javascript} est le seul langage de programmation supporté par tous les navigateurs. Il n'est donc pas idéal d'utiliser un autre langage que \gls{javascript} pour le frontend de l'application. Pour avoir une cohérence entre le frontend et le backend, il est donc possible de coder l'entièreté de l'application en ECMAScript~\cite{ecmascript}. ECMAScript est le standard sur lequel se base \gls{javascript} ou encore \gls{nodejs}~\cite{nodejs}. \gls{nodejs} quant à lui permet d'exécuter du \gls{javascript} en dehors du navigateur, ce qui permet de l'utiliser pour le backend de l'application.
Utiliser \gls{javascript} pour réaliser des applications web paraît donc une évidence. Cependant, ce dernier est un langage très permissif sans option de typage. Il est donc possible de faire de nombreuses erreurs qui ne seront détectées qu'au moment de l'exécution du code. Pour éviter ce problème, il est possible, et de plus en plus courant, d'utiliser \gls{typescript}~\cite{typescript}.
\subsection{TypeScript}
\gls{typescript} est un langage de programmation créé par Microsoft qui est un sur-ensemble de \gls{javascript}. Il est donc possible de compiler du code \gls{typescript} en \gls{javascript}, ce qui permet de l'utiliser dans n'importe quel environnement. Comme expliqué précédemment, \gls{javascript} peut être utilisé pour développer l'application entière, notamment grâce à \gls{nodejs} pour le backend. C'est bien entendu également le cas pour \gls{typescript}.
\gls{typescript} ajoute de nombreuses fonctionnalités à \gls{javascript}, comme la possibilité de créer des types, des interfaces, des énumérations et bien plus. Les avantages à utiliser \gls{typescript} sont donc nombreux:
\begin{itemize}
\item Meilleure complétion dans les \gls{ide}, comme Visual Studio Code;
\item Gestion automatique des imports dans les \gls{ide};
\item Éviter de découvrir de nombreuses erreurs au moment de l'exécution, car elles sont détectées au moment de la compilation;
\item Refactoriser le code de façon plus sûre en voyant directement les erreurs de types dans l'\gls{ide};
\item Lecture et compréhension du code plus facile, car les types sont explicitement définis.
\end{itemize}
De plus, les deux applications existantes de l'écosystème \gls{beescreens}, Pimp My Wall et Media Player, sont déjà écrites en \gls{typescript}. Il est donc agréable d'avoir une certaine cohérence et uniformité dans les technologies utilisées.
\section{Frontend}
\subsection{Framework}
De nombreux frameworks \gls{javascript} sont disponibles actuellement pour réaliser la partie frontend des applications web mais les trois principaux concurrents en terme de popularité sont React~\cite{react}, Vue.js~\cite{vue} et Angular~\cite{angular}. De plus en plus de possibilités voient le jour chaque année mais ces trois frameworks sont les plus populaires, les plus utilisés et les plus stables. Il est donc pertinent de se focaliser sur ces trois options pour le développement de \gls{beeplace}.
Le tableau \ref{tab:frameworks-frontend-js} présente les trois frameworks avec leur nombre de stars sur \gls{github}. Cette statistique permet d'avoir une idée de la popularité des frameworks. Le tableau démontre également le type de framework, soit un vrai framework avec une architecture complète à disposition ou une librairie qui permet de créer une application réactive mais qui ne propose pas de réelle structure.
\begin{table}[h]
\begin{center}
\caption{Frameworks frontend JavaScript}
\label{tab:frameworks-frontend-js}
\begin{tabular}{c|l|r}
Framework & Stars GitHub & Type \\ \hline
Angular & 89.3k & Framework \\
Vue.js & 38.9k\footnotemark & Librairie \\
React & 211k & Librairie \\
\end{tabular}
\end{center}
\end{table}
\footnotetext[1]{L'équipe Vue.js a changé de dépôt GitHub lors du passage de la version 2 à 3. L'ancien dépôt comptabilise 204.5k stars.}
\subsubsection{Angular}
Angular est le plus ancien des trois. Il est développé et maintenu par Google. Le problème principal d'Angular est la taille du code généré. En effet, comme l'indique cette comparaison~\cite{comparison-js-frameworks}, une application vierge en Angular pèse environ 560KB contre les 100KB des frameworks concurrents. Cette différence pèse d'autant plus lorsque l'application à réaliser n'est pas très conséquente, ce qui est le cas avec \gls{beeplace}. Cet écart de taille s'explique car Angular propose plus de fonctionnalités déjà intégrées que les autres frameworks. Angular est donc plus adapté pour des projets de plus grande envergure avec des équipes de développement plus importantes.
\subsubsection{React vs Vue}
Les deux options restantes sont donc React et Vue. Les différences entre ces frameworks sont moindres. Les deux s'apparentent plus à de légères librairies pour créer des applications réactives que des frameworks complets. Elles sont facilement extensibles afin d'ajouter les briques nécessaires au projet. Cependant, React a tout de mêmes quelques avantages sur Vue:
\begin{itemize}
\item React reste plus populaire comme l'indique Google Trends~\cite{google-trends-js-frameworks} et dispose donc de librairies pour répondre à tous les besoins qui pourraient survenir.
\item De par sa popularité, React dispose d'une plus grande communauté et donc d'une plus grande quantité de ressources et d'aide en ligne.
\item React est développé par un géant de l'industrie, Meta, ce qui lui assure une certaine pérennité.
\item L'application Pimp My Wall existante est elle-même écrite en React, ce qui permet d'uniformiser les technologies.
\end{itemize}
Pour conclure, les deux frameworks étant très similaires et performants, la popularité de React a été l'élément déterminant dans le choix du framework afin de ne pas rencontrer de problèmes de ressources ou de documentation.
\subsubsection{React vs Next.js}
Comme expliqué précédemment, React n'est pas vraiment un framework mais plus une librairie. Le développeur doit donc chercher quelles librairies utiliser pour répondre à ses besoins et les imbriquer ensemble. Cette solution est plus flexible mais demande également plus de temps pour la mise en place du projet. Cependant, il est possible de trouver des solutions qui permettent de créer un projet React rapidement avec des choix concernant les bonnes pratiques déjà effectués. Le plus connu d'entre eux est Next.js~\cite{nextjs}, un framework basé sur React. Les avantages principaux sont les suivants:
\begin{itemize}
\item Système de routage intégré en fonction de la structure du projet.
\item Rendre des pages côté serveur afin d'améliorer le référencement et potentiellement les performances.
\item Créer des fonctions côté serveur afin de ne pas exposer les clés d'API.
\item Utilisation des variables d'environnement pour la configuration.
\end{itemize}
Les fonctionnalités évoquées sont toutes intéressantes, mais dans le cas de ce projet, c'est surtout la dernière qui a influencé le choix. En effet, Next.js permet de définir et d'utiliser des variables d'environnement qui sont injectées dans le code au lancement de l'application. Cela évite de devoir build toute l'application à nouveau à chaque fois qu'un changement de configuration est effectué comme il est nécessaire avec une application React classique.
\subsubsection{Choix final}
Le frontend de \gls{beeplace} sera donc développé à l'aide du framework \textbf{Next.js}, pour les raisons évoquées précédemment.
\subsection{Design de l'interface}
Il existe principalement deux catégories de librairie afin de styliser des applications web:
\begin{itemize}
\item Les librairies avec des opinions très arrêtées et des composants prêts à être assemblés comme Bootstrap~\cite{bootstrap} ou Material UI~\cite{mui};
\item Les librairies facilitant l'écriture de CSS, comme Tailwind CSS~\cite{tailwindcss} ou UnoCSS~\cite{unocss}.
\end{itemize}
La première catégorie est très adaptée pour créer une application rapidement mais la personnalisation devient plus compliquée par la suite. De plus, ces librairies sont souvent plus utiles dans le design d'applications plus classiques comme des panels d'administration qui nécessitent de nombreux composants. Dans le cas de \gls{beeplace}, l'interface utilisateur ne contient que très peu d'éléments et est donc plus adaptée à la deuxième catégorie de librairies, plus souple et personnalisable.
\subsubsection{Choix final}
Le choix s'est tourné vers \textbf{Tailwind CSS} qui est une librairie de plus en plus populaire se basant sur le principe des utility classes. La librairie met à disposition de nombreuses classes CSS bien pensées et étudiées afin de styliser avec cohérence les éléments HTML. Cela permet notamment de ne pas découpler l'HTML du CSS afin de limiter les effets de bords et de faciliter la lecture et la modification du code.
\section{Backend}
\subsection{Choix du langage}
Comme expliqué précédemment, le choix s'est tourné vers \gls{nodejs}~\cite{nodejs} afin d'utiliser un seul et même langage pour l'entièreté de l'application: \gls{typescript}. \gls{nodejs} permet d'utiliser les connaissances acquises en \gls{javascript} côté client également pour le côté serveur. De plus, \gls{nodejs} est un environnement très populaire, ce qui permet, en combinaison avec \gls{npm}, de trouver des librairies pour presque toutes les problématiques possibles. En outre, les performances de \gls{nodejs} sont très bonnes et il est possible de réaliser un scaling horizontal facilement en multipliant le nombre d'instances de l'application.
Pour finir, grâce à l'utilisation de \gls{typescript} dans les deux applications, il est possible de partager du code, notamment les types entre les deux applications en créant un package. Cela permet d'éviter la duplication de code ainsi que d'être sûr de la cohérence des données.
\subsection{Framework}
Il existe de nombreux frameworks dans l'écosystème \gls{nodejs}. La comparaison se centre sur les quatre frameworks les plus populaires et les plus maintenus, à savoir Express.js~\cite{expressjs}, AdonisJS~\cite{adonisjs}, Fastify~\cite{fastify} et NestJS~\cite{nestjs}.
Comme pour les frameworks frontend, le tableau \ref{tab:frameworks-backend-nodejs} présente les quatre frameworks avec leur nombre de stars sur \gls{github}. Le tableau démontre également le type de framework, soit un vrai framework avec une architecture complète à disposition ou une simple librairie permettant surtout de gérer les routes et les middlewares.
\begin{table}[h]
\begin{center}
\caption{Frameworks backend Node.js}
\label{tab:frameworks-backend-nodejs}
\begin{tabular}{c|l|r}
Framework & Stars GitHub & Type \\ \hline
Express.js & 60.7k & Librairie \\
AdonisJS & 13.8k & Framework \\
Fastify & 27.1k & Librairie \\
NestJS & 56.2k & Framework \\
\end{tabular}
\end{center}
\end{table}
\subsubsection{Express.js et Fastify}
Bien que le plus populaire, Express n'est pas à proprement parler un framework, mais plutôt une librairie. Il est donc nécessaire d'utiliser une multitude d'autres librairies pour gérer les middlewares, la validation, les sessions et autre. Pour des applications web complexes, cela revient à essayer d'assembler un puzzle en essayant de faire fonctionner toutes les pièces ensemble. C'est pourquoi il est souvent préférable d'utiliser un framework plus dogmatique et plus complet.
De plus, aucune convention n'est imposée par Express, ce qui peut rendre les applications plus difficiles à maintenir. Lorsque l'on revient sur un projet après plusieurs mois, il est souvent difficile de se remettre dans le contexte et de comprendre la logique de l'application. C'est pourquoi il est préférable d'utiliser un framework qui impose des conventions et une architecture.
De son côté, Fastify, bien que plus rapide et plus moderne que son concurrent Express, se trouve dans la même catégorie des frameworks très minimalistes. Le problème est donc le même que pour Express et trouver une alternative se révèle nécessaire.
\subsubsection{AdonisJS et NestJS}
Il reste donc les deux frameworks plus complets, à savoir AdonisJS et NestJS. AdonisJS promet d'inclure tout ce dont le développeur a besoin afin d'être le plus productif possible. Le framework est souvent comparé au framework PHP Laravel~\cite{laravel} sur cet aspect-là. Le souci principal d'AdonisJS est sa popularité. Malheureusement, il s'agit du framework le moins connu de la liste et cela se fait ressentir dans l'écosystème. Il est plus compliqué de trouver des librairies pour des cas d'utilisations spécifiques.
La dernière option est NestJS, qui est un framework de plus en plus populaire et très complet. Son architecture fait qu'il est très facilement extensible, notamment grâce à l'utilisation de modules et d'injection de dépendances. De plus, son implémentation des WebSockets est très complète et mise en avant contrairement à AdonisJS. NestJS utilise un système de Gateway~\cite{nestjs-gateway} permettant d'abstraire le concept de WebSockets facilement. Ce dernier aspect est un point très important pour la réalisation de cette application qui contient majoritairement des communications en temps réel. Cet élément a fait pencher la balance en faveur de NestJS, en plus de sa popularité.
Pour résumer la comparaison entre les deux frameworks, le tableau \ref{tab:nestjs-vs-adonisjs} présente les avantages et les inconvénients principaux de chacun.
\begin{table}[H]
\caption{Comparaison NestJS et AdonisJS}
\label{tab:nestjs-vs-adonisjs}
\makegapedcells
\setlist[itemize]{font=\color{black},
nosep,
leftmargin=*,
after=\vspace*{-\baselineskip}}
\setlength{\tabcolsep}{3pt}
\begin{tabularx}{\linewidth}{|>{\RaggedRight}p{16mm}|*{2}{I |}}
\hline
& \mcl{Avantages} & \mcl{Inconvénients} \\
\hline
AdonisJS
& \item[$\bullet$] Architecture plus structurée et clé en main
\item[$\bullet$] De nombreuses fonctionnalités incluses dans le framework de base
& \item[$\bullet$] Moins populaire donc moins de librairies externes disponibles
\item[$\bullet$] Gestion des WebSockets peu complète
\\
\hline
NestJS
& \item[$\bullet$] Très populaire donc beaucoup de librairies externes disponibles
\item[$\bullet$] Gestion des WebSockets complète
& \item[$\bullet$] Repose sur des librairies externes pour certaines fonctionnalités, il faut parfois configurer manuellement ces librairies
\item[$\bullet$] Écriture de code parfois plus verbeuse et moins facilement compréhensible
\\
\hline
\end{tabularx}
\end{table}
\subsubsection{Choix final}
Le backend de l'application sera donc réalisé avec \textbf{NestJS} pour les raisons évoquées précédemment.
\section{Communication en temps réel}
Pour la communication en temps réel sur le web, il existe principalement trois options. Les Server-Sent Events (SSE), les WebSockets et WebRTC.
\subsection{Server-Sent Events (SSE)}
Utiliser des Server-Sent Events (SSE) est une option possible et facile à mettre en place. Cependant, cette technologie est assez limitée et ne permet pas de faire de la communication bidirectionnelle. En effet, pour réaliser une communication du client au serveur, il faudrait utiliser en addition des appels HTTP classiques. Il est donc préférable d'utiliser une autre technologie afin d'uniformiser les communications. De plus, SSE supporte uniquement les communications textuelles. Il n'est donc pas possible de transférer des données binaires, ce qui peut être limitant.
\subsection{WebRTC}
WebRTC permet de réaliser une communication bidirectionnelle entre deux clients sans passer par un serveur une fois la connexion établie. Ce concept, appelé pair-à-pair ou peer to peer en anglais, est intéressant pour des projets dans lesquels les utilisateurs créent des salons privés entre connaissances afin de ne pas surcharger le serveur. Cependant dans le cas de \gls{beeplace}, il est nécessaire de passer par le serveur afin de pouvoir synchroniser l'état de la toile entre tous les utilisateurs. WebRTC n'est donc pas une option viable pour ce projet.
\subsection{WebSockets}
Pour finir, les WebSockets mettent à disposition tout ce qui est nécessaire pour réaliser une communication bidirectionnelle entre le client et le serveur. Les WebSockets utilisent un protocole de communication bas niveau, ce qui les rend très efficaces en utilisation de ressources. Cependant, ils ont quelques désavantages, comme le fait qu'ils ne sont pas supportés par tous les navigateurs ou qu'il soit nécessaire de gérer manuellement les reconnexions.
Heureusement, de nombreuses librairies sont disponibles dans l'écosystème \gls{javascript} et \gls{typescript} afin de rendre son utilisation la plus simple possible. La plus connue est Socket.IO~\cite{socket-io} et les trois fonctionnalités les plus intéressantes qu'elle offre sont les suivantes:
\begin{itemize}
\item Auto reconnexion: Socket.IO gère automatiquement les reconnexions en cas de perte de connexion.
\item Création de salons: il est possible de créer des salons afin de limiter les communications à un groupe d'utilisateurs. Cette fonctionnalité peut être utile si l'on souhaite, dans le futur, avoir plusieurs toiles simultanément sur l'application.
\item Long polling: Socket.IO utilise le HTTP long polling afin de gérer les communications si le navigateur ne supporte pas les WebSockets. Il s'agit de requêtes HTTP qui restent ouvertes jusqu'à ce que le serveur ait une réponse à envoyer.
\end{itemize}
\subsection{Choix final}
Le choix s'est donc porté sur les \textbf{WebSockets} et plus spécifiquement sur l'implémentation de la librairie \textbf{Socket.IO} pour la communication en temps réel.
\section{Stockage}
\subsection{Bases de données}
L'idée de séparer le stockage de l'état de la toile entre plusieurs méthodes de stockage est venue assez naturellement. En effet, la toile actuelle doit être accessible très rapidement afin d'éviter un temps de chargement initial trop important à l'utilisateur lorsque celui-ci arrive sur la page. De plus, il peut être intéressant de stocker des métadonnées en plus des pixels actuels de la toile. Ces métadonnées représentent l'historique des pixels avec la date et l'utilisateur qui l'a placé afin de pouvoir retracer l'évolution de la toile ainsi qu'en faire diverses analyses. Pour conclure, il est nécessaire d'avoir deux types de stockage pour l'application:
\begin{enumerate}
\item Un stockage rapide pour l'état actuel de la toile
\item Un stockage durable pour l'historique et les métadonnées
\end{enumerate}
\subsection{Stockage de l'état actuel de la toile}
Afin de garantir un accès rapide à l'état actuel de la toile, un cache doit être mis en place. Les deux options les plus fréquentes sont Redis~\cite{redis} ou simplement stocker une structure de données dans la mémoire de l'application. La deuxième option est plus simple à mettre en \oe{}uvre car elle ne demande aucun service tiers mais le cache devrait être recréé depuis le stockage durable à chaque redémarrage de l'application. Ce qui n'est pas le cas avec Redis qui est indépendant de l'application.
D'autres alternatives sont possibles, comme utiliser un autre service de cache comme Memcached~\cite{memcached}. Cependant, Redis reste le choix le plus populaire et le plus adapté au projet. Il a donc été choisi comme solution de stockage à accès rapide.
\subsection{Stockage durable}
Pour stocker l'historique de la pose des pixels, une base de données plus conventionnelle est nécessaire en supplément à Redis. Le choix s'est tourné sur PostgreSQL~\cite{postgresql}, un système de gestion de base de données SQL open source très populaire. Les besoins n'étant pas très complexes, de nombreuses autres possibilités auraient pu être utilisées comme SQLite~\cite{sqlite} ou MySQL~\cite{mysql}. La familiarité avec PostgreSQL a été le facteur déterminant dans le choix de cette base de données.
\subsection{Choix finaux}
La toile sera donc stockée dans un cache \textbf{Redis} pour y accéder rapidement et l'historique des pixels placés dans une base de données \textbf{PostgreSQL}.