A place to cache linked articles (think custom and personal wayback machine)
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

index.html 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Codebase Collaboration Between Humans and Robots (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <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>
  31. <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>
  32. <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>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Codebase Collaboration Between Humans and Robots</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://blog.jim-nielsen.com/2021/codbase-collaboration-between-humans-and-robots/" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p>Back in 2017, <a href="https://twitter.com/jimniels/status/889921238809837568?s=20">I tweeted</a>:</p>
  71. <blockquote>
  72. <p>JS will soon read like it's written for machines</p>
  73. <pre><code>// prettier-ignore
  74. /* eslint-disable */
  75. import(/* webpackChunkName: "lodash" */ 'lodash')</code></pre></blockquote>
  76. <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>
  77. <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>
  78. <p>Eventually I found the right incantation to break the spell of a failing build: </p>
  79. <pre><code class="language language-js"></code></pre>
  80. <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>
  81. <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>
  82. <h2 id="collaborating-robots-vs-humans">Collaborating: Robots vs. Humans</h2>
  83. <p>Fast-forward to 2020 and I saw <a href="https://twitter.com/davatron5000/status/1327292373244792832">this tweet from @davatron5000</a>:</p>
  84. <blockquote>
  85. <p>Staring at 12 config files in my project root like they're my mortal enemies and not my supportive robot buddies.</p>
  86. </blockquote>
  87. <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>
  88. <p><img src="https://cdn.jim-nielsen.com/blog/2021/code-for-machines-screenshot-1.jpeg" alt="">
  89. </p>
  90. <p>For this blog post, I went out and grabbed a few more examples:</p>
  91. <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.">
  92. </p>
  93. <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>
  94. <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>
  95. <ul>
  96. <li>“Upgrade to prettier 2”</li>
  97. <li>“upgrade examples to webpack-cli major 4”</li>
  98. <li>“improve prettier and lint config and performance”</li>
  99. <li>“generate runtime code with special-lint-fix”</li>
  100. <li>“improve linting performance”</li>
  101. <li>“fix newly found eslint problems”</li>
  102. </ul>
  103. <h2 id="robot-coworkers">Robot Coworkers</h2>
  104. <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>
  105. <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>
  106. <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>
  107. <h2 id="robots--complexity">Robots &amp; Complexity</h2>
  108. <p>It makes me think of a line by John Ousterhout from his book <em>A Philosophy of Software Design</em>:</p>
  109. <blockquote>
  110. <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>
  111. </blockquote>
  112. <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>
  113. <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>
  114. <h2 id="conclusion">Conclusion</h2>
  115. <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>
  116. <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>
  117. </article>
  118. <hr>
  119. <footer>
  120. <p>
  121. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  122. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  123. </svg> Accueil</a> •
  124. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  125. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  126. </svg> Suivre</a> •
  127. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  128. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  129. </svg> Pro</a> •
  130. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  131. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  132. </svg> Email</a> •
  133. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  134. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  135. </svg> Légal</abbr>
  136. </p>
  137. <template id="theme-selector">
  138. <form>
  139. <fieldset>
  140. <legend><svg class="icon icon-brightness-contrast">
  141. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  142. </svg> Thème</legend>
  143. <label>
  144. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  145. </label>
  146. <label>
  147. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  148. </label>
  149. <label>
  150. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  151. </label>
  152. </fieldset>
  153. </form>
  154. </template>
  155. </footer>
  156. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  157. <script>
  158. function loadThemeForm(templateName) {
  159. const themeSelectorTemplate = document.querySelector(templateName)
  160. const form = themeSelectorTemplate.content.firstElementChild
  161. themeSelectorTemplate.replaceWith(form)
  162. form.addEventListener('change', (e) => {
  163. const chosenColorScheme = e.target.value
  164. localStorage.setItem('theme', chosenColorScheme)
  165. toggleTheme(chosenColorScheme)
  166. })
  167. const selectedTheme = localStorage.getItem('theme')
  168. if (selectedTheme && selectedTheme !== 'undefined') {
  169. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  170. }
  171. }
  172. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  173. window.addEventListener('load', () => {
  174. let hasDarkRules = false
  175. for (const styleSheet of Array.from(document.styleSheets)) {
  176. let mediaRules = []
  177. for (const cssRule of styleSheet.cssRules) {
  178. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  179. continue
  180. }
  181. // WARNING: Safari does not have/supports `conditionText`.
  182. if (cssRule.conditionText) {
  183. if (cssRule.conditionText !== prefersColorSchemeDark) {
  184. continue
  185. }
  186. } else {
  187. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  188. continue
  189. }
  190. }
  191. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  192. }
  193. // WARNING: do not try to insert a Rule to a styleSheet you are
  194. // currently iterating on, otherwise the browser will be stuck
  195. // in a infinite loop…
  196. for (const mediaRule of mediaRules) {
  197. styleSheet.insertRule(mediaRule.cssText)
  198. hasDarkRules = true
  199. }
  200. }
  201. if (hasDarkRules) {
  202. loadThemeForm('#theme-selector')
  203. }
  204. })
  205. </script>
  206. </body>
  207. </html>