<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jean-Noël</title>
    <description>The latest articles on DEV Community by Jean-Noël (@jnp95).</description>
    <link>https://dev.to/jnp95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F567562%2F11205636-d424-4098-bdf2-aae0f9c1651e.png</url>
      <title>DEV Community: Jean-Noël</title>
      <link>https://dev.to/jnp95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jnp95"/>
    <language>en</language>
    <item>
      <title>Comment bien signer ses programmes avec OpenSSL ?</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Tue, 07 Apr 2026 11:40:54 +0000</pubDate>
      <link>https://dev.to/younup/comment-bien-signer-ses-programmes-avec-openssl--3i2j</link>
      <guid>https://dev.to/younup/comment-bien-signer-ses-programmes-avec-openssl--3i2j</guid>
      <description>&lt;h2&gt;
  
  
  Pourquoi signer ?
&lt;/h2&gt;

&lt;p&gt;En 2025, 72% des entreprises à l'échelle mondiale ont constaté une intensification des risques de cyberattaque et 91% des experts en cybersécurité s'attendent à une augmentation des menaces augmentées à l'IA&lt;sup&gt;1&lt;/sup&gt; 😮. Et cela, notamment à partir de contenu falsifié.&lt;/p&gt;

&lt;p&gt;Face à cette menace, comment s'assurer que les données reçues à travers le réseau proviennent du bon expéditeur, et, surtout, contiennent des données authentiques plutôt qu'un programme malveillant ?&lt;/p&gt;

&lt;p&gt;Une des solutions à cela, évidemment, c'est la signature des fichiers !&lt;/p&gt;

&lt;p&gt;Aujourd'hui nous allons donc voir comment signer et vérifier la signature de ces fichiers avec &lt;a href="https://openssl-library.org/" rel="noopener noreferrer"&gt;OpenSSL&lt;/a&gt;, un outil en ligne de commande gratuit, universel (Windows, Linux, Mac OS), et largement éprouvé.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qu'est-ce que la signature, plus précisément ?
&lt;/h2&gt;

&lt;p&gt;On peut hésiter entre 4 techniques : signer, chiffrer, obfusquer ou checksum ? Même si elles sont complémentaires dans le domaine de la sécurité, elles n'ont pas les mêmes fonctions !&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chiffrement : &lt;strong&gt;protéger des données confidentielles&lt;/strong&gt; à l'aide d'une clé mathématique. Sans la clé, les données sont incompréhensibles.&lt;/li&gt;
&lt;li&gt;Obfuscation (néologisme pour "offuscation") : &lt;strong&gt;brouiller la lecture&lt;/strong&gt; humaine des données et les rendre plus difficiles à comprendre. En termes de sécurité, c'est une technique très (trop) minimaliste, mais néanmoins complémentaire. Exemple : "l'uglification"🧌 du code JavaScript pour le frontend.&lt;/li&gt;
&lt;li&gt;Checksum : &lt;strong&gt;vérifier l'intégrité&lt;/strong&gt; d'un fichier avec un hash calculé à partir de la somme des octets de ce dernier.&lt;/li&gt;
&lt;li&gt;Signature : &lt;strong&gt;authentifier la provenance ET vérifier l'intégrité&lt;/strong&gt; d'un fichier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous l'aurez remarqué : la signature est un procédé ayant une similarité avec les checksums, mais &lt;em&gt;encore plus&lt;/em&gt; sécurisé, bien qu'elle soit à peine plus complexe à utiliser !&lt;/p&gt;

&lt;p&gt;Grâce à une paire de clé privée/clé publique (algorithme asymétrique, donc) elle permet de bien séparer les rôles entre le signataire et les vérificateurs de la signature :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clé privée&lt;/strong&gt; : secret uniquement détenu par le signataire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clé publique&lt;/strong&gt; : distribuée à toutes les personnes désirant vérifier la signature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le processus de signature se fait donc en deux temps :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;La signature d'un fichier :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmay5c9qd74abdltgd17.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsmay5c9qd74abdltgd17.jpg" alt="Procédure de signature" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;La vérification de la signature par les personnes ayant reçu le fichier signé :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1nwe0qvav544th1kyi2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1nwe0qvav544th1kyi2.jpg" alt="Procédure de vérification de signature" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Ici le RSA est choisi comme algorithme de chiffrement avec un hash SHA-256. Bien entendu, il en existe d'autres dont certains seront mentionnés ci-après.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Signer avec OpenSSL
&lt;/h2&gt;

&lt;p&gt;Voyons ensemble comment signer un fichier avec OpenSSL dans un invité de commande Windows (outil que presque tout le monde doit avoir quelque part, donc 😛).&lt;/p&gt;

&lt;p&gt;Habituellement, une version d'OpenSSL est déjà présente dans l'emplacement de votre gestionnaire de version &lt;code&gt;git&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mais si la commande &lt;code&gt;where openssl&lt;/code&gt; ne vous renvoie rien, vous devrez l'installer manuellement : soit en installant &lt;code&gt;git&lt;/code&gt; (solution la plus simple finalement !), soit avec &lt;code&gt;MSYS2&lt;/code&gt; et &lt;code&gt;pacman&lt;/code&gt;, soit avec &lt;code&gt;winget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Une fois OpenSSL installé, commencez par créer une clé privée sécurisée par mot de passe :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;genrsa&lt;/span&gt; &lt;span class="na"&gt;-aes&lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="na"&gt;-out &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;.pem &lt;span class="m"&gt;4096&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notez le &lt;code&gt;-aes256&lt;/code&gt; qui indique qu'il faut utiliser l'algorithme AES-256 pour chiffrer la clé privée avec le mot de passe qui vous sera demandé lors de l'exécution. Cet algorithme de chiffrement est encore considéré comme très sécurisé, et le restera pendant encore un bon moment.&lt;br&gt;
Ainsi, même si la clé fuite par mégarde, elle restera "inutilisable".&lt;/p&gt;

&lt;p&gt;Votre fichier &lt;code&gt;private.pem&lt;/code&gt; généré doit globalement ressembler à ça :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJtTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQNNxqBgwqaJT4CYKe
[...]
TEJyVwOU/1g7ffTreVWOUx0nd4udoOoXaaT/YmSujBqQ2vpx1XzS+XpeowtwOAX+
jhnmeck3yxSGfSKhfKfGKkw00Y7ZHejOgmcgLkk/V2pISSqTywk20Bs=
-----END ENCRYPTED PRIVATE KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite, créez la clé publique associée, avec par exemple l'algorithme de chiffrement &lt;code&gt;RSA&lt;/code&gt; (pour plus de compatibilité) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;rsa&lt;/span&gt; &lt;span class="na"&gt;-in &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;.pem &lt;span class="na"&gt;-pubout -out &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;.pem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce qui donne un fichier &lt;code&gt;public.pem&lt;/code&gt; de cette forme-là :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAr4rP0humPcjod7dqwyMs
[...]
19auPMRnuCBF+dFw11PR6khBDQusw2sFYXgARgoX8nc1QECvI+hZlpm1ma+K7SjC
gco+E9Iy80pNZ5JhpAWrFNkCAwEAAQ==
-----END PUBLIC KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enfin, signez le fichier de votre choix avec la clé privée grâce aux mots clés &lt;code&gt;dgst&lt;/code&gt; (pour &lt;em&gt;digérer&lt;/em&gt; le fichier, miam 😋) et &lt;code&gt;-sign&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;dgst&lt;/span&gt; &lt;span class="na"&gt;-sha&lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="na"&gt;-sign &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;.pem &lt;span class="na"&gt;-out &lt;/span&gt;&lt;span class="kd"&gt;sign&lt;/span&gt;.sha256 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;file&lt;/span&gt;&lt;span class="na"&gt;-to-sign&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Il est possible de convertir la signature binaire en base64, parfois plus simple à échanger sur le réseau :&lt;/p&gt;


&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;base64&lt;/span&gt; &lt;span class="na"&gt;-in &lt;/span&gt;&lt;span class="kd"&gt;sign&lt;/span&gt;.sha256 &lt;span class="na"&gt;-out &lt;/span&gt;&lt;span class="kd"&gt;base64&lt;/span&gt;&lt;span class="na"&gt;-sign&lt;/span&gt;.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Vérifier une signature
&lt;/h2&gt;

&lt;p&gt;Maintenant, plaçons-nous du côté d'une personne souhaitant cette fois-ci vérifier la signature d'un fichier &lt;code&gt;program-signed.cpp&lt;/code&gt; fraîchement reçu.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;À ce stade, notez qu'il est possible de re-convertir la signature reçue en base64 vers du binaire :&lt;/p&gt;


&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;base64&lt;/span&gt; &lt;span class="na"&gt;-d -in &lt;/span&gt;&lt;span class="kd"&gt;base64&lt;/span&gt;&lt;span class="na"&gt;-sign&lt;/span&gt;.txt &lt;span class="na"&gt;-out &lt;/span&gt;&lt;span class="kd"&gt;sign&lt;/span&gt;.sha256
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;Tout d'abord cette personne doit se procurer la signature &lt;code&gt;sign.sha256&lt;/code&gt;, ainsi que la clé publique &lt;code&gt;public.pem&lt;/code&gt;, bien entendu.&lt;/p&gt;

&lt;p&gt;Elle peut alors vérifier la signature du fichier avec les mots clés &lt;code&gt;dgst&lt;/code&gt; et &lt;code&gt;-verify&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;dgst&lt;/span&gt; &lt;span class="na"&gt;-sha&lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="na"&gt;-verify &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;.pem &lt;span class="na"&gt;-signature &lt;/span&gt;&lt;span class="kd"&gt;sign&lt;/span&gt;.sha256 &lt;span class="kd"&gt;program&lt;/span&gt;&lt;span class="na"&gt;-signed&lt;/span&gt;.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Verified OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vous pouvez toujours vous amuser à changer juste un caractère à l'intérieur de ce fichier afin de volontairement le falsifier :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;openssl&lt;/span&gt; &lt;span class="kd"&gt;dgst&lt;/span&gt; &lt;span class="na"&gt;-sha&lt;/span&gt;&lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="na"&gt;-verify &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;.pem &lt;span class="na"&gt;-signature &lt;/span&gt;&lt;span class="kd"&gt;sign&lt;/span&gt;.sha256 &lt;span class="kd"&gt;FALSE&lt;/span&gt;&lt;span class="na"&gt;-program-signed&lt;/span&gt;.cpp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Verification failure
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La vérification d'authenticité échoue bien. Ouf, on a évité un logiciel potentiellement malveillant ! 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommandations en termes de sécurité
&lt;/h2&gt;

&lt;p&gt;En ce début d'année 2026, voici quelques recommandations importantes de sécurité vis-à-vis du processus de signature et de ses paramètres :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bien utiliser l'algorithme de hachage &lt;code&gt;SHA-256&lt;/code&gt; ou &lt;code&gt;SHA-512&lt;/code&gt; (famille des &lt;code&gt;SHA-2&lt;/code&gt;) plutôt que les 'SHA-1' et 'MD5' qui sont maintenant &lt;strong&gt;considérés comme compromis&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Pour le format de la clé, choisir une &lt;strong&gt;longueur minimum&lt;/strong&gt; de &lt;strong&gt;4096 bits&lt;/strong&gt; pour l'algorithme de chiffrement &lt;code&gt;RSA&lt;/code&gt;, afin d'anticiper la prochaine obsolescence du 2048 bits.&lt;/li&gt;
&lt;li&gt;Créer une &lt;strong&gt;API de signature sur un serveur&lt;/strong&gt; avec un accès restreint à une faible quantité de personnes et avec des accès temporaires (token et multifacteurs).&lt;/li&gt;
&lt;li&gt;La clé privée doit être chiffrée avec mot de passe, placée dans un &lt;strong&gt;coffre-fort numérique&lt;/strong&gt;, et n'être accessible que par le script de signature le temps de l'opération. Jamais par l'API (voire placer le script en question directement à l'intérieur du coffre-fort !). Exemple d'implémentation de l'API de signature :&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fff1rofd36jsrhl707i9e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fff1rofd36jsrhl707i9e.jpg" alt="Exemple d'implémentation d'API de signature" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Voilà, maintenant vous savez tout ce qu'il faut savoir pour sécuriser vos programmes ou packages, et protéger les utilisateurs qui recevront vos fichiers 👍.&lt;/p&gt;

&lt;p&gt;Sachez que le système de signature est très utilisé aujourd'hui dès qu'il y a un déploiement de programme inter-plateformes.&lt;br&gt;
Les gestionnaires de packages du monde UNIX (&lt;code&gt;apt-get&lt;/code&gt; ou &lt;code&gt;dnf&lt;/code&gt;) utilisent même une vérification d'identité en complément de la signature brute que nous venons de voir.&lt;/p&gt;

&lt;p&gt;Par ailleurs, nous avons ici utilisé l'algorithme de chiffrement &lt;code&gt;RSA&lt;/code&gt; largement répandu, mais il faut savoir qu'il en existe d'autres comme le &lt;a href="https://fr.wikipedia.org/wiki/EdDSA" rel="noopener noreferrer"&gt;EdDSA&lt;/a&gt; ou les &lt;a href="https://fr.wikipedia.org/wiki/Elliptic_curve_digital_signature_algorithm" rel="noopener noreferrer"&gt;ECDSA&lt;/a&gt; qui ont la particularité de présenter un niveau de sécurité similaire pour des clés beaucoup plus petites. Cela réduit la complexité algorithmique à l'exécution. Idéal donc pour des environnements limités comme l'embarqué !&lt;/p&gt;

&lt;p&gt;Un système de chiffrage post-quantique est même en préparation à l'heure où nous parlons : le &lt;code&gt;Post-quantum Cryptography (PQC)&lt;/code&gt; pour prévenir les attaques des ordinateurs quantiques.&lt;br&gt;
Très avant-gardiste, mais on n'est jamais trop prudents !&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;sup&gt;1&lt;/sup&gt; (sources : World Economic Forum 2025)&lt;/p&gt;

</description>
      <category>openssl</category>
      <category>security</category>
      <category>cra</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>Dioxus : des IHM Cross-Platform en Rust !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Tue, 17 Feb 2026 12:55:28 +0000</pubDate>
      <link>https://dev.to/younup/des-ihm-cross-platform-en-rust--28md</link>
      <guid>https://dev.to/younup/des-ihm-cross-platform-en-rust--28md</guid>
      <description>&lt;p&gt;Aujourd'hui je vous propose un petit diaporama pour découvrir un framework en Rust qui permet de développer efficacement des IHM Cross-Platform, et dont la syntaxe est largement inspirée de React : &lt;strong&gt;Dioxus&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Bonne lecture 🙂&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7yia4fcj8z2gya1phoj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy7yia4fcj8z2gya1phoj.png" alt="Philosophie cross-platform" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq216woy7os3km2g7n8wt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq216woy7os3km2g7n8wt.png" alt="Fonctions clés" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jdkg8r4y5a4a9vog6c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jdkg8r4y5a4a9vog6c5.png" alt="Syntaxe React" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdo05d0t2gs63rqjz9vu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdo05d0t2gs63rqjz9vu.png" alt="Appels du système" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6a48ciabup4fmdcl573.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6a48ciabup4fmdcl573.png" alt="Derrière le framework" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9fvpfubrebp0kf082oo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9fvpfubrebp0kf082oo.png" alt="Conclusion" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyouem6y9mg9xqp2rkxbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyouem6y9mg9xqp2rkxbk.png" alt="Page de signature" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>dioxus</category>
      <category>ihm</category>
      <category>react</category>
    </item>
    <item>
      <title>Alpha-bêta, l'algo qui a battu le champion du monde aux échecs</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Tue, 06 Jan 2026 12:38:36 +0000</pubDate>
      <link>https://dev.to/younup/alpha-beta-lalgo-qui-a-battu-le-champion-du-monde-aux-echecs-52hb</link>
      <guid>https://dev.to/younup/alpha-beta-lalgo-qui-a-battu-le-champion-du-monde-aux-echecs-52hb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Le 11 Mai 1997, pour la première fois dans l'histoire, un ordinateur, Deep Blue d'IBM, a battu le champion du monde d'échecs Garry Kasparov dans le cadre d'un tournoi. Cet évènement marqua un tournant décisif dans les débuts de l'intelligence artificielle et des avancées algorithmiques.&lt;/p&gt;

&lt;p&gt;Pourtant, il existe environ 10&lt;sup&gt;120&lt;/sup&gt; parties théoriques possibles aux échecs (à un pion près 😅), soit 10&lt;sup&gt;40&lt;/sup&gt; de plus que le nombre d'atomes qui constitue l'Univers observable !&lt;/p&gt;

&lt;p&gt;Comment un ordinateur avec des capacités matérielles beaucoup plus limitées que les supercalculateurs d'aujourd'hui a pu déterminer &lt;em&gt;en un temps réalisable&lt;/em&gt; les meilleurs coups menant à une victoire quasi certaine ?&lt;/p&gt;

&lt;p&gt;L'heure est venue de découvrir (ou redécouvrir ?) les algorithmes &lt;strong&gt;MinMax&lt;/strong&gt; – aussi appelé "minimax" – et l'&lt;strong&gt;élagage alpha-bêta&lt;/strong&gt;, bijoux d'aide à la prise de décision stratégique, même encore aujourd'hui !&lt;/p&gt;

&lt;h2&gt;
  
  
  L'algorithme de recherche MinMax
&lt;/h2&gt;

&lt;p&gt;Commençons par l'épine dorsale de la théorie des jeux : évaluer tous les coups possibles et les gains théoriques associés. Plaçons-nous justement dans le contexte d'une partie d'échecs entre un joueur humain et un ordinateur.&lt;/p&gt;

&lt;p&gt;On souhaite faire gagner l'ordinateur.&lt;/p&gt;

