KeiruaProd - Blog
Je suis développeur web freelance et propose des formations à Symfony2 ! Contactez-moi pour en discuter.

I was at Rustfest this weekend. As expected, it was a great conference ! Lots of things to learn, and great people to meet.

I could not attend the workshops (nor the Impl days), but this cool community puts so many things on Github that I’m gonna be able to do them anyway, see for instance:

Also, the videos are on the web already, and you can download lrlna’s zine about memory

What follows is a summary of the talks I liked the most.

Tech:

Non-tech:

Yew, JavaScript without JavaScript

Denis Kolodin talked about Yew, the rust framework he develops.

As a web developper, this is really exciting : we can have both the power and safety of Rust, with the reach of web applications ! Yew looks a lot like doing React development with Redux.

Let’s take an example : imagine we want to create a counter, with 2 buttons to increment/decrement the value. We would:

  1. Create a model
pub struct Model {
    value: i64,
}
  1. Create the messages
pub enum Msg {
    Increment,
    Decrement
}
  1. Implement the message handling
impl<CTX> Component<CTX> for Model
where
    CTX: AsMut<ConsoleService>,
{
    type Message = Msg;
    type Properties = ();

    fn create(_: Self::Properties, _: &mut Env<CTX, Self>) -> Self {
        Model { value: 0 }
    }

    fn update(&mut self, msg: Self::Message, env: &mut Env<CTX, Self>) -> ShouldRender {
        match msg {
            Msg::Increment => {
                self.value = self.value + 1;
            }
            Msg::Decrement => {
                self.value = self.value - 1;
            }
        }
        true
    }
}
  1. Create a view that displays the value and the buttons, and sends the messages on a click
impl<CTX> Renderable<CTX, Model> for Model
where
    CTX: AsMut<ConsoleService> + 'static,
{
    fn view(&self) -> Html<CTX, Self> {
        html! {
            <div>
                <nav class="menu",>
                    <button onclick=|_| Msg::Increment,>{ "Increment" }</button>
                    <button onclick=|_| Msg::Decrement,>{ "Decrement" }</button>
                </nav>
                <p>{ self.value }</p>
                <p>{ Date::new().to_string() }</p>
            </div>
        }
    }
}

and that’s pretty much it ! It works well with stdweb and cargo web.

… have a look at the examples (I took the counter example there), and enjoy how easy it is to do javascript without writing javascript.

Immutable data structures and why you want them

A great talk with a great slide deck. I’m a bit sad @bodil talked mostly about the data structures, I’d have loved to hear more about the necessity for their immutability.

Anyway, if you wanna learn stuff on

…go watch the talk ! She provides an impressive reading list of papers regarding RRB trees :

After skimming through a few of them… I know I’m gonna need more time during lunch breaks this week to dive deeper on the topic 🙂

She also dropped some cools remarks:

  • nobody is gonna use a library with a bad documentation. Sounds obvious ? It is. And yet as developpers we don’t like to write docs anyway, but we should work on that.
  • I can’t wait for the moment I’m gonna use The « Haskell Defence » in an argument, aka « immutable values make it easier to reason about your program »

Building reliable infrastructure

@spacejam talked about how to introduce verifications in complex architectures… and he introduced tons of great tools that can help us, software developpers, write better applications, with an amazing set of references.

The issue with everything we build stems from our brain : everything we know is subject to bias, and everything we build reflects these biases (see Rationality: From AI to Zombies (confonting assumptions)). Since our code reflects our biases, our automated tests do as well…so our tests tend not to be as effective as they could be.

A solution: don’t write tests. Write expectations instead, and have the machine generate random test cases.

There is a for that, called proptest.

It gives non-determinism in test execution, but with replayability (if a test case crashes, it does not simply crash randomly : you can relaunch it). It is used in im-rs, where there are tons of examples.

Another option is Model based testing:

  1. write a simplified model of a system
  2. apply random sequences of operations on both the implementation and the model
  3. if the model and implementation behave differently, it means we’ve found a problem
  4. the library will rerun the test, dropping out operations until it finds a minimal failing sequence (the machine just wrote a regression test for you!!!)

There’s a crate for that: model

Another option is fault injection. You make your system crash, and see how behaves. Sounds obvious ? Well the problem is not solved anyway. « in 58% of the catastrophic failures, the underlying faults could easily have been detected through simple testing of error handling code. », according to Yuan et al., OSDI 2014. Again, there are crates for that :

There were things about jepsen and TLA+, but by now if you are interested you should at least watch the slides.

