Browse Source

More cache

master
David Larlet 3 years ago
parent
commit
a9970114dd

+ 187
- 0
cache/2021/0e0d866f920298fbc0624c03ddc83d24/index.html View File

@@ -0,0 +1,187 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the <title>
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f0f0ea">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f0f0ea">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://www.ledevoir.com/societe/594536/reconnaissance-faciale-clearview-ai-a-viole-la-vie-privee-des-canadiens">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick">

<article>
<header>
<h1>Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://www.ledevoir.com/societe/594536/reconnaissance-faciale-clearview-ai-a-viole-la-vie-privee-des-canadiens" title="Lien vers le contenu original">Source originale</a>
</p>
</nav>
<hr>
<p>Dans un rapport publié mercredi avec trois de ses homologues provinciaux, le commissaire fédéral à la protection de la vie privée, Daniel Therrien, affirme qu’en prélevant des milliards d’images de personnes sur Internet, l’entreprise a violé les lois canadiennes sur la protection de la vie privée.</p>

<p>La technologie de Clearview AI permet la collecte d’un grand nombre d’images provenant de diverses sources. Cette vaste banque d’images peut ensuite aider les policiers, les institutions financières et d’autres clients à identifier des inconnus, grâce à la technologie de reconnaissance faciale.</p>

<p>Le rapport note entre autres que l’entreprise américaine a constitué une base de données de « plus de trois milliards d’images de visages », y compris ceux d’un grand nombre de Canadiens et d’enfants. Des forces policières y ont eu accès, tout comme des organisations commerciales, et ce, sans le consentement des personnes, déplorent le commissaire Daniel Therrien et ses homologues du Québec, de l’Alberta et de la Colombie-Britannique.</p>

<p>Les commissaires estiment que cette « surveillance de masse » pratiquée par Clearview pour construire sa banque d’images constitue « un affront au droit à la vie privée » et inflige « un préjudice général à tous les membres de la société, qui se retrouvent constamment dans une parade d’identification policière ».</p>

<p>« C’est tout à fait inacceptable », a déclaré M. Therrien lors d’une conférence de presse, mercredi.</p>

<p><span class="intertitre">Clearview se défend</span></p>

<p>Clearview AI a déclaré aux enquêteurs que les lois canadiennes sur la protection de la vie privée ne s’appliquaient pas à ses activités parce que l’entreprise n’avait pas de « lien réel et substantiel » avec le Canada et que le consentement n’était pas nécessaire parce que l’information était accessible au public.</p>

<p>Les commissaires ont rejeté ces arguments. Ils ont découvert que Clearview avait non seulement recueilli des images de Canadiens, mais également commercialisé activement ses services auprès de corps de police du pays.</p>

<p>M. Therrien avait annoncé l’année dernière que Clearview AI cesserait d’offrir ses services de reconnaissance faciale au Canada en réponse à l’enquête. Clearview devait ainsi suspendre indéfiniment son contrat avec la GRC, le seul client qu’il lui reste au pays. L’entreprise américaine a toutefois rejeté les recommandations des quatre commissaires de cesser de colliger des images de personnes au Canada et de supprimer les images et détails biométriques d’individus qu’elle possède déjà.</p>

<p>Les commissaires ont prévenu mercredi que, si l’entreprise continue de résister, ils « entreprendront les autres actions » à leur disposition en vertu de leurs lois respectives.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
</svg> RSS</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 32
- 0
cache/2021/0e0d866f920298fbc0624c03ddc83d24/index.md View File

@@ -0,0 +1,32 @@
title: Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens
url: https://www.ledevoir.com/societe/594536/reconnaissance-faciale-clearview-ai-a-viole-la-vie-privee-des-canadiens
hash_url: 0e0d866f920298fbc0624c03ddc83d24
<p>Dans un rapport publié mercredi avec trois de ses homologues provinciaux, le commissaire fédéral à la protection de la vie privée, Daniel Therrien, affirme qu’en prélevant des milliards d’images de personnes sur Internet, l’entreprise a violé les lois canadiennes sur la protection de la vie privée.</p>
<p>La technologie de Clearview AI permet la collecte d’un grand nombre d’images provenant de diverses sources. Cette vaste banque d’images peut ensuite aider les policiers, les institutions financières et d’autres clients à identifier des inconnus, grâce à la technologie de reconnaissance faciale.</p>
<p>Le rapport note entre autres que l’entreprise américaine a constitué une base de données de « plus de trois milliards d’images de visages », y compris ceux d’un grand nombre de Canadiens et d’enfants. Des forces policières y ont eu accès, tout comme des organisations commerciales, et ce, sans le consentement des personnes, déplorent le commissaire Daniel Therrien et ses homologues du Québec, de l’Alberta et de la Colombie-Britannique.</p>
<p>Les commissaires estiment que cette « surveillance de masse » pratiquée par Clearview pour construire sa banque d’images constitue « un affront au droit à la vie privée » et inflige « un préjudice général à tous les membres de la société, qui se retrouvent constamment dans une parade d’identification policière ».</p>
<p>« C’est tout à fait inacceptable », a déclaré M. Therrien lors d’une conférence de presse, mercredi.</p>
<p><span class="intertitre">Clearview se défend</span></p>
<p>Clearview AI a déclaré aux enquêteurs que les lois canadiennes sur la protection de la vie privée ne s’appliquaient pas à ses activités parce que l’entreprise n’avait pas de « lien réel et substantiel » avec le Canada et que le consentement n’était pas nécessaire parce que l’information était accessible au public.</p>
<p>Les commissaires ont rejeté ces arguments. Ils ont découvert que Clearview avait non seulement recueilli des images de Canadiens, mais également commercialisé activement ses services auprès de corps de police du pays.</p>
<p>M. Therrien avait annoncé l’année dernière que Clearview AI cesserait d’offrir ses services de reconnaissance faciale au Canada en réponse à l’enquête. Clearview devait ainsi suspendre indéfiniment son contrat avec la GRC, le seul client qu’il lui reste au pays. L’entreprise américaine a toutefois rejeté les recommandations des quatre commissaires de cesser de colliger des images de personnes au Canada et de supprimer les images et détails biométriques d’individus qu’elle possède déjà.</p>
<p>Les commissaires ont prévenu mercredi que, si l’entreprise continue de résister, ils « entreprendront les autres actions » à leur disposition en vertu de leurs lois respectives.</p>

+ 246
- 0
cache/2021/321b85630164ca075bd3be265f23aed5/index.html View File