&lt;p&gt;Chaque mouvement d'une pièce de l'ordinateur ou du joueur humain conduit à une nouvelle situation de jeu. On peut modéliser ces situations de jeu à travers un arbre :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ra1cob2o93dsvbrjq95.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ra1cob2o93dsvbrjq95.png" alt="Arbre plateau échecs" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imaginons maintenant que la partie soit un peu plus avancée, et que ce soit à l'ordinateur de jouer.&lt;/p&gt;

&lt;p&gt;Afin de trouver &lt;em&gt;LE&lt;/em&gt; meilleur coup possible pour l'ordinateur, on commence par déterminer une profondeur de recherche maximum – ici 3 – puis on construit l'arbre des évolutions du jeu en fonction des coups joués par chaque adversaire :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ud707uf8vbg6220o53f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ud707uf8vbg6220o53f.png" alt="Arbre des possibilités MinMax" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Si vous n'êtes pas familier de la notation algébrique des coups aux échecs "Cc3, Pa3, ...", vous pouvez toujours aller &lt;a href="https://fr.wikipedia.org/wiki/Notation_alg%C3%A9brique" rel="noopener noreferrer"&gt;jeter un œil ici&lt;/a&gt;, mais ce n'est pas indispensable pour comprendre l'algorithme dans cet article.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chaque nœud est un choix&lt;/strong&gt; de coup parmi toutes les branches descendantes directes.&lt;/p&gt;

&lt;p&gt;On appelle &lt;strong&gt;nœuds Max&lt;/strong&gt; les décisions prises par l'ordinateur à son tour de jeu. En effet, étant donné que l'on souhaite le faire gagner, nous allons lui faire jouer les meilleurs coups (donc gain &lt;em&gt;Maximal&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A contrario&lt;/em&gt;, on dit que c'est un &lt;strong&gt;nœud Min&lt;/strong&gt; lorsque c'est au joueur humain de jouer, car on considère qu'il va jouer le coup le plus défavorable dans l'intérêt de l'ordinateur, et donc &lt;em&gt;Minimiser&lt;/em&gt; les gains de son adversaire.&lt;/p&gt;

&lt;p&gt;Arrivés à la profondeur maximale, on calcule &lt;strong&gt;le gain&lt;/strong&gt; qu'offre chaque situation de jeu atteinte.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Le gain peut-être estimé de différentes façons : gain matériel, positionnel, victoire par mat, égalité par pat, etc. Pour simplifier l'explication, nous modéliserons le gain par une simple valeur qui peut très bien représenter la valeur d'une prise. Par exemple, prendre une Tour (valeur 5) donnera un gain matériel supérieur à la prise d'un Pion (valeur 1).&lt;/p&gt;

&lt;p&gt;Notez également que seuls quelques coups seront traités dans notre exemple. Tous les autres coups possibles seront représentés par les flèches en pointillé et ne seront pas évalués dans l'algorithme (sinon imaginez la tête du schéma 😜).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En remontant tous les gains du bas vers le haut de l'arbre avec cette logique, on peut alors conclure que le meilleur coup à jouer pour l'ordinateur dans la situation de départ sera Cc3 👍 (et donc le cavalier en c3).&lt;/p&gt;

&lt;p&gt;Seulement voilà, comme on peut le constater, l'arbre peut rapidement devenir gigantesque, même en limitant la profondeur de recherche. Et les calculs de gains peuvent nécessiter des algorithmes lourds si on ne se limite pas à un gain matériel. Il faudrait trouver un moyen de réduire cette complexité d'exploration.&lt;/p&gt;

&lt;p&gt;Mais d'ailleurs, en y réfléchissant bien, est-il réellement nécessaire d'explorer absolument &lt;em&gt;tous&lt;/em&gt; les nœuds ? 🤔&lt;/p&gt;

&lt;h2&gt;
  
  
  L'optimisation par élagage alpha-bêta
&lt;/h2&gt;

&lt;p&gt;L'idée de cette optimisation est simple : si nous sommes capables d'affirmer avec certitude qu'une branche ne changera pas la valeur d'un nœud Min parent ou d'un nœud Max parent, il est alors inutile d'aller explorer cette branche enfant et de calculer ses gains. On peut alors l'&lt;strong&gt;élaguer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eh oui ! Quel intérêt d'envisager ce que donnerait la partie en prenant un Pion, si nous venons de trouver un autre coup qui permet de prendre une Dame ? (toujours dans une logique purement matérielle)&lt;/p&gt;

&lt;p&gt;Pour appliquer cette optimisation, on définit deux variables &lt;strong&gt;α&lt;/strong&gt; et &lt;strong&gt;β&lt;/strong&gt; dont les valeurs se transmettent de parent à enfant dans l'arbre :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;α contient la valeur maximale rencontrée par les nœuds Max, et ne sera &lt;strong&gt;mis à jour que sur des nœuds Max&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;β contient la valeur minimale rencontrée par les nœuds Min, et ne sera &lt;strong&gt;mis à jour que sur des nœuds Min&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On fixe la règle suivante : &lt;strong&gt;si dans un nœud α &amp;gt; β, alors on élague les branches enfants&lt;/strong&gt; non explorées sous ce nœud. Pas la peine d'aller plus loin ! 🫥&lt;/p&gt;

&lt;p&gt;Voyons concrètement ce que cela donne avec notre partie d'échec :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4hmeoxtp4mt3su8ea0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4hmeoxtp4mt3su8ea0z.png" alt="Élagage alpha-bêta 1" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En parcourant la branche de gauche (Cc3) on transmet α et β à chaque nœud avec leurs valeurs initiales respectives &lt;code&gt;-infini&lt;/code&gt; et &lt;code&gt;+infini&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On commence à évaluer les gains tout en bas à gauche. Puisque c'est un nœud Max, on &lt;strong&gt;met à jour α&lt;/strong&gt; qui vaut maintenant 5, car &lt;code&gt;5 &amp;gt; -infini&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On remonte le gain au nœud parent (le nœud Min 5). Puisque c'est un nœud Min, on &lt;strong&gt;met à jour β&lt;/strong&gt; qui vaut alors 5, car &lt;code&gt;5 &amp;lt; +infini&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On redescend les valeurs α et β dans le deuxième nœud enfant, et en déterminant seulement les gains 3 et 10, on se rend compte que &lt;strong&gt;α &amp;gt; β&lt;/strong&gt; (car &lt;code&gt;10 &amp;gt; 3 &amp;gt; -infini&lt;/code&gt; pour α). Alors on peut se permettre d'élaguer les autres branches à droite du nœud 10 sans même les regarder !&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;De la même manière, on remonte le gain 5 au premier nœud tout en haut en mettant à jour α, car c'est un nœud Max :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypqhbouhhziyfc4ltnqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypqhbouhhziyfc4ltnqa.png" alt="Élagage alpha-bêta 2" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et on réapplique la même logique sur les branches de droite !&lt;/p&gt;

&lt;p&gt;On remarque très vite que sur le nœud Min 1 de droite, &lt;strong&gt;α &amp;gt; β&lt;/strong&gt;. Bim ! On peut appliquer un deuxième élagage de toute la partie droite ! 😎&lt;/p&gt;

&lt;p&gt;Bilan ? Avec ces deux élagages, nous venons d'économiser 3 calculs de gains sur 11, si on ne compte que les coups visibles sur le schéma. Soit environ 30 % de complexité en moins sur l'algorithme MinMax initial !&lt;/p&gt;

&lt;h2&gt;
  
  
  Le mot de la fin
&lt;/h2&gt;

&lt;p&gt;Nous venons de comprendre comment un problème à &lt;em&gt;explosion combinatoire&lt;/em&gt; peut être simplifié jusqu'à une échelle devenue résoluble. Un des secrets de la victoire de l'ordinateur Deep Blue, donc.&lt;/p&gt;

&lt;p&gt;L'élagage alpha-bêta est d'ailleurs &lt;strong&gt;d'autant plus efficace qu'il y a de possibilités à chaque nœud&lt;/strong&gt;. Ce qui est une aubaine pour des modèles plus riches et plus ancrés dans la réalité.&lt;/p&gt;

&lt;p&gt;Depuis la victoire de Deep Blue, d'autres techniques d'élagage ont vu le jour dans d'autres domaines, comme la PVS (&lt;em&gt;Principal Variation Search&lt;/em&gt;) ou les élagages probabilistes, comme dans certaines IA d'aujourd'hui où l'approche &lt;em&gt;peut&lt;/em&gt; être plus heuristique.&lt;/p&gt;

&lt;p&gt;Outre les échecs, les algorithmes MinMax sont utilisés aujourd'hui dans bien d'autres cas d'application comme la prise de décision en robotique, des scénarios politiques, la gestion des risques financiers, etc.&lt;/p&gt;

&lt;p&gt;Tant que la meilleure décision est gardée à la fin… 😄&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxj6xt15wc0d4g84rr0br.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxj6xt15wc0d4g84rr0br.png" alt="Échec et mat" width="557" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>chess</category>
      <category>programming</category>
      <category>echecs</category>
    </item>
    <item>
      <title>Top 4 des astuces avec WSL !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Tue, 15 Jul 2025 08:53:51 +0000</pubDate>
      <link>https://dev.to/younup/top-4-des-astuces-avec-wsl--434h</link>
      <guid>https://dev.to/younup/top-4-des-astuces-avec-wsl--434h</guid>
      <description>&lt;h1&gt;
  
  
  Top 5 des astuces WSL
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Connaissez-vous le WSL ou &lt;strong&gt;Windows Subsystem for Linux&lt;/strong&gt;, cette fonction très pratique permettant d'exécuter un système Linux au sein de Windows, mais sans passer par une virtualisation lourde comme VirtualBox ?&lt;/p&gt;

&lt;p&gt;En tant que développeur, sous Windows, c'est l'outil idéal au quotidien. Il permet de travailler facilement et simultanément avec les environnements Windows et Linux pour différents besoins.&lt;/p&gt;

&lt;p&gt;La techno du WSL s'améliorant chaque année, il nous paraissait logique aujourd'hui de partager avec vous nos meilleures trouvailles, de la petite ligne de commande astucieuse jusqu'à la fonctionnalité cachée 🙂 (oui, il y en a !).&lt;/p&gt;

&lt;h2&gt;
  
  
  Astuce n°1 : Manager ses WSL en CLI
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Gérer de multiples instances
&lt;/h3&gt;

&lt;p&gt;Le programme WSL2 nous permet de gérer non pas une, mais plusieurs instances Linux, et ce, directement depuis l'invité de commande (ou PowerShell).&lt;/p&gt;

&lt;p&gt;Avant d'installer une distribution de Linux, nous pouvons commencer par afficher les distributions disponibles au téléchargement :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--online&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Voici&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;une&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;liste&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;des&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;distributions&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;valides&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;qui&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;peuvent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ê&lt;/span&gt;&lt;span class="nx"&gt;tre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="nx"&gt;es.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Installer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;en&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;utilisant&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'wsl.exe --install &amp;lt;Distro&amp;gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="w"&gt;                            &lt;/span&gt;&lt;span class="nx"&gt;FRIENDLY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;NAME&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt;                          &lt;/span&gt;&lt;span class="nx"&gt;Debian&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GNU/Linux&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;kali-linux&lt;/span&gt;&lt;span class="w"&gt;                      &lt;/span&gt;&lt;span class="nx"&gt;Kali&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Rolling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu-18.04&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;18.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LTS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu-20.04&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;20.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LTS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu-22.04&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;22.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LTS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu-24.04&lt;/span&gt;&lt;span class="w"&gt;                    &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;24.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LTS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;OracleLinux_7_9&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nx"&gt;Oracle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;7.9&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;OracleLinux_8_7&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nx"&gt;Oracle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;8.7&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;OracleLinux_9_1&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nx"&gt;Oracle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;9.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;openSUSE-Leap-15.6&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nx"&gt;openSUSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Leap&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;15.6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;SUSE-Linux-Enterprise-15-SP5&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;SUSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Enterprise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SP5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;SUSE-Linux-Enterprise-15-SP6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;SUSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Linux&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Enterprise&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SP6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;openSUSE-Tumbleweed&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;openSUSE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Tumbleweed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Avec la commande &lt;code&gt;wsl --install&lt;/code&gt;, la distribution installée par défaut sera normalement la dernière version LTS d'Ubuntu.&lt;br&gt;
Mais il est possible d'installer également une 2e distribution spécifique qui nous intéresse. Par exemple, la 22.04 LTS, plus ancienne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu-22.04&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On peut alors lister toutes nos versions installées avec un &lt;code&gt;wsl -l&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Ubuntu-22.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="nx"&gt;faut&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Ubuntu-24.04&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note : il faut bien se rappeler que chaque distribution est &lt;strong&gt;une instance bien différente&lt;/strong&gt; avec un espace de stockage différent :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;toutes les instances Linux peuvent accéder aux fichiers du lecteur &lt;code&gt;C:\&lt;/code&gt; avec un &lt;code&gt;cd /mnt/c/&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;mais depuis le PowerShell, on accède aux fichiers Linux via &lt;code&gt;cd \\wsl$\Ubuntu-24.04&lt;/code&gt; (ou &lt;code&gt;cd \\wsl$\Ubuntu-22.04&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maintenant que plusieurs instances WSL sont présentes sur Windows, il faudra penser à désigner la bonne à chaque commande &lt;code&gt;wsl&lt;/code&gt;, histoire de ne rien laisser au hasard.&lt;/p&gt;

&lt;p&gt;Pour cela, deux options s'offrent à nous :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;soit sélectionner l'instance par défaut avec un &lt;code&gt;wsl --set-default Ubuntu-24.04&lt;/code&gt;, qui sera implicitement choisie pour toutes les futures commandes &lt;code&gt;wsl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;soit indiquer l'instance utilisée uniquement pour la commande actuelle : &lt;code&gt;wsl -d Ubuntu-22.04&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exécuter des commandes dans WSL depuis Windows
&lt;/h3&gt;

&lt;p&gt;Avec l'argument &lt;code&gt;--exec&lt;/code&gt;, on peut exécuter une commande simple directement dans la machine Linux, mais sans quitter son PowerShell ! 😯&lt;br&gt;
Par exemple, avec cette commande qui nous permet d'obtenir la version du système :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/etc/os-release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce qui nous affiche :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PRETTY_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Ubuntu 22.04.3 LTS"&lt;/span&gt;
&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Ubuntu"&lt;/span&gt;
&lt;span class="nv"&gt;VERSION_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"22.04"&lt;/span&gt;
&lt;span class="nv"&gt;VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"22.04.3 LTS (Jammy Jellyfish)"&lt;/span&gt;
&lt;span class="nv"&gt;VERSION_CODENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;jammy
&lt;span class="nv"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ubuntu
&lt;span class="nv"&gt;ID_LIKE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;debian
&lt;span class="nv"&gt;HOME_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://www.ubuntu.com/"&lt;/span&gt;
&lt;span class="nv"&gt;SUPPORT_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://help.ubuntu.com/"&lt;/span&gt;
&lt;span class="nv"&gt;BUG_REPORT_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://bugs.launchpad.net/ubuntu/"&lt;/span&gt;
&lt;span class="nv"&gt;PRIVACY_POLICY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"&lt;/span&gt;
&lt;span class="nv"&gt;UBUNTU_CODENAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;jammy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et pour des commandes plus complexes, on peut exécuter un script bash présent sur le système de fichiers Linux :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;~/my_script.sh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;D'expérience, lancer des commandes avec &lt;code&gt;--exec&lt;/code&gt; permet de réduire les intermédiaires en agissant directement dans l'environnement voulu, ce qui est très pratique pour lancer des commandes dans une double virtualisation avec Docker Linux par exemple (voir section "Docker dans WSL").&lt;/p&gt;

&lt;h3&gt;
  
  
  Changer l'emplacement du disque virtuel WSL
&lt;/h3&gt;

&lt;p&gt;Il n'y a pas de magie : s'il y a un système de fichiers persistant dans les WSL, c'est qu'il y a un emplacement de stockage réservé quelque part !&lt;/p&gt;

&lt;p&gt;Les fichiers des environnements Linux sont en réalité stockés dans &lt;code&gt;C:\Users\&amp;lt;UserName&amp;gt;\AppData\Local\Packages\CanonicalGroupLimited.&amp;lt;Distrib&amp;gt;_&amp;lt;ID&amp;gt;\LocalState\&lt;/code&gt; sous forme de fichier &lt;code&gt;*.vhdx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pour rappel, un fichier &lt;code&gt;vhdx&lt;/code&gt; ou "Virtual Hard Disk V2" est un disque dur virtuel. Créé initialement par &lt;em&gt;Connectix&lt;/em&gt; puis repris par &lt;em&gt;Microsoft&lt;/em&gt;, il peut être utilisé avec les émulateurs VirtualBox, Parallels Desktop, ou Hyper-V. Il peut s'étendre jusqu'à 64 To (contre 2 To avec l'ancien format &lt;code&gt;vhd&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Pour en revenir à notre espace de stockage WSL : si on voulait stocker nos instances sur un autre disque physique situé sur le lecteur &lt;code&gt;D:&lt;/code&gt; ? (Au hasard, un bon SSD 🙃)&lt;/p&gt;

&lt;p&gt;Eh bien, c'est possible. Pour déplacer ce fameux fichier VHDX :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--shutdown&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--manage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Ubuntu-24.04&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--move&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;D:\My-WSLs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Astuce n°2 : Une IHM avec WSLg
&lt;/h2&gt;

&lt;p&gt;Nous avons appris comment installer et accéder à WSL en ligne de commande. Mais depuis le build 19044 de Windows 10 (et depuis le début de Windows 11), il est également possible d'exécuter des applications possédant une interface graphique. Ces applications sont alors intégrées dans notre environnement Windows (raccourci dans le menu démarrer, icône dans la barre des tâches durant l'exécution, accès au presse-papier, etc.)&lt;/p&gt;

&lt;p&gt;Sur une machine Windows 10 sur laquelle WSL était déjà installé, il est nécessaire de réaliser quelques vérifications avant de lancer des applications :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vérifier que la distribution se lance bien en mode WSL version 2
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  wsl &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="nt"&gt;--verbose&lt;/span&gt;

  NAME      STATE           VERSION
  &lt;span class="k"&gt;*&lt;/span&gt; Ubuntu    Running         2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si ce n'est pas le cas, la commande suivante y remédiera : &lt;code&gt;wsl --set-version Ubuntu 2&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;S'assurer que le noyau WSL soit à jour :
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;--update&lt;/span&gt;
wsl &lt;span class="nt"&gt;--shutdown&lt;/span&gt; &lt;span class="c"&gt;# Attention: cela équivaut a éteindre WSL, toute application éxécutée sera terminée"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Une fois cela fait, ou si la machine était suffisamment à jour, la manipulation est transparente :&lt;/p&gt;

&lt;p&gt;On commence par installer une application possédant une interface graphique (ex : GIMP) : &lt;code&gt;sudo apt install gimp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Il ne nous reste plus qu'à lancer l'application :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Soit par l'icône qui est apparue dans le menu démarrer (sous le dossier qui porte le nom de votre distribution)&lt;/li&gt;
&lt;li&gt;Soit lancer l'application via une CLI ouverte dans la distribution WSL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'application devrait maintenant s'afficher sur votre bureau.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv14a002nvc7mcxcno93s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv14a002nvc7mcxcno93s.png" alt="Gimp depuis le WSL" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Astuce n°3 : Docker dans WSL
&lt;/h2&gt;

&lt;p&gt;Docker Desktop est le moyen le plus courant pour installer Docker sous Windows. Cependant l'application Docker Desktop (pas le moteur d'exécution de conteneur docker lui-même) requiert maintenant une licence dans un cadre professionnel pour toute entreprise d'une certaine taille.&lt;/p&gt;