He did not cover how to build such architectures, but provided some great references:

Learning how to learn

Link to the slide deck

In 2015, @vaidehijoshi learnt computer science on her own through her project basecs: study a CS topic every week for a year, and publish a blog post. She created her own curriculum through those 52 articles. It had unexpected side effects ! The writen baseCS turned into a podcast, and a video serie.

One the main lesson is that learning new things is extremely hard. So she studied the psychology & science behind learning. It led her to Richard Feynman, a famous phisicist who had a Nobel prize. Unsurprisingly, he also taught physics, but… he was also an artist, a philosopher, a bongo player, and many other things you don’t expect from a Nobel. Like, he particularly liked to break safes.
The thread through all his achievements is that he was super great at learning and understand things he was unconfortable with.

Let’s talk about how he learnt, and then I’ll summarize why it works well.

The Feynman Technique

Feynman left what is now called the Feynman Technique for learning, which has four steps:

  1. Identify the subject, the thing we want to learn

write down everything we know, and add things to this repository

  1. Explain it to someone who’d knw nothing about the topic (teach it as if it was to a 5yo child) => It forces you to use plain, simple terms

« When we speack without jargon, it frees us from hiding behind knowledge we don’t have ». We are pushed to go the the heart of a concept. Brevity is important and necessary, because childs don’t have a long attention span. Do not fear using diagrams. They were one of Feynman’s most important tools.

  1. identify any gaps in your understanding. Arguably the most important, it’s where the learning happens.

  2. Organize & simplify into a narrative. Use simple sentences for story telling, analogies…

Here is how he would explain atoms work, in a sentence:
« all things are made from atoms – little particles that move around in perpetual motion, attracting each other when they are a little distance apart, but repelling upon being squeezed into one another »

Feynman was nicknamed « The Great Explainer » (« the best teacher I never had », bill gates)=> maybe one of the important aspects of learning is to be able to teach things
Another is component is curiosity: he had a notebook « Notebook of things I don’t know about ». In his bio, Genius, he said he tried to find the essential kernels of each subjects.

This methodology:

  • tests our understanding
  • challenges our assumptions. Often, we you start learning a topic, you don’t know what you don’t know. « I’m smart enough to know that I’m dumb », said Feynman.
  • Reinforces what we do know
  • teaches us to be better explainers. By reframing stuff we know, and forcing us to teach things simply, we know that we know something once we are able to do that. Even for particularly complex topics.

Also, it makes knowledge accessible. People get interested to stuff when you explain it to them simply. Tech needs more great explainers !
As a side-effect, it makes our industry more diverse and inclusive.

Supercharging Rust Communities

Matt Gathu (@swissgathu) talked about what made the rust communities such a success.

  • Flat governance. There is no chain of command, no hierarchy. Teams are more or less independant. As a consequence, things get to move very fast, because there is not the bureaucracy of having someone to approve of a choice
  • Diversity & Inclusivity as a goal. Be deliberate about diversity and inclusion.
  • Having a roadmap allows to have a shared vision
  • Collective decision making. In the « RFC decision process », everyone has a say. Decisions are not made behind a closed door, you can always know why a given choise has been made.
  • Having a Code of Conduct. It’s a conscious effort to make sure everyone would be safe. People have joined because other communities were toxic to them.
  • Retrospectives. Take time to reflect on what you did: what is going right ? what can we improve ? This let’s you iterate faster.

It was also noted in another conference that the Rust’s language itself is really good due to the presence of great docs, a build system, package manager, memory safety…

An intro to rust

19 février, 2018

I recently gave an introductory talk about the Rust language, to experienced programmers who did not know the language. The presentation can be seen here and downloaded on Github. This article is a short summary of what I described.

The idea was not to enumerate features, but to highlight some of the cool things that have made this language so popular and growing quickly with a lot of enthusiasm.

I chose to focus on the 4 following elements:

  • Tools
  • Borrow checker
  • Community
  • Integrations with other languages

There are more of course, but hey, attention and time are limited resources, tech talk are no exception. Lire la suite »

I had a hard time learning rust at first. I didn’t quite know where to start, I focused on the wrong resources and lost some time. Here are my suggestions about everything you may need in order to learn and work with rust: where and what to learn, how to properly install the compiler, what tools you need and how to use them.

Lire la suite »

Parsing XML in Go

21 février, 2017

There is no example about how to use XML with Go on GoByExample, so here is how to do it. We’ll use the encoding/xml package for the standard library.