@@ -0,0 +1,246 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the <title>
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Codebase Collaboration Between Humans and Robots (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f0f0ea">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f0f0ea">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick">

<article>
<header>
<h1>Codebase Collaboration Between Humans and Robots</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/" title="Lien vers le contenu original">Source originale</a>
</p>
</nav>
<hr>
<p>Back in 2017, <a href="https://twitter.com/jimniels/status/889921238809837568?s=20">I tweeted</a>:</p>

<blockquote>
<p>JS will soon read like it's written for machines</p>
<pre><code>// prettier-ignore
/* eslint-disable */
import(/* webpackChunkName: "lodash" */ 'lodash')</code></pre></blockquote>

<p>It’s a bit of a silly statement. Of course JavaScript is written for machines. It’s a programming language. It’s instructions for a machine. But, JavaScript is also written for humans. As Knuth’s statement goes, “Programs are meant to be read by humans and only incidentally for computers to execute.”</p>

<p>If I remember correctly, my tweet came from a place of frustration and exhaustion with eslint. I was trying to find the right eslint instructions so the husky prebuild hook (which was linting my changes) would stop yelling at me for sloppy code in a prototype/throw-away branch I just wanted to commit and push so that the CI/CD would kick-in and get me a preview build—that’s a mouthful. I couldn’t remember at the time what I needed. Was it <code>es-lint-disable</code> or <code>es-lint-disable-next-line</code>? Or maybe <code>es-lint-disable-line</code>? Oh that’s right, <code>eslint-disable</code> is the one I have to re-enable with <code>eslint-enable</code>, but this project’s linting configuration doesn’t actually allow the nuclear <code>eslint-disable</code> without explicitly stating which rules to disable. </p>

<p>Eventually I found the right incantation to break the spell of a failing build: </p>

<pre><code class="language language-js"></code></pre>

<p>This made me start to notice how frequently I read or even wrote code comments as tooling instructions (i.e. telling prettier to stop or webpack where to code split). Code comments for machines were more prevalent than code comments for humans. My code contained instructions for two masters: 1) the one that would parse, build, transpile, compile, deploy, or whatever else it, and 2) the one that would eventually execute it (the client).</p>

<p>In my exhaustion, I did what many others do as an outlet: I complained on twitter—that <a href="/2021/fav-excerpts-from-the-postlight-podcast/">“firehouse of human anguish”</a>. Then I moved on. But I never forgot.</p>

<h2 id="collaborating-robots-vs-humans">Collaborating: Robots vs. Humans</h2>

<p>Fast-forward to 2020 and I saw <a href="https://twitter.com/davatron5000/status/1327292373244792832">this tweet from @davatron5000</a>:</p>

<blockquote>
<p>Staring at 12 config files in my project root like they're my mortal enemies and not my supportive robot buddies.</p>
</blockquote>

<p>That resonated. Tooling configs remain one of the most perplexing aspects of any project for me. To express my sympathy (but also to point out that I thought twelve configs was on the low-end) I found a popular project on Github, took a screenshot of the project root, highlighted all the tooling configurations, and reply’d to the tweet. What strikes me about this image is the contrast between the amount of instructions in the codebase around collaboration and conduct for machines vs. humans.</p>

<p><img src="https://cdn.jim-nielsen.com/blog/2021/code-for-machines-screenshot-1.jpeg" alt="">

</p>

<p>For this blog post, I went out and grabbed a few more examples:</p>

<p><img src="https://cdn.jim-nielsen.com/blog/2021/code-for-machines-repos.png" alt="Screenshot of multiple repos on Github highlighting code specific to robots vs. humans.">

</p>

<p>Take a moment to let this all soak in. Can you imagine having to setup, configure, update, and maintain all of these? Thank goodness somebody knows how. Every single one of those configs has <code>n</code> number of settings. Think of the incredible amount of work that would be required to read the docs for each config and understand A) what it’s doing, and B) what else is possible that isn’t yet configured.</p>

<p>Side note: I’ll grant that these screenshots aren’t meant to be a perfectly accurate representation of managing robot collaborators vs. human ones. I’m sure I missed configs/tooling in some places and wrongly highlighted them in others. Additionally, there’s no real science behind what constitutes being for machines or not (<code>.gitattributes</code> seems rationale and part of local file development, while <code>.circleci</code> is clearly for CI/CD). All that said, there’s a lot of commit messages in these repos relating to robot care and maintenance. Just look at these examples commit messages from a single repo:</p>

<ul>
<li>“Upgrade to prettier 2”</li>
<li>“upgrade examples to webpack-cli major 4”</li>
<li>“improve prettier and lint config and performance”</li>
<li>“generate runtime code with special-lint-fix”</li>
<li>“improve linting performance”</li>
<li>“fix newly found eslint problems”</li>
</ul>

<h2 id="robot-coworkers">Robot Coworkers</h2>

<p>Now I get it. These tools are helpful in their own way, especially as projects scale in size (both in contributors and lines of code). You need a way to provide structure and consistency through the codebase, to compile the code, and to deploy it. Doing that at the scale of many of today’s projects would be difficult, maybe nigh impossible, for a human. It’s the perfect job for an automated robot collaborator. But damn if employing those robot collaborators and keeping them in line isn’t overwhelming at times.</p>

<p>Thinking on prior experience, when I try to make a meaningful contribution to a project it feels like my merge request is quite often rejected. Why? One of two reasons: 1) something is wrong with the code I wrote, or 2) some configuration of the myriad of automated tools that work together on the project is broken and the build won’t pass. Based on experience, it feels like it’s a 50/50 chance of being either. Like Dave, trust for my “robot buddies” can be low. </p>

<p>Imagine if you had a human on your team who acted like these robots, just completely irregular on blocking your productivity. How long do you think they’d continue to have a place on the team? But because this is a little robot buddy contributor, we’re much more forgiving. Can’t merge your PR? “Oh yeah, sorry, that was the tooling’s fault. We’ll fix it.” But then shortly after the human fixes it, the robot is back on its bullshit without any repercussions or serious consideration of whether it should remain on the team. “Ah it’s the build again. We’ll fix it.”</p>

<h2 id="robots--complexity">Robots &amp; Complexity</h2>

<p>It makes me think of a line by John Ousterhout from his book <em>A Philosophy of Software Design</em>:</p>

<blockquote>
<p>Each piece of design infrastructure added to a system...adds complexity, since developers must learn about this element. In order for an element to provide a net gain against complexity, it must eliminate some complexity that would be present in the absence of the design element. </p>
</blockquote>

<p>As much as we talk about avoiding complexity <em>in</em> our programs, we seem to love the complexity of the tooling <em>around</em> our programs. As Ousterhout notes, every time you add a tool or configuration to a project, you’re adding an element that developers must learn, be aware of, or at minimum be exposed to. So while we think we’re lowering the bar of contributing and collaborating on a project — which may be true for <em>some</em> people — it’s possible we’re actually excluding people from contribution and collaboration because of the overwhelming complexity of our team of robots. “Hey, don’t worry about getting a PR declined because of some minor cosmetic aspect of the code, our new linter and code formatter will take care of all that for you! You <em>just</em> have to...” And I think many of us have experienced the pain and difficulty that can arise from the “you just have to...” in that sentence.</p>

<p>Now I recognize that not every project intends to accept contributions from beginners. Nor does every person who contributes to a project need to understand all the tooling configurations. If they are not in a position where they have visibility or control over aspects of the software lifecycle, like cutting releases or publishing artifacts, can’t they simply ignore all those configurations? I suppose that’s possible. But it sure would be a lot easier if they weren’t right in your face in the root of the project. For simplicity’s sake, imagine a standardized <code>.machines/</code> folder where you could stick all the robot stuff. At least then it would be obscured in a purposeful way. That’s a tangent though.</p>

<h2 id="conclusion">Conclusion</h2>

