★ Co-organisation de conférences

Tickets are earned, not bought

In Edgeryders tradition, anyone should have access to knowledge and meaningful experiences whether or not they have the financial means for that. However, we don’t have the resources to grant free-as-in-beer access, so we are asking people who come to contribute their skills in exchange for the tickets.

In order to come, you have to complete up to 3 tasks, as per the instructions in each. We will be adding new tasks every week, so there is always something to choose from. There are two types of tasks:

  1. Worth a whole ticket: Tasks to contribute content, such as proposing a session, a workshop, a talk; contribute a case study on failure in one of the key conference tracks (open care track, development track, tba); lead documentation of the event; or anything that you want to propose and is OKed by organisers
  2. Worth part of a ticket: Organisational tasks such as leading community calls in the runup of Lote, cooking on site, compiling newsletters, social media sharing etc.

We are keeping track of all contributions in this spreadsheet. If you end up contributing more than one ticket, you can safely transfer your “completed tasks” to another participant.

Ticket policy | Edgeryders (cache)

Cela me rappelle la comptabilité de DevOpenSud qui est ouverte et qui permet de savoir en temps-réel quel est le coût final du ticket à régler. Un montant indicatif est estimé au départ pour avoir un pot commun et il est ensuite réajusté (généralement à la baisse) en fin d’évènement.

Il y a beaucoup de choses à explorer pour changer la relation organisateur/conférencier/spectateur et la proposition est toujours la même : tous participants pour fluidifier les échanges et encourager l’intelligence collective. Passer du être ensemble au faire ensemble.

On n’achète plus un billet mais on devient membre d’une association qui porte le projet auquel on peut participer financièrement et/ou par un travail avec une gouvernance démocratique. La conférence n’est plus un évènement ponctuel mais un bien commun qui vit tout au long de l’année, que l’on s’approprie et que l’on fait évoluer ensemble.

★ Programmation et appréhension

It’s unnecessary and complicated at almost every layer. At best I can congratulate someone for quickly and simply solving a problem on top of the shit that they are given. The only software that I like is one that I can easily understand and solves my problems. The amount of complexity I’m willing to tolerate is proportional to the size of the problem being solved.

I hate almost all software (cache)

Les deux derniers cours ont été dédiés au développement de petites fonctionnalités qui ont permis de révéler que la compréhension de JavaScript est bien éloignée de la pratique.

Deux points bloquants ont été remontés par les étudiants :

  • la syntaxe difficile à appréhender et l’on en revient à l’abstraction ;
  • les concepts liés à la programmation qui demandent du temps pour être assimilés.

Syntaxe et abstraction

