#1 Ma vie de Principal Engineer
On me demande souvent “Mais c’est quoi ton taf ? Que fais tu de tes journées ?”
⚠️ Pensez à télécharger les images ou à lire cette lettre dans le navigateur sinon vous ratez une partie du contenu
Mon travail consiste à faire en sorte que Sipios soit une boîte d’artisans passionnés qui s’épanouissent en livrant des produits de qualité.
Pour ça, voici à quoi j’occupe mes journées :
Du pair programming
Dans mon agenda, tous les mercredi matin il y a un créneau réservable pour faire du pair programming (PP) ou du mob
Pour le moment il n’y a qu’un créneau par semaine. Si la demande augmente j’en ajouterai 😉
Ce que j’adore avec le PP c’est que quelque soit notre niveau on a toujours un truc ou deux à apprendre.
Comment tester des services tierce-partie
Avec Eloi nous avons vu
Comment tester une requête construite avec Retrofit
Comment mocker un service externe SOAP
Découvrir une pépite
Nous avons également eu le plaisir de constater que Vavr était dans les dépendances de Mothership (Projet BPI) !
Vavr (prononcer “vaveur”) est une librairie qui introduit des patterns de programmation fonctionnelle (FP) en Java.
Si vous voulez apprendre des patterns de FP, vous pouvez upvoter ce talk du vendredi :
Ecrire des tests avec Angular Testing Library
Avec Loona nous avons essuyé quelques plâtres en écrivant ce test :
test('should close the modal on save click with valid values', async () => {
await setup({ ... });
...
const submitButton = screen.getByRole(...);
userEvent.click(submitButton);
expect(closeFn).toHaveBeenCalled();
});
Stupeur : le test se comporte comme si le clic n’avait jamais lieu. pourtant un console.log nous montre que la callback sur le bouton est bien invoquée !
Google ne nous a pas été d’une grande aide sur ce coup. En revanche l’IDE essayait de nous dire un truc depuis le début :
💡Toutes les interactions utilisateur (userEvent
) sont des Promises et doivent être décorées avec await
sinon le test arrive sur l’expect avant d’avoir effectué l’action.
Améliorer sa pratique
Ne le prenez pas mal mais parfois en pair ce gag de Leonard me vient irrésistiblement en tête
L’IDE n’est pas un simple éditeur de texte très gourmand en ressources, il peut écrire la plupart du code à votre place !
💡 Pro-tip, commencez par écrire ce que vous voulez obtenir et laissez l’IDE vous guider.
Par exemple prenons cette méthode :
public static String getMainReviewerFromProject(
DetailedProjectDto project
)
{
if (project.getUserAuthorisations() == null) return null;
return project
.getUserAuthorisations()
...
.orElse(null);
}
Nous voulons qu’elle retourne un Optional plutôt que null.
Commençons (bien sûr) par écrire un test pour fixer l’objectif
F2 (jump to error)
Alt-Entrée (ouvrir le menu contextuel)
flèche du bas pour sélectionner “Create local variable”
Et hop l’IDE m’a généré la variable avec le bon type
F2
Alt-Entrée
“Initialize variable”
Je sélectionne new DetailedProjectDto()
et il n’y a plus d’erreur de compilation.
Je peux maintenant passer à la suite :
Je tape “Opt” et l’IDE me propose directement “Optional<T>” je n’ai qu’à appuyer sur Entrée
Ensuite je choisis le nom de la variable
F2
Alt-Entrée
“Make getMainReviewerFromProject return Optional”
Mon test compile.
Maintenant c’est le code de prod qui ne compile plus bien sûr.
Je mets mon curseur sur getMainReviewerFromProject
et je fais Ctrl-b (goto declaration)
F2 pour voir ce que l’IDE me propose
Pour le coup mon IDE ne me propose aucune action intéressante. Mais le fix est facile il me suffit de retirer le orElse
final.
Je place mon curseur sur orElse
Ctrl-w (widen scope) pour sélectionner toute l’expression “orElse(null)”
3x Shift-Backspace pour effacer en conservant la mise en forme
Il me reste le return null pour lequel l’IDE affiche un warning
Shift-F2 (comme F2 mais en remontant dans le code source)
Alt-Entrée
J’adore mon IDE, il a compris mon intention et me propose de remplacer null par Optional.empty()
Sur mon clavier les touches F2, Alt et Entrée sont très usées mais le reste est flambant neuf 😄
Bien sûr vos raccourcis peuvent être différents des miens. Si vous utilisez IntelliJ je recommande ce plugin pour vous aider à prendre de bonnes habitudes :
L’idée principale : laisser l’IDE écrire le code “de construction”. Ce qui vous revient c’est de nommer les variables et de choisir les algo.
Souvent le dev inexpérimenté sous-estime la puissance de refacto d’un bon IDE en se disant que si ce n’est pas évident pour lui (le dev) alors comment une machine pourrait comprendre son intention ?
Mais l’IDE a un atout dans sa manche : l’Abstract Syntax Tree.
Pour en savoir plus, please upvote ce talk du vendredi :
Formations Craft
Une autre partie importante de mon taf consiste à préparer des formations pour les techs.
Ces formations ont pour but d’améliorer la qualité des produits livrés par Sipios.
Mes inputs sont :
La classifications des bugs remontés par les équipes
Les interviews avec les développeurs afin de cerner les compétences qu’ils aimeraient acquérir et les problèmes rencontrés sur le terrain
Eviter les bugs liés à une mauvaise compréhension du domaine métier
La première formation portait sur le Domain Driven Design (DDD) pour sensibiliser les équipes aux problématiques métier.
Concrètement il s’agit de former les tech leads (TL) à mettre en place un indicateur au niveau d’un projet pour mesurer l’adéquation entre le code et le domaine métier.
C’est un travail itératif et après quelques retours la documentation a été mise à jour
Apprendre à reconnaitre un mauvais pattern et à y remédier
C’est toujours facile de dire qu’un code est “moche”. Mais expliquer pourquoi et comment y remédier est plus délicat. C’est l’objet de cette autre formation sur les code smells
Le format self-service permet de se former tout seul à n’importe quel moment. Une première partie théorique est suivi de quelques kata, ici sous forme de Google Forms, vous pouvez même les faire dans les transports sur votre smartphone 😉.
Veille
Ma veille je la fais plutôt sur mon temps libre. Mais le poste de PE me demande encore + d’être à jour sur ce qui se passe dans notre industrie.
Aujourd’hui je souhaite vous partager cette vidéo sur les nouveautés très excitantes qui arrivent (beaucoup sont en preview) sur Java 19
Et comme il n’y a pas que Java dans la vie, voici un autre article sur Angular 14
Puzzler du jour
Question naïve
Sur la Terre, le 30 octobre 2022,
Un évènement A a lieu à 2h30
Un évènement B a lieu à 0h30
⇒ Est-ce que les évènements A et B sont simultanés ?
Bien sûr vous sentez le piège et vous allez me demander “Dans quelle timezone ?”
Je précise donc :
A a lieu à 2h30 dans la zone “Europe/Paris”
B a lieu à 0h30 UTC
Et là vous allez vous demander “Ok, Europe/Paris selon qu’on est en heure d’hiver (CET) ou en heure d’été (CEST) l’offset est respectivement +1 ou +2. Il suffit donc de vérifier si le 30 octobre 2022 est dans la période hiver ou été”
Tiens tiens, le 30 octobre 2022 c’est pile le jour où on change d’horaire !
Pas de problème, est-ce que 2h30 se situe avant ou après le changement d’horaire ?
Et là… C’est le drame. Quand on passe en heure d’hiver, la plage de 2h à 3h devient ambiguë (on appelle ça un chevauchement (overlap)).
Elle peut correspondre à la plage 0h - 1h UTC (heure d’été) ou 1h - 2h UTC (heure d’hiver).
Conclusion intermédiaire
Parler de Zone “Europe/Paris” est ambigu. Il vaut mieux parler d’offset.
Ceci dit dans un programme quand on déclare une horloge on a envie qu’elle change d’heure en même temps que nous et on a envie de la déclarer comme ceci (en Java) :
Clock.system(ZoneId.of("Europe/Paris"))
Et non comme cela (décalée d’une heure la moitié de l’année) :
Clock.system(ZoneOffset.ofHours(+1))
La vraie question
Supposons qu’on a déclaré une ZonedDateTime comme ceci (2h30, le 30 octobre 2022, heure de Paris) :
ZonedDateTime zonedDateTime = ZonedDateTime.of(2022, 10, 30, 2, 30, 0, 0, ZoneId.of("Europe/Paris"))
Que retourne l’expression zonedDateTime.toInstant().toString()
?
2022-10-30T00:30:00Z
?2022-10-30T01:30:00Z
?
Et surtout : pourquoi ?
La réponse au prochain numéro !