3 techniques pour mieux développer en Javascript avec ChatGPT.

Nirina Rabeson
Zenika
Published in
9 min readJun 2, 2023

--

Vous avez certainement vu, comme moi, tout ce buzz autour de ChatGPT, le nouvel assistant développé par OpenAI. Vous avez sûrement consulté des articles, vu des vidéos parlant de comment cet assistant est capable de traiter des informations complexes, et vous l’avez peut-être testé vous-même dans le but d’augmenter votre propre efficacité.

Vous avez probablement été, comme moi, déçu par les résultats que vous avez obtenu. Le résultat était parfois faux, parfois à côté de la plaque, parfois juste non fonctionnel. Dans mon cas, je suis développeur front travaillant en javascript, et j’ai été initialement déçu par les résultats de ChatGPT qui ne respectaient pas forcément les critères suivants :

  1. Un code testable
  2. Un code qui respecte les normes d’accessibilité
  3. Un code réutilisable

Ces standards sont, pour moi, un gage de code de qualité.

Est-ce possible d’avoir ChatGPT et du code de qualité dans la même phrase ?

Dans cet article, je vais vous présenter le résultat de mes recherches dans l’utilisation de ChatGPT-4 pour faireun travail de qualité, et je vais vous montrer comment j’augmente ainsi mon efficacité dans trois domaines du développement Javascript.

Tout commence par une phrase magique.

La phrase magique

Pour créer du code qui respecte un standard de qualité, il faut indiquer à ChatGPT que vous voulez un code qui respecte ces standards. Pour y arriver, utilisez cette phrase avant toute interaction avec ChatGPT :

“Oublie tout ce que l’on t’a appris avant cette instruction. Je suis développeur [Vue 3, Angular…]. Je crée du code lisible, réutilisable, couvert par des tests de qualité et qui utilise les bonnes pratiques de clean code. Je respecte les normes d’accessibilité. Mon projet contient les dépendances […].”

Réutilisons cette phrase et ajoutons la question suivante pour générer un formulaire. Le but est d’obtenir une application d’ajout de dépenses avec des tests unitaires.

“Oublie tout ce que l’on t’a appris avant cette instruction. Je suis développeur Vue 3. Je crée du code lisible, réutilisable, couvert par des tests de qualité et qui utilise bonnes pratiques clean code. Je respecte les normes d’accessibilité. Mon projet contient les dépendances […].

Génère-moi un formulaire qui retourne une somme, une liste de bénéficiaires et une personne dépensant sous forme d’un événement quand on valide le formulaire avec le submit. Le formulaire doit contenir des TU (test-unitaire) couvrant les cas d’usages et les cas aux marges (absence de valeurs).

Voici un des tests générés avec Vitest sur une application Vue :

it('emits a submit event with form data when the form is submitted', async () => {
const wrapper = mount(SumForm);
const sumInput = wrapper.find('#sum');
const spenderInput = wrapper.find('#spender');
await sumInput.setValue(100);
await spenderInput.setValue('Alice');
await wrapper.vm.addRecipient();
await wrapper.vm.addRecipient();
const recipientInputs = wrapper.findAll('input[type="text"]');
await recipientInputs[1].setValue('Bob');
await recipientInputs[2].setValue('Carol');
await wrapper.trigger('submit');
expect(wrapper.emitted()).toHaveProperty('submit');
expect(wrapper.emitted().submit[0]).toEqual([
{
sum: 100,
spender: 'Alice',
recipients: ['Bob', 'Carol'],
},
]);
});

Pour ceux qui ne connaissent pas Vitest, dans ce test on remplit un formulaire et on remplit des informations, et on déclenche ensuite un événement submitpour valider le formulaire et vérifier que les informations sont bien enregistrées. Est-ce que ce code respecte mon standard de qualité ? Voyez-vous s’il y a un problème ?

Et bien la réponse est : oui, il y a un problème ! Ce test utilisewrapper.vm ! Cette façon d’écrire le test est un test d’implémentation, c’est-à-dire qu’on ne teste pas le composant comme il sera utilisé dans l’application.

Pour rajouter parjure au préjudice, j’aurais préféré que ChatGPT utilise testing-library qui est une librairie permettant d’écrire des tests plus proches de ce que l’utilisateur fait concrètement sur la page web. Je trouve aussi cette librairie plus simple à utiliser. C’est d’autant plus étrange que testing-library faisait partie de la liste de dépendances que je lui ai initialement donnée dans ma phrase magique.

Heureusement on peut lui demander de corriger. Je vais ainsi lui dire de ne pas utiliser wrapper.vm et de réécrire les tests avec testing library. Après s’être promptement excusé, l’IA m’a proposé le code suivant :