Du coup j’ai revu ma copie une dizaine de fois (merci ##openweb) pour arriver à l’abstraction suivante :

window.$ = selector => Array.from(document.querySelectorAll(selector))
window.$$ = document.querySelector.bind(document)
window.on = Node.prototype.on = Array.prototype.on = function(type, ...rest) {
    let listener
    if (typeof rest[0] === 'function') {
        listener = rest[0]
    } else {
        const [targetNodeName, innerListener] = rest
        listener = function(event) {
            if (event.target.nodeName.toLowerCase() === targetNodeName) {
                innerListener(event)
            }
        }
    }
    Array.concat(this).forEach(element => element.addEventListener(type, listener))
}
window.$.on = window.on.bind(document)
window.trigger = Node.prototype.trigger = function(type, detail) {
    const event = new CustomEvent(type, { detail: detail })
    this.dispatchEvent(event)
}
Array.prototype.trigger = function(type, detail) {
    this.forEach(element => element.trigger(type, detail))
}
window.$.trigger = window.trigger.bind(document)

Moins de 30 lignes pour réussir à avoir du JavaScript qui permette de sélectionner des éléments et d’y associer des évènements de manière plus simple dans un contexte didactique. Un tel code permettant ensuite d’écrire :

function tests() {
    // Attaching/passing events for all titles.
    $('h1').on('changeColor', event => {
        console.log('changeColor received', event.detail)
        event.target.classList.add(`turn-${event.detail.color}`)
    })
    $('h1').on('click', event => {
        // Intentionally overcomplicated :-).
        console.log('changeColor triggered', event.target)
        event.target.trigger('changeColor', {color: event.target.innerHTML})
    })
    // Event delegation for a single item (works with many too).
    $$('ul').on('click', 'a', event => {
        event.preventDefault()
        console.log(event.target.innerHTML)
    })
    // Anonymous pub/sub.
    $.on('anonymousEvent', event => {
        console.log('anoynmous event received')
    })
    $.trigger('anonymousEvent')
}
on('DOMContentLoaded', tests);

C’est déjà mieux. Si je devais aller plus loin, je pense que je me tournerais vers des solutions comme RiotJS qui ont une approche par composants web et une barrière à l’entrée relativement basse. Il y aurait du matériel pédagogique à créer dans ce domaine, peut-être plus utile qu’un n-ème framework JS/CSS.

Concepts et algorithmes

Ici le blocage se situe dans le découpage fonctionnel et la peur de la page blanche. Et aussi peut-être un peu dans l’appréhension qui entoure tout ce qui a trait au code.

J’ai essayé de les faire travailler en amont, de leur fournir un canvas où ils n’avaient plus qu’à compléter les parties manquantes, de commencer par définir la logique avant de coder mais aucune des approche n’a vraiment portée ses fruits. La contrainte de temps était peut-être trop importante pour ce que j’ambitionnais mais pour introduire des interactions avec l’utilisateur il faut au moins savoir manipuler des éléments et y associer des évènements… sinon on reste dans la théorie.

Les savoirs s’acquièrent dans le temps, la pratique et la répétition. Il est difficile d’évaluer l’impact que l’on peut avoir dans une transmission. Parfois cette itération sera percutante, parfois elle se révèlera dans la durée, d’autres fois elle aura été complètement inutile. Ces interrogations sont probablement le quotidien de tout enseignant.

★ Réduire, expérimenter et bouger

Rester, c’est exister : mais voyager, c’est vivre.

Gustave Nadaud

Réduire

Réduire les contraintes, réduire les possessions, réduire le bruit, réduire mon alimentation. J’ai eu l’impression de m’imposer beaucoup trop de choses ces dernières années et il est temps de réajuster le cap. Il faut que j’apprenne à me libérer de ce qui m’étouffe et me stresse, de ce qui me rend sédentaire et m’oppresse.

Dans la réduction, il y a aussi l’idée d’extraire de l’eau pour augmenter la saveur, de réduire le bruit pour augmenter le signal.

Expérimenter

Plus que jamais envie d’essayer des choses. Peut-être éphémères, peut-être futiles, peut-être techniques, peut-être même inutiles. (Non, je ne parle pas de React. :p) Expérimenter pour le fun et pour savoir ce qu’il advient lorsque je deviens acteur sans forcément chercher à maîtriser tout ce qu’il se passe. Essayer, apprendre, recommencer et/ou changer à différents niveaux.

Aquarelle, trottinette, calligraphie, musique, caricature, sports divers et variés, cuisine, chant et sûrement pleins d’autres auxquels je ne pense pas.

Bouger

Être père me donne une certaine responsabilité dans le choix de l’environnement que je choisis pour évoluer et transmettre dans la bienveillance. Un microcosme familial ne suffit pas/plus pour limiter les agressions systémiques et il faut trouver un environnement adapté plus large pour qu’un accompagnement dans l’autonomie et l’acquisition de savoirs puisse s’effectuer dans de bonnes conditions.

Cette année sera dédiée à trouver un lieu et une ambiance adéquats pour instruire de manière sereine, fût-il à l’étranger.

Dans les épisodes précédents

★ JavaScript de zéro

When it comes to problem-solving in general (and JavaScript in particular), I have a similar bias towards single-purpose solutions. Rather than creating a monolithic framework that attempts to solve all possible problems, I prefer a collection of smaller scripts that only do one thing, but do it really well; the UNIX philosophy.

Small lessons, loosely learned (cache)

En un temps relativement restreint (8 heures de cours), j’ai essayé d’enseigner JavaScript à des étudiants n’ayant aucune notion de programmation en ne partant finalement d’aucun niveau d’abstraction. Pour seuls outils : le navigateur et son inspecteur/console et un fichier HTML de test, l’objectif étant d’alterner entre du théorique avec ce fichier et du pratique en manipulant des pages existantes. J’appréhendais un peu suite aux désillusions de l’année dernière mais j’avais gagné en expérience à la fois en JS et en réduisant mes prétentions sur ce que je voulais leur transmettre.

La première heure, compréhension des notions de variable et d’opérateur puis introduction de console.log pour faire la différence entre un script et son exécution dans la console. La deuxième heure a été consacrée à document.querySelector et document.querySelectorAll où l’on parle forcément de tableaux/listes et c’est peut-être à ce moment là que j’aurais dû introduire la conversion d’un NodeList en Array mais on n’en avait pas encore le besoin… En troisième heure, on commence à jouer avec les styles avec Element.style et surtout Element.classList et ça commence à être ludique d’aller modifier des pages existantes. Enfin pour clôturer la session, on expérimente avec innerHTML et outerHTML pour introduire du dynamisme. Et de manière transverse on parle de NaN, d’undefined et des commentaires.

À la fin de cette première demi-journée j’étais très optimiste car tous les étudiants avaient compris et savaient appliquer ce genre de code (valide) :

<!doctype html>
<meta charset="utf-8">
<title>Test JavaScript</title>
<style>
    .turn-red { color: red; }
    .turn-green { color: green; }
    .turn-blue { color: blue; }
</style>
<h1>red</h1>
<h1>green</h1>
<h1>blue</h1>
<script>
    var titles = document.querySelectorAll('h1')
    titles[0].classList.add('turn-' + titles[0].innerHTML)
    titles[1].classList.add('turn-' + titles[1].innerHTML)
    titles[2].classList.add('turn-' + titles[2].innerHTML)
</script>

Mine de rien ça fait énormément de concepts à assimiler pour les 24 personnes n’ayant jamais fait de programmation ! Et la transition est toute trouvée pour parler de la répétition avec les boucles et les fonctions. Hop, une semaine de repos pendant laquelle ils n’ont… rien fait :’(.

Voir ces 3 lignes répétées doit faire bondir un développeur, j’ai commencé par introduire la notion de fonction avec un nom suffisamment explicite pour limiter les commentaires puis l’usage d’une boucle for pour itérer sur les éléments. Au passage on a besoin d’Array.length et de comprendre les conditions. Jusque là tout allait bien, j’en profite pour montrer qu’il est possible de le faire avec un while et déjà ça amène de la confusion mais alors là où ça a vraiment bloqué c’est au passage à forEach. Je ne sais pas si c’est la syntaxe ou la conversion en Array ou le fait d’avoir des fonctions anonymes ou la fatigue cognitive mais toujours est-il que ça a commencé à décrocher à ce moment là. Il faut dire qu’un Array.prototype.slice.call en plein milieu n’arrange pas les choses. Peut-être qu’un Array.from ou un for(… of …) eut été plus explicite mais limité en terme de support. Dur.

Pour finir, j’ai montré qu’une fonction pouvait retourner une valeur avant d’enchaîner sur les évènements à base d’addEventListener ce qui ouvre la porte des interactions avec l’utilisateur. On arrive à cet enchaînement :

function addClassFromHTML(element) {
    element.classList.add('turn-' + element.innerHTML)
}
function dealWithTitleOnClick(title) {
    title.addEventListener('click', function() {
        addClassFromHTML(title)
    })
}
var titles = document.querySelectorAll('h1')
titles = Array.prototype.slice.call(titles)
titles.forEach(dealWithTitleOnClick)

Je retiendrai qu’il faut un peu plus de temps pour découvrir certains concepts. Travail demandé pour la semaine suivante : faire une fonction qui permette à partir d’un article de presse d’avoir une version lisible avec uniquement le titre et le contenu sans images. Une sorte de bookmarklet à la readability. Et jouer aussi.

Enseigner JavaScript ET la programmation à partir de zéro est un moyen d’identifier les forces et faiblesses du langage. D’un côté on a le TDD du pauvre avec un feedback visuel immédiat et la possibilité d’utiliser la console du navigateur. De l’autre les plusieurs façons de faire la même chose et les restrictions liées au non-support d’ES6 par les navigateurs. J’ai presque envie de troller sur la programmation fonctionnelle mais je vais plutôt ajouter une couche d’abstraction pour la prochaine fois, ce sera plus simple en demi-groupes. En espérant que ça devienne davantage compréhensible et utilisable par des néophytes, le code précédent devenant :

$('h1').on('click', function(event) {
    addClassFromHTML(event.target)
})

2016-01-10

Depuis la semaine dernière :

  • j’ai attaqué un texte sur les « Communs »
  • j’ai mis à jour celui sur « Soupapes » suite à une remarque d’Aurélien, je n’ai pas (encore ?) de versions pour visualiser un diff
  • j’ai réfléchi à ces notions d’URL et d’auto-référencement grâce à Karl et je continue l’expérience pour en découvrir les limites
  • j’ai remis en question le projet suite à une remarque de ma douce et tendre qui me trouve aigri et méprisant, au final elle trouvait (aussi) que je ne me justifiais pas assez…
  • du coup, j’ai mis le texte en justify (une première douloureuse) et joué avec le design, ça ne doit passer qu’avec ma configuration mais ça m’amuse :-)

Je découvre le fait de revenir sur un texte plusieurs fois, c’est un nouvel exercice qui m’est très difficile. L’action de publication est décorrélée de celle de rédaction elle-même désynchronisée de la notification et de ses multiples ajustements. Le lâcher-prise sur un texte ne se fait plus au moment de la publication et j’ai du mal à savoir quand du coup. Il y a un rapport à la vie/mort d’une production que je continue de creuser.

★ Apprentissage et auto-dépréciation

This unfortunately became a trend. I don’t really go to local tech meetups anymore because I don’t feel like I fit in both due to age demographic and the age related comments I get. Usually whenever my age was bought up it was met with shock and awe.

I hated it. I don’t need to be told facts about myself. It didn’t make me feel special or unique, it just made me feel very different and abnormal. Once I had someone harass me for an entire meetup about my age and I ended up going home feeling like shit and crying myself to sleep.

My age was particularly of concern whenever I’d go to the US for work or conferences. The tech industry has a strong drinking culture and not being able to go into bars is very socially isolating. Whenever I go to the US I feel like a child and even get asked at customs why I’m travelling alone.

~2015 in review - Medium (cache)

Le dernier cours a été l’occasion de faire une restitution d’un travail sur le long terme. Le résultat fut assez terrible principalement car les étudiants ne savaient pas mettre en valeur leurs connaissances. J’essaye toujours de mettre en contexte les évaluations, que ce soit via une candidature spontanée ou une critique de site. Cette fois-ci, il s’agissait de présenter leur travail à une personne rencontrée pendant un événement qui voulait voir de quoi était capable l’étudiant rapidement dans le but de l’embaucher. Toute ma démarche a été de les pousser du comment scolaire au pourquoi professionnel. Décrire ce qu’ils ont fait est intuitif pour eux mais prendre du recul et décrire ce qu’ils ont vraiment acquis et comment est-ce qu’il pourraient le mettre en application — voire pourquoi est-ce que c’est une bonne pratique — est beaucoup plus compliqué. Or c’est ce qui me semble pertinent dans un tel contexte.

J’ai du mal à identifier pourquoi est-ce qu’ils arrivent avec un tel manque de confiance en eux à cette étape de leur vie mais c’est vraiment dommageable pour qu’ils réussissent à trouver un emploi s’ils n’arrivent pas à valoriser un minimum ce qu’ils ont appris. Peut-être poussent-ils l’auto-critique et l’humilité trop loin ?

The reason it’s so difficult to test and improve is that it requires you to acknowledge that your original plan wasn’t perfect. And to have the humility and care to go ahead and fix it.

Software is testing (cache)

Peut-être sont-ils fatigués d’avance (cache) par l’ampleur de la tâche qui les attend ? Ou peut-être que leur formation est trop généraliste ? Je vais essayer de leur faire (re)prendre confiance en eux en introduisant JavaScript avec le moins d’abstraction possible.

2016-01-03

Je songe sérieusement à décorréler les notifications de la production avec ce que je suis en train d’expérimenter sur le lexique. En effet c’est un travail sur le long terme avec des ajustements nombreux au cours de la première semaine notamment. Je compte faire un bilan par semaine pour vous tenir informés de l’avancement et vous demander votre avis, il n’y aura pas de publication autre que celle d’un item du flux (pas de page dédiée, tweet ou autre).

Je suis en cours de finalisation de « Soupapes » et j’ai commencé « Web » avec un peu d’avance mais j’en avais besoin pour développer l’outil de liens dynamiques. Je rencontre déjà des problèmes au niveau de la nomenclature (comment gérer les synonymes), de la pérennité (que doit-il advenir d’un fragment d’url si le titre change), des versions (un lien externe doit-il forcément pointer sur la dernière version) et de l’ampleur de la tâche :-).