&lt;p&gt;Comment faire pour utiliser docker si nous n'avons pas besoin de Docker Desktop ?&lt;/p&gt;

&lt;p&gt;Utilisons WSL !&lt;/p&gt;

&lt;p&gt;Nous allons principalement suivre les instructions pour la distribution que nous avons installée, ici, Ubuntu : &lt;a href="https://docs.docker.com/engine/install/ubuntu/" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/ubuntu/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Toute commande fournie ci-dessous devra être exécutée dans le contexte de votre distribution WSL, sauf mention contraire.&lt;/p&gt;

&lt;p&gt;Commençons par nous assurer de commencer sur une base propre et de désinstaller tout paquet existant pouvant avoir un lien avec docker :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;pkg &lt;span class="k"&gt;in &lt;/span&gt;docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get remove &lt;span class="nv"&gt;$pkg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il est possible qu'aucun de ces paquets ne soient installés et qu'&lt;em&gt;apt&lt;/em&gt; vous en notifie.&lt;/p&gt;

&lt;p&gt;Configurons le dépôt &lt;em&gt;apt&lt;/em&gt; de docker (pour avoir des versions à jour) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add Docker's official GPG key:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.asc
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.asc

&lt;span class="c"&gt;# Add the repository to Apt sources:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;UBUNTU_CODENAME&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maintenant, installons docker et ses utilitaires :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nous pouvons maintenant utiliser docker, mais nous avons besoin de le faire en utilisant &lt;code&gt;sudo&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5714kpgvet02mo55yn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5714kpgvet02mo55yn5.png" alt="Logo Docker" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pour pouvoir l'utiliser de manière plus fluide, il nous faut ajouter notre utilisateur au groupe &lt;code&gt;docker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Commençons par le créer : &lt;code&gt;sudo groupadd docker&lt;/code&gt;.&lt;br&gt;
Puis, ajoutons ce groupe à notre utilisateur : &lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Forçons la déconnexion en lançant depuis un terminal windows (non WSL) : &lt;code&gt;wsl --shutdown&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Et nous pouvons maintenant utiliser : &lt;code&gt;docker run hello-world&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Astuce bonus : un alias pour utiliser docker directement depuis windows
&lt;/h3&gt;

&lt;p&gt;Sous PowerShell éditez votre fichier de profil :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;notepad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CurrentUserAllHosts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;et ajoutez-y ce contenu :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$args&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vous pourrez maintenant, pour vos prochaines sessions PowerShell appeler les commandes docker directement (ex : &lt;code&gt;docker ps&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Pour CMD, la mise en place d'alias est bien plus complexe et sort du cadre de cet article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Astuce n°4 : Passerelle USB avec Usbipd
&lt;/h2&gt;

&lt;p&gt;D'accord, il est possible d'échanger des fichiers entre l'hôte Windows et l'environnement Linux. Mais qu'en est-il des périphériques USB ?&lt;/p&gt;

&lt;p&gt;En vérité cette passerelle existe depuis un certain nombre d'années, mais aujourd'hui elle est grandement simplifiée avec l'outil en CLI &lt;a href="https://github.com/dorssel/usbipd-win" rel="noopener noreferrer"&gt;usbipd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Comme son nom l'indique, c'est un programme qui va &lt;strong&gt;ouvrir un canal d'échange TCP/IP&lt;/strong&gt; sur un réseau local à la machine, et rediriger les flux d'un périphérique USB vers et depuis ce canal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fousnqizt0turdjgiwx3j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fousnqizt0turdjgiwx3j.png" alt="IHM Usbip" width="732" height="953"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notez qu'il existe &lt;a href="https://gitlab.com/alelec/wsl-usb-gui" rel="noopener noreferrer"&gt;une version IHM&lt;/a&gt; de l'outil (capture d'écran ci-dessus), mais en tant que développeurs, nous allons nous concentrer sur la version CLI qui nous offre une interopérabilité plus intéressante, par exemple avec des scripts.&lt;/p&gt;

&lt;p&gt;Après avoir installé l'outil depuis &lt;a href="https://github.com/dorssel/usbipd-win/releases" rel="noopener noreferrer"&gt;le setup&lt;/a&gt; ou le package manager de Windows : &lt;code&gt;winget install usbipd&lt;/code&gt;, nous allons être capables de lister les devices disponibles :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;usbipd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Connected:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BUSID&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;VID:PID&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;DEVICE&lt;/span&gt;&lt;span class="w"&gt;                                                        &lt;/span&gt;&lt;span class="nx"&gt;STATE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;-6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;c45:6a17&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Integrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Webcam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Integrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Webcam&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;Not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;-10&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;8087&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0033&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Intel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Wireless&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Bluetooth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;R&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;                                &lt;/span&gt;&lt;span class="nx"&gt;Not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="nt"&gt;-6&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0424&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;284&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Hub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;P&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="nx"&gt;riph&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="nx"&gt;rique&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="nx"&gt;entr&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;USB&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;Not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;shared&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="nt"&gt;-3&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;bda:8153&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Realtek&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;USB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GbE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Family&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#2                          Not shared&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sur cette liste, on notera le &lt;strong&gt;BUSID&lt;/strong&gt; qui nous permettra de désigner un périphérique spécifique à partager, ainsi que le &lt;strong&gt;STATE&lt;/strong&gt; qui nous indique l'état de partage à proprement parler.&lt;/p&gt;

&lt;p&gt;En ouvrant un PowerShell administrateur, on saisit la commande &lt;code&gt;bind&lt;/code&gt; pour ouvrir un canal de partage, par exemple sur la webcam :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;usbipd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2-6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;À ce stade, si on liste à nouveaux les périphériques, on doit voir apparaître le statut &lt;code&gt;Shared&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Connected:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;BUSID&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;VID:PID&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;DEVICE&lt;/span&gt;&lt;span class="w"&gt;                                                        &lt;/span&gt;&lt;span class="nx"&gt;STATE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nt"&gt;-6&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;c45:6a17&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;Integrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Webcam&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Integrated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Webcam&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;Shared&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il ne nous reste plus qu'à assigner le périphérique à une instance WSL :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;usbipd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--busid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2-6&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;usbipd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;info:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WSL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;distribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Ubuntu-22.04'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;attach&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;available&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;WSL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;distributions.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;usbipd:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;info:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;IP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;172.25.224.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;host.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le device passe alors dans l'état &lt;code&gt;Attached&lt;/code&gt; côté Windows, et apparaît dans le contexte Linux :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsusb

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID 0c45:6a17 Microdia Integrated_Webcam_FHD
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le tour est joué ! 🙂&lt;/p&gt;

&lt;h2&gt;
  
  
  Le mot de la fin
&lt;/h2&gt;

&lt;p&gt;Nous avons pu vous montrer plusieurs astuces assez étonnantes autour du WSL qui, en parallèle, continue d'évoluer, permettant ainsi de se passer d'outils de virtualisation lourde comme VirtualBox.&lt;/p&gt;

&lt;p&gt;Si, comme nous, vous aimez en apprendre toujours plus, il reste encore d'autres sujets très intéressants à explorer du côté des IHM de configuration, de la nouvelle distribution Red Hat &lt;a href="https://www.redhat.com/fr/blog/bringing-red-hat-enterprise-linux-windows-subsystem-linux" rel="noopener noreferrer"&gt;RHEL&lt;/a&gt;, ou encore de l'import/export des WSL &lt;a href="https://learn.microsoft.com/fr-fr/windows/wsl/basic-commands#export-a-distribution" rel="noopener noreferrer"&gt;sous forme de fichier&lt;/a&gt;, etc.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cet article a été coécrit avec Antoine-Ali. N'hésitez pas à aller voir également ses &lt;a href="https://www.younup.fr/blog?category=antoine-ali" rel="noopener noreferrer"&gt;publications&lt;/a&gt; !&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>microsoft</category>
      <category>devops</category>
      <category>cmd</category>
    </item>
    <item>
      <title>AVIF : le nouveau format d'image Next-Gen !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Mon, 26 May 2025 12:12:21 +0000</pubDate>
      <link>https://dev.to/younup/avif-le-nouveau-format-dimage-next-gen--5ee2</link>
      <guid>https://dev.to/younup/avif-le-nouveau-format-dimage-next-gen--5ee2</guid>
      <description>&lt;p&gt;Aujourd'hui je vous propose un article rapide sous forme de mini-diaporama, sur ce nouveau format d'image révolutionnaire !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyms3vkhl0jb4awfdebol.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyms3vkhl0jb4awfdebol.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi020ujprxbbbql7v84e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi020ujprxbbbql7v84e.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9nucfb6pw86fu3z41fb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9nucfb6pw86fu3z41fb.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykdfpozqpwn7xg5v6ixq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykdfpozqpwn7xg5v6ixq.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cmmbr55duk7jbm8argk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cmmbr55duk7jbm8argk.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
Le lien du comparateur en question &lt;a href="https://shorturl.at/jzhB4" rel="noopener noreferrer"&gt;ICI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86dyptpcoxfd22caheso.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86dyptpcoxfd22caheso.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqm91h1zs1r5gj5feka33.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqm91h1zs1r5gj5feka33.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8ownnyhxj5o2635wq7p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8ownnyhxj5o2635wq7p.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hwbg2ma8531g86948fi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hwbg2ma8531g86948fi.jpg" alt="Image description" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>avif</category>
      <category>webdev</category>
      <category>picture</category>
      <category>av1</category>
    </item>
    <item>
      <title>Codez votre PPT avec Slidev !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Thu, 06 Mar 2025 14:40:47 +0000</pubDate>
      <link>https://dev.to/younup/codez-votre-ppt-avec-slidev--32gg</link>
      <guid>https://dev.to/younup/codez-votre-ppt-avec-slidev--32gg</guid>
      <description>&lt;h1&gt;
  
  
  Codez votre PPT avec Slidev
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Vous qui avez déjà peaufiné des dizaines de présentations PowerPoint, que ce soit pour une soutenance, un support de formation, des solutions techniques, ou d'adorables petits exposés scolaires 😇, savez-vous qu'il existe des alternatives logicielles à PowerPoint ou Keynote mais &lt;strong&gt;ultra orientées dev&lt;/strong&gt; ?&lt;/p&gt;

&lt;p&gt;Il existe en réalité plusieurs projets comme &lt;a href="https://revealjs.com/" rel="noopener noreferrer"&gt;Reveal.js&lt;/a&gt; ou &lt;a href="https://marp.app/" rel="noopener noreferrer"&gt;Marp&lt;/a&gt; qui proposent concrètement d'utiliser un langage de programmation ou &lt;em&gt;équivalent&lt;/em&gt; pour préparer un diaporama avec du contenu multimédia et des animations.&lt;br&gt;
Mais aujourd'hui je vous invite à en découvrir un en particulier : &lt;a href="https://sli.dev/" rel="noopener noreferrer"&gt;Slidev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Slidev est un jeune projet Node.js Open Source et un peu "fou". Essentiellement écrit en TypeScript, il est doté d'une interface graphique en Vue.js.&lt;br&gt;
Il propose de &lt;strong&gt;coder ses diapos à l'aide de Markdown enrichi&lt;/strong&gt;, un format assez simple et déjà bien connu de tous.&lt;/p&gt;

&lt;p&gt;À l'heure où j'écris ces lignes, Slidev est encore en version 0.49 – donc très expérimental – mais vous allez voir à travers ce tuto qu'il présente déjà quelques fonctionnalités qui valent vraiment le détour !&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note : pour ceux qui sont pressés, vous pouvez directement tester Slidev &lt;a href="https://sli.dev/new" rel="noopener noreferrer"&gt;ici&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Pourquoi diable s'embêter à coder un diaporama ?
&lt;/h2&gt;

&lt;p&gt;On pourrait croire qu'un pseudo langage comme le Markdown nous ferait économiser du temps d'écriture, comparé aux déplacements sinueux de la souris dans un logiciel classique (PowerPoint, Keynote, …).&lt;/p&gt;

&lt;p&gt;Oubliez ça.&lt;/p&gt;

&lt;p&gt;Bien que l'on puisse gagner un peu de temps lorsqu'on se contente d'un &lt;em&gt;layout&lt;/em&gt; très simple (car Slidev positionne automatiquement les éléments sur chaque diapositive avec le layout et le thème choisis), il y a une autre &lt;em&gt;vraie&lt;/em&gt; bonne raison : les &lt;strong&gt;possibilités&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Les possibilités, c'est de pouvoir faire des présentations ultra techniques avec &lt;strong&gt;une meilleure intégration de code&lt;/strong&gt; (une intégration de code tout court, en fait 😄). Vous pouvez par exemple montrer des extraits de code avec coloration syntaxique, créer des animations avancées sur des parties précises, intégrer des formules LaTeX, coder directement en &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt; ou même ajouter des fonctionnalités dynamiques comme le "live coding" !&lt;/p&gt;

&lt;p&gt;Enfin, une autre bonne raison est de pouvoir mettre en place un système de synchronisation entre &lt;strong&gt;un thème de référence&lt;/strong&gt; et celui appliqué sur le diaporama. Ainsi, votre diaporama suivra automatiquement les évolutions de la charte graphique de l'entreprise !&lt;/p&gt;

&lt;p&gt;Explorons maintenant ensemble toutes ces possibilités offertes par cette étonnante lib.&lt;/p&gt;
&lt;h2&gt;
  
  
  Codons un diaporama
&lt;/h2&gt;
&lt;h3&gt;
  
  
  La base
&lt;/h3&gt;

&lt;p&gt;Commencez par initialiser un projet Node.js en suivant les instructions &lt;a href="https://sli.dev/guide/#create-locally" rel="noopener noreferrer"&gt;ici&lt;/a&gt; et créez un fichier d'entrée &lt;code&gt;slides.md&lt;/code&gt; à la racine.&lt;/p&gt;

&lt;p&gt;Placez une image d'arrière-plan dans un répertoire &lt;code&gt;imgs&lt;/code&gt;, et ajoutez alors ce contenu minimal dans votre fichier &lt;code&gt;slides.md&lt;/code&gt; (pensez à adapter le chemin de votre image) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./imgs/background.webp&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Le titre de ma première diapo&lt;/span&gt;

Créez des diapos tech et dynamiques !

&amp;lt;!--
Quelques notes réservées au présentateur pour la première diapo.
--&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lancez la commande &lt;code&gt;npm exec slidev -- --port 3030 "slides.md"&lt;/code&gt;.&lt;br&gt;
Vous aurez alors accès à 3 espaces principaux :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;une interface web sur &lt;code&gt;http://localhost:3030/&lt;/code&gt; pour montrer le diaporama à votre public (et avec une &lt;strong&gt;vignette caméra&lt;/strong&gt; déplaçable, trop cool !) :&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd1r1qexflktb7uk1vly.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkd1r1qexflktb7uk1vly.jpg" alt="Slidev présentation avec caméra" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;une page &lt;code&gt;localhost:3030/presenter&lt;/code&gt; pour contrôler votre diaporama en mode présentateur :&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0ybj9sd7m8uytpd0ipl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0ybj9sd7m8uytpd0ipl.jpg" alt="Slidev : mode présentateur" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;et une dernière page &lt;code&gt;localhost:3030/overview&lt;/code&gt; histoire d'avoir un aperçu global de toutes vos diapos, même si vous préfèrerez sûrement l'affichage en grille depuis le mode présentateur (icône "Show slide overview").&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vous pouvez également installer &lt;a href="https://marketplace.visualstudio.com/items?itemName=antfu.slidev" rel="noopener noreferrer"&gt;une extension pour VS Code&lt;/a&gt; qui ajoute l'autocomplétion, vous permet de vous déplacer directement à une section depuis un titre, de réorganiser l'ordre des diapos, ou même d'avoir un aperçu en temps réel dans une vignette :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnbz6za5nc92yahimfcj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpnbz6za5nc92yahimfcj.jpg" alt="Intégration de Slidev dans VS Code" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et tous ces espaces sont globalement synchronisés entre eux !&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Attention&lt;/strong&gt; : si vous utilisez Prettier, il faudra &lt;a href="https://sli.dev/features/prettier-plugin" rel="noopener noreferrer"&gt;le configurer&lt;/a&gt; pour éviter les conflits avec ce Markdown un peu spécial !&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Configurez le thème et les layouts
&lt;/h3&gt;