<p>I didn’t mean to make this a rant. I wish I had answers to these kinds of problems, but I don’t. I find a lot of value in many of these tools. I merely want to raise my voice and say, “this stuff is confusing as hell for me” and I’d bet I’m not the only one.</p>

<p>All of this did get me thinking: imagine if we put the same amount of effort into supporting the humans who help build our projects as we do for the robots who help us? Maybe a few more of the cultural/social problems associated with programming would “magically” disappear.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
</svg> RSS</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 51
- 0
cache/2021/321b85630164ca075bd3be265f23aed5/index.md View File

@@ -0,0 +1,51 @@
title: Codebase Collaboration Between Humans and Robots
url: https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/
hash_url: 321b85630164ca075bd3be265f23aed5

<p>Back in 2017, <a href="https://twitter.com/jimniels/status/889921238809837568?s=20">I tweeted</a>:</p>
<blockquote>
<p>JS will soon read like it's written for machines</p>
<pre><code>// prettier-ignore
/* eslint-disable */
import(/* webpackChunkName: "lodash" */ 'lodash')</code></pre></blockquote>
<p>It’s a bit of a silly statement. Of course JavaScript is written for machines. It’s a programming language. It’s instructions for a machine. But, JavaScript is also written for humans. As Knuth’s statement goes, “Programs are meant to be read by humans and only incidentally for computers to execute.”</p>
<p>If I remember correctly, my tweet came from a place of frustration and exhaustion with eslint. I was trying to find the right eslint instructions so the husky prebuild hook (which was linting my changes) would stop yelling at me for sloppy code in a prototype/throw-away branch I just wanted to commit and push so that the CI/CD would kick-in and get me a preview build—that’s a mouthful. I couldn’t remember at the time what I needed. Was it <code>es-lint-disable</code> or <code>es-lint-disable-next-line</code>? Or maybe <code>es-lint-disable-line</code>? Oh that’s right, <code>eslint-disable</code> is the one I have to re-enable with <code>eslint-enable</code>, but this project’s linting configuration doesn’t actually allow the nuclear <code>eslint-disable</code> without explicitly stating which rules to disable. </p>
<p>Eventually I found the right incantation to break the spell of a failing build: </p>
<pre><code class="language language-js"></code></pre>
<p>This made me start to notice how frequently I read or even wrote code comments as tooling instructions (i.e. telling prettier to stop or webpack where to code split). Code comments for machines were more prevalent than code comments for humans. My code contained instructions for two masters: 1) the one that would parse, build, transpile, compile, deploy, or whatever else it, and 2) the one that would eventually execute it (the client).</p>
<p>In my exhaustion, I did what many others do as an outlet: I complained on twitter—that <a href="/2021/fav-excerpts-from-the-postlight-podcast/">“firehouse of human anguish”</a>. Then I moved on. But I never forgot.</p>
<h2 id="collaborating-robots-vs-humans">Collaborating: Robots vs. Humans</h2>
<p>Fast-forward to 2020 and I saw <a href="https://twitter.com/davatron5000/status/1327292373244792832">this tweet from @davatron5000</a>:</p>
<blockquote>
<p>Staring at 12 config files in my project root like they're my mortal enemies and not my supportive robot buddies.</p>
</blockquote>
<p>That resonated. Tooling configs remain one of the most perplexing aspects of any project for me. To express my sympathy (but also to point out that I thought twelve configs was on the low-end) I found a popular project on Github, took a screenshot of the project root, highlighted all the tooling configurations, and reply’d to the tweet. What strikes me about this image is the contrast between the amount of instructions in the codebase around collaboration and conduct for machines vs. humans.</p>
<p><img src="https://cdn.jim-nielsen.com/blog/2021/code-for-machines-screenshot-1.jpeg" alt="">

</p><p>For this blog post, I went out and grabbed a few more examples:</p>
<p><img src="https://cdn.jim-nielsen.com/blog/2021/code-for-machines-repos.png" alt="Screenshot of multiple repos on Github highlighting code specific to robots vs. humans.">

</p><p>Take a moment to let this all soak in. Can you imagine having to setup, configure, update, and maintain all of these? Thank goodness somebody knows how. Every single one of those configs has <code>n</code> number of settings. Think of the incredible amount of work that would be required to read the docs for each config and understand A) what it’s doing, and B) what else is possible that isn’t yet configured.</p>
<p>Side note: I’ll grant that these screenshots aren’t meant to be a perfectly accurate representation of managing robot collaborators vs. human ones. I’m sure I missed configs/tooling in some places and wrongly highlighted them in others. Additionally, there’s no real science behind what constitutes being for machines or not (<code>.gitattributes</code> seems rationale and part of local file development, while <code>.circleci</code> is clearly for CI/CD). All that said, there’s a lot of commit messages in these repos relating to robot care and maintenance. Just look at these examples commit messages from a single repo:</p>
<ul>
<li>“Upgrade to prettier 2”</li>
<li>“upgrade examples to webpack-cli major 4”</li>
<li>“improve prettier and lint config and performance”</li>
<li>“generate runtime code with special-lint-fix”</li>
<li>“improve linting performance”</li>
<li>“fix newly found eslint problems”</li>
</ul>
<h2 id="robot-coworkers">Robot Coworkers</h2>
<p>Now I get it. These tools are helpful in their own way, especially as projects scale in size (both in contributors and lines of code). You need a way to provide structure and consistency through the codebase, to compile the code, and to deploy it. Doing that at the scale of many of today’s projects would be difficult, maybe nigh impossible, for a human. It’s the perfect job for an automated robot collaborator. But damn if employing those robot collaborators and keeping them in line isn’t overwhelming at times.</p>
<p>Thinking on prior experience, when I try to make a meaningful contribution to a project it feels like my merge request is quite often rejected. Why? One of two reasons: 1) something is wrong with the code I wrote, or 2) some configuration of the myriad of automated tools that work together on the project is broken and the build won’t pass. Based on experience, it feels like it’s a 50/50 chance of being either. Like Dave, trust for my “robot buddies” can be low. </p>
<p>Imagine if you had a human on your team who acted like these robots, just completely irregular on blocking your productivity. How long do you think they’d continue to have a place on the team? But because this is a little robot buddy contributor, we’re much more forgiving. Can’t merge your PR? “Oh yeah, sorry, that was the tooling’s fault. We’ll fix it.” But then shortly after the human fixes it, the robot is back on its bullshit without any repercussions or serious consideration of whether it should remain on the team. “Ah it’s the build again. We’ll fix it.”</p>
<h2 id="robots--complexity">Robots &amp; Complexity</h2>
<p>It makes me think of a line by John Ousterhout from his book <em>A Philosophy of Software Design</em>:</p>
<blockquote>
<p>Each piece of design infrastructure added to a system...adds complexity, since developers must learn about this element. In order for an element to provide a net gain against complexity, it must eliminate some complexity that would be present in the absence of the design element. </p>
</blockquote>
<p>As much as we talk about avoiding complexity <em>in</em> our programs, we seem to love the complexity of the tooling <em>around</em> our programs. As Ousterhout notes, every time you add a tool or configuration to a project, you’re adding an element that developers must learn, be aware of, or at minimum be exposed to. So while we think we’re lowering the bar of contributing and collaborating on a project — which may be true for <em>some</em> people — it’s possible we’re actually excluding people from contribution and collaboration because of the overwhelming complexity of our team of robots. “Hey, don’t worry about getting a PR declined because of some minor cosmetic aspect of the code, our new linter and code formatter will take care of all that for you! You <em>just</em> have to...” And I think many of us have experienced the pain and difficulty that can arise from the “you just have to...” in that sentence.</p>
<p>Now I recognize that not every project intends to accept contributions from beginners. Nor does every person who contributes to a project need to understand all the tooling configurations. If they are not in a position where they have visibility or control over aspects of the software lifecycle, like cutting releases or publishing artifacts, can’t they simply ignore all those configurations? I suppose that’s possible. But it sure would be a lot easier if they weren’t right in your face in the root of the project. For simplicity’s sake, imagine a standardized <code>.machines/</code> folder where you could stick all the robot stuff. At least then it would be obscured in a purposeful way. That’s a tangent though.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I didn’t mean to make this a rant. I wish I had answers to these kinds of problems, but I don’t. I find a lot of value in many of these tools. I merely want to raise my voice and say, “this stuff is confusing as hell for me” and I’d bet I’m not the only one.</p>
<p>All of this did get me thinking: imagine if we put the same amount of effort into supporting the humans who help build our projects as we do for the robots who help us? Maybe a few more of the cultural/social problems associated with programming would “magically” disappear.</p>