Si vous avez des remarques je suis joignable par email, je ne sais pas encore à quel moment votre inclusion devient pertinente dans le processus. Vous pouvez aussi suggérer des termes bien sûr. Et là j’en viens à me re-questionner sur l’intérêt d’une liste de diffusion pour tout ça afin de fluidifier les échanges…

Marks in Terminal.app

For a while after updating to El Capitan, I've seen those weird marks in front of every line. I thought it was an incompatibily with oh-my-zsh. Turns out it isn't and I've discovered that through John Siracusa.

He links to a wonderful stack exchange answer. It explains in details what they are and how to change their behaviour, so I won't repeat it here. I just want to highlight the keyboard shortcuts to navigate through them:

  • Cmd+Up/Down lets you move up and down between those marks.
  • Cmd+Shift+Up/Down lets you select the text between marks.

I found this very convenient to copy/paste the output of a script. Will use a lot.

Une nouvelle aventure

Après cinq ans chez Mozilla, j'ai décidé de partir pour une nouvelle aventure qui débutera le premier août. Je ne sais pas encore où elle sera et c'est pour cela que je publie ce billet.

Je cherche une société qui travaille sur ses propres produits (cela exclut donc les agences) et qui n'est pas financée par de la publicité. Je cherche aussi une équipe qui sait transcender les rôles attitrés, où tout le monde participe pour trouver la solution adéquate.

Si vous êtes intéressés par mon profil, mon CV est disponible. Si vous avez une idée de société qui pourrait m'intéresser, n'hésitez pas à me contacter.

A little performance trick from Amazon

Have you noticed that Amazon search results feel really really fast? I've noticed that they use a little trick to achieve that. They preload a few results from the next page (6 in my example). So when you click on "Next page", they can display those items immediately and start fetching the other results. On most screens, those preloaded items should be enough to fill the visible viewport. And hopefully, once the user has scanned the first items and is ready to scroll, the rest of the items are loaded.

I've zoomed out my browser to illustrate the effect in the video.