&lt;p&gt;Commençons à configurer les slides de notre diaporama.&lt;/p&gt;

&lt;p&gt;Il faut savoir que Slidev construit chaque diaporama en composant le contenu des fichiers &lt;code&gt;.md&lt;/code&gt; avec &lt;strong&gt;un thème graphique&lt;/strong&gt; et un ensemble de &lt;strong&gt;layouts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tout d'abord je vous propose de choisir un thème dans la &lt;a href="https://sli.dev/resources/theme-gallery" rel="noopener noreferrer"&gt;galerie officielle&lt;/a&gt;.&lt;br&gt;
Vous pouvez le spécifier une (et une seule) fois dans ce que l'on appelle la partie &lt;code&gt;headmatter&lt;/code&gt;, tout en haut du fichier Markdown :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;transition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;slide-left&lt;/span&gt;
&lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./imgs/background.webp&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Mon premier diaporama&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Le titre de ma première diapo&lt;/span&gt;

Créez des diapos tech et dynamiques !
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Toutes les polices, tailles, couleurs et images par défaut seront automatiquement configurées !&lt;/p&gt;

&lt;p&gt;Notez bien les &lt;code&gt;---&lt;/code&gt; avant et après l'en-tête, car ils délimitent la partie "en-tête" de la partie "contenu" pour chaque slide.&lt;/p&gt;

&lt;p&gt;Au passage, on en profite également pour configurer les animations entre chaque diapo : &lt;code&gt;transition: slide-left&lt;/code&gt; qui va faire glisser la diapo suivante de la droite vers la gauche. Sobre, mais efficace.&lt;/p&gt;

&lt;p&gt;Ensuite, créez une nouvelle slide et ajoutez un layout &lt;code&gt;image-right&lt;/code&gt;, dans la partie que l'on appelle alors &lt;code&gt;frontmatter&lt;/code&gt; (tout un vocabulaire 😌).&lt;br&gt;
Ce layout vous permettra d'ajouter le chemin d'une image, qui peut tout à fait être une URL d'ailleurs !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Le titre de ma première diapo&lt;/span&gt;

Créez des diapos tech et dynamiques !
&lt;span class="p"&gt;
---&lt;/span&gt;
layout: image-right
&lt;span class="gh"&gt;image: https://domain.org/imgs/background.webp
---
&lt;/span&gt;
Ici on ajoute du contenu uniquement sur la partie gauche de la diapo.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mygvg99w1d9vzhpj1xc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mygvg99w1d9vzhpj1xc.jpg" alt="Diapo avec une image à droite" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il &lt;a href="https://sli.dev/builtin/layouts" rel="noopener noreferrer"&gt;existe&lt;/a&gt; également les layouts &lt;code&gt;center&lt;/code&gt;, &lt;code&gt;full&lt;/code&gt;, &lt;code&gt;fact&lt;/code&gt;, &lt;code&gt;iframe-right&lt;/code&gt;, &lt;code&gt;quote&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Il ne peut y avoir qu'&lt;strong&gt;un seul thème par diaporama&lt;/strong&gt;, mais chaque slide peut avoir un layout différent.&lt;/p&gt;

&lt;p&gt;De manière générale, les layouts disponibles par défaut restent très simples et la plupart du temps, ils sont suffisants.&lt;br&gt;
Si toutefois vous cherchez une disposition personnalisée, il faudra soit aller chercher un plugin existant, soit écrire quelques lignes de code (cf. &lt;a href="https://sli.dev/guide/write-layout" rel="noopener noreferrer"&gt;doc officielle&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Maintenant, entrons dans le vif du sujet et expérimentons des contenus riches autour de code et de schémas qu'un logiciel de diaporama classique ne serait pas en mesure de gérer !&lt;/p&gt;
&lt;h3&gt;
  
  
  Présentez du code avec classe
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Extraits de code et animations
&lt;/h4&gt;

&lt;p&gt;Dans la diapo que vous venez de créer, commencez par ajouter un extrait de code de la même façon qu'en Markdown :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91s0s4j712xr6njsukhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91s0s4j712xr6njsukhx.png" alt="Extrait de code Hello World en markdown" width="756" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbtgovfwlhmawdh7kqvp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbtgovfwlhmawdh7kqvp.jpg" alt="Rendu de la slide 2 Hello World" width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On obtient une présentation basique du code avec coloration syntaxique et le texte sélectionnable.&lt;/p&gt;

&lt;p&gt;Mais avec le Markdown enrichi que nous propose Slidev, nous allons pouvoir ajouter des options très intéressantes, comme l'affichage du numéro des lignes et la &lt;strong&gt;surbrillance successive&lt;/strong&gt; des lignes 5, 1 puis 2 au clic de souris (ou les flèches du clavier), comme si l'on simulait un débogage !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few1vbdje7prsonlc7g59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Few1vbdje7prsonlc7g59.png" alt="Animation du code en Markdown" width="475" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4julkqobe3lzcouydpc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4julkqobe3lzcouydpc.gif" alt="Rendu de l'animation de code" width="433" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et si on allait un peu plus loin dans les animations ?&lt;/p&gt;

&lt;p&gt;Imaginez que vous souhaitiez présenter une refactorisation ou tout simplement un JSON, par exemple, qui évoluerait plusieurs fois, successivement.&lt;br&gt;
Eh bien, vous allez pouvoir animer ce code automatiquement avec la feature &lt;code&gt;shiki-magic-move&lt;/code&gt; pour mettre en évidence ces évolutions :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07xt5ru85aujdo5022vk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F07xt5ru85aujdo5022vk.png" alt="Exemple code Shiki-magic-move" width="348" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et le rendu slidev, toujours animé au clic de souris ou flèches clavier :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fski1tr0nk3geb8s6sk3g.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fski1tr0nk3geb8s6sk3g.gif" alt="Rendu Slidev avec Shiki-magic-move" width="607" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Magique ! 😲&lt;/p&gt;
&lt;h4&gt;
  
  
  Live Coding
&lt;/h4&gt;

&lt;p&gt;Nous venons de voir la présentation de code statique. Maintenant nous allons construire une slide qui va nous permettre de réaliser &lt;strong&gt;une démonstration de code en direct&lt;/strong&gt;, et sans quitter la présentation.&lt;/p&gt;

&lt;p&gt;Ajoutez une nouvelle slide avec un layout de type &lt;code&gt;full&lt;/code&gt; pour un affichage confortable. Puis ajoutez la suite de Fibonacci dans un extrait de code avec la mention &lt;code&gt;{monaco-run}&lt;/code&gt; pour activer l'éditeur.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhodmzku04vdt4ahpnsfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhodmzku04vdt4ahpnsfd.png" alt="Code Markdown pour du live coding" width="605" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L'éditeur Monaco intégré va alors nous permettre de modifier le code en direct avec le linter, l'autocomplétion, et même l'exécution en temps réel !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi2dmjm5nkusekz4uspa.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foi2dmjm5nkusekz4uspa.gif" alt="Live coding dans Slidev" width="1055" height="477"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Construisez des schémas avancés
&lt;/h3&gt;

&lt;p&gt;Slidev prend en charge les graphes &lt;a href="https://plantuml.com/" rel="noopener noreferrer"&gt;PlantUML&lt;/a&gt; et &lt;a href="https://mermaid.js.org/" rel="noopener noreferrer"&gt;Mermaid&lt;/a&gt;. Si vous ne connaissez pas encore ce dernier, je vous conseille d'aller faire un tour sur &lt;a href="https://www.younup.fr/blog/graphes-avec-mermaid" rel="noopener noreferrer"&gt;notre article ici&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mermaid offre beaucoup plus de possibilités qu'un système de drag-n-drop de formes qu'on trouverait dans un logiciel classique : diagrammes de séquence, classes, mindmap, git graph…&lt;/p&gt;

&lt;p&gt;Ici je vous propose de partir sur un diagramme de Gantt, car c'est typiquement le genre de diagramme qui pourrait décourager à dessiner dans un soft classique.&lt;/p&gt;

&lt;p&gt;Créez une nouvelle slide intitulée "Organisation du projet", avec le layout &lt;code&gt;default&lt;/code&gt; qui, ici, convient à un diagramme qui a tendance à s'étendre sur la longueur. Ensuite, vous allez pouvoir ajouter directement un extrait de code de type &lt;code&gt;mermaid&lt;/code&gt; pour dessiner un &lt;a href="https://mermaid.js.org/syntax/gantt.html" rel="noopener noreferrer"&gt;diagramme de Gantt&lt;/a&gt;, par exemple, sur l'organisation des développements d'une appli web entre une équipe UI/UX, une front, et une back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F447zj2w1xfi8pkebt29q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F447zj2w1xfi8pkebt29q.png" alt="Gantt avec mermaid" width="487" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ce qui nous génère un magnifique diagramme de Gantt dans notre diapo !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2eo3k3lffg7n7votnuka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2eo3k3lffg7n7votnuka.png" alt="Rendu slidev du diagramme de Gantt avec Mermaid" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comme vous pouvez le constater, la syntaxe nécessite quand même une &lt;em&gt;certaine&lt;/em&gt; prise en main. Mais avec un peu d'expérience, l'écriture, et surtout, la mise à jour du diagramme dans le diaporama deviennent très intéressantes !&lt;/p&gt;
&lt;h3&gt;
  
  
  Multipliez les possibilités avec des composants externes
&lt;/h3&gt;

&lt;p&gt;Dans cette partie nous allons pousser l'intégration d'éléments externes en combinant une scène 3D du système solaire avec un &lt;code&gt;Component&lt;/code&gt; Vue.js dans une seule et même diapositive.&lt;/p&gt;

&lt;p&gt;Tout d'abord, commençons par créer une diapo très simple, qui va juste se contenter d'afficher notre composant Vue.js :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Contenus externes&lt;/span&gt;
&lt;span class="na"&gt;layout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;full&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Un composant Vue.js dynamique&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;PlanetTeleporter&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensuite, créez un fichier &lt;code&gt;components/PlanetTeleporter.vue&lt;/code&gt; à la racine du projet.&lt;/p&gt;

&lt;p&gt;Dans ce nouveau composant, nous allons construire :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;un &lt;code&gt;iframe&lt;/code&gt; ouvert sur une page web intégrant un système solaire en 3D (basé sur &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;Three.js&lt;/a&gt;) ;&lt;/li&gt;
&lt;li&gt;et un bouton superposé qui va légèrement modifier l'URL de la scène 3D pour se téléporter directement à la planète Saturne.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://eyes.nasa.gov/apps/solar-system/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toSaturn&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://eyes.nasa.gov/apps/solar-system/#/saturn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"url"&lt;/span&gt; &lt;span class="na"&gt;title=&lt;/span&gt;&lt;span class="s"&gt;"Page externe système solaire"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toSaturn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Vers Saturne !&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;section&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;85%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;380px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mono&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;iframe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si vous regardez alors le rendu :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F625af84e0d2f6fdd03734ac8%2F67af46bd144c794196470812_67af43840afd3c34406a2637_slidev-to-saturn-ezgif.com-resize.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.prod.website-files.com%2F625af84e0d2f6fdd03734ac8%2F67af46bd144c794196470812_67af43840afd3c34406a2637_slidev-to-saturn-ezgif.com-resize.webp" alt="Rendu slidev du système solaire dynamique" width="640" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;… et toujours sans quitter votre slide !&lt;/p&gt;

&lt;p&gt;Imaginez maintenant tout ce que vous allez pouvoir faire en intégrant des composants dynamiques encore plus avancés, ou en manipulant directement du SVG pour une qualité graphique toujours nickel ! 🤩&lt;/p&gt;

&lt;p&gt;Maintenant, vous avez toutes les clés en main pour créer des diaporamas techniques complètement dingues !&lt;/p&gt;

&lt;p&gt;Et si vous cherchez encore de l'inspiration, je vous invite à jeter un œil à &lt;a href="https://sli.dev/resources/showcases" rel="noopener noreferrer"&gt;la galerie d'exemples&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;À travers ce tuto, nous avons pu explorer de nombreuses fonctionnalités qu'offre la lib Slidev, surtout d'un point de vue &lt;strong&gt;intégration de code dynamique, de schémas et contenus externes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Avec du recul, on constate également que Slidev est un projet encore très récent, qui manque peut-être encore un peu de stabilité et d'uniformité dans la syntaxe par rapport à d'autres projets comme &lt;a href="https://revealjs.com/" rel="noopener noreferrer"&gt;Reveal.js&lt;/a&gt;.&lt;br&gt;
Par ailleurs, dès que l'on souhaite une disposition ou une animation particulière, la tâche peut rapidement s'annoncer plus ardue que prévu et nécessiter un investissement assez important. Mais au bout du compte, le jeu en vaut peut-être la chandelle ?&lt;/p&gt;

&lt;p&gt;Et comme je le disais au début de ce tuto, ce qui nous intéresse surtout ici, ce sont les possibilités !&lt;/p&gt;

</description>
      <category>slidev</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>vue</category>
    </item>
    <item>
      <title>J'ai essayé de passer à Vue.js depuis React.js</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Mon, 04 Nov 2024 09:59:28 +0000</pubDate>
      <link>https://dev.to/younup/jai-essaye-de-passer-a-vuejs-depuis-reactjs-2e88</link>
      <guid>https://dev.to/younup/jai-essaye-de-passer-a-vuejs-depuis-reactjs-2e88</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Il y a quelques années, comme beaucoup d'autres, j'étais "hypé" par l'arrivée des &lt;a href="https://legacy.reactjs.org/blog/2019/02/06/react-v16.8.0.html" rel="noopener noreferrer"&gt;hooks&lt;/a&gt; et les composants fonctionnels de la librairie frontend React.js. Ils proposaient une toute nouvelle manière de développer en écrivant beaucoup moins de code qu'avec les &lt;code&gt;class Components&lt;/code&gt;. J'ai véritablement accroché, et pour un bon moment.&lt;/p&gt;

&lt;p&gt;Aujourd'hui, j'ai dû opter pour le framework Vue.js afin de répondre aux besoins d'un tout nouveau projet client. Et étant arrivé au bout de ce projet, je me suis dit que c'était l'occasion de vous proposer &lt;strong&gt;un retour d'expérience&lt;/strong&gt; en tant que nouvel utilisateur de ce framework !&lt;/p&gt;

&lt;p&gt;Alors, est-ce que cette montée en compétence a été à la hauteur de la notoriété de Vue.js ?&lt;br&gt;
Est-ce qu'il vaut mieux, aujourd'hui, développer du frontend en Vue qu'en React ?&lt;/p&gt;

&lt;p&gt;C'est ce que nous allons voir !&lt;/p&gt;
&lt;h2&gt;
  
  
  Démarrage du projet
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Boilerplate
&lt;/h3&gt;

&lt;p&gt;Qui dit démarrage de projet, dit recherche d'un bon &lt;em&gt;boilerplate&lt;/em&gt; pour nous épargner des heures, voire des jours de configuration laborieuse !&lt;br&gt;
Sans avoir besoin de chercher très loin, la commande &lt;code&gt;npm create vue@latest&lt;/code&gt; répond largement à mes besoins :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✔ Project name: … myproject-vue
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router &lt;span class="k"&gt;for &lt;/span&gt;Single Page Application development? … No / Yes
✔ Add Pinia &lt;span class="k"&gt;for &lt;/span&gt;state management? … No / Yes
✔ Add Vitest &lt;span class="k"&gt;for &lt;/span&gt;Unit Testing? … No / Yes
✔ Add an End-to-End Testing Solution? › Playwright
✔ Add ESLint &lt;span class="k"&gt;for &lt;/span&gt;code quality? … No / Yes
✔ Add Prettier &lt;span class="k"&gt;for &lt;/span&gt;code formatting? … No / Yes
? Add Vue DevTools 7 extension &lt;span class="k"&gt;for &lt;/span&gt;debugging? &lt;span class="o"&gt;(&lt;/span&gt;experimental&lt;span class="o"&gt;)&lt;/span&gt; › No / Yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le langage &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt; est déjà pris en charge, un système de routage et un store sont proposés, et il y a même de quoi réaliser des tests unitaires et End-to-End !&lt;/p&gt;

&lt;p&gt;Par défaut, c'est le bundler &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt; qui est installé. Ce qui n'est pas pour me déplaire !😄 En effet, les builds sont rapides et, la plupart du temps le Hot Module Replacement (HMR) fonctionne bien.&lt;/p&gt;

&lt;p&gt;Un petit &lt;code&gt;npm run dev&lt;/code&gt; pour lancer le serveur de dev local, et hop ! Ça tourne déjà dans le navigateur !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxyn588lseyjg3x4dtbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbxyn588lseyjg3x4dtbj.png" alt="Vue.js 3 boilerplate" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et pour la mise en prod ? Il suffit de saisir la commande &lt;code&gt;npm run build&lt;/code&gt;, et le projet s'exporte en fichiers statiques dans un répertoire &lt;code&gt;dist&lt;/code&gt; après avoir vérifié les typages (dans le cas où l'on a activé le Typescript) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vite v5.2.11 building &lt;span class="k"&gt;for &lt;/span&gt;production...
✓ 48 modules transformed.
dist/index.html                      0.43 kB │ &lt;span class="nb"&gt;gzip&lt;/span&gt;:  0.28 kB
dist/assets/AboutView-C6Dx7pxG.css   0.09 kB │ &lt;span class="nb"&gt;gzip&lt;/span&gt;:  0.10 kB
dist/assets/index-D6pr4OYR.css       4.21 kB │ &lt;span class="nb"&gt;gzip&lt;/span&gt;:  1.30 kB
dist/assets/AboutView-CEwcYZ3g.js    0.22 kB │ &lt;span class="nb"&gt;gzip&lt;/span&gt;:  0.20 kB
dist/assets/index-CfPjtpcd.js       89.23 kB │ &lt;span class="nb"&gt;gzip&lt;/span&gt;: 35.29 kB
✓ built &lt;span class="k"&gt;in &lt;/span&gt;591ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architecture du projet
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
├── README.md
├── e2e/
├── index.html
├── package.json
├── public/
├── src/
│   ├── App.vue
│   ├── assets/
│   ├── components/
│   │   ├── HelloWorld.vue
│   │   ├── TheWelcome.vue
│   │   ├── WelcomeItem.vue
│   │   ├── __tests__/
│   │   └── icons/
│   ├── main.ts
│   ├── router/
│   │   └── index.ts
│   ├── stores/
│   │   └── counter.ts
│   └── views/
│       ├── AboutView.vue
│       └── HomeView.vue
├── tsconfig.json
└── vite.config.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Côté architecture du projet, on trouve notamment :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le fichier &lt;code&gt;index.html&lt;/code&gt;, avec la balise &lt;code&gt;&amp;lt;div id="app"&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt; sur laquelle vient se greffer toute notre application Vue ;&lt;/li&gt;
&lt;li&gt;le &lt;code&gt;main.ts&lt;/code&gt;, avec la création successive du composant App, du router et du store :
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./assets/main.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createApp&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPinia&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pinia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./router&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// composant racine&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createPinia&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// store&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// routage des pages front&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;des fichiers &lt;code&gt;.ts&lt;/code&gt; purs, pour gérer le routage et le store ;&lt;/li&gt;
&lt;li&gt;quelques fichiers de config et de test ;&lt;/li&gt;
&lt;li&gt;... et bien sûr les fichiers &lt;code&gt;*.vue&lt;/code&gt;, distingués en &lt;strong&gt;components&lt;/strong&gt; (qui correspondent plutôt à des éléments génériques et réutilisables), et &lt;strong&gt;views&lt;/strong&gt; (qui correspondent plutôt à des pages haut niveau)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En bref, l'architecture des fichiers est plutôt simple et relativement similaire à celle de React, même en ayant coché pas mal d'options dans le boilerplate.&lt;br&gt;
Jusque-là, venant de React, rien de bien nouveau. C'est ensuite qu'apparaissent des différences significatives !&lt;/p&gt;
&lt;h3&gt;
  
  
  Architecture d'un fichier Vue
&lt;/h3&gt;

&lt;p&gt;Voici un extrait de code inspiré du &lt;a href="https://vuejs.org/examples/#attribute-bindings" rel="noopener noreferrer"&gt;site officiel&lt;/a&gt;. Il se contente de changer la couleur du texte si l'on clique dessus et d'afficher la phrase "Le texte ci-dessus est vert", le cas échéant, mais il représente une architecture typique des fichiers &lt;code&gt;*.vue&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleColor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"main-text"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"toggleColor"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Cliquez sur ce texte pour changer de couleur.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"color === 'green'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Le texte ci-dessus est vert.&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.main-text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v-bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notez le binding des évènements avec &lt;code&gt;@click&lt;/code&gt;, l'affichage conditionnel avec le &lt;code&gt;v-if&lt;/code&gt;, et le binding dans le CSS avec &lt;code&gt;v-bind()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Le code est séparé en 3 parties bien distinctes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;script&lt;/strong&gt; : le code de contrôle ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;template&lt;/strong&gt; : la structure HTML ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;style&lt;/strong&gt; : la feuille de style CSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et ces trois parties ne se mélangent &lt;em&gt;jamais&lt;/em&gt; 😮.&lt;br&gt;
Cela présente plusieurs avantages que j'ai personnellement éprouvés tout au long mon expérience sur le projet client :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;La structure HTML est claire, fixe, et dans un style très &lt;strong&gt;déclaratif&lt;/strong&gt; - tout est là, même les balises affichées sous conditions ;&lt;/li&gt;
&lt;li&gt;la partie logique est bien séparée de la partie affichage ;&lt;/li&gt;
&lt;li&gt;on peut écrire du pur CSS en place, directement lié au composant, et sans installer de librairies tierce ;&lt;/li&gt;
&lt;li&gt;malgré la séparation du style, on peut quand même insérer des variables dans le CSS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avec le tag &lt;code&gt;scoped&lt;/code&gt; sur la balise &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt;, on peut même générer automatiquement des classes locales afin d'isoler sa feuille de style !&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Petit inconvénient : &lt;em&gt;a priori&lt;/em&gt; il n'existe pas de polyfill CSS automatique. Il faut alors plutôt viser une librairie comme &lt;a href="https://github.com/egoist/vue-emotion" rel="noopener noreferrer"&gt;vue-emotion&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;De mon point de vue, je trouve que ce genre de librairie "all-in-JS" casse un peu l'architecture que propose Vue, et de toute évidence, les propriétés CSS spécifiques aux navigateurs sont beaucoup plus rares de nos jours. La balise &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; de Vue est donc souvent autosuffisante.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bref, j'ai trouvé très plaisante cette architecture tout-en-un mais avec des sections bien séparées. Cela permet de garder un &lt;strong&gt;code propre&lt;/strong&gt;, mais aussi &lt;strong&gt;plus concis&lt;/strong&gt;. En effet, la présence simultanée des 3 sections "logique métier / affichage / style" incite souvent à redécouper son code en plus petits modules, et donc en plus petits fichiers.&lt;/p&gt;

&lt;p&gt;Maintenant, si on se penchait un peu plus sur l'API Vue.js elle-même ?&lt;/p&gt;
&lt;h2&gt;
  
  
  L'API Vue.js
&lt;/h2&gt;

&lt;p&gt;Ici je ne vous ferai pas la liste exhaustive de tous les éléments de l'API Vue.js que j'ai pu rencontrer, mais seulement de certains, bien spécifiques, que j'ai trouvés assez représentatifs de la logique de Vue.&lt;/p&gt;
&lt;h3&gt;
  
  
  Les valeurs (re)calculées
&lt;/h3&gt;

&lt;p&gt;Commençons par une opération bien connue de l'univers React : recalculer intelligemment un rendu HTML (ou une variable) suite à la mise à jour d'une donnée.&lt;br&gt;
Il y a la fonction très intuitive &lt;code&gt;computed()&lt;/code&gt; qui bénéficie d'un système de &lt;strong&gt;mémoïsation&lt;/strong&gt; (sorte de "cache") pour éviter de recalculer à chaque fois la valeur de sortie :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7eyvh8mhfxlbh6wdlvrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7eyvh8mhfxlbh6wdlvrr.png" alt="Rendu du code vuejs computed" width="178" height="99"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pushedBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;magicNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;computed again!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;pushedBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pushedBtn = 1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Button 1&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"pushedBtn = 2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Button 2&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Magic number: {{magicNumber}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ici le &lt;code&gt;magicNumber&lt;/code&gt; est calculé uniquement si la valeur de &lt;code&gt;pushedBtn&lt;/code&gt; vient à changer. Et c'est vérifiable : le message &lt;code&gt;"computed again!"&lt;/code&gt; ne s'affiche dans la console que lorsqu'un bouton différent est cliqué.&lt;br&gt;
Donc, contrairement à React, pas besoin de spécifier explicitement les variables qu'il faut surveiller dans cette fonction.&lt;/p&gt;

&lt;p&gt;Dans la même lignée, on trouve également les &lt;code&gt;watch&lt;/code&gt; et &lt;code&gt;watchEffect&lt;/code&gt; qui permettent respectivement de réagir aux changements de tout ou partie des propriétés du composant, à l'image du &lt;code&gt;useEffect&lt;/code&gt; en React :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;countWatchs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Attente d'un changement de 'num'&lt;/span&gt;
  &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;countWatchs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"num += 4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Modify num&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"text += 'a'"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Modify text&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Props:&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;num: {{num}}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;text: {{text}}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;hr&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Nb watchs calls: {{countWatchs}}&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xy23j0z0l0j89fuhrop.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1xy23j0z0l0j89fuhrop.gif" alt="Seul le premier bouton incrémente le compteur" width="325" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seul un clic sur le bouton modificateur de &lt;code&gt;num&lt;/code&gt; va incrémenter le compteur de "watchs".&lt;br&gt;
Le &lt;code&gt;watch()&lt;/code&gt; nous permet alors de déclencher une callback à chaque fois que certaines variables changent.&lt;/p&gt;

&lt;p&gt;La force de cette fonction réside dans l'analyse &lt;strong&gt;en profondeur&lt;/strong&gt; des modifications de variable : Vue détecte les changements même au fin fond d'un sous-objet !&lt;/p&gt;
&lt;h3&gt;
  
  
  La synchronisation bidirectionnelle
&lt;/h3&gt;

&lt;p&gt;Déclarer et transmettre une propriété d'un composant parent à un composant enfant est une opération assez récurrente. Synchroniser cette valeur entre l'enfant et le parent l'est également, par exemple dans l'input un formulaire.&lt;/p&gt;

&lt;p&gt;Aussi, plutôt que de gérer à la fois une propriété et une callback de mise à jour sur évènement comme ici :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Child.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineProps&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myModelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// déclaration propriété&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;emit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineEmits&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update:myModelValue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// déclaration callback&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Textfield:&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
    &lt;span class="na"&gt;:value=&lt;/span&gt;&lt;span class="s"&gt;"props.modelValue"&lt;/span&gt;
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;input=&lt;/span&gt;&lt;span class="s"&gt;"emit('update:myModelValue', 
     ($event.target as HTMLInputElement).value)"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;… il est possible d'utiliser à la place la macro &lt;code&gt;defineModel&lt;/code&gt; qui permet de simplifier l'écriture :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Child.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myModelValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myModel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Textfield:&lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"myModelValue"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beaucoup plus court ! 😎 D'ailleurs, n'ayant qu'un seul modèle, j'aurais même pu me dispenser de le nommer !&lt;/p&gt;