+ 196
- 0
cache/2021/59bd3fea3b3b370bd6b116e77effb69e/index.html View File

@@ -0,0 +1,196 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the <title>
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Nostalgie de l'ancien web (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f0f0ea">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f0f0ea">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://osd.ovh/index.php?article10/nostalgie-de-lancien-web">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick">

<article>
<header>
<h1>Nostalgie de l'ancien web</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://osd.ovh/index.php?article10/nostalgie-de-lancien-web" title="Lien vers le contenu original">Source originale</a>
</p>
</nav>
<hr>
<p>
Petit écart sur la tech suite à la lecture de l'article : <i>lehollandaisvolant</i> : <a href="https://lehollandaisvolant.net/?d=2021/01/19/09/09/59-recentrage-sur-le-blog">recentrage-sur-le-blog</a>
</p>

<p><hr>
<p>
Je bosse dans la « Tech » ou plutôt la « old-school » tech. Je me plais à dire que je suis Informaticien à l’ancienne.
</p>
<p>
J’ai quitté les réseaux sociaux il y a bien longtemps, qu’en j’ai compris que la plupart des gens sur facebouck passaient leur temps à bader la vie des autres ou essayer de chopper tout ce qui bouge. Et que twitteour est simplement le paradis des haters et râleurs en tout genre. Bref chacun sa came.
</p>
<p>
Je suis nostalgique de l’ancien web, celui où les pages finissaient pour la plupart en .html ou de simples petits scripts PHP. À chaque page tu risquais la crise d’épilepsie car les gifs étaient agressifs ! À cette époque le web était libre ! <br>
Bloguer n’était pas un métier, personne n’essayait d’influencer personne ou de placer du produit. Il te suffisait de coder un peu en HTML/PHP et tu étais le roi du web. Tu n’avais pas besoin de brasser de l’air sur les réseaux sociaux, en podcast ou de vendre ton cul aux GAFAM. Les réseaux sociaux sont apparus, avec toutes leurs merdes et leurs stats. Les gens se sont laissés enfermer dans des cyber-bocaux et y déversent leurs conneries comme s’ils allaient changer le monde planqué derrière leurs claviers à la con.
</p>
<p>
La tech va mal, les applications sont de plus en plus merdiques, et les piles technologiques bancales, voir volontairement complexifiées. Il y a quelque temps j’ai fait un gros rétropédalage. J’ai quitté python, nodejs et toutes ces merdes pour revenir à du Php. C’est moins à la mode, mais niveau perf tout y est, mon code est redevenu simple et robuste, ça coûte souvent que-dalle à mettre en prod, et je suis rentré à la maison. J’y suis bien, et les utilisateurs sont contents.
</p>
<p>
Bref, on parle de liberté. De décentralisation. A force de s’agiter dans un bocal on fait monter la mayonnaise. C’est exactement ce qui se passe du côté des réseaux sociaux. C’est des ruches et les algos s’amusent à secouer la boite pour voir comment réagissent les masses. Que des cobayes. La plupart sont des moutons, ne pouvant se passer d’un GPS, de vidéos merdiques sur YooupyTube et chialent quand ils ont oublié leur smartphone. Ils acceptent n’importe quoi du moment qu’on leur laisse leurs applications d’assistés. Côté dev c’est pas mieux, on veut du bling bling on se soumet aux APIs et Cloud des géants. On ne sait plus coder, on sait juste manipuler des ressources et des frameworks obscurs. Bien entendu les connaissances durement aqcuisent, entre deux framework et parfois deux versions ne sont pas transposables ailleurs, les compétences deviennent périssables ! Merci G@@gle !. Enfin je dis on … comme certain gaulois, je fais du old-school et je mange pas de ce pain là. Je me soumets pas au marketing agressif des soi-disant ‘sources d’actualité » de la tech. Avec leurs sondages bidonnés cherchant à convertir les devs à de nouveaux langages. On dirait des gourous essayant de recruter de nouveaux fidèles pour les frameworks offert "gratuitement" par les géants du web. Ce n’est plus des sources d’actualités mais des comptoirs de pubs. Ils vendent leurs culs « aux nouvelles techs » pour toucher des gros chèques car ils arrivent pas à se faire du blé autrement. (Bien-sûr que j'utilise toujours Jquery, Javascript c'est pour manipuler du DOM et basta. L'async et toutes ces prises de têtes sont contre productives dans 99% des cas. Un bon vieux callback et ça repart.) La plupart des mecs qui viennent t'apprendre à coder, n'ont jamais dépassé des "hello world", ni mis leurs applications d'étudiants toute neuve dans un vrai environnement de production avec de la charge. Je te parle des boîtes où si l'application est down, tes collègues sont à l'arrêt. Là bas ils en ont rien à foutre de l'index TIOBE, il veulent que sa roxe, et que ça fonctionne H24. Note que je dis collègue et pas client, sous-traiter le développement et l'infra c'est irresponsable.
</p>
<p> L'esclavagisme 2.0, tu suis leurs technos ou tu crèves. Enfin ça c'est ce qu'ils veulent faire croire à la masse et aux entreprises qui lâchent les billets pour des applications toujours plus grosses et instables, là ou une caissière suffit à faire le job pour bien moins cher qu'une armée de dev. Et ces devs, qui passent leur vie à apprendre des choses qu'ils savaient déjà faire dans une autre techno devenu ringarde du jour au lendemain... tout ça gratos de peur de ne plus être bon sur le marché de l'emploi. Les machines j'en ai ma claque, quand ça merde on est tous bien content de trouver le bouton "contact" et de tomber sur un humain en chair et os. "Faut évoluer, faut vivre avec son temps !", ça sera sans moi. On ne vit pas la révolution numérique, on s'assure simplement que l'homme avance au même rythme que les machines ... ou plutôt du business. Money, money la tech a perdu la tête. Nous les vieux de la vielle, on a pas oublié les SSI - Sociétés Service Informatique. Vous les avez renommés ESN Entreprise de Services du Numérique, cela reste des machines à cash où les riches placent leur pognon. Siphonner les petites TPE,PME, prendre en otage leur systèmes informatique en leur vendant du rêve tout en exploitant les salariés du digital... ça aussi, ça cassera la gueule. Alors amusez-vous bien dans vos recrutements, les bons sont partis depuis bien longtemps, et malheureusement souvent loin de la tech. Vous avez de la chance, demain avec le No-CODE les commerciaux pourront enfin assumer leurs mensonges ! Comme si le métier d'un dev se limitait à savoir coder et celui d'un administrateur système à d'éditer des fichiers de confs ... Bonne révolution numérique à tous!
</p>
<p>
Réveillez-vous, sortez vos lecteurs de flux RSS. Ouvrez-vos blogs.
On peut toujours tisser la toile et libérer l’information, suffit de lever un peu la tête de son nombril.
Arrêter de prendre la béquée de papa G@@gl€ et aller chercher soi-même ses sources d’informations.
</p></p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
</svg> RSS</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 31
- 0
cache/2021/59bd3fea3b3b370bd6b116e77effb69e/index.md View File

@@ -0,0 +1,31 @@
title: Nostalgie de l'ancien web
url: https://osd.ovh/index.php?article10/nostalgie-de-lancien-web
hash_url: 59bd3fea3b3b370bd6b116e77effb69e
<p>
Petit écart sur la tech suite à la lecture de l'article : <i>lehollandaisvolant</i> : <a href="https://lehollandaisvolant.net/?d=2021/01/19/09/09/59-recentrage-sur-le-blog">recentrage-sur-le-blog</a>
</p>
<hr>
<p>
Je bosse dans la « Tech » ou plutôt la « old-school » tech. Je me plais à dire que je suis Informaticien à l’ancienne.
</p>
<p>
J’ai quitté les réseaux sociaux il y a bien longtemps, qu’en j’ai compris que la plupart des gens sur facebouck passaient leur temps à bader la vie des autres ou essayer de chopper tout ce qui bouge. Et que twitteour est simplement le paradis des haters et râleurs en tout genre. Bref chacun sa came.
</p>
<p>
Je suis nostalgique de l’ancien web, celui où les pages finissaient pour la plupart en .html ou de simples petits scripts PHP. À chaque page tu risquais la crise d’épilepsie car les gifs étaient agressifs ! À cette époque le web était libre ! <br>
Bloguer n’était pas un métier, personne n’essayait d’influencer personne ou de placer du produit. Il te suffisait de coder un peu en HTML/PHP et tu étais le roi du web. Tu n’avais pas besoin de brasser de l’air sur les réseaux sociaux, en podcast ou de vendre ton cul aux GAFAM. Les réseaux sociaux sont apparus, avec toutes leurs merdes et leurs stats. Les gens se sont laissés enfermer dans des cyber-bocaux et y déversent leurs conneries comme s’ils allaient changer le monde planqué derrière leurs claviers à la con.
</p>
<p>
La tech va mal, les applications sont de plus en plus merdiques, et les piles technologiques bancales, voir volontairement complexifiées. Il y a quelque temps j’ai fait un gros rétropédalage. J’ai quitté python, nodejs et toutes ces merdes pour revenir à du Php. C’est moins à la mode, mais niveau perf tout y est, mon code est redevenu simple et robuste, ça coûte souvent que-dalle à mettre en prod, et je suis rentré à la maison. J’y suis bien, et les utilisateurs sont contents.
</p>
<p>
Bref, on parle de liberté. De décentralisation. A force de s’agiter dans un bocal on fait monter la mayonnaise. C’est exactement ce qui se passe du côté des réseaux sociaux. C’est des ruches et les algos s’amusent à secouer la boite pour voir comment réagissent les masses. Que des cobayes. La plupart sont des moutons, ne pouvant se passer d’un GPS, de vidéos merdiques sur YooupyTube et chialent quand ils ont oublié leur smartphone. Ils acceptent n’importe quoi du moment qu’on leur laisse leurs applications d’assistés. Côté dev c’est pas mieux, on veut du bling bling on se soumet aux APIs et Cloud des géants. On ne sait plus coder, on sait juste manipuler des ressources et des frameworks obscurs. Bien entendu les connaissances durement aqcuisent, entre deux framework et parfois deux versions ne sont pas transposables ailleurs, les compétences deviennent périssables ! Merci G@@gle !. Enfin je dis on … comme certain gaulois, je fais du old-school et je mange pas de ce pain là. Je me soumets pas au marketing agressif des soi-disant ‘sources d’actualité » de la tech. Avec leurs sondages bidonnés cherchant à convertir les devs à de nouveaux langages. On dirait des gourous essayant de recruter de nouveaux fidèles pour les frameworks offert "gratuitement" par les géants du web. Ce n’est plus des sources d’actualités mais des comptoirs de pubs. Ils vendent leurs culs « aux nouvelles techs » pour toucher des gros chèques car ils arrivent pas à se faire du blé autrement. (Bien-sûr que j'utilise toujours Jquery, Javascript c'est pour manipuler du DOM et basta. L'async et toutes ces prises de têtes sont contre productives dans 99% des cas. Un bon vieux callback et ça repart.) La plupart des mecs qui viennent t'apprendre à coder, n'ont jamais dépassé des "hello world", ni mis leurs applications d'étudiants toute neuve dans un vrai environnement de production avec de la charge. Je te parle des boîtes où si l'application est down, tes collègues sont à l'arrêt. Là bas ils en ont rien à foutre de l'index TIOBE, il veulent que sa roxe, et que ça fonctionne H24. Note que je dis collègue et pas client, sous-traiter le développement et l'infra c'est irresponsable.
</p>
<p> L'esclavagisme 2.0, tu suis leurs technos ou tu crèves. Enfin ça c'est ce qu'ils veulent faire croire à la masse et aux entreprises qui lâchent les billets pour des applications toujours plus grosses et instables, là ou une caissière suffit à faire le job pour bien moins cher qu'une armée de dev. Et ces devs, qui passent leur vie à apprendre des choses qu'ils savaient déjà faire dans une autre techno devenu ringarde du jour au lendemain... tout ça gratos de peur de ne plus être bon sur le marché de l'emploi. Les machines j'en ai ma claque, quand ça merde on est tous bien content de trouver le bouton "contact" et de tomber sur un humain en chair et os. "Faut évoluer, faut vivre avec son temps !", ça sera sans moi. On ne vit pas la révolution numérique, on s'assure simplement que l'homme avance au même rythme que les machines ... ou plutôt du business. Money, money la tech a perdu la tête. Nous les vieux de la vielle, on a pas oublié les SSI - Sociétés Service Informatique. Vous les avez renommés ESN Entreprise de Services du Numérique, cela reste des machines à cash où les riches placent leur pognon. Siphonner les petites TPE,PME, prendre en otage leur systèmes informatique en leur vendant du rêve tout en exploitant les salariés du digital... ça aussi, ça cassera la gueule. Alors amusez-vous bien dans vos recrutements, les bons sont partis depuis bien longtemps, et malheureusement souvent loin de la tech. Vous avez de la chance, demain avec le No-CODE les commerciaux pourront enfin assumer leurs mensonges ! Comme si le métier d'un dev se limitait à savoir coder et celui d'un administrateur système à d'éditer des fichiers de confs ... Bonne révolution numérique à tous!
</p>
<p>
Réveillez-vous, sortez vos lecteurs de flux RSS. Ouvrez-vos blogs.
On peut toujours tisser la toile et libérer l’information, suffit de lever un peu la tête de son nombril.
Arrêter de prendre la béquée de papa G@@gl€ et aller chercher soi-même ses sources d’informations.
</p>

+ 309
- 0
cache/2021/6d16a2f955aeaa4f23c239373824143f/index.html View File

@@ -0,0 +1,309 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the <title>
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Maintaining JavaScript applications in the long term (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f0f0ea">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f0f0ea">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://9elements.com/blog/maintaining-javascript-applications-in-the-long-term/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick">

<article>
<header>
<h1>Maintaining JavaScript applications in the long term</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://9elements.com/blog/maintaining-javascript-applications-in-the-long-term/" title="Lien vers le contenu original">Source originale</a>
</p>
</nav>
<hr>
<p>In 2019, I wrote an article on <a href="https://9elements.com/blog/maintaining-large-javascript-projects/">maintaining large JavaScript applications</a>. As a follow-up, I’d like to describe a client project we are maintaining since 2014.</p>

<h2 id="the-oecd-data-portal">The OECD Data Portal</h2>

<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://9elements.com/blog/content/images/2021/01/oecd-data-portal1.jpg" class="kg-image"><figcaption>Start page of the Data Portal</figcaption></figure>

<p>The Organisation for Economic Co-operation and Development (OECD) is an intergovernmental body that collects data and publishes studies on behalf of its member states. The fields of work, amongst others, include economy, environmental issues, well-being or education.</p>

<p>The <a href="https://data.oecd.org"><strong>OECD Data Portal</strong></a> is the central hub for statistical data. It helps researchers, journalists and policymakers to find meaningful data and to visualize it quickly with different charts. It connects with the <a href="https://www.oecd-ilibrary.org/">OECD iLibrary</a>, hosting the publications, and <a href="https://stats.oecd.org/">OECD.Stat</a>, storing the full data.</p>

<p>The OECD is funded by its member states, so eventually by taxpayers like you and me. Using cost-effective, sustainable technologies was one of the requirements so the code can be maintained in the long term.</p>

<p>The Data Portal is a joint work by OECD staff as well as external developers and designers. The initial design and prototyping came from <a href="https://truth-and-beauty.net">Moritz Stefaner</a> and <a href="https://raureif.net/">Raureif</a>. 9elements developed the production front-end code and still maintains it.</p>

<h2 id="complex-javascript-codebase">Complex JavaScript codebase</h2>

<p>The most complex part of the front-end is the JavaScript charting engine. It features ten main chart types with numerous configuration options. Using powerful interfaces, users can query the database and create charts for embedding or sharing.</p>

<p>We started working on the Data Portal in 2014. Since then, there was no “big rewrite”, only new features, gradual improvements and refactoring. Recently, for the <a href="https://www.oecd.org/economic-outlook/">OECD Economic Outlook in December 2020</a>, we added several features, including four new chart types. Also we refactored the codebase significantly.</p>

<p>In this article I’m going to describe how we maintained the code for so long and how we improved the code step by step. Also I will point out things that did not work well.</p>

<h2 id="boring-mainstream-technology">Boring mainstream technology</h2>

<p>When the project started in 2014, we chose plain HTML, XSLT templates, Sass for stylesheets and CoffeeScript as compile-to-JavaScript language. As JavaScript libraries, we chose jQuery, D3, D3.chart as well as Backbone.</p>

<p>Back in 2014, these technologies were the safest, most compatible available. Only CoffeeScript was kind of a venture. We chose CoffeeScript because it made us more productive and helped us to write reliable code. But we were aware that it poses a liability.</p>

<p>From 2015 on, 9elements has been using React for most JavaScript web applications. We considered to migrate the Data Portal chart engine to React, but we could not find the right moment. And in the end, it was probably a good decision to stick with the original stack.</p>

<p>From today, the described JavaScript stack might seem outdated. But in fact the codebase stood the test of time. One reason is that the technologies we chose have aged well.</p>

<h2 id="the-ravages-of-time">The ravages of time</h2>

<p>While plenty of JavaScript libraries appeared and vanished, jQuery remains the most popular JavaScript library. It is robust, well-maintained and widely deployed. According to the <a href="https://almanac.httparchive.org/en/2020/javascript#libraries">Web Almanac 2020</a>, jQuery is used on 83% of all web sites. (For comparison, React was detected on 4% of all web sites.)</p>

<p>Without doubt, jQuery has lost its dominance for non-trivial DOM scripting tasks. As mentioned, we would choose React or Preact for a project like the Data Portal today.</p>

<p>The second library, <a href="https://d3js.org/">D3</a>, remains the industry standard when it comes to data visualization in the browser. It exists since 2010 and is still leading. While several major releases changed the structure and the API significantly, it is still an outstanding work of engineering.</p>

<p>The <a href="https://backbonejs.org/">Backbone</a> library is not as popular, but has other qualities. Backbone is a relatively simple library. You can read the source code in one morning and could re-implement the core parts yourself in one afternoon. Backbone is still maintained, but more importantly it is feature-complete.</p>

<p>From today’s perspective, only CoffeeScript poses a significant technical debt. CoffeeScript was developed because of blatant deficits in ECMAScript 5. Later, many ideas from CoffeeScript were incorporated into the ECMAScript 6 (2015) and ECMAScript 7 (2016) standards. Since then, there is no compelling reason to use CoffeeScript any longer.</p>

<p>We picked CoffeeScript in 2014 because its philosophy is “it’s just JavaScript”. In contrast to other languages that compile to JavaScript, CoffeeScript is a straight-forward abstraction. CoffeeScript code compiles to clean JavaScript code without surprises.</p>

<p>Today, most companies have migrated their CoffeeScript codebases to modern JavaScript. That’s what we did as well.</p>

<h2 id="from-coffeescript-to-typescript">From CoffeeScript to TypeScript</h2>

<p>Using the <a href="https://github.com/decaffeinate/decaffeinate">decaffeinate</a> tool, we converted the CoffeeScript code to ECMAScript 6 (2015). We still wanted to support the same browsers, so we now use the Babel compiler to produce backwards-compatible ECMAScript 5.</p>

<p>All in all, this migration went smoothly. But we did not want to stop there.</p>

<p>In new projects, 9elements is using TypeScript. In my opinion, TypeScript is best thing that happened in the JavaScript world in the last couple of years. As I mentioned in my previous article, <a href="https://9elements.com/blog/maintaining-large-javascript-projects/#avoid-creating-untyped-objects">TypeScript forces you to think about your types</a> and name them properly.</p>

<p>For the Data Portal, we wanted to have the development benefits of TypeScript without converting the codebase to fully typed TypeScript.</p>

<p>TypeScript is a superset of JavaScript. The compiler understands .js files pretty well. So we gradually added type annotations with a 20-year-old technology: <a href="https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html">JSDOC</a>. In addition, we wrote few typings in .ts files in order to reference them in the JSDOC annotations.</p>

<p>This way, the developing experience in Visual Studio Code improved greatly with little effort. While there is no strict type checking, code editing feels as good as in an average TypeScript project.</p>

<p>By combining a rather boring but rock-solid technology with the latest TypeScript compiler, we could add new features and refactor the code safely and easily.</p>

<p>On the surface, coding is a conversation between you and the computer: You tell the computer what it should do.</p>

<p>But more importantly, coding is a conversation between you and the reader of the code. It is a well-known fact that code is written once but read again and again. First and foremost, the reader is your future self.</p>

<p>The Data Portal codebase contains many comments and almost all proved valuable during the last six years. Obviously, code should be structured to help human readers understanding it. But I do not believe in “self-descriptive” or “self-documenting” code.</p>

<p>Before we switched to JSDOC, we had human-readable type annotations, documented function parameters and return values. Also we documented the main data types, complex nested object structures.</p>

<p>These human-readable comments proved to be really helpful six years later. We translated them into machine-readable JSDOC and type declarations for the TypeScript compiler.</p>

<h2 id="things-will-break-have-a-test-suite">Things will break – have a test suite</h2>

<p>The project has only a few automated unit tests, but more than 50 test pages that demonstrate all Data Portal pages, components, data query interfaces, chart types and chart configuration options. They test against live or staging data, but also against fabricated data.</p>

<p>These test pages serve the same purpose as automated tests: If we fix a bug, we add the scenario to the corresponding test page first. If we develop a new feature, we create a comprehensive test page simultaneously.</p>

<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://9elements.com/blog/content/images/2021/01/oecd-data-portal4.jpg" class="kg-image"><figcaption>Test page for the line chart responsiveness</figcaption></figure>

<p>Before a release, we check all test pages manually and compare them to the last release – both visually and functionally. This is time-consuming, but it lets us find regressions quickly.</p>

<p>I don’t think an automated test suite would serve us better. It is almost impossible to test interactive data visualizations in the browser in an automated way. Visual regression testing is a valuable tool in general, but would produce too many false positives in our case.</p>

<h2 id="backward-and-forward-compatibility">Backward and forward compatibility</h2>

<p>In 2014, the Data Portal had to work with Internet Explorer 9. Today, Internet Explorer has no importance when you develop a dynamic, in-browser charting engine.</p>

<p>We decided to keep the compatibility with old browsers. The Data Portal is an international platform, so users visit from all over the world. They do not have the latest hardware and newest browsers.</p>

<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://9elements.com/blog/content/images/2021/01/oecd-data-portal5-ie9.jpg" class="kg-image"><figcaption>The Data Portal in Internet Explorer 9</figcaption></figure>

<p>We accomplished to maintain the browser support baseline by using boring standard technologies. We do use several modern web features. But we apply <a href="https://en.wikipedia.org/wiki/Progressive_enhancement">Progressive Enhancement</a> to activate them only if the browser supports them. Also we use Babel and polyfills to make the modern JavaScript features work in old browsers.</p>

<h2 id="your-abstractions-will-bite-you">Your abstractions will bite you</h2>

<p>The technology stack was not the limit we faced in this project over the years. It was rather the abstractions we created our own that got in our way.</p>

<p>We divided the user interface into views and created a base class similar to Backbone.View. (Today, all big JavaScript libraries use the term “component” instead of “view” for parts of the UI.) For holding the data and the state, we used Backbone.Model. This worked quite well, but we should have stuck to our own best practices.</p>

<p>The idea of Backbone’s model-view separation is to have the model as the single source of truth. The DOM should merely reflect the model data. All changes should originate from the model. Modern frameworks like React, Vue and Angular enforce the convention that the UI is “a function of the state”, meaning the UI is derived from the state deterministically.</p>

<p>We violated this principle and sometimes made the DOM the source of truth. This led to confusion with code that treated the model as authoritative.</p>

<h2 id="object-oriented-charts">Object-oriented charts</h2>

<p>For the charts, we chose yet another approach. We created chart classes not based on the view class described above.</p>

<p>D3 itself is functional. A chart is typically created and updated with a huge <code>render</code> function that calls other functions. The chart data is the input for this large function. More state is held in specific objects.</p>

<p>This makes D3 tremendously expressive and flexible. But D3 code is hard to read since there are little conventions on the structure of a chart.</p>

<p>Folks at Bocoup, Irene Ros and Mike Pennisi, invented <a>d3.chart</a>, a small library on top of D3 that introduced class-based OOP. Its main goal was to structure and reuse charting code. These charts are made of layers. A layer renders and updates a specific part of the DOM using D3. Charts can have other charts attached.</p>

<p>A general rule of OOP is “favor composition over inheritance”. Unfortunately, we used a weird mix of composition <em>and</em> inheritance to mix chart behavior.</p>

<p>We should have used functions or simple classes instead of complex class hierarchies. People still wrap D3 in class-based OOP today, but no class-based solution has prevailed against D3’s functional structure. </p>

<h2 id="summary">Summary</h2>

<p>Since we designed the Data Portal front-end architecture in 2014, powerful patterns for JavaScript-driven web interfaces have emerged.</p>

<p>Instead of rendering string-based HTML templates and updating the DOM manually, UI components are declarative nowadays. You simply update the state and the framework updates the DOM accordingly. This unidirectional data flow eliminates a whole class of bugs.</p>

<p>The technologies we picked in 2014 either stood the test of time or offered a clear migration path. You could say we were lucky, but together with the client, we also chose long-lasting technologies deliberately.</p>

<p>At 9elements, we take pride in using cutting-edge technologies. This includes assessing experimental front-end technologies that probably are not maintained any longer in three to four years from now. Unfortunately, many open source JavaScript projects are technically groundbreaking yet prove to be unsustainable.</p>

<p>For each client project, we seek the right balance between well-established, zero-risk technologies as well as innovative technologies that help us to deliver an outstanding product in time.</p>

<p><a href="https://9elements.com/contact"><strong>We're open for business so feel free to contact us for your next project.</strong></a></p>

<h2 id="acknowledgments">Acknowledgments</h2>

<figure class="kg-card kg-image-card"><img src="https://9elements.com/blog/content/images/2020/12/maintaining-large-javascript-projects.svg" class="kg-image"></figure>

<p>Thanks to <a href="https://dribbble.com/LittleSue">Susanne Nähler</a>, designer at 9elements, for creating the teaser illustration.</p>

<p>Thanks to the kind folks at OECD for the great collaboration over the course of the last six years.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
</svg> RSS</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 5
- 0
cache/2021/6d16a2f955aeaa4f23c239373824143f/index.md
File diff suppressed because it is too large
View File


+ 286
- 0
cache/2021/6faa32ba37a3b1232125db9858700627/index.html
File diff suppressed because it is too large
View File


+ 69
- 0
cache/2021/6faa32ba37a3b1232125db9858700627/index.md
File diff suppressed because it is too large
View File


+ 10
- 0
cache/2021/index.html View File

@@ -87,6 +87,8 @@
<li><a href="/david/cache/2021/b19c86fa9c66389e26495165b442d0c0/" title="Accès à l’article dans le cache local : L’emprise de la machine : une critique décroissanciste de la domination technique">L’emprise de la machine : une critique décroissanciste de la domination technique</a> (<a href="https://polemos-decroissance.org/lemprise-de-la-machine-une-critique-decroissanciste-de-la-domination-technique/" title="Accès à l’article original distant : L’emprise de la machine : une critique décroissanciste de la domination technique">original</a>)</li>
<li><a href="/david/cache/2021/321b85630164ca075bd3be265f23aed5/" title="Accès à l’article dans le cache local : Codebase Collaboration Between Humans and Robots">Codebase Collaboration Between Humans and Robots</a> (<a href="https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/" title="Accès à l’article original distant : Codebase Collaboration Between Humans and Robots">original</a>)</li>
<li><a href="/david/cache/2021/1cb1c46e0a1adcd0917179a214a16e0a/" title="Accès à l’article dans le cache local : DNA seen through the eyes of a coder (or, If you are a hammer, everything looks like a nail)">DNA seen through the eyes of a coder (or, If you are a hammer, everything looks like a nail)</a> (<a href="https://berthub.eu/articles/posts/amazing-dna/" title="Accès à l’article original distant : DNA seen through the eyes of a coder (or, If you are a hammer, everything looks like a nail)">original</a>)</li>
<li><a href="/david/cache/2021/765e28efb1fa6aa0dc9c15166f66cdf3/" title="Accès à l’article dans le cache local : How Silicon Valley, in a Show of Monopolistic Force, Destroyed Parler">How Silicon Valley, in a Show of Monopolistic Force, Destroyed Parler</a> (<a href="https://greenwald.substack.com/p/how-silicon-valley-in-a-show-of-monopolistic" title="Accès à l’article original distant : How Silicon Valley, in a Show of Monopolistic Force, Destroyed Parler">original</a>)</li>
@@ -115,6 +117,8 @@
<li><a href="/david/cache/2021/3d3e8962a6319ee4d41a75b1cd5abd38/" title="Accès à l’article dans le cache local : How the novel coronavirus has evolved">How the novel coronavirus has evolved</a> (<a href="https://graphics.reuters.com/HEALTH-CORONAVIRUS/EVOLUTION/yxmpjqkdzvr/index.html" title="Accès à l’article original distant : How the novel coronavirus has evolved">original</a>)</li>
<li><a href="/david/cache/2021/6d16a2f955aeaa4f23c239373824143f/" title="Accès à l’article dans le cache local : Maintaining JavaScript applications in the long term">Maintaining JavaScript applications in the long term</a> (<a href="https://9elements.com/blog/maintaining-javascript-applications-in-the-long-term/" title="Accès à l’article original distant : Maintaining JavaScript applications in the long term">original</a>)</li>
<li><a href="/david/cache/2021/5f1c22e9a41d209ff84218b3d6faf676/" title="Accès à l’article dans le cache local : Reverse Engineering Source Code of the Biontech Pfizer Vaccine: Part 2">Reverse Engineering Source Code of the Biontech Pfizer Vaccine: Part 2</a> (<a href="https://berthub.eu/articles/posts/part-2-reverse-engineering-source-code-of-the-biontech-pfizer-vaccine/" title="Accès à l’article original distant : Reverse Engineering Source Code of the Biontech Pfizer Vaccine: Part 2">original</a>)</li>
<li><a href="/david/cache/2021/f1df3d5f1720e137130581d5a2b8549f/" title="Accès à l’article dans le cache local : Built to Last">Built to Last</a> (<a href="https://logicmag.io/care/built-to-last/" title="Accès à l’article original distant : Built to Last">original</a>)</li>
@@ -141,6 +145,8 @@
<li><a href="/david/cache/2021/c177668b263f39d20788f002446d2a47/" title="Accès à l’article dans le cache local : 6-month consequences of COVID-19 in patients discharged from hospital: a cohort study">6-month consequences of COVID-19 in patients discharged from hospital: a cohort study</a> (<a href="https://www.thelancet.com/journals/lancet/article/PIIS0140-6736(20)32656-8/fulltext" title="Accès à l’article original distant : 6-month consequences of COVID-19 in patients discharged from hospital: a cohort study">original</a>)</li>
<li><a href="/david/cache/2021/59bd3fea3b3b370bd6b116e77effb69e/" title="Accès à l’article dans le cache local : Nostalgie de l'ancien web">Nostalgie de l'ancien web</a> (<a href="https://osd.ovh/index.php?article10/nostalgie-de-lancien-web" title="Accès à l’article original distant : Nostalgie de l'ancien web">original</a>)</li>
<li><a href="/david/cache/2021/0c6966a8e9543b52c361ac6de68f08e4/" title="Accès à l’article dans le cache local : Understanding ProRAW">Understanding ProRAW</a> (<a href="https://blog.halide.cam/understanding-proraw-4eed556d4c54" title="Accès à l’article original distant : Understanding ProRAW">original</a>)</li>
<li><a href="/david/cache/2021/aeb0a60038b91bf1fbbbd39b358366fb/" title="Accès à l’article dans le cache local : ☕️ Journal : Statu quo">☕️ Journal : Statu quo</a> (<a href="https://oncletom.io/2021/01/05/statu-quo/" title="Accès à l’article original distant : ☕️ Journal : Statu quo">original</a>)</li>
@@ -153,6 +159,10 @@
<li><a href="/david/cache/2021/44064d714aff0deac9f882cc429d8b9d/" title="Accès à l’article dans le cache local : Some rambling thoughts about the stuttering end of the last ice age and what lockdown means">Some rambling thoughts about the stuttering end of the last ice age and what lockdown means</a> (<a href="http://interconnected.org/home/2020/04/20/continuous_partial_lockdown" title="Accès à l’article original distant : Some rambling thoughts about the stuttering end of the last ice age and what lockdown means">original</a>)</li>
<li><a href="/david/cache/2021/0e0d866f920298fbc0624c03ddc83d24/" title="Accès à l’article dans le cache local : Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens">Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens</a> (<a href="https://www.ledevoir.com/societe/594536/reconnaissance-faciale-clearview-ai-a-viole-la-vie-privee-des-canadiens" title="Accès à l’article original distant : Reconnaissance faciale: Clearview AI a violé la vie privée des Canadiens">original</a>)</li>
<li><a href="/david/cache/2021/6faa32ba37a3b1232125db9858700627/" title="Accès à l’article dans le cache local : Design Justice : repolitiser le design">Design Justice : repolitiser le design</a> (<a href="https://www.internetactu.net/2021/02/03/design-justice-repolitiser-le-design/" title="Accès à l’article original distant : Design Justice : repolitiser le design">original</a>)</li>
<li><a href="/david/cache/2021/30069f97e4aa989a1d89fe8d88538da8/" title="Accès à l’article dans le cache local : We Had the COVID-19 Vaccine the Whole Time">We Had the COVID-19 Vaccine the Whole Time</a> (<a href="https://nymag.com/intelligencer/2020/12/moderna-covid-19-vaccine-design.html" title="Accès à l’article original distant : We Had the COVID-19 Vaccine the Whole Time">original</a>)</li>
</ul>

Loading…
Cancel
Save