Lire la suite »

I’m using Markdown as a markup syntax for many things: the syntax is indeed really simple to use, it lets me focus on the content I need to write, and it can later be converted to HTML for « real life » display once I’m done. In the open-source community, it has become largely spread, and many developpers use it, like me, for non code-related stuff, like keeping notes or writing their journal. Lire la suite »

La plupart du temps, pour tester si une clé est présente dans un tableau, il faut utiliser array_key_exists. Pourtant on trouve encore des empty et isset à sa place, en pensant que ces 3 fonctions sont interchangeables : ce n’est pas le cas. Fin 2016 on trouve encore des confusions, donc cet article me servira de référence pour les futures revues de code 🙂

Lire la suite »

C’est bientôt Noël. Et si vous vous faisiez le cadeau d’apprendre quelque chose de radicalement nouveau, comme un nouveau langage de programmation ?

Lire la suite »

La semaine dernière, j’ai eu un problème avec un exécutable, celui de wkhtmltopdf qui n’arrivait pas à générer de PDF et le log n’était pas clair. D’après certaines indications sur StackOverflow, ca pouvait être du à un problème de version de la librairie libjpeg. On peut le vérifier avec strace, c’est un utilitaire qui intercepte et loggue tous les appels systèmes, ce qui permet de voir ce qui se passe en fouillant dans les logs. Je ne connaissais pas cet outil, c’était une bonne occasion de découvrir.

La commande à inspecter est la suivante :

$ ./wkhtmltopdf-amd64 in.html out.pdf

On prend un fichier html en entrée, et on chercher à générer à en faire un fichier pdf.

Pour inspecter la trace d’exécution avec strace, on fait comme ça :

$ strace -f -o trace.log ./wkhtmltopdf-amd64 in.html out.pdf

L’option -f permet d’enregistrer égalements les appels systèmes des processus fils, -o indique un fichier dans lequel stocker les logs.

On peut ensuite chercher à voir quels sont les appels au chargement de libjpeg.so. On trouve vite ce qu’on cherche :

$ cat trace.log |grep libjpeg
18590 open("/usr/lib/x86_64-linux-gnu/libjpeg.so.8", O_RDONLY|O_CLOEXEC) = 3

On voit donc que l’exécutable cherche à charger libjpeg dans sa version 8 dans un répertoire particulier. En cherchant les installations de libjpeg ($ locate libjpeg), j’ai pu voir que la version installée sur la machine en question est libjpeg.so.62, ce n’est donc pas la bonne version, un problème résolu avec un apt-get install libjpeg8. Bref, un problème pas banal mais qui m’a permis d’apprendre plein de choses 🙂

J’ai eu l’occasion de participer à plusieurs projets, le plus souvent de développement. Ils ont eu des durées et des importances variées. Certains se sont cassés la figure d’une manière ou d’une autre, et d’autres se sont très bien passés. Ces expériences m’ont permis de constater quelques unes des caractéristiques de projets qui marchent bien. Cela n’est pas valable que pour du développement, cela marche pour vraiment n’importe quel type de projet.

Quand je parle de réussir, je ne m’intéresse ici qu’à la réalisation technique du projet. C’est mon métier. Ce n’est pas le seul, et souvent d’autre éléments sont en jeu, l’aspect commercial par exemple. en sont un autre et je ne suis pas la bonne personne pour en parler.

Deux manières de procéder

Il y a plusieurs manières de lire cette liste :
  • Lancement d’un projet : elle peut servir de checklist
  • Projet en cours : risquez-vous d’aller dans le mur ? Vous pourrez peut-être corriger le tir.
  • Projet terminé : permet d’en faire une rétrospective, où l’on peut identifier quels éléments du projet étaient fragiles

Caractéristiques clé

Facile à comprendre

Les projets sont souvent rangés dans une application de gestion de projet (cela peut être un simple fichier google doc partagé, ou bien dans Jira, Trello…).

Le titre du projet, ou bien la définition macro du besoin doivent être clairs. Au premier contact avec un projet, ce qui se fait souvent par un titre assez succin, on doit savoir de quoi il retourne.
Si ce n’est pas le cas, c’est en général mauvais signe : « Ce qui se conçoit bien s’énonce clairement ». Si l’initiateur du projet ne fait pas l’effort de présenter son projet clairement ou si le projet est flou car le projet lui même n’est pas encore abouti, il risque d’y avoir des problèmes de communication rapidement.

Le périmètre fonctionnel est clair