&lt;p&gt;Et avec le parent :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Parent.vue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Child&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Child.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my default value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Parent value: {{data}}&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Child&lt;/span&gt; &lt;span class="na"&gt;v-model:my-model=&lt;/span&gt;&lt;span class="s"&gt;"data"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/Child&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbukts4uuk2hj1yxzqq5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbukts4uuk2hj1yxzqq5.gif" alt="Gif synchro input enfant et parent" width="450" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  La boucle for
&lt;/h3&gt;

&lt;p&gt;Enchaîner sur les &lt;code&gt;v-for&lt;/code&gt; après avoir vu les &lt;code&gt;v-model&lt;/code&gt; m'a fait réaliser que Vue.js commençait à introduire pas mal de "magie" à travers du code implicite :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commonGitActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Commit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Push&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Merge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rebase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Actions git communes&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- Boucle "for" intégrée --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"action in commonGitActions"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{action}}&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Et le rendu :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzpsy0td9i125jz9b392f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzpsy0td9i125jz9b392f.png" alt="Vuejs3 v-for instruction" width="367" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comme on pouvait s'y attendre, l'instruction &lt;code&gt;v-for&lt;/code&gt; permet donc de répéter automatiquement une partie d'un patron HTML (ici la balise &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;) pour chaque élément d'un itérable.&lt;/p&gt;

&lt;p&gt;Côté React, il aurait fallu utiliser du JSX pour construire soi-même chaque élément, rendant le code moins lisible au fur et à mesure que le composant grandit :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commonGitActions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Commit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Push&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Merge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rebase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Actions git communes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;commonGitActions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Personnellement, j'ai une préférence pour la structure de Vue en termes de propreté de code, tant qu'il n'y a pas besoin de déboguer. 😅&lt;br&gt;
Et d'ailleurs, puisqu'on parle de déboguer, qu'en est-il des outils de l'écosystème Vue ?&lt;/p&gt;
&lt;h2&gt;
  
  
  Les outils de dev
&lt;/h2&gt;

&lt;p&gt;Voici 3 outils qui ont retenu mon attention dans le développement de mon projet.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extension VSCode : Vue Official
&lt;/h3&gt;

