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.

3 年之前
3 年之前
3 年之前
3 年之前
3 年之前
3 年之前
3 年之前
3 年之前
3 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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>136 facts every web dev should know before they burn out and turn to landscape painting or nude modelling (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://www.baldurbjarnason.com/2021/100-things-every-web-developer-should-know/">
  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>136 facts every web dev should know before they burn out and turn to landscape painting or nude modelling</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.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://www.baldurbjarnason.com/2021/100-things-every-web-developer-should-know/" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p>Everything I’ve learned about web development in the almost twenty-five years I’ve been practising. All boiled down into a neat little list that I put together over a week.</p>
  71. <p>I’m Icelandic, so I’m prone to absolute statements. It’s a cultural thing.</p>
  72. <p><em>No, I’m not going to explain any of these.</em></p>
  73. <ol>
  74. <li>There are exceptions to most rules.</li>
  75. <li>Web development becomes more complicated the more you pull it apart and less so the more you step back.</li>
  76. <li>The best way to improve software UX is regular direct observation, by everybody on the team, of the work done.</li>
  77. <li>Software development needs to support the needs of those in the organisation. Otherwise, its ability to serve the needs of the customer will fall apart in short order.</li>
  78. <li>You may think that software development at a software company serves the customer directly, but you’d be mistaken. The organisation is the software development team’s primary customer.</li>
  79. <li>One of the biggest problems in web development, specifically and software development in general, is <a href="https://vanguard-method.net/failure-demand/">failure demand</a>. <a href="https://vanguard-method.net/library/systems-principles/failure-demand/">“Failure demand is demand caused by a failure to do something or do something right for the customer."</a> (John Seddon, 2003).</li>
  80. <li>Examples of failure demand in software development:
  81. <ol>
  82. <li>Having to rewrite code because, while you fulfilled the documented requirements, you didn’t meet the organisation’s actual needs.</li>
  83. <li>Having to spend all your time fixing bugs. Your sole focus at the start of the project was delivering features. Now you don’t have time to do your work cleanly <em>without creating bugs</em> because all your time goes into fixing them.</li>
  84. <li>Building the wrong product because you didn’t understand the needs of the customer.</li>
  85. <li>Spending all your time deploying or testing by hand because you never spent time on automation.</li>
  86. <li>Having to redo a feature because the spec was unclear.</li>
  87. <li>And more.</li>
  88. </ol>
  89. </li>
  90. <li>Most software projects consume 5x, 10x, 20x more resources than they should because failure demand consumes most of the organisation’s resources.</li>
  91. <li>HTML is fantastic. Even if you can do a task without it, keep using HTML to manage, update, or encapsulate your CSS or JS work. (Custom Elements!)</li>
  92. <li>Everybody has small screens, and they all know how to scroll: only make UI widgets ‘sticky’ or ‘fixed’ if you have to. They know where your navigation bar is. You don’t have to push it in their face the whole time.</li>
  93. </ol>
  94. <hr>
  95. <ol start="11">
  96. <li>Everybody has small screens, and they all know how to scroll: make sure that what they see when the page loads tells them there is something below the fold. They will scroll down if they have the slightest reason to. If only to see how dumb your work is.</li>
  97. <li>Everybody has small screens, and they all know how to scroll: scroll position is a part of the application’s core state. Preserving scroll position across navigations is an easy UX win.</li>
  98. <li>If the user has big screens, make use of them. When you have space, opt for detail over decoration, data over branding, buttons and navigation over menus.</li>
  99. <li>Sturgeon’s law applies to your work as well. Don’t linger on one project forever. Make new things. That’s the only way to learn.</li>
  100. <li>The trick is to recognise when it’s time to move on.</li>
  101. <li>A visitor to your site begins by building a map of it in their heads. Because without that internal map, nothing they will ever do on your site will fully make sense to them because it has no context.</li>
  102. <li>Context is essential.
  103. <ol>
  104. <li>Show them what you got, yes, but show it to them <em>in context</em>.</li>
  105. <li>Visible context is always preferable to the context that has been shuffled off into a hidey-hole somewhere.</li>
  106. <li>See above about using the big screen if you have it.</li>
  107. </ol>
  108. </li>
  109. <li>Use multiple screens if you can. The web is hypertext. Your app can exist on anything that can load an URL over HTTP. Try and do something useful with it.</li>
  110. <li>Have some personality: web dev is a pop culture and rewards personality. It doesn’t necessarily reward originality or quality but, as long as you don’t let us down elsewhere, it does reward having character.</li>
  111. <li>Have some personality:
  112. <ol>
  113. <li>MID (Medium-Inspired Design) is mediocre.</li>
  114. <li>Everything looks the goddamn same. Same sans serif fonts. Same flat illustrations. Same colour schemes. Same. Same. Same.</li>
  115. <li>You can get away with looking boring if something else about your work is inventive but not if the whole thing you’re doing is by-the-numbers.</li>
  116. <li>Even if what you’re making is original, why not look memorable while you’re at it?</li>
  117. </ol>
  118. </li>
  119. </ol>
  120. <hr>
  121. <ol start="21">
  122. <li>Most products don’t need the features that SPAs provide. Teams need SPAs but not for the product itself. SPAs make for great demos and lovely presentations, which leads to more support for the team, more funding, and that way, SPAs improve the odds of success.</li>
  123. <li>Then SPAs take away what they give because they are error-prone and costly to develop. So much state to track. So many built-in features to reimplement.
  124. <ol>
  125. <li>The first rule of SPAs: we always underestimate the complexity of handling state. Often by a large margin.</li>
  126. <li>The second rule of SPAs: we always underestimate the complexity of reimplementing history and link navigation. Often by a large margin. But we get away with not caring because <em>nobody</em> tests history management properly.</li>
  127. </ol>
  128. </li>
  129. <li>SPAs are too much work: take the time and money you’d spend on SPAs and frameworks and spend it on the UX design instead. SPAs aren’t necessary for good UX design. Animation and swishy transitions aren’t good interactivity design. (“Design is how it works.") Which reminds me.</li>
  130. <li>Every SPA I’ve ever used has at some point let me down when it comes to navigation or history management:
  131. <ol>
  132. <li>Resetting a view when you click the back button (browsers have an excellent back-forward cache! Use it!).</li>
  133. <li>Not loading the correct view.</li>
  134. <li>Failing to load a part of the screen.</li>
  135. <li>Losing data/context when opening a link in a new tab.</li>
  136. <li>Or just giving up altogether.</li>
  137. <li>They all fuck up at some point. Server-routed sites aren’t perfect, but there’s a lot less that can go wrong.</li>
  138. </ol>
  139. </li>
  140. <li>Every SPA breaks the back button in some way. Often it won’t let you ‘back’ out of a site, where it always redirects you forward again whenever you hit the initial page that sets everything up. Other times it’s a more subtle error, but they all break it somehow.</li>
  141. <li>Design is what we do. Design is what the user does. Design is our actions that result in a field of possibilities for the user. The web is an interactive medium. If it isn’t something done by somebody – the digital embodiment of an action somebody has taken – then it is garbage, and you should do away with it.</li>
  142. <li>Minimalism is garbage. Simplicity is great, but minimalism sucks. Everything you see on the screen should have a reason to be there (be an embodiment of ‘doing’), but if the reasons are complicated, then the design should represent that complexity. Hiding complications makes everything harder, and excessive minimalism is just as harmful as excessive decoration.</li>
  143. <li>Data processing is not a complication. That can safely be shuffled off into the background or behind an abstraction.</li>
  144. <li>Complication is something involved that the user has to be aware of or do. If it’s something to be automated or handed off, then you still can’t get away with hiding away.</li>
  145. <li>Feedback loops are what interfaces run on, and hiding details away is a surefire way of breaking a feedback loop.</li>
  146. </ol>
  147. <hr>
  148. <ol start="31">
  149. <li>Decoration is like junk food. It’s great in moderation. A little bit here and there is necessary to give life colour and vividness. But too much of it will kill you.</li>
  150. <li>You still need some decoration. See ‘have a personality’ above. But not as much as you think because—</li>
  151. <li>It isn’t decoration if it changes the ‘doing’. When it frames something and changes its meaning, it’s a frame (<em>parergon</em> if you’re a Derrida fan).</li>
  152. <li>It isn’t decoration if it changes the ‘doing’. Styling Tetris so that it’s now a game about stacking bodies in a mass grave isn’t decoration but <em>design</em>. Horrifying, but still a design.</li>
  153. <li>Metaphors are fantastic. When you combine them with thoughtful visual design, they can transform a by-the-numbers web service or app into something groundbreaking.</li>
  154. <li>Naming things is fantastic. Everything on the screen should have a name. It’s better for your work. It’s better for accessibility. It’s better for your design. Take a table view and name it ‘Inbox’, ‘Screener’, or ‘Paper Trail’, and they suddenly mean something. What you do with them has changed. A good name transforms design and action.</li>
  155. <li>Prefer HTML over CSS over Images over Typefaces over JavaScript, in that order. Roughly.</li>
  156. <li>Don’t be mean. Make sure that undo works. And don’t get hung up on complex computer science. ‘Undo’ in this context means ‘can I make it right if I do something I immediately regret?’ Put a slight time delay on the action. Fake those deletes for a few hours. Every update should preserve the version you are replacing <em>somewhere</em>, even if it’s only in this one tab on this one device. That way, you can give them one level of undoing. They already regret having to use your app; don’t make them regret you were ever born. (Too late! Hah!)</li>
  157. <li>Use URLs, links, and hypertext. Try not to hardcode relationships or URLs.</li>
  158. <li>Use URLs from links with rel values over URLs in attributes over URLs in properties over URLs in source code. Do it in that order. Apply that to anything that speaks HTTP in your app.</li>
  159. </ol>
  160. <hr>
  161. <ol start="41">
  162. <li>Try to write HTML that would make sense and be usable without the CSS. Not because you ever expect that to happen (<strong>cough</strong>reader modes<strong>cough</strong>) but because that way you get a ton of freebies: appropriate default styles and built-in default behaviours. HTML-first means less work <em>overall</em>, both in styling and interactivity, because you start by seeing how much work HTML can provide before you step up to other layers.</li>
  163. <li>Try to write HTML that works and is usable without JS. Not because you ever expect that to happen, but because that way you get a ton of freebies: built-in input validation, form submission through a variety of input modes, UI widgets that are accessible out of the box, link navigation that fully supports the options the user’s OS provides.</li>
  164. <li>Try to write your CSS in layers.
  165. <ol>
  166. <li>A settings stylesheet that collects all of your base variables.</li>
  167. <li>A base stylesheet that serves as the foundation.</li>
  168. <li>Layout stylesheets. Each one should implement a layout or composition without depending on other stylesheets.</li>
  169. <li>Block stylesheets that are the <em>motif</em> to your composition, the phrases in your structure, the recurring themes of your design.</li>
  170. <li>And the utilities that do one thing and one thing only.</li>
  171. </ol>
  172. </li>
  173. <li>Load your styles <em>in that order</em>. Your utilities should override your motifs, your motifs should override your compositions, your compositions should override your element styles, and the variables from everything else should override your default variables. Use the cascade, Luke! Use the cascade!</li>
  174. <li>Style JS-driven state using ‘data-*’ attributes, style app design using classes, and style defaults using elements. Don’t let JS drive classes if you can help it. And don’t set style defaults using the class attribute.</li>
  175. <li>Only target CSS with the ID selector as a last resort. IDs are already used by JS, ARIA attributes, link navigation, input labelling, and more. Even without specificity issues, the ID attribute would be too overloaded, too tightly coupled to other layers in the web stack, to be anything but trouble.</li>
  176. <li>Only use the ID selector in your CSS as a last resort to fix extreme and hard-to-solve specificity issues. Try doubling up on a class first. <code>.class.class</code> is a valid selector and can work wonders.</li>
  177. <li>A specificity problem that’s hard to solve without <code>!important</code> usually means you haven’t thought through the structure of your CSS. Reaching for that <code>!important</code> instead of refactoring means you’re letting your CSS rot: technical debt is piling up.</li>
  178. <li>Because of the cascade, CSS is more sensitive to structure than most other code. You probably should refactor your stylesheets more often than you do your JS.</li>
  179. <li>Add IDs to every landmark and every paragraph if your tools let you. It’s rare to find a widely supported API that is usable by a broad section of the population. Links with fragment selectors are one of them. But to make them work, your HTML needs to have IDs.</li>
  180. </ol>
  181. <hr>
  182. <ol start="51">
  183. <li>Make the problem browser your development home. If Firefox always gives you pain, live in it. Make it your work browser. Almost all of your Firefox-specific problems will disappear because you end up fixing them as you go, without thinking. Tight feedback loops are magic.</li>
  184. <li>The only exceptions to this are the mobile browsers because mobile OSes are garbage. They don’t let you do any real work or development. Maybe they work for you. Great for you. But the inflexibilities of mobile OSes mean that they just can’t serve the variety that desktop OSes do. Which means that—</li>
  185. <li>Mobile websites are always going to suck. They’re going to suck for development. They are going to suck for users. We can put in the work to make sure they don’t suck for the user, but that just means they suck extra hard for us.</li>
  186. <li>Tight feedback loops are magic: live reloading is magical. Hot module replacement less so. With live reload, your development browser automatically reloads your dev page when your code changes. If you suck and your page loads slowly, then you suffer. Hot module replacement hides the pain and lets you pass the suffering onto the user.</li>
  187. <li>Tight feedback loops are magic: build processes suck. They will always suck because they always loosen up the feedback loop. You can make builds quicker, but until they are virtually instantaneous, they will always suck. (Which could happen. <em>waves towards esbuild</em>.) If you can make something without a build step, do so. If you can make something without compilation or building, do that.</li>
  188. <li>Svelte and Typescript are very useful, but the cost of building is always more than you think, especially once the codebase grows.</li>
  189. <li>JS building adds the most value when you have many dependencies. In that case, it’s essential. But if you have few to no dependencies, most of the caveats about not building your JS go away. If you find yourself in that position: skip the build.</li>
  190. <li>Dependencies suck; dependencies rule. Other people’s code is like getting other people’s work for free. The downside is that it comes with their opinions, hobbies, and hygiene attached. All code comes bundled with a code smell. Usually, there isn’t anything you can do to prevent it from stinking up the place.</li>
  191. <li>Every dependency you use has security issues: if you don’t check them all to see if their issues are ones you can live with, then you’re probably going to pay for it later.</li>
  192. <li>Sometimes, the best thing an open-source project can do is demonstrate how you solve a problem. Adding it as a dependency afterwards is often a huge mistake.</li>
  193. </ol>
  194. <hr>
  195. <ol start="61">
  196. <li>The job of development is to build a theory in your mind about the codebase.</li>
  197. <li>Too many dependencies can make that <em>harder</em>, not easier. Having too many dependencies can obfuscate the work that you are now having done for you by proxy.</li>
  198. <li>The developers' mental model of the codebase is what keeps it alive.</li>
  199. <li>DRY (don’t repeat yourself) is a luxury for when you have a coherent theory in your mind of the app’s code.
  200. <ol>
  201. <li>It’s for when you have that theory contained in a worldview in your mind that helps you quickly test out decisions and plans against that theory.</li>
  202. <li>Until then, you should repeat yourself. Seeing your code repeat itself – when rhyming phrases start to pop up throughout – is a vital tool for building a theory about your app.</li>
  203. </ol>
  204. </li>
  205. <li>Avoid using web workers (the web stack’s equivalent for a process) or threads if you can. They make theory-building harder. Only use them when they can be wrapped in a nice metaphor and modelled as standalone services or isolated functions, like a service worker or an unzip utility.</li>
  206. <li>Dependencies can sometimes do what you would never do, use bad ideas, take risks you never would. At least that way, when something blows up, you have someone else to blame.</li>
  207. <li>Of course, you chose to add the dependency, so either way, you are responsible.</li>
  208. <li>Despite what you may think, offline-first isn’t essential. It’s a lot of work, changes everything you make in the app, and, while everybody loves it when they need it, almost nobody will pay for it. Given two options, the odds are that buyers will buy the one that doesn’t support offline. (‘Buyer’ here being anything from an end consumer to an in-house stakeholder.) Why? Because it’s almost certainly cheaper and more reliable in a highly connected environment.</li>
  209. <li>The buyer is quite often wrong. That fact never changes their mind.</li>
  210. <li>Working on a functioning app’s codebase does more to increase its quality than adding features.</li>
  211. </ol>
  212. <hr>
  213. <ol start="71">
  214. <li>Managers will always undervalue plain old code work.
  215. <ol>
  216. <li>Working on an iffy codebase (and they all start iffy) to make it cleaner, more sensible, and more robust without adding features or functionality can save you weeks if not months of future work.</li>
  217. <li>Once you have a working app, working on code quality is just as likely to provide as much business value as a new feature.</li>
  218. <li>Managers will never, ever, ever be able to see or understand this.</li>
  219. <li>But a <em>good</em> manager doesn’t have to because they will give your team the autonomy to do things they don’t understand. A good manager will trust that you are working to address the organisation’s needs (and the needs of those in it) without arguing with you.</li>
  220. </ol>
  221. </li>
  222. <li>A good manager <em>will</em> debate you, and that’s awesome.</li>
  223. <li>Fuck ups happen. Nobody is to blame even when somebody is responsible. Use it as an opportunity to see where the process didn’t work. And if you don’t have a process—well, that’s what’s wrong. Right?</li>
  224. <li>Fuck-ups happen. The run-up to the fuck-up is more interesting than the fuck-up itself. How did it happen? What made it get this far? Why didn’t anybody speak out sooner? Why didn’t somebody try to help sooner?</li>
  225. <li>Fuck-ups happen. Some people make it their mission in life to make sure that whenever a fuck-up happens, somebody will suffer. Don’t be that person, and don’t let that person get to you. They’re an ass.</li>
  226. <li>Fuck-ups happen, but they don’t always have to: a checklist does wonders. No, really. It will save your ass even without automation or coding.</li>
  227. <li>Every manager has an inappropriate love that will make life miserable for their reports. Some love meetings but will rarely put in the work to make those meetings worthwhile. Some love email but are incapable of putting together a coherent sentence.</li>
  228. <li>Prefer structured communications tools like an in-house blog, a wiki, Basecamp, Notion, or GitHub over unstructured messaging platforms like email or Slack. Your work has structure; so should your communications.</li>
  229. <li>Don’t rely too much on tools. They will let you down.</li>
  230. <li>Digital publishing is, for the most part, just a bunch of unrelated business models wrapped up in an exterior layer of design metaphors. Without the metaphors, it’s just sparkling websites.</li>
  231. </ol>
  232. <hr>
  233. <ol start="81">
  234. <li>We have already baked in all of the downsides of XHTML into all of our dev tools. They tend to be stricter and more fragile than XML ever was and require you to use a pseudo-, often home-baked, markup format (<em>cough</em>JSX<em>cough</em>) that breaks just as often. Meanwhile, XHTML has semantic extensibility and native CSS support for extension namespacing. Both natively implemented by the browser. Not saying we should all switch back to XHTML (browser support is still there!) but I <em>am</em> saying XHTML had a lesson to teach us, but we didn’t pay attention and haven’t learned a thing.</li>
  235. <li>In other words: web dev is a pop culture with no regard for history, dooming each successive generation to repeat the blunders of the old, in a cycle of garbage software, wrapped in ever-escalating useless animations, transitions, and framework rewrites.</li>
  236. <li>The term ‘project’ is a poor metaphor for the horticultural activity that is software development.
  237. <ul>
  238. <li>Some software is seasonal and has crops, but unless you want your business to end with the first harvest, you need to treat it like a living ecosystem.</li>
  239. <li>Some software components are perennial and evergreen. Others are seasonal and need regular replanting. The project metaphor treats them both the same and increases the risk of code rot.</li>
  240. </ul>
  241. </li>
  242. <li>“Project management” is often used as a label for the somewhat helpful tools we use to organise work. Don’t let the project metaphor lead you to misuse these tools or to disregard them.</li>
  243. <li>Most project management software is garbage because organisations generally don’t lack the tools to manage work. You could replace most project management software with a spreadsheet with no issue. The problem all organisations have, which most <em>think</em> is a project management problem, is team and organisation communications.</li>
  244. <li>You can get away with simple management tools and tactics (a whiteboard and a spreadsheet) if your organisation has good trust and communications. Most <em>don’t</em>, however.</li>
  245. <li>Most ‘innovative’ tech startups face what I like to call ‘the clear field problem’. Whenever you have an app or business idea that nobody else seems to have done successfully before, it’s never because you are particularly clever or original. It’s always because everybody else who has tried is now dead in a ditch somewhere (metaphorically speaking).</li>
  246. <li>The only exception to this is when a brand new technical innovation opens up a new field. Which is rarer than you think as a better design doesn’t qualify as sufficient innovation. Unless you are the one who spent years developing that innovation from scratch, you are only performing arbitrage. That’s a recipe for squashed margins and brutal competition.</li>
  247. <li>If you’re lucky, the first-mover advantage will save your ass. The odds are against you, though.</li>
  248. <li>Some fields, when unregulated, will inevitably get dominated by a monopolist or an oligopoly. Monopolies are never the good guys. Don’t aspire to become one.</li>
  249. </ol>
  250. <hr>
  251. <ol start="91">
  252. <li>Any field with multiple successful competitors is good news. It means that there is demand, which you can tap in by addressing the problem in your way. In a sector with solid margins, this is an opportunity for design innovation to shine.</li>
  253. <li>Any field where all of the other competitors are free services, outdated desktop apps, open-source communities with no revenue, or wannabe startup cults burning through cash is a lethal minefield covered in a cloud of mustard gas.</li>
  254. <li>Never go up against a free service from a multinational. At least, never directly.</li>
  255. <li>Try to position yourself so that the free services from other companies complement your paid service.</li>
  256. <li>Try not to couple your service tightly with one provided by a multinational (free or paid). Almost all software is garbage. The problem with other people’s software is that they (justifiably) don’t care if it’s breaking your stuff.</li>
  257. <li>One (possible) exception is when you are an actual paying customer. Build your business on AWS by all means but be wary of making Google Docs the foundation of your service.</li>
  258. <li>You are occasionally warned against building an app that should just be a feature of some other app or service. This advice is unhelpful. Apps with limited scope that interoperate through shared file formats (usually text, sometimes images) are a great productivity enabler.</li>
  259. <li>What you should avoid is building apps that are <em>complements</em> to other, more successful services. That applies to direct ones, like plugins or extensions, and indirect ones like EPUB reading apps. All the money, power, and control is in the other service, which is a recipe for a miserable time.</li>
  260. <li>Counter-intuitively, the same type of app can complement or be standalone depending on the <em>file format</em>. An EPUB reader is almost always a support function for either an ebook library service or an ebook retailer, as those are pretty much the only ways people use EPUB files. A PDF reader, however, can be a sustainable business because the file format is a commodity. Anybody can make one. Anybody can read one. It’s used everywhere and by everybody.</li>
  261. <li>Commonly used file formats with robust ecosystems enable software diversification as no single tool has to solve all of the problems.</li>
  262. </ol>
  263. <hr>
  264. <ol start="101">
  265. <li>HTTP, links and URLs are powerful, even if you aren’t working with HTML or JSON.</li>
  266. <li>Web software is generally rubbish. You can explain this, at least partially, by the dominance of APIs over file formats in web tech circles.</li>
  267. <li>A service that requires a new file format is going to have a hard time. It’s going to have an even harder time if it is competing with a service that works with standard file formats, even when the former is objectively better for the problem at hand.</li>
  268. <li>Your service will have difficulties competing if it expects its API to solve the same problems for its users as a standard file format would.</li>
  269. <li>Any field where all of the other competitors have five (or more) salespeople for every developer isn’t going to be pleasant for the developer, no matter if they’re an employee or a founder. Probably great if you’re a salesperson, though.</li>
  270. <li>People lie when you do research. Watching what they do for an hour will tell you more than a hundred hours of interviews.</li>
  271. <li>People lie when you do research but pay attention to the tools they reach for, the pains they describe, because those can reveal threads you can pull on to unravel your way to the actual problem. It takes practice, though.</li>
  272. <li>Web dev is pop culture. Don’t get too stuck on trend-du-jour. Give it enough time and what was old is new again.</li>
  273. <li>Web dev is pop culture. You have two choices: keep up with the trends or have enough individuality to be timeless. (Which is easier said than done, though.)</li>
  274. <li>Web dev is pop culture, and managers have no taste. Most managers have no taste or judgement of their own when it comes to web development. The only tools they have to assess web dev are current trends and fashions in web dev pop culture. There is nothing you can do about this. Try to either find a manager with taste (rare!) or find one that trusts their developers to do the job despite not understanding the details.</li>
  275. </ol>
  276. <hr>
  277. <ol start="111">
  278. <li>Trust is a recurring theme when it comes to teamwork. Clear communications and trust will smooth over a lot of fuck-ups.</li>
  279. <li>A solid business model will smooth over a lot of fuck-ups. You can get away with a bit of mismanagement if your margins are big enough.</li>
  280. <li>It all comes down to needs. If an organisation isn’t addressing the employees' needs, nothing in the organisation will be sustainable in the long term.</li>
  281. <li>Your needs come first. Then come those of your co-workers. Both come before that of the customer and before that of your manager. You need to be healthy, learning about the task at hand, improving your mental model of the product, and building a theory of how the code works. Otherwise, you aren’t going to be able to address anybody else’s needs.</li>
  282. <li>A good manager will structure the organisation and processes so that the workers' needs, when fulfilled, will result in them being able to meet the customer’s needs.</li>
  283. <li>A bad manager will churn through employees like tissue paper, sacrificing their well-being for vague and distant business goals.</li>
  284. <li>The worst manager sacrifices their well-being as well as their employees' well-being.</li>
  285. <li>As Deming said: <a href="https://deming.org/nobody-gives-a-hoot-about-profit/">‘nobody gives a hoot about profits’</a>. The manager who cares about company profits doesn’t exist.</li>
  286. <li>A manager who seems to care about company profits is more dangerous than most. They are suffering from one or more psychological complication.
  287. <ul>
  288. <li>“If the company does well, then I’m a good person.”</li>
  289. <li>“If we make money, then my mother will be proud of me.”</li>
  290. <li>“My dad—I mean the CEO—thinks I’m great.”</li>
  291. </ul>
  292. </li>
  293. <li>A lack of self-awareness is always trouble. In yourself, it causes misery. In a co-worker, it causes tension. In a boss or manager, it spells disaster. The only person you can send to therapy is yourself. The rest require firm boundaries and <a href="https://en.wikipedia.org/wiki/Nonviolent_Communication">non-violent communication</a>.</li>
  294. </ol>
  295. <hr>
  296. <ol start="121">
  297. <li>The web enables remote work. That doesn’t mean work in isolation. Pick your people. Choose your society.</li>
  298. <li>The web exists in many forms, all of them valid in some context. Sometimes SPAs are the right solution. Native apps can use parts of the web stack and use them well. Understanding each medium is the key to understand the form you have chosen. Each form lends itself to specific actions. <a href="https://en.wikipedia.org/wiki/The_medium_is_the_message">The medium is the message.</a></li>
  299. <li>Most of the <em>major</em> web dev innovations over the past decade, at least, are optimisation functions designed to help dysfunctional organisations extract value from open source without blowing up. They serve to gloss over communications problems, subsidise training, offload recruitment costs onto somebody else, make it easier to collaborate on problems that aren’t actual problems. They help implement ideas that probably shouldn’t become a reality. All to suck value that ultimately was created by open-source software.</li>
  300. <li>Web dev frameworks are for organisations, not small software teams or individual developers. The value frameworks provide lies in bridging team boundaries: they create a shared understanding that aids in collaboration across groups, simplify messaging, and establish clear conventions. Frameworks turn teams in large organisations into service interfaces.</li>
  301. <li>Individual teams or individual developers don’t have that problem, so they get less value from a web dev framework. The more opinionated the framework is and the more of the web platform it abstracts away, the more its value proposition skews towards solving organisational problems and the less value it provides to individual teams.</li>
  302. <li>None of this applies to learning. Having experience using frameworks can be extraordinarily useful. Being able to use the powerful capabilities of the platform itself is also an advantage. Individual needs and priorities vary too much. The above framework heuristic isn’t always correct.</li>
  303. <li>Some tools feel more natural than others. Others remain opaque as hell. Which tool is which will vary from person to person, age to age, job to job.</li>
  304. <li>Sometimes it’s rewarding to work with a tool that clicks for you, gets you into that flow to just get things done.</li>
  305. <li>Sometimes the most rewarding thing to do is to work with a tool that <strong>doesn’t</strong> click, is hard as hell for you to understand, and feels like a never-ending slog.</li>
  306. <li>Sometimes all you need is a single web page with no interactivity.</li>
  307. </ol>
  308. <hr>
  309. <ol start="131">
  310. <li>Sometimes deliberate complication is just plain fun, and that has value in and of itself.</li>
  311. <li>You could replace most web services and apps with a blog, wiki, forum, or spreadsheet. Your service needs to be much better.</li>
  312. <li>You could replace most web services and apps with a pen and paper. All forms of productivity, writing, or organisation software compete directly with pencils, notepads, and post-its. And those are <em>amazing</em>. They work offline, don’t need power, never need rebooting, are robust as hell, and cheap as chips. They also have decades or centuries of history. You need to either be 100x better or to enable activities that aren’t possible otherwise.</li>
  313. <li>Just because you did something to make the impossible possible doesn’t mean that it’s worthwhile or that anybody cares. Society has no obligation to reward hard work or new invention. Just because you made it possible doesn’t mean it’s sensible.</li>
  314. <li>Making the complex simple also isn’t worth anything in and of itself. What is worthwhile is when you encode knowledge, skills, and practices into an interactive design and make something that’s rare and exclusive, distributed and accessible.</li>
  315. <li>You could say that this is the contribution the web has made to the modern world that has had the most impact: things that once existed in isolation are now widespread and accessible. Connecting and conveying is the web’s killer app.</li>
  316. </ol>
  317. <p>Things I didn’t have time for:</p>
  318. <ul>
  319. <li>Reed’s law and Metcalfe’s law don’t mean what you think they mean.</li>
  320. <li>The germ theory of management.</li>
  321. <li>How most managers think that ‘autonomy’ means the freedom to do whatever you want as long as it’s what they think you should be doing.</li>
  322. <li>There’s no silver bullet.</li>
  323. <li>Alan Kay’s ‘doing with images makes symbols.’</li>
  324. <li>Wiki’s aren’t what you think they are. (All note-taking apps will grow until they contain an ad-hoc, haphazardly designed, poorly-thought-out reimplementation of a wiki.)</li>
  325. <li>Ted Nelson didn’t say what you think he said.</li>
  326. <li>Lessons from Hypercard (cards, stacks, plus links is a fantastic conceptual model for hypertext design)</li>
  327. <li>Lessons from Flash (a timeline metaphor plus symbols and actions is a fantastic conceptual model for interactivity design).</li>
  328. </ul>
  329. </article>
  330. <hr>
  331. <footer>
  332. <p>
  333. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  334. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-home"></use>
  335. </svg> Accueil</a> •
  336. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  337. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-rss2"></use>
  338. </svg> Suivre</a> •
  339. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  340. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-user-tie"></use>
  341. </svg> Pro</a> •
  342. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  343. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-mail"></use>
  344. </svg> Email</a> •
  345. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  346. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-hammer2"></use>
  347. </svg> Légal</abbr>
  348. </p>
  349. <template id="theme-selector">
  350. <form>
  351. <fieldset>
  352. <legend><svg class="icon icon-brightness-contrast">
  353. <use xlink:href="/static/david/icons2/symbol-defs.svg#icon-brightness-contrast"></use>
  354. </svg> Thème</legend>
  355. <label>
  356. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  357. </label>
  358. <label>
  359. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  360. </label>
  361. <label>
  362. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  363. </label>
  364. </fieldset>
  365. </form>
  366. </template>
  367. </footer>
  368. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  369. <script>
  370. function loadThemeForm(templateName) {
  371. const themeSelectorTemplate = document.querySelector(templateName)
  372. const form = themeSelectorTemplate.content.firstElementChild
  373. themeSelectorTemplate.replaceWith(form)
  374. form.addEventListener('change', (e) => {
  375. const chosenColorScheme = e.target.value
  376. localStorage.setItem('theme', chosenColorScheme)
  377. toggleTheme(chosenColorScheme)
  378. })
  379. const selectedTheme = localStorage.getItem('theme')
  380. if (selectedTheme && selectedTheme !== 'undefined') {
  381. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  382. }
  383. }
  384. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  385. window.addEventListener('load', () => {
  386. let hasDarkRules = false
  387. for (const styleSheet of Array.from(document.styleSheets)) {
  388. let mediaRules = []
  389. for (const cssRule of styleSheet.cssRules) {
  390. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  391. continue
  392. }
  393. // WARNING: Safari does not have/supports `conditionText`.
  394. if (cssRule.conditionText) {
  395. if (cssRule.conditionText !== prefersColorSchemeDark) {
  396. continue
  397. }
  398. } else {
  399. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  400. continue
  401. }
  402. }
  403. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  404. }
  405. // WARNING: do not try to insert a Rule to a styleSheet you are
  406. // currently iterating on, otherwise the browser will be stuck
  407. // in a infinite loop…
  408. for (const mediaRule of mediaRules) {
  409. styleSheet.insertRule(mediaRule.cssText)
  410. hasDarkRules = true
  411. }
  412. }
  413. if (hasDarkRules) {
  414. loadThemeForm('#theme-selector')
  415. }
  416. })
  417. </script>
  418. </body>
  419. </html>