Il ne doit pas y avoir d’ambiguïté sur ce qui doit être réalisé. Cela peut être lié au problème précédent (préférer « Concevoir l’interface de gestion des messages privés entre utilisateurs » à « Outils de discussions interne »).

Lorsque le titre ne suffit pas à préciser ce qui doit être fait, il faut aller plus loin : texte de description, maquettes, documents de spécification… Tout dépend du projet et de l’autonomie dont dispose (en théorie, et surtout en réalité) l’équipe.

Les actions à réaliser sont listées de manière exhaustives et précise

Avant de commencer à faire quoi que ce soit, on doit savoir ce qu’il faut faire; c’est un travail collaboratif ! Seul, on a vite fait d’oublier une tâche qui va s’avérer importante par la suite, en minorer le temps nécessaire ou l’importance. Tous les acteurs du projet doivent contribuer à lister ce qui doit être fait, et réfléchir à leur faisabilité.

Certaines actions ne seront pas forcément réalisables immédiatement (ex: la migration d’un module dans un nouveau framework nécessite la refonte du modèle de base de données). Il faut trouver des solutions (ex: bridge temporaire avec l’ancien modèle, et initiation d’un projet plus globale de refonte du modèle).

Cette étape est cruciale car on a vite fait d’omettre des éléments clés qui peuvent remettre en cause le temps effectif de réalisation, ainsi que les choix techniques mis en places.

Les livrables sont définis précisément

Livrer un site responsive, ce n’est pas la même chose que livrer un site ET une application mobile. Cela peut sembler évident, mais ca ne l’est pas. Penser à lever les ambiguïtés et les non-dits sur ce qu’il faut rendre en fin de projet.

Les experts et les ressources matérielles sont accessibles

Dans n’importe quel projet on a besoin d’avoir accès à des personnes et des ressources. Les personnes vont par exemple avoir une expertise métier nécessaire à la conception du produit (ou plutôt à l’avant projet, ce qui peut être considéré comme un projet en soit).

Les ressources matérielles nécessaires doivent également être fournies ou disponibles. Cela peut être :

  • Les accès aux différents serveurs nécessaires (base de donnée, accès SSH)
  • Les licences nécessaires (IDE, applicatifs, outils SaaS…)
  • Les applicatifs sont correctement configurés. Si ce n’est pas le cas, on doit avoir la possibilité de le faire. Le temps nécessaire devra alors être anticipé et alloué pour cela

Quoi qu’il en soit, il faut savoir à l’avance de quoi on aurait besoin et pouvoir y avoir accès lorsque c’est nécessaire.

Une date butoire réaliste

Ha, les estimations… On ne va pas se mentir, les estimations, c’est de la magie noire et personne ne peut prédire précisément le temps que va prendre la réalisation d’un projet.

C’est pourtant un indicateur clé qu’il ne faut pas négliger. Elle doit être réaliste : si on laisse 15 jours pour faire quelque chose qui prend de toute évidence 2 mois, on va dans le mur en niant l’évidence (c’est plus courant qu’on ne le croit).
La pertinence d’une date butoire est difficile à évaluer a priori, mais on peut mesurer sa dérive en cours de projet. A mi-projet, on peut tenter d’estimer si on est encore dans les clous ou si on est déjà foutus. Si on a de l’avance (c’est plus rare que l’inverse), en profiter pour améliorer la qualité.

Découper en milestones

Si le projet est long, il peut devenir pertinent de le découper à l’aide de milestones, des dates clés auxquelles on va vérifier un certain nombre de choses (livrables intermédiaires). On peut alors considérer chaque milestone comme un sous projet, qui doit alors avoir les mêmes caractéristiques que le reste (date butoire réaliste, livrables précisément définis, etc.)

Pas d’interruptions

Nous, les humains, sommes très mauvais pour faire deux choses à la fois. Quand on travaille sur un projet, c’est mieux de se concentrer sur celui ci plutôt que d’essayer d’en développer plusieurs à la fois. Passer d’une tâche à l’autre est une catastrophe pour la concentration. Quand on est sur un projet, cela veut dire, autant que possible : pas de debug d’un autre projet, pas de R&D en parallèle du projet…

Cela n’empêche pas de le faire, et c’est d’ailleurs ce qui arrive assez souvent. Dans ce cas, le temps nécessaire à la réalisation des diverses tâches et projets doit être clairement défini et alloué dans ce sens.

Eviter de changement