&lt;p&gt;Je commence par une évidence, mais oui, il y a bien une extension pour VSCode &lt;a href="https://marketplace.visualstudio.com/items?itemName=Vue.volar" rel="noopener noreferrer"&gt;Vue&lt;/a&gt; (et pour d'autres IDEs) qui ajoute la coloration syntaxique, autocomplétion, snippets, etc. Un indispensable !&lt;/p&gt;

&lt;p&gt;Toutefois, j'ai constaté quelques instabilités sur la coloration et l'autocomplétion, qui étaient parfois un peu capricieuses 😕, là où j'ai pu apprécier une plus grande stabilité côté React.&lt;/p&gt;
&lt;h3&gt;
  
  
  Vue.js devtools
&lt;/h3&gt;

&lt;p&gt;À l'image du plugin de navigateur &lt;code&gt;React Developer Tools&lt;/code&gt;, il existe le &lt;a href="https://devtools.vuejs.org/" rel="noopener noreferrer"&gt;plugin&lt;/a&gt; &lt;code&gt;Vue.js devtools&lt;/code&gt;, qui, je dois l'avouer, est déjà très bien fourni :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0rynrq9sq1er6xmpssz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0rynrq9sq1er6xmpssz.png" alt="VueJS dev tools" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On y retrouve 4 onglets :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Components&lt;/strong&gt;, où on l'on peut observer, mais également modifier les états des composants ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeline&lt;/strong&gt;, qui permet d'enregistrer les évènements et les temps de rendu des composants, ce qui correspond en fait à une version de l'onglet "Performances" du navigateur mais focalisée sur Vue ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinia&lt;/strong&gt;, qui permet d'observer et modifier directement les états du store standard 😯, une intégration déjà toute prête que j'ai trouvée particulièrement bienvenue ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes&lt;/strong&gt;, où l'on peut lister les différentes routes et leur activité - c'est un onglet que j'ai trouvé un peu gadget sur mon projet de taille modérée (d'autant plus que les informations sont un peu redondantes avec celles de l'onglet "Components"), mais qui peut s'avérer bien utile sur un routage complexe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bref, pour du débogage, il y a tout ce qu'il faut et même plus !&lt;/p&gt;
&lt;h3&gt;
  
  
  Vuetify
&lt;/h3&gt;

&lt;p&gt;Quasiment sans surprise (mais avec du mérite tout de même !), il existe aussi une librairie UI pour Vue qui implémente les &lt;a href="https://m2.material.io/components" rel="noopener noreferrer"&gt;Material Design de Google&lt;/a&gt; et fournit également une liste d'icônes standards : &lt;a href="https://v2.vuetifyjs.com/" rel="noopener noreferrer"&gt;Vuetify&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;v&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;alert&lt;/span&gt; &lt;span class="na"&gt;border&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'left'&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'$mdiVuetify'&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'success'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;v&lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="na"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau2u4fenuj4i1urverla.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau2u4fenuj4i1urverla.png" alt="Rendu alerte Vuetify" width="455" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cela permet de gagner beaucoup de temps sur des démarrages de projet, ou sur des projets qui ne nécessitent pas de personnalisation graphique trop poussée.&lt;/p&gt;

&lt;p&gt;Mais comme toujours, je recommande de garder un œil sur les performances de rendu avec ce genre de librairie haut niveau. La capacité de configuration d'une librairie se paie souvent ailleurs !&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Que dire de cette expérience de migration de React vers Vue ?&lt;/p&gt;

&lt;p&gt;Tout d'abord, d'un point de vue du code, par rapport à React je dirais que la lib Vue est :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;plus structurée&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plus déclarative&lt;/strong&gt; ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;plus concise&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Toutefois, grâce à son code qui s'écrit plutôt en JSX, je trouve que React reste beaucoup plus interopérable, plus programmatique et plus explicite que Vue, et avec une meilleure stabilité du linter.&lt;/p&gt;

&lt;p&gt;Côté environnement de développement et communauté, Vue a pour moi toutes les cartes en main pour assurer des développements efficaces jusqu'à la mise en prod.&lt;/p&gt;

&lt;p&gt;Alors est-ce que cette montée en compétence sur Vue a été à la hauteur de sa notoriété ? Je dirais que oui. J'ai trouvé la courbe d'apprentissage efficace, et je continuerai de développer avec Vue si l'occasion se présente.&lt;/p&gt;

&lt;p&gt;Enfin, est-ce qu'aujourd'hui il vaut mieux développer du frontend en Vue qu'en React ?&lt;br&gt;
D'un point de vue totalement personnel, je pense que non. Même si Vue et React ont chacun des cas d'application un peu différents, je préfère me fier à un système de typage fiable et à un code plus souple avec React. Mais peut-être que les prochaines versions de Vue et leurs outils me feront changer d'avis ?&lt;/p&gt;

&lt;p&gt;Et vous, quels sont vos retours d'expérience ?&lt;/p&gt;

</description>
      <category>vue</category>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>CSS : En 2024 les Grids c'est has been ?</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Mon, 29 Jul 2024 08:56:19 +0000</pubDate>
      <link>https://dev.to/younup/css-en-2024-les-grids-cest-has-been--lmc</link>
      <guid>https://dev.to/younup/css-en-2024-les-grids-cest-has-been--lmc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Tout le monde sait ce qu'est un affichage responsive en 2024 : c'est &lt;strong&gt;occuper intelligemment l'espace disponible pour un affichage optimal&lt;/strong&gt; en terme d'esthétique et d'ergonomie vis-à-vis des différents supports d'affichage (smartphone, tablette, ordinateur de bureau...).&lt;/p&gt;

&lt;p&gt;Mais histoire de revenir aux fondamentaux, en full CSS comment fait-on du responsive design aujourd'hui ?&lt;/p&gt;

&lt;p&gt;Pour ce faire, le CSS a mis à notre disposition ces principaux outils :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;les grids (...et subgrids 😯) !&lt;/li&gt;
&lt;li&gt;les flexboxs&lt;/li&gt;
&lt;li&gt;et les media queries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En pratique, nombreux sont les développeurs à avoir complètement abandonné les grids (plutôt historiques, donc) au profit des flexboxs, qui paraissent très similaires tout en étant (un peu) plus modernes.&lt;/p&gt;

&lt;p&gt;Mais alors : pourquoi les grids existent toujours ? Ne serait-on pas là, en présence d'un outil quelque peu dépassé ?&lt;/p&gt;

&lt;p&gt;Dans l'optique de mieux situer les grids par rapport aux flexboxs, je vous propose de refaire un tour d'horizon de leurs fonctionnalités : &lt;em&gt;comment&lt;/em&gt;, mais aussi &lt;em&gt;quand&lt;/em&gt; se servir plutôt de l'un ou de l'autre. Et vous allez voir que les grids ont peut-être un peu plus à proposer que ce qu'on croyait !&lt;/p&gt;

&lt;h2&gt;
  
  
  Les Flexboxs
&lt;/h2&gt;

&lt;p&gt;Comme vous le savez sans doute, la Flexbox propose un système d'alignement beaucoup plus flexible que son homologue Grid. Mais elle a la particularité de se concentrer avant tout sur &lt;em&gt;1 seul&lt;/em&gt; axe principal pour la répartition des éléments :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column col1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Colonne 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column col2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Colonne 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column col3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Colonne 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"column col4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Colonne 4&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Activation de la flexbox */&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Choix de la direction principale */&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Centrage des éléments sur l'axe principal */&lt;/span&gt;

  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff9e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.column&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fbbe00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce qui nous donne :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffasy94zi86xjhjv7jf5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffasy94zi86xjhjv7jf5d.png" alt="Centrage avec une flexbox" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En fait, la Flexbox est &lt;strong&gt;idéale pour aligner un nombre variable d'éléments&lt;/strong&gt; sur un seul axe, sans définir au préalable le nombre de colonnes.&lt;/p&gt;

&lt;p&gt;Mais il est tout de même possible de régler l'alignement sur l'axe secondaire (vertical dans notre cas 🙂) si, par exemple, notre &lt;code&gt;.container&lt;/code&gt; occupait plus de place :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;

  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Occuper toute la hauteur du viewport */&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Centrer sur l'axe secondaire */&lt;/span&gt;

  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* (Autre exemple d'alignement sur l'axe principal) */&lt;/span&gt;

  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdyoa0bwjn544m3zug7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjdyoa0bwjn544m3zug7g.png" alt="Centrage avec une flexbox" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...Et il est par ailleurs possible d'utiliser la propriété &lt;code&gt;flex-wrap&lt;/code&gt; pour autoriser la création d'une ou plusieurs lignes supplémentaires dans le cas où nos éléments seraient trop grands pour tenir sur une seule ligne :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
  &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* ... */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feihvawt37q36sqxvq55p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feihvawt37q36sqxvq55p.png" alt="Flex wrap sur deux lignes" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vous noterez qu'en réalisant ce dernier exemple, j'ai volontairement introduit des tailles différentes sur les éléments 4 et 5. On constate alors que les flexboxs ne garantissent pas un alignement identique des colonnes sur plusieurs lignes 😕. La flexbox s'est juste contentée d'afficher les éléments les uns derrière les autres. C'est une limitation à prendre en compte.&lt;/p&gt;

&lt;p&gt;Enfin, pour terminer ce tour d'horizon sur les Flexboxs, je mentionnerai la propriété notable &lt;code&gt;flex&lt;/code&gt; sur les éléments enfants pour justement répondre à la problématique responsive "occuper intelligemment l'espace disponible" :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* (Espaces inter-éléments) */&lt;/span&gt;

  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff9e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.column&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fbbe00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.col2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Petite capacité d'occupation d'espace */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.col3&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Moyenne capacité d'occupation d'espace */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.col4&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Grande capacité d'occupation d'espace */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps310en28v2lsng85tnt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fps310en28v2lsng85tnt.png" alt="Répartition espace avec flex" width="800" height="75"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La propriété &lt;code&gt;flex&lt;/code&gt; nous permet donc de simplifier la &lt;strong&gt;répartition et le partage de l'espace disponible&lt;/strong&gt; entre les éléments, ici en suivant un coefficient.&lt;/p&gt;

&lt;p&gt;Mais attention à ne pas tout confondre : il s'agit bien ici d'&lt;strong&gt;étirer les éléments&lt;/strong&gt; pour occuper l'espace, et non de leur attribuer une ou plusieurs colonnes ! On ne peut donc pas non plus espérer garantir un alignement, par exemple, entre plusieurs flexboxs sur une même colonne ! ...Ca, c'est le boulot des Grids !😋&lt;/p&gt;

&lt;h2&gt;
  
  
  Les Grids
&lt;/h2&gt;

&lt;h3&gt;
  
  
  L'usage classique
&lt;/h3&gt;

&lt;p&gt;Parfois un peu "oublié", comme je vous le disais, depuis les multiples évolutions du CSS, le système de grid consiste à déclarer une grille 2D invisible sur laquelle on peut positionner les éléments enfants. Chaque case de cette grille étant dynamiquement extensible selon la taille du viewport et/ou des éléments.&lt;/p&gt;

&lt;p&gt;Le système de Grid est idéal, par exemple, pour définir les dispositions fondamentales d'une page avec ce genre de structure :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Header&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;aside&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Sidebar&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/aside&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;main&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Main Title&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Content content content...&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/main&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On peut alors typiquement déclarer une grille avec le &lt;code&gt;grid-template-areas&lt;/code&gt; que je qualifierai d'assez visuel :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Activation de la grille */&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;/* Déclaration des zones de la grille */&lt;/span&gt;
    &lt;span class="s1"&gt;"header header header header"&lt;/span&gt;
    &lt;span class="s1"&gt;"sidebar content content content"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* Répartition des longueurs de nos 4 colonnes */&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Répartition des hauteurs de nos 2 lignes */&lt;/span&gt;

  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* (Pour étendre notre grille... */&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* ...sur toute la page) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Attribution à la zone 'header' de la grille */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fbbe00&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;aside&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sidebar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c"&gt;/* Attribution à la zone 'sidebar' de la grille */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff9e6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c"&gt;/* Attribution à la zone 'content' de la grille */&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fak6sz481m287w21ky811.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fak6sz481m287w21ky811.png" alt="Usage basic d'une grid" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La propriété &lt;code&gt;grid-template-areas&lt;/code&gt; nous permet donc de définir un ensemble de colonnes et de lignes en leur donnant un nom arbitraire (et explicite tant qu'à faire ! 😊). Les balises enfants pouvant alors être attribuées aux zones ainsi nommées grâce à la propriété &lt;code&gt;grid-area&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto flow
&lt;/h3&gt;

&lt;p&gt;Si vous trouvez le système de Grid un peu trop "rigide" 🤖, sachez qu'il est également possible d'utiliser un &lt;strong&gt;layout automatique&lt;/strong&gt; indépendamment du nombre d'éléments, un petit peu comme les flexboxs :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Activation de la grille */&lt;/span&gt;

  &lt;span class="py"&gt;grid-auto-flow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* &amp;lt;== Répartition automatique sur les colonnes */&lt;/span&gt;

  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* (Pour étendre notre grille... */&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* ...sur toute la page) */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsfy6d2lw1h4rtdg6kl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsfy6d2lw1h4rtdg6kl9.png" alt="Layout auto avec une grid" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Il faut noter cependant, que si l'on spécifie les dimensions des colonnes et lignes avec un &lt;code&gt;grid-template&lt;/code&gt; par exemple, la grille &lt;em&gt;peut&lt;/em&gt; se permettre de modifier l'ordre d'apparition des éléments, et ce afin de privilégier ceux qui peuvent rentrer en premier dans les cases du template. Comportement qui peut être un poil déconcertant pour les non avertis...&lt;/p&gt;

&lt;p&gt;Souvenez-vous : les Grids gèrent une répartition en &lt;em&gt;2&lt;/em&gt; dimensions ! Contrairement aux flexboxs il n'y a &lt;em&gt;pas&lt;/em&gt; d'axe principal !&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Le saviez-vous ? Les propriétés &lt;code&gt;justify-items&lt;/code&gt; et &lt;code&gt;align-items&lt;/code&gt; peuvent aussi être utilisées sur les grids pour gérér l'alignement des éléments sur les axes verticaux et horizontaux, à la manière des Flexboxs !&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Les Subgrids
&lt;/h3&gt;

