A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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>
  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>Learning from mistakes (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="#f0f0ea">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f0f0ea">
  26. <!-- Documented, feel free to shoot an email. -->
  27. <link rel="stylesheet" href="/static/david/css/style_2020-06-19.css">
  28. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  29. <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>
  30. <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>
  31. <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>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <script type="text/javascript">
  36. function toggleTheme(themeName) {
  37. document.documentElement.classList.toggle(
  38. 'forced-dark',
  39. themeName === 'dark'
  40. )
  41. document.documentElement.classList.toggle(
  42. 'forced-light',
  43. themeName === 'light'
  44. )
  45. }
  46. const selectedTheme = localStorage.getItem('theme')
  47. if (selectedTheme !== 'undefined') {
  48. toggleTheme(selectedTheme)
  49. }
  50. </script>
  51. <meta name="robots" content="noindex, nofollow">
  52. <meta content="origin-when-cross-origin" name="referrer">
  53. <!-- Canonical URL for SEO purposes -->
  54. <link rel="canonical" href="https://www.jackfranklin.co.uk/blog/learning-from-mistakes/">
  55. <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick">
  56. <article>
  57. <header>
  58. <h1>Learning from mistakes</h1>
  59. </header>
  60. <nav>
  61. <p class="center">
  62. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  63. <a href="https://www.jackfranklin.co.uk/blog/learning-from-mistakes/" title="Lien vers le contenu original">Source originale</a>
  64. </p>
  65. </nav>
  66. <hr>
  67. <main>
  68. <p><em>Today I'm kicking off a new series on writing and maintaining JavaScript software titled "Designing Good JavaScript" by looking at learning at our mistakes. I hope you enjoy this post and the series!</em></p>
  69. <p>How many times have you loaded up a file in your codebase to make some quick changes, only to be confused by the choices you made six months ago? How many times has that architecture you worked so hard on in the past come back to bite you? How often do you find yourself bemoaning a section of the codebase to a colleague, thinking that the only way to solve it is a complete rewrite?</p>
  70. <p>The good news is that if you answered "yes" to any of those questions, you're not alone, and you have something in common with me! I've spent the most part of my career maintaining large JavaScript applications and what I've come to realise is that <strong>it's easy to write code you can understand now, but hard to write code you'll understand in six months.</strong> The best engineers I've worked with aren't the best because they know every API method under the sun, or because they can turn five lines of code into two with a clever <code>reduce</code> call, but because they write <strong>code that they (and their colleagues) can understand now and code that can be understood in the future.</strong> They have an awareness of how a particular decision now can impact your velocity further down the line and an ability to predict problems before they happen.</p>
  71. <p>How do these engineers get this ability? <strong>Experience.</strong> They don't foresee problems because they are able to look into a crystal ball, or experience premonitions of the future like that kid in Final Destination, but because they've been there, done that, countless times. How do they know that a particular approach might backfire? Because two years ago working at Company X, it did.</p>
  72. <p>The good news is that whilst there is no substitute for experience and learning from your mistakes (<a href="/blog/the-three-software-developers/">and being nice to yourself in the process</a>) there are many people, including yours truly, willing to share their mistakes and lessons learned from them. No engineer knows everything, and no engineer makes the right decision on software every time. Opinions on software are formed over time as we write code, make decisions, and learn what works and what doesn't. That's what this series is all about. Over the coming weeks I'll be sharing opinions and stories from when a software decision backfired - or when one really paid off - so that you can keep them in your back pocket when the next time a similar decision has to be made. I'll reflect on teams that I've worked on that have executed efficiently, and teams who have got bogged down in process, and everything inbetween. Think of this as a series where I share my experiences so that you can take them and use them to inform your decisions. There's no lecturing here.</p>
  73. <p>If you've got any questions, comments, feedback, or just want to say hello, <a href="https://www.twitter.com/Jack_Franklin">get in touch with me on Twitter</a>. I'm excited to share these articles and would love to hear what you think, or any suggestions for content.</p>
  74. </main>
  75. </article>
  76. <hr>
  77. <footer>
  78. <p>
  79. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  80. <a href="/david/log/" title="Accès au flux RSS">🤖</a> •
  81. <a href="http://larlet.com" title="Go to my English profile" data-instant>🇨🇦</a> •
  82. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">📮</a> •
  83. <abbr title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340">🧚</abbr>
  84. </p>
  85. <template id="theme-selector">
  86. <form>
  87. <fieldset>
  88. <legend>Thème</legend>
  89. <label>
  90. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  91. </label>
  92. <label>
  93. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  94. </label>
  95. <label>
  96. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  97. </label>
  98. </fieldset>
  99. </form>
  100. </template>
  101. </footer>
  102. <script type="text/javascript">
  103. function loadThemeForm(templateName) {
  104. const themeSelectorTemplate = document.querySelector(templateName)
  105. const form = themeSelectorTemplate.content.firstElementChild
  106. themeSelectorTemplate.replaceWith(form)
  107. form.addEventListener('change', (e) => {
  108. const chosenColorScheme = e.target.value
  109. localStorage.setItem('theme', chosenColorScheme)
  110. toggleTheme(chosenColorScheme)
  111. })
  112. const selectedTheme = localStorage.getItem('theme')
  113. if (selectedTheme && selectedTheme !== 'undefined') {
  114. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  115. }
  116. }
  117. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  118. window.addEventListener('load', () => {
  119. let hasDarkRules = false
  120. for (const styleSheet of Array.from(document.styleSheets)) {
  121. let mediaRules = []
  122. for (const cssRule of styleSheet.cssRules) {
  123. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  124. continue
  125. }
  126. // WARNING: Safari does not have/supports `conditionText`.
  127. if (cssRule.conditionText) {
  128. if (cssRule.conditionText !== prefersColorSchemeDark) {
  129. continue
  130. }
  131. } else {
  132. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  133. continue
  134. }
  135. }
  136. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  137. }
  138. // WARNING: do not try to insert a Rule to a styleSheet you are
  139. // currently iterating on, otherwise the browser will be stuck
  140. // in a infinite loop…
  141. for (const mediaRule of mediaRules) {
  142. styleSheet.insertRule(mediaRule.cssText)
  143. hasDarkRules = true
  144. }
  145. }
  146. if (hasDarkRules) {
  147. loadThemeForm('#theme-selector')
  148. }
  149. })
  150. </script>
  151. </body>
  152. </html>