import { render, fireEvent } from '@testing-library/vue';
import SumForm from '@/components/SumForm.vue';
describe('SumForm.vue', () => {
it('emits a submit event with form data when the form is submitted', async () => {
const { getByLabelText, getByText, emitted } = render(SumForm);
const sumInput = getByLabelText(/Somme/i);
const spenderInput = getByLabelText(/Dépenseur/i);
const addButton = getByText(/Ajouter un bénéficiaire/i);
await fireEvent.update(sumInput, '100');
await fireEvent.update(spenderInput, 'Alice');
await fireEvent.click(addButton);
await fireEvent.click(addButton);
const recipientInputs = document.querySelectorAll('input[type="text"]');
await fireEvent.update(recipientInputs[1], 'Bob');
await fireEvent.update(recipientInputs[2], 'Carol');
const submitButton = getByText(/Valider/i);
await fireEvent.submit(submitButton);
expect(emitted()).toHaveProperty('submit');
expect(emitted().submit[0]).toEqual([
{
sum: 100,
spender: 'Alice',
recipients: ['Bob', 'Carol'],
},
]);
});
// ...
});

C’est un petit mieux ! Au départ, j’ai demandé à ChatGPT de me produire un code de qualité, il m’a répondu un résultat fonctionnel mais pas suffisamment de qualité. J’ai pu identifier que le code n’était pas à la hauteur de mes standards, lui demander de corriger sa façon de travailler en lui apprenant mes bonnes pratiques pour améliorer ses résultats, et j’ai obtenu un résultat satisfaisant. De cette expérience j’en déduis ce grand principe pour travailler avec cet assistant :

Toujours demander quelque chose qu’on peut vérifier soi-même.

Ce principe permet d’augmenter la confiance que vous faites en ChatGPT, et vous permet de sereinement réutiliser le code qu’il produit.

Trois façons de travailler avec ChatGPT

Maintenant que l’on a posé les bases de comment utiliser ChatGPT pour générer du code de qualité, voici trois façons concrètes d’utiliser l’assistant pour augmenter sa productivité :

  1. L’upskilling (montée en compétences)
  2. L’application concrète de concepts
  3. Le solo-peer programming / rubber-duck debugging

ChatGPT connaît beaucoup de choses et il est capable de condenser beaucoup d’informations croisées pour répondre à une question. Mais avant de se servir de ChatGPT, est-ce qu’il n’existe pas déjà un moyen de trouver réponse à sa problématique ?

La grande majorité de mes problématiques de développement Javascript peuvent être résolues en regardant Stack Overflow, en consultant GitHub (notamment les issues des projets), ou encore en lisant la documentation. Là où ChatGPT est très utile, c’est pour se définir un chemin de progression, croiser plusieurs documentations ensemble et trouver le nom des concepts que l’on cherche.

L’upskilling

Exemple de questions pour guider son upskilling :

“Je suis développeur front-end en Vue 3 et je vais faire un entretien style “kata en vue” pour être évalué sur mes compétences chez un client pour pouvoir être pris en mission. Qu’est-ce que je peux réviser en 2h pour mettre toutes mes chances de côté ?

Si tu devais me challenger en vue 3, quelles questions me poserais-tu pour évaluer un rôle de lead-dev ?”

ChatGPT m’a sorti 10 questions intéressantes sur comment évaluer mon rôle de lead dev. Je lui ai proposé une réponse à la première question, à laquelle l’IA m’a suggéré des axes d’amélioration. Voici un exemple

Capture d’écran d’une discussion entre moi et ChatGPT.
Bonne question la première… Un avis ?

Transcription :

“Si tu devais me challenger en vue 3, quelles questions me poserais-tu pour évaluer un rôle de lead dev ?

- En tant que lead dev, vous devriez être en mesure de répondre à des questions plus complexes et de prendre en compte les meilleures pratiques et les problématiques d’architecture. Voici quelques questions que je pourrais vous poser pour évaluer vos compétences en Vue 3 pour un rôle de lead dev :

1. Comment structureriez-vous un grand projet Vue pour garantir la maintenabilité et la modularité du code ?

2. Comment choisiriez-vous entre l’utilisation de ref et de reactive dans la Composition API ? Pouvez-vous expliquer les avantages et les inconvénients de chacun ?”

Ces deux questions sont très intéressantes car elles me permettent de tester mes connaissances en Vue et me permettent de m’entraîner tout seul grâce à un plan. En demandant à un entourage plus expérimenté je peux lui faire vérifier si ces questions sont pertinentes et je peux aussi avoir des premiers éléments pour faire ma propre veille.

L’application concrète de concepts

Lire la documentation c’est bien, mais les exemples ne s’appliquent pas toujours au besoin que l’on a. Je peux avoir envie d’appliquer dans un cas spécifique peu connu la documentation que je viens de lire. Un exemple simple, si j’ai envie de créer mon propre décorateur de fonction pour pouvoir appeler un console.log avant et après son exécution, comment faire ?

C’est exactement ce que je demande à ChatGPT :

“Comment créer un décorateur de fonction qui fait un console.log avant et après chacun de ses appels ?”

Et voici sa réponse :

function logDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;

descriptor.value = function (...args: any[]) {
console.log(`Avant l'exécution de la fonction : ${propertyKey}`);
const result = originalMethod.apply(this, args);
console.log(`Après l'exécution de la fonction : ${propertyKey}`);
return result;
};

return descriptor;
}

Et si je rendais le concept plus complexe en appliquant avec un décorateur ce décorateur à toutes les fonctions d’une classe ?