&lt;p&gt;Une propriété qui gagne à se faire connaître depuis quelques années ! (cf &lt;a href="https://2023.stateofcss.com/en-US/awards/" rel="noopener noreferrer"&gt;State of CSS 2023&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Admettons que vous ayez défini les colonnes principales de votre site (exactement comme nous venons de le voir tout au début avec les &lt;code&gt;grid-template-areas&lt;/code&gt;). La hiérarchie HTML commence à grandir à force de rajouter du contenu.&lt;/p&gt;

&lt;p&gt;Comment alors garantir que les balises n-ièmes sous-enfants sont correctement alignées sur nos colonnes définies à la racine du site, à l'image des &lt;a href="https://m2.material.io/design/layout/responsive-layout-grid.html#columns-gutters-and-margins" rel="noopener noreferrer"&gt;Layout du Material Design 2&lt;/a&gt; ?&lt;/p&gt;

&lt;p&gt;C'est là que les &lt;a href="https://developer.mozilla.org/fr/docs/Web/CSS/CSS_grid_layout/Subgrid" rel="noopener noreferrer"&gt;subgrids&lt;/a&gt; interviennent ! Elles nous donnent la possibilité de se référer au template du parent direct (donc forcément, il faudra transmettre la subgrid à chaque niveau) :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Attribution à la zone 'content' de la grille */&lt;/span&gt;

  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subgrid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* &amp;lt;== Héritage du template de colonnes du parent ! */&lt;/span&gt;

  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ce qui nous permet de retrouver les 3 colonnes de la partie "content" parfaitement alignées avec les colonnes du parent. Le graal 😎!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x6jy9900ftmu8j9ifex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x6jy9900ftmu8j9ifex.png" alt="Alignement colonnes subgrid" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Les zones violettes ont été ajoutées pour mettre en valeur les alignements)&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Alors, les grids c'est has been ?&lt;/p&gt;

&lt;p&gt;Comme nous avons pu le voir, si les grids ne sont pas dépréciées, c'est qu'il y a de bonnes raisons !&lt;/p&gt;

&lt;p&gt;La Grid reste idéale pour &lt;strong&gt;définir des zones&lt;/strong&gt; de base sur la page web, et &lt;strong&gt;garantir le même alignement 2D&lt;/strong&gt;, inter-lignes ou inter-colonnes.&lt;/p&gt;

&lt;p&gt;De son côté, la Flexbox est idéale pour définir plus simplement des &lt;strong&gt;alignements sur un seul axe&lt;/strong&gt; ou &lt;strong&gt;partager l'espace disponible&lt;/strong&gt; par rapport à un nombre &lt;strong&gt;variable&lt;/strong&gt; d'éléments, et ce à un niveau plutôt secondaire, donc.&lt;/p&gt;

&lt;p&gt;Au final, l'idée, c'est de savoir doser, comme une recette de cuisine :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;des grids pour les fondations&lt;/li&gt;
&lt;li&gt;quelques subgrids pour les sous-zones de la page&lt;/li&gt;
&lt;li&gt;des flexboxs pour les alignements secondaires et/ou dynamiques&lt;/li&gt;
&lt;li&gt;...et le tout saupoudré de media queries pour adapter les dimensions et nombre de colonnes en fonction du support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus d'excuses pour être responsives avec les bons outils ! 🙂&lt;/p&gt;

</description>
      <category>css</category>
      <category>design</category>
      <category>html</category>
      <category>flexbox</category>
    </item>
    <item>
      <title>À quel niveau de qualité est votre code ?</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Mon, 18 Mar 2024 13:00:41 +0000</pubDate>
      <link>https://dev.to/younup/level-up-sur-la-qualite-du-code--f16</link>
      <guid>https://dev.to/younup/level-up-sur-la-qualite-du-code--f16</guid>
      <description>&lt;h1&gt;
  
  
  Level up sur la qualité du code
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Vous êtes-vous déjà dit en regardant votre code "Je peux faire mieux !" ?&lt;/p&gt;

&lt;p&gt;C'est normal. On peut toujours mieux faire.&lt;/p&gt;

&lt;p&gt;Mais la vraie question est : jusqu'où aller ? Quel niveau de qualité faut-il donc atteindre pour les besoins du projet ?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l9krwugqowu2ywvp6ds.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8l9krwugqowu2ywvp6ds.jpg" alt="Développeur manga a une idée" width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;À moins d'être vraiment (super) balèze, il faudra repasser plusieurs fois sur un même code pour atteindre un niveau satisfaisant.&lt;/p&gt;

&lt;p&gt;À travers toutes mes expériences et tout un panel de langages, j'ai justement pu identifier cinq niveaux de qualité du code. Et croyez-moi, atteindre chacun de ces niveaux n'est jamais une évidence !&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 1 : le code est fonctionnel
&lt;/h2&gt;

&lt;p&gt;Est-ce qu'on commence par enfoncer une porte ouverte ? Sans aucun doute. Est-ce que ce niveau est systématiquement atteint ? Hélas, non.&lt;/p&gt;

&lt;p&gt;La question n'est pas d'avoir un code qui &lt;em&gt;peut&lt;/em&gt; ou ne peut pas s'exécuter, encore que dans certains langages comme le Python ou le Javascript, c'est souvent le grand suspens étant donné que l'exécution n'est pas garantie en amont par un compilateur au même titre qu'avec le Rust.&lt;/p&gt;

&lt;p&gt;Je parle de &lt;strong&gt;répondre effectivement à la problématique de départ&lt;/strong&gt;, à la specification fonctionnelle (quand elle a la chance d'exister 😬).&lt;/p&gt;

&lt;p&gt;Il est vrai, cela nécessite d'avoir une chaîne de définition et développement de produit impeccable : bien identifier le besoin client, bien le traduire, bien le comprendre, et bien l'implémenter. Mais c'est un niveau hyper important à garder à l'esprit dans tous les choix techniques car il constitue l'unique valeur perceptible depuis l'extérieur du projet.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pour l'anecdote : dans un de mes projets client d'IHM, l'équipe UX &amp;amp; Produit souhaitait que l'on rajoute un nouvelle stratégie de sauvegarde à travers le parcours utilisateur d'un Wizard, car ils avaient identifié &lt;em&gt;un besoin&lt;/em&gt;. Sauf qu'en tant que développeurs nous savions que cette nouvelle stratégie était contradictoire avec les contraintes techniques existantes, et présentait même des failles fonctionnelles. Mais c'était pourtant l'objectif, ce qui était &lt;em&gt;demandé&lt;/em&gt; et validé par l'équipe produit, et dans le Sprint actuel.&lt;/p&gt;

&lt;p&gt;Alors qu'avons-nous fait ?&lt;/p&gt;

&lt;p&gt;Totalement à l'improviste, j'ai proposé au responsable UX un petit brainstorming devant un tableau blanc pour présenter nos points de vue respectifs. Et ça a été la discussion la plus enrichissante et créative qu'on ait jamais eue. Ai-je réussi à démontrer que j'avais raison ? Spoiler alert : &lt;strong&gt;on avait tort tous les deux&lt;/strong&gt;. Nos deux stratégies comportaient chacune des failles et si on en avait suivi une seule, on serait tombés systématiquement dans des comportements indéterminés.&lt;br&gt;
Cela nous a permis de recréer une nouvelle spec juste &lt;em&gt;impeccable&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alors en amont, n'hésitez pas à poser des questions au Product Owner, à décortiquer les problèmes, à essayer de &lt;strong&gt;comprendre le pourquoi du comment&lt;/strong&gt;. Plus vous serez informé et concerné par l'objectif, mieux vous l'implémenterez.&lt;/p&gt;

&lt;p&gt;De même, lors de l'implémentation, vérifiez &lt;strong&gt;que le code répond bien au besoin et ce dans les conditions du client&lt;/strong&gt;. Souvenez-vous que même si votre programme marche sur votre PC, ce n'est pas votre PC qui sera vendu au client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 2 : le code est fiable
&lt;/h2&gt;

&lt;p&gt;D'accord, le code répond maintenant au cas nominal. Mais est-ce vraiment le seul cas que l'on va rencontrer ?&lt;/p&gt;

&lt;p&gt;D'expérience je peux d'ores et déjà vous répondre "non".&lt;/p&gt;

&lt;p&gt;Déjà car la spec fonctionnelle recense rarement tous les cas d'usage du premier coup. Mais aussi (et surtout) car l'ajout de nouveau code introduit statistiquement de nouveaux bugs et comportements inattendus.&lt;/p&gt;

&lt;p&gt;On repense aux fameuses dix lignes de code efficaces produites par jour et par développeur ("The Mythical Man Month" - Brooks). En tant que développeur, il faudra tester et corriger son code un bon nombre de fois afin de gérer correctement tous les cas d'erreurs possibles. Votre code doit être &lt;strong&gt;à l'épreuve des balles !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl8yxxo2n56tr4qq6zio.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyl8yxxo2n56tr4qq6zio.jpg" alt="Développeur manga ultra déterminé avec une aura" width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tout d'abord il faut identifier les situations qui ne sont pas gérées dans le code : un champ qui pourrait être vide ? Une combinaison de valeurs qui donne lieu à une situation inattendue ? Un serveur qui ne répond plus ? La saturation de l'espace disque ?... Le code doit les gérer.&lt;/p&gt;

&lt;p&gt;Pour s'aider, on devra aussi implémenter des tests End-to-End, tests unitaires et d'intégration. Ces phases de tests doivent être vues comme de véritables crash-tests : si vous rencontrez des erreurs, c'est gagné ! L'occasion de corriger une faille ! Souvenez-vous que des tests qui n'échouent jamais n'ont aucun intérêt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.younup.fr/blog/estimer-la-qualite-de-vos-suites-de-tests-grace-au-mutation-testing" rel="noopener noreferrer"&gt;Voir aussi le mutation testing.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 3 : le code est générique
&lt;/h2&gt;

&lt;p&gt;Je pourrais écrire une flopée d'articles rien que sur ce niveau, car il regroupe en fait de nombreuses qualités en termes d'&lt;strong&gt;architecture&lt;/strong&gt; ou de &lt;strong&gt;scalabilité&lt;/strong&gt; (même si ce dernier aspect est plutôt propre aux projets web).&lt;/p&gt;

&lt;p&gt;En fait l'idée de ce niveau est de pouvoir &lt;strong&gt;gérer un maximum de cas d'usage avec un minimum de code&lt;/strong&gt;.&lt;br&gt;
Il faut être capable de lire entre les lignes de l'énoncé, d'être visionnaire !&lt;/p&gt;

&lt;p&gt;Dit autrement, demain on doit pouvoir ajouter facilement de nouvelles fonctionnalités avec moins de code que ce qu'il a fallu au départ à la création de l'architecture, voire sans ajouter de code du tout ✌️.&lt;/p&gt;

&lt;p&gt;De nombreuses méthodes existent pour y parvenir, comme par exemple :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;implémenter une architecture &lt;a href="https://fr.wikipedia.org/wiki/SOLID_(informatique)" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; ;&lt;/li&gt;
&lt;li&gt;ajouter des niveaux d'abstraction sur les objets ;&lt;/li&gt;
&lt;li&gt;utiliser des templates ;&lt;/li&gt;
&lt;li&gt;refactoriser les parties de code similaires en fonctions réutilisables ;&lt;/li&gt;
&lt;li&gt;découper en petits modules indépendants plutôt que tout coder au même endroit ;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avec un code générique, on balaie déjà la plus grande partie d'une dette technique qui pourrait nous retomber dessus dans un avenir souvent plus proche qu'on ne l'imagine.&lt;/p&gt;

&lt;p&gt;Attention : piège, un code trop générique peut vite perdre en lisibilité si on ne fait pas attention ! C'est donc un équilibre à trouver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 4 : le code est performant
&lt;/h2&gt;

&lt;p&gt;Ici on parle de consommation de ressources matérielles et de rapidité d'exécution. Ce niveau peut parfois être facultatif, car les ressources de nos machines sont chaque jour un peu plus fournies, et bien souvent si un programme répond déjà au besoin initial, on ne se soucie des problèmes de performances que lorsqu'ils deviennent vraiment gênants.&lt;/p&gt;

&lt;p&gt;Toutefois pour éviter d'être débordé à moyen terme, il vaut mieux &lt;strong&gt;rester consciencieux&lt;/strong&gt; à chaque ligne de code que l'on écrit au fur et à mesure : chaque structure de donnée, chaque boucle, chaque requête réseau a une empreinte plus ou moins importante qu'il faut jauger.&lt;/p&gt;

&lt;p&gt;Voici quelques généralités applicables dans une grande partie des langages :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;évitez les copies inutiles&lt;/strong&gt; de données en utilisant le système de références du langage ;&lt;/li&gt;
&lt;li&gt;méfiez-vous des conteneurs à taille dynamique (par exemple, &lt;code&gt;string&lt;/code&gt;), &lt;strong&gt;si possible, réservez une capacité&lt;/strong&gt; en amont pour éviter les multiples réallocations et copies en interne à force de redimensionnement ;&lt;/li&gt;
&lt;li&gt;placez toujours les conditions (&lt;code&gt;if&lt;/code&gt;) qui ont le plus de chances de se produire en premier ;&lt;/li&gt;
&lt;li&gt;si applicable, utilisez des fonctions asynchrones pour les opérations longues en attente afin d'éviter les blocages ;&lt;/li&gt;
&lt;li&gt;spécifiez des &lt;strong&gt;types de variables adaptés&lt;/strong&gt; au besoin (par exemple, un entier sur 64 bits n'est pas nécessaire pour des nombres allant de 0 à 10 000) ;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libérez la mémoire&lt;/strong&gt; et les verrous (mutex) au plus tôt ;&lt;/li&gt;
&lt;li&gt;réduisez les boucles de traitement successives sur une même liste de données en les regroupant en une seule ;&lt;/li&gt;
&lt;li&gt;utilisez le mot-clé &lt;code&gt;const&lt;/code&gt; car, dans la plupart des langages, il réduit drastiquement les instructions bas niveau générées derrière (assembleur ou autres) ;&lt;/li&gt;
&lt;li&gt;regroupez les accès disques et les requêtes réseaux ;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gardez aussi à l'esprit le classement général des goulots d'étranglement en termes de temps d'accès (du plus lent au plus rapide) :&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;accès réseaux ;&lt;/li&gt;
&lt;li&gt;disque dur ;&lt;/li&gt;
&lt;li&gt;SSD ;&lt;/li&gt;
&lt;li&gt;RAM ;&lt;/li&gt;
&lt;li&gt;caches CPU (L1-L2-L3) ;&lt;/li&gt;
&lt;li&gt;registres CPU.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bref, il y a vraiment de quoi faire sur ce sujet, et à défaut d'avoir &lt;em&gt;besoin&lt;/em&gt; d'un code performant dans le projet, il faut avoir conscience de ces enjeux pendant la conception de l'architecture et l'écriture du code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.younup.fr/blog/replay-meet-up-tu-es-sur-e-que-tu-veux-optimiser-ton-code" rel="noopener noreferrer"&gt;Plus de réflexion sur l'optimisation ici.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Level 5 : le code est... simple
&lt;/h2&gt;

&lt;p&gt;J'en avais déjà parlé dans &lt;a href="https://www.younup.fr/blog/5-erreurs-que-commettent-les-developpeurs" rel="noopener noreferrer"&gt;cet article&lt;/a&gt; en citant Léonard de Vinci, et ce n'est pas un hasard si cette qualité arrive en dernier : "La simplicité est la sophistication suprême".&lt;/p&gt;

&lt;p&gt;Cela peut paraître contradictoire avec le "Level 3 : le code est générique", mais c'est là toute la difficulté de mise en place !&lt;/p&gt;

&lt;p&gt;C'est un luxe qu'on ne se permet d'appliquer que trop rarement. Pourtant il s'inscrit aussi dans le cadre de la pérennité du code, et de la facilité à le maintenir, le relire dans le temps !&lt;/p&gt;

&lt;p&gt;Cela implique un code explicite, concis, qui dans le meilleur des cas ne nécessite même pas de commentaires pour comprendre ce qu'il fait et pourquoi. Sur ce sujet je ne peux que vous conseiller le livre "Coder proprement" (Robert C. Martin).&lt;/p&gt;

&lt;p&gt;Excellente nouvelle : dans la majorité des cas, &lt;strong&gt;plus le code est simple et plus il sera fiable et performant&lt;/strong&gt;, car il réduit le nombre d'étapes et la complexité pour atteindre la même finalité. De quoi passer 3 Levels en 1 ! 😎&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2obs6ebu68w300bmf1e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2obs6ebu68w300bmf1e.jpg" alt="Développeur manga satisfait avec le poing levé" width="512" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Vous l'aurez deviné : atteindre systématiquement les cinq niveaux de qualité de code est rare. D'autant plus que les priorités peuvent varier d'un projet à un autre, et que bien souvent tous les niveaux précédents ont tendance à empiéter sur la simplicité du code.&lt;/p&gt;

&lt;p&gt;D'un côté, se soucier de cette simplicité le plus tôt possible apporte un retour sur investissement ultra rentable. Mais comme toujours, les délais de livraison obligent parfois à faire des compromis pour atteindre les objectifs en temps et en heure.&lt;/p&gt;

&lt;p&gt;Malgré tout, ces niveaux restent un véritable défi d'amélioration continue et de perfectionnement pour réaliser des projets toujours plus impeccables. À la fois pour les développeurs, et pour le client final.&lt;/p&gt;

&lt;p&gt;Et vous, quel niveau atteignez-vous ?&lt;/p&gt;

&lt;p&gt;(Mention : toutes les images de cet article ont été générées avec Microsoft Copilot.)&lt;/p&gt;

</description>
      <category>general</category>
      <category>development</category>
      <category>developer</category>
      <category>codequality</category>
    </item>
    <item>
      <title>L'ownership en Rust !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Wed, 15 Nov 2023 11:20:25 +0000</pubDate>
      <link>https://dev.to/younup/lownership-en-rust--7lh</link>
      <guid>https://dev.to/younup/lownership-en-rust--7lh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;On m'a souvent demandé :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Parmi toutes les fonctionnalités de Rust, si tu devais en retenir une seule qui fait sa force, ce serait quoi ?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eh ben ce serait ça.&lt;/p&gt;

&lt;p&gt;Aujourd'hui, je vais vous parler de ce concept clé du langage, et pas des moindres : ☄ &lt;strong&gt;L'Ownership&lt;/strong&gt; ☄. Je vais ainsi vous montrer pourquoi Rust est un langage &lt;em&gt;sûr&lt;/em&gt; pour la mémoire.&lt;/p&gt;

&lt;p&gt;À celles et ceux qui veulent un résumé rapide pour découvrir le langage : &lt;a href="https://www.younup.fr/blog/rust-ce-langage-natif-safe-et-puissant"&gt;Rust : ce langage natif safe et puissant&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Principes fondamentaux de l'ownership
&lt;/h2&gt;

&lt;p&gt;L'allocation mémoire dans un programme, c'est le nerf de la guerre. Une mauvaise gestion des allocations peut entraîner une surcharge de la RAM, des pointeurs zombies 🧟‍♂️,... bref, des trucs vraiment pas cool et qu'on a malheureusement trop rencontré avec des langages comme le C++.&lt;/p&gt;

&lt;p&gt;Le but de l'Ownership, c'est justement de &lt;strong&gt;maintenir la mémoire propre&lt;/strong&gt; : minimiser les duplications de données, éviter les comportements imprévisibles avec les opérations de lectures/écritures, et nettoyer rapidement les données inutilisées.&lt;/p&gt;

&lt;p&gt;Alors, comment ça marche ?&lt;/p&gt;

&lt;p&gt;Concrètement, toutes les allocations suivent les règles fondamentales suivantes :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaque allocation mémoire a un &lt;strong&gt;unique propriétaire&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Seul le propriétaire (ou l'emprunteur dans certains cas) a les droits de modification&lt;/li&gt;
&lt;li&gt;S'il n'y a plus de propriétaire, la mémoire est libérée&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ces règles sont appliquées sur l'ensemble de notre code, à chaque compilation ! Bien évidemment si une seule règle est enfreinte..., ça ne compile pas !&lt;/p&gt;

&lt;p&gt;Notez que le concept de &lt;em&gt;lifetime&lt;/em&gt; participe aussi activement à la protection mémoire, mais c'est un sujet à part entière que je ne traiterai pas dans cet article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sémantique de mouvement
&lt;/h2&gt;

&lt;p&gt;Etant donné que les allocations n'ont pas toutes le même coût, le comportement du symbol &lt;code&gt;=&lt;/code&gt; va être différent selon le type de variable.&lt;/p&gt;

&lt;p&gt;Par exemple, sur l'affectation d'un entier, que l'on peut considérer comme une variable "simple" :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// allocation à taille fixe&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// l'affectation d'un entier déclenche une copie par défaut&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x = {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Jusque là, rien de bien nouveau. Mais si l'on essaye de faire la même chose avec un String, que l'on peut considérer comme une variable "complexe" :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// allocation à taille dynamique, s1 est propriétaire&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// s2 prend désormais l'ownership&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// erreur de compilation : s1 has moved!!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;"Quoi ? quoi ? 😲"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Féliciations, vous venez de rencontrer &lt;strong&gt;la sémantique de mouvement&lt;/strong&gt; en Rust ! 😀&lt;br&gt;
Par défaut en Rust, les variables complexes (allocation dynamique, taille variable, structures,...) ne sont pas copiées. Il y a simplement un transfert de propriété !&lt;/p&gt;

&lt;p&gt;Attention, cela n'a rien à voir avec les références implicites d'objets comme en Java ! Ici il n'y a pas de référence.&lt;/p&gt;

&lt;p&gt;Autre exemple avec une fonction :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// allocation à taille variable, s1 est propriétaire&lt;/span&gt;
    &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// s1 est transféré dans le scope my_func !&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// erreur de compilation : s1 has moved!!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// s est le propriétaire de "hello"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La bonne pratique ici est donc de passer la valeur par référence immutable :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// s1 est passé par référence immutable dans le scope my_func&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK : s1 est toujours propriétaire&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;my_func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}, world!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// s est une référence immutable&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Remarque&lt;/strong&gt; : pour les structures légères, on peut aussi implémenter automatiquement les traits &lt;a href="https://doc.rust-lang.org/std/clone/trait.Clone.html"&gt;Clone&lt;/a&gt; et &lt;a href="https://doc.rust-lang.org/std/marker/trait.Copy.html"&gt;Copy&lt;/a&gt;. Mais cela risque de dupliquer inutilement les données, ce qu'on veut justement éviter ! À utiliser consciencieusement donc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Avec cette référence immutable, on vient d'aborder une autre notion : &lt;strong&gt;l'emprunt (borrowing)&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les emprunts (borrowing)
&lt;/h2&gt;

&lt;p&gt;En toute franchise, il est difficile de prévoir la réaction du compilateur et de son redoutable &lt;strong&gt;borrow checker&lt;/strong&gt; sans une bonne expérience, mais on pourrait résumer les règles de borrowing comme suit :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S'il n'y a pas de référence mutable, il peut y avoir autant de références immutables que l'on souhaite sur une même variable.&lt;/li&gt;
&lt;li&gt;Il ne peut y avoir &lt;strong&gt;qu'une seule référence mutable à la fois&lt;/strong&gt; sur une même variable =&amp;gt; et c'est ce concept qui nous protège de bien des erreurs en écriture concurrentielle ! Et directement à la compilation ! ✌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;C'est là que les choses peuvent se compliquer un peu... mais c'est pour notre bien !&lt;/p&gt;

&lt;p&gt;Observons quelques exemples :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// référence immutable 1 : OK&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// référence immutable 2 : OK&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{} and {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// affiche "hello and hello"&lt;/span&gt;
    &lt;span class="c1"&gt;// variables r1 et r2 ne sont plus utilisées après ce point&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 emprunt par référence mutable : no problemo&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;" world"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// modification de la String d'origine par déréférencement&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK : affiche "hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais si on modifiait juste la fin de cet exemple :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// [...]&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 emprunt par référence mutable : no problemo&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;" world"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// erreur de compilation : "cannot borrow `s` as immutable because it is also borrowed as mutable"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK : affiche "hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Impossible d'emprunter et printer &lt;code&gt;s&lt;/code&gt; car il est potentiellement en cours de modification par &lt;code&gt;r3&lt;/code&gt; ! Et cela est vrai seulement car &lt;code&gt;r3&lt;/code&gt; est utilisé juste après dans le &lt;code&gt;print&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Si on change alors simplement l'ordre des &lt;code&gt;print&lt;/code&gt;s :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// [...]&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;r3&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;" world"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK : affiche "hello world"&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OK : r3 ne peut plus être utilisé ici&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bingo ! le compilateur est rassuré 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;On a vu comment étaient transmises les variables d'un contexte à un autre, et des exemples simples pour comprendre la puissance des vérifications d'ownership.&lt;/p&gt;

&lt;p&gt;Au final, &lt;strong&gt;Rust révèle les erreurs potentielles à la compilation plutôt que nous laisser subir les conséquences à l'exécution&lt;/strong&gt;, ce qui constitue une de ses plus grandes forces. Dites vous bien que si votre programme compile &lt;del&gt;enfin&lt;/del&gt;, c'est que votre code est sûr !&lt;/p&gt;

&lt;p&gt;On pourrait passer des journées entières à tester d'autres cas, mais c'est justement l'expérience pratique qui permet de découvrir les différentes problématiques au fil du temps. Je vous invite donc à expérimenter par vous même le borrow checker sur le &lt;a href="https://play.rust-lang.org"&gt;Rust Playground&lt;/a&gt; 😉&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"...et sinon, qu'en est-il des accès concurrents dans du multithreading ?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;C'est un autre sujet très intéressant que nous aborderons sans doute une prochaine fois, et vous verrez qu'avec des outils comme les &lt;code&gt;Mutex&amp;lt;T&amp;gt;&lt;/code&gt; et &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt;, on peut aussi venir efficacement à bout de ces problématiques ! Affaire à suivre...&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ownership</category>
      <category>memory</category>
      <category>allocation</category>
    </item>
    <item>
      <title>Javascript: on clone des robots !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Wed, 12 Apr 2023 15:02:11 +0000</pubDate>
      <link>https://dev.to/younup/javascript-on-clone-des-robots--4afn</link>
      <guid>https://dev.to/younup/javascript-on-clone-des-robots--4afn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Le Javascript est un langage souple qui peut paraître facile au premier abord. Mais je vous le dis : en réalité, il recèle de subtilités qui peuvent rapidement mettre le bazar si on ne les maîtrise pas !&lt;/p&gt;

&lt;p&gt;Une de ces subtilités dont on va parler aujourd'hui, c'est &lt;strong&gt;le clonage d'objets&lt;/strong&gt;. Et pour changer un peu des moutons, on va cloner des objets robots (n'en déplaise à Will Smith, alias Del Spooner) ! C'est parti !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib30ew8lq614fo528t0c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib30ew8lq614fo528t0c.jpg" alt="Binome Will Smith scientifique" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Le clonage naïf
&lt;/h2&gt;

&lt;p&gt;Partons du principe que l'on dispose d'une instance d'un premier prototype de robot, et que l'on veuille alors le cloner dans une production. Ici, on représentera une production par un tableau &lt;code&gt;production&lt;/code&gt; contenant nos robots :&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/xbxa8n?embed=1&amp;amp;file=index.ts&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;theme=dark" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;(Notez que pour aider à modéliser le problème, j'utiliserai du &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Résultat de la console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------- Production check -------
robot 1 = {id: 10, isConform: true}
robot 2 = {id: 10, isConform: true}
robot 3 = {id: 10, isConform: true}
robot 4 = {id: 10, isConform: true}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Quoi ?! Mais ils ont tous les mêmes identifiants !&lt;/em&gt; 😱&lt;/p&gt;

&lt;p&gt;Si vous le souhaitez, vous pouvez vous exercer à débugger le code ci-dessus en ajoutant du code et des logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fquwvsanrj5n46ud9jozj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fquwvsanrj5n46ud9jozj.jpg" alt="Will Smith devant clones" width="800" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et en effet, il y a bien un problème dans cette production : en JS, l'opérateur &lt;code&gt;=&lt;/code&gt; n'effectue &lt;strong&gt;Pas&lt;/strong&gt; de copie d'un objet ou d'un array à proprement parler, mais uniquement de la &lt;strong&gt;référence&lt;/strong&gt; de cet objet en question.&lt;/p&gt;

&lt;p&gt;Ainsi, &lt;code&gt;const newRobot = robotProto;&lt;/code&gt; ne crée pas un nouvel objet mais référence le robot proto. &lt;em&gt;A chaque&lt;/em&gt; tour de boucle.&lt;/p&gt;

&lt;p&gt;Du coup, sans le savoir, on a toujours affecté le même objet dans toutes les cases du tableau, et par conséquent modifié le même objet à chaque itération. Au final, on se retrouve évidemment avec la dernière valeur enregistrée : 10.&lt;/p&gt;

&lt;p&gt;Cette explication est d'ailleurs vérifiable avec l'opérateur de comparaison &lt;code&gt;===&lt;/code&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 2 contenus identiques mais dans des objets différents&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;robot1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isConform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;robot2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;isConform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;robot1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;robot2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// false =&amp;gt; pas les mêmes objets&lt;/span&gt;

&lt;span class="c1"&gt;//...et si on revient à notre production râtée&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;production&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;production&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// true =&amp;gt; c'est le même objet !&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bon, comment corriger cette production ?&lt;/p&gt;

&lt;h2&gt;
  
  
  Nouvel objet et spread operator
&lt;/h2&gt;

&lt;p&gt;Une solution consiste à utiliser le &lt;strong&gt;spread operator&lt;/strong&gt;. Combiné aux accolades &lt;code&gt;{}&lt;/code&gt; pour déclarer un nouvel objet, le spread operator &lt;code&gt;...&lt;/code&gt; permet de copier tous les champs de l'objet &lt;code&gt;robotProto&lt;/code&gt;. Très efficace si l'on a un paquet de champs à copier d'un coup !&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/xbxa8n-jn7qhc?ctl=1&amp;amp;embed=1&amp;amp;file=index.ts&amp;amp;hideExplorer=1&amp;amp;hideNavigation=1&amp;amp;theme=dark" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Résultat de la console :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;------- Production check -------
robot 1 = {id: 1, isConform: true}
robot 2 = {id: 2, isConform: true}
robot 3 = {id: 3, isConform: true}
robot 4 = {id: 4, isConform: true}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Aah c'est mieux !&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dans notre cas, cette solution minimaliste convient parfaitement !&lt;/p&gt;

&lt;p&gt;Sauf que cette technique a des limites... En effet, le spread operator souffre du même défaut que l'opérateur &lt;code&gt;=&lt;/code&gt; : il ne clone pas réellement les champs qui sont de type objets et arrays 😟&lt;/p&gt;

&lt;p&gt;Ainsi, si l'on enrichit la structure de données avec des objets à plusieurs niveaux, on retombe sur le problème des références aux niveaux plus profonds :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Robot&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;isConform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;eyesColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;material&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Robot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;isConform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;head&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;eyesColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;material&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;carbon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;badClone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;badClone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;//true =&amp;gt; on a encore le même objet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  La méthode stringify
&lt;/h2&gt;

&lt;p&gt;Une solution consiste à transformer un objet en string, puis le re-parser successivement :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRobot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cela peut paraître empirique, je vous l'accorde. Pourtant dans beaucoup de cas, c'est le meilleur équilibre entre fiabilité et rapidité d'exécution dans la catégorie du clonage en profondeur.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gros warning cependant&lt;/strong&gt; : du fait de la transformation intermédiaire en string, les types correctement pris en charge sont très limités. Les fonctions par exemple seront tout simplement perdues !&lt;/p&gt;

&lt;h2&gt;
  
  
  structuredClone
&lt;/h2&gt;

&lt;p&gt;La fonction &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/structuredClone"&gt;structuredClone&lt;/a&gt; est une nouveauté supportée par tous les principaux navigateurs depuis début 2022. Elle permet de cloner automatiquement et en profondeur tout le contenu d'un objet :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRobot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;L'avantage par rapport au &lt;code&gt;JSON.stringify&lt;/code&gt;, c'est qu'elle prend en charge plus d'objets spéciaux comme les Date, RegExp ou Set, mais toujours pas de prise en charge de types spéciaux comme les fonctions. Voir &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm#supported_types"&gt;ici la liste exhaustive&lt;/a&gt; des types supportés.&lt;/p&gt;

&lt;p&gt;Toute puissance ayant un coût, c'est également la méthode standard la plus lente à exécuter pour le clonage.&lt;/p&gt;

&lt;h2&gt;
  
  
  L'historique Object.assign
&lt;/h2&gt;

&lt;p&gt;Parce qu'il faut respecter les anciens 😄, je terminerai cette liste en évoquant &lt;code&gt;Object.assign&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Très similaire au spread operator, il a l'avantage de pouvoir modifier un objet déjà instancié tout en se conformant au type d'origine et à ses méthodes lorsque c'est une classe. Personnellement, je trouve qu'avec le Typescript cette méthode a moins de cas d'usage, car on va utiliser des types (comme l'&lt;code&gt;interface&lt;/code&gt;) qui vont déjà nous aider à garantir la conformité d'une structure de données avec ses attributs et ses fonctions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// usage basique dans notre cas&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRobot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;complexRobot&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mais tout comme le spread operator, il ne clone qu'au premier niveau, et ne copie que les références des objets et arrays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;De manière générale, il ne faut cloner que s'il y a un réel besoin. Si par défaut le clonage des objets et arrays n'est pas automatique, c'est qu'il y a une raison : l'optimisation.&lt;/p&gt;

&lt;p&gt;Mais dans le cas où le clonage est nécessaire, il vaut mieux choisir :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;le spread operator pour une copie à un seul niveau (sans objets ou arrays)&lt;/li&gt;
&lt;li&gt;l'&lt;code&gt;Object.assign&lt;/code&gt; pour une assignation à un seul niveau (sans objets ou arrays) plutôt pour des classes&lt;/li&gt;
&lt;li&gt;le JSON parse/stringify pour une copie en profondeur rapide (mais sans objets spéciaux)&lt;/li&gt;
&lt;li&gt;le structuredClone pour une copie en profondeur plus complète mais plus lente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et si aucune de ces méthodes standard n'est satisfaisante, je vous invite à chercher du côté d'une librairie comme &lt;a href="https://lodash.com/docs/#cloneDeep"&gt;lodash&lt;/a&gt;, ou à implémenter votre propre méthode de clonage adaptée à votre cas d'usage !&lt;/p&gt;

&lt;p&gt;Comme toujours, il faut s'adapter à chaque situation...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla7u1w0bjklshcc7mo4v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fla7u1w0bjklshcc7mo4v.jpg" alt="Will Smith posé" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>clone</category>
      <category>object</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Rust : l'héritage n'existe pas !</title>
      <dc:creator>Jean-Noël</dc:creator>
      <pubDate>Fri, 21 Oct 2022 08:32:13 +0000</pubDate>
      <link>https://dev.to/younup/rust-lheritage-nexiste-pas--5dc1</link>
      <guid>https://dev.to/younup/rust-lheritage-nexiste-pas--5dc1</guid>
      <description>&lt;h1&gt;
  
  
  Rust : l'héritage n'existe pas
&lt;/h1&gt;

&lt;p&gt;Après avoir vu le dernier opus de la saga &lt;em&gt;The Matrix&lt;/em&gt;, j'ai été pris d'une envie de revenir aux sources. Alors, ici, il ne sera pas question de critique de film, mais de revenir sur un sujet technique essentiel qu'est l'héritage.&lt;/p&gt;

&lt;p&gt;Tenez, Rust par exemple. Un langage natif, certes, mais moderne (&lt;a href="https://www.younup.fr/blog/rust-ce-langage-natif-safe-et-puissant" rel="noopener noreferrer"&gt;article découverte ici&lt;/a&gt;). Eh bien ! il faut faire éclater une vérité, Néo : en Rust, l'héritage n'existe pas !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3p5gaz3guadohrilz7b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3p5gaz3guadohrilz7b.jpg" alt="la cuillère n'existe pas"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alors dans ce cas, comment transmettre des fonctions ou des propriétés qui sont communes à de multiples structures de données, ou encore imposer un pattern de fonctionnalités ? Bref, ce qu'on a toujours fait avec les classes abstraites en C++, par exemple ?&lt;/p&gt;

&lt;p&gt;Si vous aussi vous vous êtes déjà posé ces questions, alors suivez le lapin blanc...&lt;/p&gt;

&lt;p&gt;Note : tous les extraits de code ci-après sont testables sur le &lt;a href="https://play.rust-lang.org/" rel="noopener noreferrer"&gt;Playground Rust&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pas d'héritage : pourquoi ?
&lt;/h2&gt;

&lt;p&gt;Soyons clair, l'héritage est un concept essentiel de la programmation orientée objet (OOP en anglais), ce que Rust n'est pas.&lt;/p&gt;

&lt;p&gt;Rust est un &lt;strong&gt;langage C-like&lt;/strong&gt; où les "classes" sont avant tout des structures de données, et pas nécessairement des fonctionnalités. C'est aussi un langage qui se veut &lt;strong&gt;explicite&lt;/strong&gt;. En C++, à travers plusieurs héritages successifs, on a tendance à perdre cet aspect.&lt;/p&gt;

&lt;p&gt;En Rust, on est incité à coder des &lt;strong&gt;petits modules indépendants et génériques&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Bien entendu, Rust n'est pas en reste (haha) pour autant. Il a été pourvu d'un minimum vital pour gérer un certain niveau d'abstraction. Il y a principalement 2 solutions qui s'offrent à vous : les traits et les compositions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1yv22ukdc56nuc9v5te.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1yv22ukdc56nuc9v5te.jpg" alt="Dilemne des pilules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilule rouge : les traits
&lt;/h2&gt;

&lt;p&gt;Un &lt;code&gt;trait&lt;/code&gt; est l'équivalence d'une interface en Java : on impose l'implémentation d'une liste de fonctions.&lt;/p&gt;

&lt;p&gt;Prenons l'exemple des 3 grands agents du film : Smith, Jones et Brown (si vous ne connaissiez pas les 2 derniers noms, c'est cadeau !). Ils font initialement tous partie d'une même faction : les agents. Un agent, quel qu'il soit, doit être en mesure de repérer et d'éliminer les anomalies de la Matrice.&lt;/p&gt;

&lt;p&gt;Si on devait les modéliser avec des &lt;code&gt;struct&lt;/code&gt; on pourrait donc imposer la compétence &lt;code&gt;eliminer_anomalies&lt;/code&gt; de cette manière :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Trait générique&lt;/span&gt;
&lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Différentes "classes"&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Smith&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Jones&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Brown&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// Implémentations des traits&lt;/span&gt;
&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Smith&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Smith doit éliminer anomalies"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Jones&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Jones doit éliminer anomalies"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Brown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Brown doit éliminer anomalies"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;agent_smith&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Smith&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;agent_jones&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Jones&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;agent_brown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Brown&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

    &lt;span class="n"&gt;agent_smith&lt;/span&gt;&lt;span class="nf"&gt;.eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Smith doit éliminer anomalies"&lt;/span&gt;
    &lt;span class="n"&gt;agent_jones&lt;/span&gt;&lt;span class="nf"&gt;.eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Jones doit éliminer anomalies"&lt;/span&gt;
    &lt;span class="n"&gt;agent_brown&lt;/span&gt;&lt;span class="nf"&gt;.eliminer_anomalies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Brown doit éliminer anomalies"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Voilà nos 3 agents opérationnels !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yrfvrqzr1d5em8xjeu9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yrfvrqzr1d5em8xjeu9.jpg" alt="Les 3 agents"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pour information, on peut voir les traits en Rust un peu comme des traits de caractère d'un personnage : une structure peut également implémenter autant de traits que nécessaire.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilule bleue : les compositions
&lt;/h2&gt;

&lt;p&gt;Autre solution à préférer si vous avez besoin de transmettre des propriétés (et des fonctions par la même occasion) : composer les structures entre elles. C'est ce qui se rapproche le plus d'un "héritage" de propriétés.&lt;/p&gt;

&lt;p&gt;Plaçons nous cette fois-ci du côté des êtres humains. Ils ont chacun un nom et peuvent évoluer au sein de la Matrice. Puis il y a les humains libérés qui en plus ont la capacité de sortir de la Matrice comme bon leur semble. Et pour finir, il y a l'élu : il dispose de toutes les capacités précédentes, et en plus il sait voler (le veinard !).&lt;/p&gt;

&lt;p&gt;On pourrait donc imaginer une modélisation de ces classes de personnes comme suit :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Humain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;nom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Humain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;evoluer_dans_matrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Dans la matrice..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;humain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Humain&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;sortir_de_la_matrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hors de la matrice..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Elu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;libere&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Elu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// (constructeur pour gagner en lisibilité)&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Elu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;libere&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;humain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Humain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;nom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;String&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Néo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;voler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Vole dans les airs !"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;elu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Elu&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nom de l'élu: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="py"&gt;.libere.humain.nom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Nom de l'élu: Néo"&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="py"&gt;.libere&lt;/span&gt;&lt;span class="nf"&gt;.sortir_de_la_matrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Hors de la matrice..."&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="py"&gt;.libere.humain&lt;/span&gt;&lt;span class="nf"&gt;.evoluer_dans_matrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Dans la matrice..."&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="nf"&gt;.voler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Vole dans les airs !"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ainsi, Néo hérite bien de toutes les compétences et propriétés en tant qu'élu et humain libéré. Evidemment d'un point de vue modélisation UML, l'élu devrait être une instance unique, mais ce n'est pas le sujet ici.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7w0dl9t9a85oponshtf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7w0dl9t9a85oponshtf.gif" alt="Néo qui vole"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Petit inconvénient : la composition n'impose pas l'implémentation de fonctions. Pour ça, il faut compléter avec les &lt;code&gt;trait&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Vous l'aurez compris, il y a un autre inconvénient bien plus visible : le code est bien explicite, mais il faut traverser toute la hiérarchie manuellement pour accéder aux propriétés les plus hautes. Pas toujours folichon.&lt;/p&gt;

&lt;p&gt;En réalité, il existe une astuce lorsque la profondeur de données devient trop grande...&lt;/p&gt;

&lt;h2&gt;
  
  
  Ptit verre d'eau pour faire passer : Deref
&lt;/h2&gt;

&lt;p&gt;Le trait &lt;a href="https://doc.rust-lang.org/std/ops/trait.Deref.html" rel="noopener noreferrer"&gt;std::ops::Deref&lt;/a&gt; sert à la base à surcharger le déréférencement des pointeurs, et il est conseillé de plutôt les utiliser sur les &lt;em&gt;smart pointers&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Mais ici nous allons l'utiliser pour simplifier l'accès à nos variables, en ajoutant :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;ops&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Deref&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Deref&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Humain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;deref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Humain&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.humain&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Deref&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;Elu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Libere&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;deref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Libere&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.libere&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nous pouvons alors changer notre main :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nom de l'élu: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="py"&gt;.nom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Nom de l'élu: Néo"&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="nf"&gt;.sortir_de_la_matrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Hors de la matrice..."&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="nf"&gt;.evoluer_dans_matrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Dans la matrice..."&lt;/span&gt;
    &lt;span class="n"&gt;elu&lt;/span&gt;&lt;span class="nf"&gt;.voler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Vole dans les airs !"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Et hop, un accès direct !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dbkazla2pc12whaqwnk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dbkazla2pc12whaqwnk.gif" alt="Néo met ses lunettes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si besoin, il faudra aussi implémenter le trait &lt;a href="https://doc.rust-lang.org/std/ops/trait.DerefMut.html" rel="noopener noreferrer"&gt;std::ops::DerefMut&lt;/a&gt; pour obtenir un accès mutable à ces éléments. Rappelez vous : par défaut, tout est immuable en Rust.&lt;/p&gt;

&lt;p&gt;Toutefois, retenez bien que c'est plus un hack utilitaire. À utiliser avec modération donc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;L'héritage en Rust est un sujet qui revient régulièrement dans les discussions et les demandes d'évolution du langage. Mais bien que Rust ne soit pas un langage fondamentalement orienté objet, il dispose tout de même de fonctionnalités suffisantes pour gérer les abstractions. C'est aussi un coup à prendre ! Une autre façon de coder.&lt;/p&gt;

&lt;p&gt;En résumé, privilégiez une déclaration explicite avec des &lt;code&gt;trait&lt;/code&gt;s pour des fonctions virtuelles, et passez plutôt par des compositions de &lt;code&gt;struct&lt;/code&gt; pour transmettre des propriétés.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxlazeexii9yn2pxfswz.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwxlazeexii9yn2pxfswz.gif" alt="La matrice qui défile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;One More thing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pour votre curiosité, il existe un &lt;code&gt;crate&lt;/code&gt; (comprenez module) intitulé &lt;code&gt;inheritance&lt;/code&gt; en &lt;a href="https://docs.rs/inheritance/0.0.1-alpha.2/inheritance/index.html" rel="noopener noreferrer"&gt;version alpha&lt;/a&gt;. Il propose des macros pour implémenter automatiquement des traits sans avoir besoin de les réécrire dans toute la hiérarchie. Mais qui est seulement resté au stade expérimental...&lt;/p&gt;

</description>
      <category>rust</category>
      <category>heritage</category>
      <category>matrix</category>
    </item>
  </channel>
</rss>