Les caractéristiques décrites ici s’insèrent très bien dans une méthodologie agile, qui prône une réactivité presque totale au changement. D’une itération à l’autre, ce qui est conçu peut être jeté pour faire complètement autre chose que ce qui était prévu au départ. C’est une bonne chose (pas forcément toujours bonne à entendre pour le développeur qui conçoit l’application, certes), car elle permet d’assurer que le produit réalisé est bien le bon.

Par contre, il faut un peu de rigueur pour utiliser cette méthodologie correctement, et ne pas interrompre ou altérer un sprint à tout bout de champ. Ajouter de nouvelles tâches, ou modifier les tâches existantes est le meilleur moyen d’aller dans le mur en croyant bien faire. Rapidement, cela peut réduire à néant tout ce qui a été précieusement préparé (périmètre fonctionnel, livrables attendus, date butoire qui devient difficile à respecter, etc.), tout en faisant baisser la qualité du résultat ainsi que la motivation des parties prenantes.

Tout est communication

Finalement, toutes ces remarques gravitent autour de la problématique de la communication. N’importe qui devrait pouvoir comprendre les caractéristiques du projet, et en comprendre les tenants et aboutissants. Il ne doit pas y avoir de non-dits, ou d’idées tacites qui ne soient pas exprimées, explicitées, clarifiées, couchées sur papier.

Ce qui est clair pour quelqu’un ne l’est souvent pour plusieurs personnes que quand elles en ont discuté et se sont mises d’accord à grand coup de schéma. Noter le résultat permet d’y revenir plus tard.

Vous constaterez probablement qu’il n’y a rien de fou dans cette liste et probablement pas d’idée nouvelle. Comme souvent en management ou en gestion de projet, il est question de bon sens. Bien que tout le monde croit en avoir, trop souvent les les projets en manquent d’une manière ou d’une autre. La clé d’un projet qui démarre bien, c’est finalement la rigueur avec laquelle il est décrit.

Gérer les cases à cocher avec angularJS est un peu plus compliqué que les autres associations. On ne peut pas simplement utiliser ng-model, il faut gérer la possibilité que plusieurs cases soient cochées et cela nécessite d’implémenter cette logique métier.

Nous allons voir comment le faire à la main, puis à l’aide de la directive checklist-model.

Gérer la checkbox « à la main »

Le moyen le plus simple, c’est d’avoir un tableau des différentes possibilités, de boucler dessus. Pour chaque case à cocher, lors d’un clic on va déclencher une action de contrôleur. On va également tester si la case est cochée ou non via une autre action de contrôleur.

Il faut donc dans le contrôleur plusieurs choses :

  • Une liste des différentes possibilités (availableTypes)
  • La propriété qui va stocker le modèle (types)
  • Une méthode pour dire si une case est cochée ou non (isTypeChecked)
  • Une méthode pour cocher les cases (toggleTypeSelection)

Le javascript associé contient donc ces quatres choses :


$scope.types = [];

$scope.availableTypes = {
'apple': 'Pomme',
'peach': 'Peche',
'pear': 'Poire'
}

// Dit si une case est cochée
// en testant si le tableau types contient la propriété testée.
$scope.isTypeChecked = function(typeName){
return $scope.types.indexOf(typeName) > -1;
}

// Coche ou décoche une case
// en ajoutant ou supprimant une propriété du tableau types
$scope.toggleTypeSelection = function(typeName){
if ($scope.isTypeChecked(typeName)) {
var index = $scope.types.indexOf(typeName);
$scope.types.splice(index, 1);
}
else {
$scope.types.push(typeName);
}
}

Factorisation grâce à checklist-model

En fait, on se rend assez vite compte que les deux actions de contrôleur sont toujours les mêmes. Pour éviter de devoir la réécrire à chaque fois, on peut donc les factoriser, dans une directive ou un service. Plutôt que de le faire soi-même, il existe une directive, checklist-model qui fait cela.

Le code HTML fait la même taille, mais la philosophie est différente. checklist-model devient l’équivalent du classique ng-model, et checklist-value va devenir la propriété à ajouter au tableau types lorsque la case est cochée ou non. La directive peut également savoir si une case est cochée, en testant si le tableau du modèle contient cette propriété.

Le contrôleurs devient beaucoup plus simple. Il n’y a plus besoin d’implémenter les logique d’actions au clic, et pour tester si une case est cochée, c’est géré par la directive. Il suffit de déclarer les différents tableaux :


$scope.types = [];

$scope.availableTypes = {
'apple': 'Pomme',
'peach': 'Peche',
'pear': 'Poire'
}