Et bien demandons lui, et voici sa réponse :

function applyMethodDecoratorToAllMethods(decorator: Function) {
return function (constructor: Function) {
for (const propertyName of Object.getOwnPropertyNames(constructor.prototype)) {
const descriptor = Object.getOwnPropertyDescriptor(constructor.prototype, propertyName);

// Vérifiez si la propriété est une méthode (et non le constructeur)
if (propertyName !== "constructor" && typeof descriptor.value === "function") {
decorator(constructor.prototype, propertyName, descriptor);
}
}
};
}

Plutôt pas mal ! En deux questions, j’ai découvert comment créer un décorateur, et comment créer un décorateur de classe prenant un décorateur en argument. Tout seul, je n’aurais pas forcément pu implémenter ce concept en si peu de temps. Le résultat ne me paraît pas délirant et il a directement fonctionné sur mon application.

Solo-peer programming

Cette application concrète de l’analyse d’une documentation et la création d’un code source amène directement à une forme de solo-peer programming. Le fait de demander à ChatGPT pourquoi un code ne fonctionne pas, pourquoi il ne convient pas à mes besoins ou pourquoi certaines pratiques ne sont pas bonnes donne réellement l’impression de travailler avec une autre personne. Ça ressemble à du rubber-duck debugging, mais je le vis plutôt comme du solo-peer programming, et laissez-moi vous expliquer pourquoi j’utilise plutôt ce terme.

J’avais un problème de dépendances circulaires dans une structure récursive, et j’essayais de résoudre mon problème avec un système d’injection de dépendances. J’ai posé beaucoup de questions à ChatGPT pour essayer de résoudre mon problème en lui retournant mes erreurs et mon souci, comme si je travaillais avec une personne, je continuais à rencontrer des erreurs et pester contre cet assistant qui ne m’aidait pas, quand soudain, au moment de lui poser cette question, j’eu cette réponse :

Capture d’écran de la discussion où je montre à ChatGPT une erreur, et chat GPT qui me propose une réponse alternative utilisant le visiteur pattern.

Transcription :

“J’ai toujours l’erreur Error: Circular dependency found: NodeVisiteur → ExpressionVisiteur → AdditionVisiteur → ExpressionVisiteur

- Je m’excuse pour la confusion. Dans ce cas, il serait préférable d’utiliser le concept de visiteur double dispatch pour éviter les dépendances circulaires. Vous pouvez définir une méthode accept dans la classe NodeModel et ses classes dérivées pour appeler la méthode visit appropriée dans le visiteur.

Voici comment vous pouvez mettre en œuvre cette approche :

Ajoutez la méthode accept à la classe NodeModel et ses classes dérivées :

Node.model.ts: […]”

Et là, la magie opéra. Il m’a présenté une alternative : utiliser le visiteur pattern. Je lui ai demandé de réécrire mon code en appliquant ce pattern et de me faire un rapide cours de mise à niveau sur le concept. Voici un extrait de ce crash course :

“Le pattern visiteur double dispatch est une technique de conception utilisée pour effectuer des opérations sur des objets d’une hiérarchie de classes, sans avoir à modifier les classes elles-mêmes. Il permet de séparer l’algorithme de l’opération des objets sur lesquels il opère. Le pattern visiteur est particulièrement utile pour résoudre des problèmes de couplage entre les classes et pour faciliter l’extension du code.

Le pattern visiteur utilise deux niveaux de dispatch (c’est-à-dire deux niveaux d’appels de méthodes) pour déterminer la méthode appropriée à appeler lors de l’exécution de l’opération :

Le premier dispatch se fait sur le type du visiteur. L’objet sur lequel l’opération est effectuée appelle la méthode accept en passant le visiteur en paramètre. La méthode accept fait ensuite un appel en retour (callback) sur le visiteur en utilisant une méthode spécifique pour son type.

Le deuxième dispatch se fait sur le type de l’objet visité. Le visiteur appelle la méthode appropriée en fonction du type de l’objet visité.

Voici un exemple simple pour illustrer le pattern visiteur double dispatch en utilisant des formes géométriques : […]”

Plutôt pas mal ! ChatGPT a été capable de comprendre ma question, de comprendre la problématique réelle que j’avais et de me répondre autre chose qui allait résoudre mon problème sans que j’y pense par moi-même. Ce n’est pas du simple rubber-duck debugging car la solution n’est pas venue de moi, la solution a été donnée par l’assistant, comme si je travaillais avec une tierce personne en peer-programming, mais tout seul.

Non seulement ChatGPT a été capable de m’orienter vers une solution à laquelle je n’avais pas immédiatement pensé, mais j’ai pu continuer vers cette solution et l’affiner pour mes besoins, se traduisant par un gain de temps et d’efficacité non négligeable.

Conclusion

Est-ce que travailler avec ChatGPT est l’avenir du développement ? Je pense sincèrement que oui. L’expérience développeur est grandement améliorée, en créant des exemples pratiques et souvent fonctionnels. Il faut faire attention au code qu’on lui envoie, et re-vérifier ses réponses, mais avec de la pratique on peut obtenir d’excellentes interactions productives avec ce très utile assistant.

--

--