⚠️ Lisez cette lettre dans votre navigateur pour profiter des corrections de dernière minute
Les liens marqués avec 🔒 sont accessibles seulement aux membres du groupe Theodo
(\ /)
( . .)
o((")(")Pôle de formation Craft
Je parle ici de mes activités transverses au sein de Sipios
Pair programming
Afin d’organiser les séances de pair programming que je vais passer avec les équipes je me suis équipé d’un managment visuel.
Chauvinisme oblige je suis passé à Mistral pour m’aider à écrire les scripts de récupération et mise en forme de l’information. Qualitativement je n’ai noté aucune différence notable entre Mistral et ChatGPT 3.5, mise à part que Mistral, en plus d’expliquer ce que fait le code qu’il propose, ajoute des commentaires dans le code, presque à chaque ligne.
On aime ou on aime pas, mais en ce qui me concerne j’ai pu ainsi obtenir facilement la liste des projets triés en fonction de leur flux hebdomadaire de bug
Améliorer sa pratique
Quelques réflexions issues de mes observations sur les projets
ngSwitchCase sur un tableau vide
Avec VincentD nous avons besoin d’implémenter un cas assez courant : un composant Angular affiche des données dans un tableau :
Tant que les données ne sont pas téléchargé on affiche un spinner.
Si les données sont vides on affiche une illustration pour indiquer à l’utilisateur qu’il n’a rien à faire
Sinon on affiche le tableau.
Nous avons implémenté cette logique dans le template :
<ng-container [ngSwitch]="data">
<spinner *ngSwitchCase="null">...
<no-data *ngSwitchCase="[]">...
<data-table *ngSwitchDefault>...
</ng-container>ngSwitch prend en argument une “switch expression” et ngSwitchCase une “match expression”. Au runtime Angular réalise l’évaluation suivante :
switch_expression === match_expressionTous les ngSwitchCase pour lesquels cette évaluation retourne true sont ajoutés au DOM. Si aucun n’est ajouté, alors ngSwitchDefault est ajouté au DOM.
Seulement nous ignorions que même si data est un tableau vide, [] === [] retourne false ! ([] == [] aussi d’ailleurs)
Heureusement dans notre cas le contournement est facile :
<ng-container [ngSwitch]="data?.length">
<spinner *ngSwitchCase="undefined">...
<no-data *ngSwitchCase="0">...
<data-table *ngSwitchDefault>...
</ng-container>Veille
Quelques pépites que j’ai envie de partager avec vous
JPA est une API fort bien adaptée aux architectures en couches. Pour toutes les autres je suis plutôt promoteur de jOOQ. Mais cela pourrait bien changer avec l’arrivée de Jakarta Data 1.0 qui bouscule le game ! De quelle façon ? Tout est expliqué ici :
IntelliJ 2024.1 vient de sortir ! Ce que je retiens : les sticky lines qui facilitent la lecture de code trop volumineux, le full-line code completion (merci l’IA mais pourrais-tu ajouter les imports pendant que tu y es ?) la code-review intégrée dans l’éditeur. Toutes les nouveautés sont là :
Un Dev Scala qui cherche à améliorer la/le dev en toi :
Puzzler
Ici un petit challenge pour apprendre en s’amusant !
Réponse à l’énigme précédente
D’abord un peu de contexte : la méthode apply est une scope function, c’est à dire une fonction qui s’exécute dans le contexte de l’objet sur lequel elle est appelée.
Autrement dit dans le corps de apply, la référence this (le “receiver”) est celle de l’objet sur lequel elle est appelée et non celle de l’objet externe.
Ceci étant dit, on voulait expliquer ce que le code suivant affiche1
open class Node(val name: String) {
fun printMe() = println(name)
}
class Parent: Node("parent") {
fun addChild(name: String): Node? = Node(name)
val child1 = addChild("child1")?.apply { printMe() }
val child2 = addChild("child2").apply { printMe() }
}
fun main() {
Parent()
}On pourrait s’attendre à
child1
child2mais on obtient
child1
parentBien sûr vous aurez deviné qu’il y a une astuce avec le safe-call operator “?.”.
Curieusement Kotlin nous laisse invoquer la méthode apply sur un object nullable. En revanche il ne nous laisse pas utiliser la référence this car rien ne garantit qu’elle ne soit pas nulle !
Par exemple ce code ne compile pas :
...
val child2 = addChild("child2").apply { this.printMe() }
// Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type Node?Conclusion : afin d’éviter une Null Pointer Exception, le “receiver” de l’invocation de printMe n’est pas la référence retournée par addChild("child2") mais l’objet Parent !
En revanche lorsque l’invocation est protégée par le safe-call operator, alors la référence this est garantie non-null et le “receiver” de printMe est bien la référence retournée par addChild("child1")
Enigme du jour
Si vous avez été attentif vous avez vu que j’ai dû me frotter aux bizarreries de JavaScript.
En lisant la spec d’ECMAScript on réalise qu’on peut s’amuser sans fin avec l’opérateur “==”.
Par exemple saurez-vous expliquer pourquoi un objet truthy est == false ?
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??"); Cette énigme est honteusement pompée du talk de Anton Keks (qui date un peu (le talk, pas Anton), certaines dingueries ne fonctionnent plus avec les versions récentes de Kotlin)




