A place to cache linked articles (think custom and personal wayback machine)
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

index.html 27KB

il y a 4 ans
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  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,minimum-scale=1,initial-scale=1,shrink-to-fit=no">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>In Pursuit of Production Minimalism (archive) — David Larlet</title>
  13. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  14. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons/apple-touch-icon.png">
  15. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons/favicon-32x32.png">
  16. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons/favicon-16x16.png">
  17. <link rel="manifest" href="/manifest.json">
  18. <link rel="mask-icon" href="/static/david/icons/safari-pinned-tab.svg" color="#5bbad5">
  19. <link rel="shortcut icon" href="/static/david/icons/favicon.ico">
  20. <meta name="apple-mobile-web-app-title" content="David Larlet">
  21. <meta name="application-name" content="David Larlet">
  22. <meta name="msapplication-TileColor" content="#da532c">
  23. <meta name="msapplication-config" content="/static/david/icons/browserconfig.xml">
  24. <meta name="theme-color" content="#f0f0ea">
  25. <!-- That good ol' feed, subscribe :p. -->
  26. <link rel=alternate type="application/atom+xml" title=Feed href="/david/log/">
  27. <meta name="robots" content="noindex, nofollow">
  28. <meta content="origin-when-cross-origin" name="referrer">
  29. <!-- Canonical URL for SEO purposes -->
  30. <link rel="canonical" href="https://brandur.org/minimalism">
  31. <style>
  32. /* http://meyerweb.com/eric/tools/css/reset/ */
  33. html, body, div, span,
  34. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  35. a, abbr, address, big, cite, code,
  36. del, dfn, em, img, ins,
  37. small, strike, strong, tt, var,
  38. dl, dt, dd, ol, ul, li,
  39. fieldset, form, label, legend,
  40. table, caption, tbody, tfoot, thead, tr, th, td,
  41. article, aside, canvas, details, embed,
  42. figure, figcaption, footer, header, hgroup,
  43. menu, nav, output, ruby, section, summary,
  44. time, mark, audio, video {
  45. margin: 0;
  46. padding: 0;
  47. border: 0;
  48. font-size: 100%;
  49. font: inherit;
  50. vertical-align: baseline;
  51. }
  52. /* HTML5 display-role reset for older browsers */
  53. article, aside, details, figcaption, figure,
  54. footer, header, hgroup, menu, nav, section { display: block; }
  55. body { line-height: 1; }
  56. blockquote, q { quotes: none; }
  57. blockquote:before, blockquote:after,
  58. q:before, q:after {
  59. content: '';
  60. content: none;
  61. }
  62. table {
  63. border-collapse: collapse;
  64. border-spacing: 0;
  65. }
  66. /* http://practicaltypography.com/equity.html */
  67. /* https://calendar.perfplanet.com/2016/no-font-face-bulletproof-syntax/ */
  68. /* https://www.filamentgroup.com/lab/js-web-fonts.html */
  69. @font-face {
  70. font-family: 'EquityTextB';
  71. src: url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff2') format('woff2'),
  72. url('/static/david/css/fonts/Equity-Text-B-Regular-webfont.woff') format('woff');
  73. font-weight: 300;
  74. font-style: normal;
  75. font-display: swap;
  76. }
  77. @font-face {
  78. font-family: 'EquityTextB';
  79. src: url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff2') format('woff2'),
  80. url('/static/david/css/fonts/Equity-Text-B-Italic-webfont.woff') format('woff');
  81. font-weight: 300;
  82. font-style: italic;
  83. font-display: swap;
  84. }
  85. @font-face {
  86. font-family: 'EquityTextB';
  87. src: url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff2') format('woff2'),
  88. url('/static/david/css/fonts/Equity-Text-B-Bold-webfont.woff') format('woff');
  89. font-weight: 700;
  90. font-style: normal;
  91. font-display: swap;
  92. }
  93. @font-face {
  94. font-family: 'ConcourseT3';
  95. src: url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff2') format('woff2'),
  96. url('/static/david/css/fonts/concourse_t3_regular-webfont-20190806.woff') format('woff');
  97. font-weight: 300;
  98. font-style: normal;
  99. font-display: swap;
  100. }
  101. /* http://practice.typekit.com/lesson/caring-about-opentype-features/ */
  102. body {
  103. /* http://www.cssfontstack.com/ Palatino 99% Win 86% Mac */
  104. font-family: "EquityTextB", Palatino, serif;
  105. background-color: #f0f0ea;
  106. color: #07486c;
  107. font-kerning: normal;
  108. -moz-osx-font-smoothing: grayscale;
  109. -webkit-font-smoothing: subpixel-antialiased;
  110. text-rendering: optimizeLegibility;
  111. font-variant-ligatures: common-ligatures contextual;
  112. font-feature-settings: "kern", "liga", "clig", "calt";
  113. }
  114. pre, code, kbd, samp, var, tt {
  115. font-family: 'TriplicateT4c', monospace;
  116. }
  117. em {
  118. font-style: italic;
  119. color: #323a45;
  120. }
  121. strong {
  122. font-weight: bold;
  123. color: black;
  124. }
  125. nav {
  126. background-color: #323a45;
  127. color: #f0f0ea;
  128. display: flex;
  129. justify-content: space-around;
  130. padding: 1rem .5rem;
  131. }
  132. nav:last-child {
  133. border-bottom: 1vh solid #2d7474;
  134. }
  135. nav a {
  136. color: #f0f0ea;
  137. }
  138. nav abbr {
  139. border-bottom: 1px dotted white;
  140. }
  141. h1 {
  142. border-top: 1vh solid #2d7474;
  143. border-bottom: .2vh dotted #2d7474;
  144. background-color: #e3e1e1;
  145. color: #323a45;
  146. text-align: center;
  147. padding: 5rem 0 4rem 0;
  148. width: 100%;
  149. font-family: 'ConcourseT3';
  150. display: flex;
  151. flex-direction: column;
  152. }
  153. h1.single {
  154. padding-bottom: 10rem;
  155. }
  156. h1 span {
  157. position: absolute;
  158. top: 1vh;
  159. left: 20%;
  160. line-height: 0;
  161. }
  162. h1 span a {
  163. line-height: 1.7;
  164. padding: 1rem 1.2rem .6rem 1.2rem;
  165. border-radius: 0 0 6% 6%;
  166. background: #2d7474;
  167. font-size: 1.3rem;
  168. color: white;
  169. text-decoration: none;
  170. }
  171. h2 {
  172. margin: 4rem 0 1rem;
  173. border-top: .2vh solid #2d7474;
  174. padding-top: 1vh;
  175. }
  176. h3 {
  177. text-align: center;
  178. margin: 3rem 0 .75em;
  179. }
  180. hr {
  181. height: .4rem;
  182. width: .4rem;
  183. border-radius: .4rem;
  184. background: #07486c;
  185. margin: 2.5rem auto;
  186. }
  187. time {
  188. display: bloc;
  189. margin-left: 0 !important;
  190. }
  191. ul, ol {
  192. margin: 2rem;
  193. }
  194. ul {
  195. list-style-type: square;
  196. }
  197. a {
  198. text-decoration-skip-ink: auto;
  199. text-decoration-thickness: 0.05em;
  200. text-underline-offset: 0.09em;
  201. }
  202. article {
  203. max-width: 50rem;
  204. display: flex;
  205. flex-direction: column;
  206. margin: 2rem auto;
  207. }
  208. article.single {
  209. border-top: .2vh dotted #2d7474;
  210. margin: -6rem auto 1rem auto;
  211. background: #f0f0ea;
  212. padding: 2rem;
  213. }
  214. article p:last-child {
  215. margin-bottom: 1rem;
  216. }
  217. p {
  218. padding: 0 .5rem;
  219. margin-left: 3rem;
  220. }
  221. p + p,
  222. figure + p {
  223. margin-top: 2rem;
  224. }
  225. blockquote {
  226. background-color: #e3e1e1;
  227. border-left: .5vw solid #2d7474;
  228. display: flex;
  229. flex-direction: column;
  230. align-items: center;
  231. padding: 1rem;
  232. margin: 1.5rem;
  233. }
  234. blockquote cite {
  235. font-style: italic;
  236. }
  237. blockquote p {
  238. margin-left: 0;
  239. }
  240. figure {
  241. border-top: .2vh solid #2d7474;
  242. background-color: #e3e1e1;
  243. text-align: center;
  244. padding: 1.5rem 0;
  245. margin: 1rem 0 0;
  246. font-size: 1.5rem;
  247. width: 100%;
  248. }
  249. figure img {
  250. max-width: 250px;
  251. max-height: 250px;
  252. border: .5vw solid #323a45;
  253. padding: 1px;
  254. }
  255. figcaption {
  256. padding: 1rem;
  257. line-height: 1.4;
  258. }
  259. aside {
  260. display: flex;
  261. flex-direction: column;
  262. background-color: #e3e1e1;
  263. padding: 1rem 0;
  264. border-bottom: .2vh solid #07486c;
  265. }
  266. aside p {
  267. max-width: 50rem;
  268. margin: 0 auto;
  269. }
  270. /* https://fvsch.com/code/css-locks/ */
  271. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  272. font-size: 1rem;
  273. line-height: calc( 1.5em + 0.2 * 1rem );
  274. }
  275. h1 {
  276. font-size: 1.9rem;
  277. line-height: calc( 1.2em + 0.2 * 1rem );
  278. }
  279. h2 {
  280. font-size: 1.6rem;
  281. line-height: calc( 1.3em + 0.2 * 1rem );
  282. }
  283. h3 {
  284. font-size: 1.35rem;
  285. line-height: calc( 1.4em + 0.2 * 1rem );
  286. }
  287. @media (min-width: 20em) {
  288. /* The (100vw - 20rem) / (50 - 20) part
  289. resolves to 0-1rem, depending on the
  290. viewport width (between 20em and 50em). */
  291. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  292. font-size: calc( 1rem + .6 * (100vw - 20rem) / (50 - 20) );
  293. line-height: calc( 1.5em + 0.2 * (100vw - 50rem) / (20 - 50) );
  294. margin-left: 0;
  295. }
  296. h1 {
  297. font-size: calc( 1.9rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  298. line-height: calc( 1.2em + 0.2 * (100vw - 50rem) / (20 - 50) );
  299. }
  300. h2 {
  301. font-size: calc( 1.5rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  302. line-height: calc( 1.3em + 0.2 * (100vw - 50rem) / (20 - 50) );
  303. }
  304. h3 {
  305. font-size: calc( 1.35rem + 1.5 * (100vw - 20rem) / (50 - 20) );
  306. line-height: calc( 1.4em + 0.2 * (100vw - 50rem) / (20 - 50) );
  307. }
  308. }
  309. @media (min-width: 50em) {
  310. /* The right part of the addition *must* be a
  311. rem value. In this example we *could* change
  312. the whole declaration to font-size:2.5rem,
  313. but if our baseline value was not expressed
  314. in rem we would have to use calc. */
  315. p, li, pre, code, kbd, samp, var, tt, time, details, figcaption {
  316. font-size: calc( 1rem + .6 * 1rem );
  317. line-height: 1.5em;
  318. }
  319. p, li, pre, details {
  320. margin-left: 3rem;
  321. }
  322. h1 {
  323. font-size: calc( 1.9rem + 1.5 * 1rem );
  324. line-height: 1.2em;
  325. }
  326. h2 {
  327. font-size: calc( 1.5rem + 1.5 * 1rem );
  328. line-height: 1.3em;
  329. }
  330. h3 {
  331. font-size: calc( 1.35rem + 1.5 * 1rem );
  332. line-height: 1.4em;
  333. }
  334. figure img {
  335. max-width: 500px;
  336. max-height: 500px;
  337. }
  338. }
  339. figure.unsquared {
  340. margin-bottom: 1.5rem;
  341. }
  342. figure.unsquared img {
  343. height: inherit;
  344. }
  345. @media print {
  346. body { font-size: 100%; }
  347. a:after { content: " (" attr(href) ")"; }
  348. a, a:link, a:visited, a:after {
  349. text-decoration: underline;
  350. text-shadow: none !important;
  351. background-image: none !important;
  352. background: white;
  353. color: black;
  354. }
  355. abbr[title] { border-bottom: 0; }
  356. abbr[title]:after { content: " (" attr(title) ")"; }
  357. img { page-break-inside: avoid; }
  358. @page { margin: 2cm .5cm; }
  359. h1, h2, h3 { page-break-after: avoid; }
  360. p3 { orphans: 3; widows: 3; }
  361. img {
  362. max-width: 250px !important;
  363. max-height: 250px !important;
  364. }
  365. nav, aside { display: none; }
  366. }
  367. ul.with_columns {
  368. column-count: 1;
  369. }
  370. @media (min-width: 20em) {
  371. ul.with_columns {
  372. column-count: 2;
  373. }
  374. }
  375. @media (min-width: 50em) {
  376. ul.with_columns {
  377. column-count: 3;
  378. }
  379. }
  380. ul.with_two_columns {
  381. column-count: 1;
  382. }
  383. @media (min-width: 20em) {
  384. ul.with_two_columns {
  385. column-count: 1;
  386. }
  387. }
  388. @media (min-width: 50em) {
  389. ul.with_two_columns {
  390. column-count: 2;
  391. }
  392. }
  393. .gallery {
  394. display: flex;
  395. flex-wrap: wrap;
  396. justify-content: space-around;
  397. }
  398. .gallery figure img {
  399. margin-left: 1rem;
  400. margin-right: 1rem;
  401. }
  402. .gallery figure figcaption {
  403. font-family: 'ConcourseT3'
  404. }
  405. footer {
  406. font-family: 'ConcourseT3';
  407. display: flex;
  408. flex-direction: column;
  409. border-top: 3px solid white;
  410. padding: 4rem 0;
  411. background-color: #07486c;
  412. color: white;
  413. }
  414. footer > * {
  415. max-width: 50rem;
  416. margin: 0 auto;
  417. }
  418. footer a {
  419. color: #f1c40f;
  420. }
  421. footer .avatar {
  422. width: 200px;
  423. height: 200px;
  424. border-radius: 50%;
  425. float: left;
  426. -webkit-shape-outside: circle();
  427. shape-outside: circle();
  428. margin-right: 2rem;
  429. padding: 2px 5px 5px 2px;
  430. background: white;
  431. border-left: 1px solid #f1c40f;
  432. border-top: 1px solid #f1c40f;
  433. border-right: 5px solid #f1c40f;
  434. border-bottom: 5px solid #f1c40f;
  435. }
  436. </style>
  437. <h1>
  438. <span><a id="jumper" href="#jumpto" title="Un peu perdu ?">?</a></span>
  439. In Pursuit of Production Minimalism (archive)
  440. <time>Pour la pérennité des contenus liés. Non-indexé, retrait sur simple email.</time>
  441. </h1>
  442. <section>
  443. <article>
  444. <h3><a href="https://brandur.org/minimalism">Source originale du contenu</a></h3>
  445. <p>While working at Lockheed during the cold war, Kelly
  446. Johnson was reported to have coined <a href="https://en.wikipedia.org/wiki/KISS_principle">KISS</a> (“keep it
  447. simple, stupid”); a principle that suggests glibly that
  448. systems should be designed to be as simple as possible.</p>
  449. <p>While complexity is never a conscious design goal of any
  450. project, it arises inherently as new features are pursued
  451. or new components are introduced. KISS encourages designers
  452. to actively counteract this force by making simplicity an
  453. objective in itself, and thus produce products that are
  454. more maintainable, more reliable, and more flexible. In the
  455. case of jet fighters, that might mean a plane that can be
  456. repaired in the field with few tools and under the
  457. stressful conditions of combat.</p>
  458. <p>During his tenure, Lockheed’s Skunk Works would produce
  459. planes like the U-2 and SR-71; so notable for their
  460. engineering excellence that they’ve left a legacy that we
  461. reflect on even today.</p>
  462. <figure>
  463. <p><a href="/assets/minimalism/sr71@2x.jpg"><img src="/assets/minimalism/sr71.jpg" srcset="/assets/minimalism/sr71@2x.jpg 2x, /assets/minimalism/sr71.jpg 1x" class="overflowing"/></a></p>
  464. <figcaption>The famous SR-71, one of the flag ships of Lockheed's Skunk Works. Very fast even if not particularly simple.</figcaption>
  465. </figure>
  466. <p>Many of us pursue work in the engineering field because
  467. we’re intellectually curious. Technology is cool, and new
  468. technology is even better. We want to be using what
  469. everyone’s talking about.</p>
  470. <p>Our news sources, meetups, conferences, and even
  471. conversations bias towards shiny new tech that’s either
  472. under active development or being energetically promoted.
  473. Older components that sit quietly and do their job well
  474. disappear into the background.</p>
  475. <p>Over time, technologies are added, but are rarely removed.
  476. Left unchecked, production stacks that have been around
  477. long enough become sprawling patchworks combining
  478. everything under the sun. This effect is dangerous:</p>
  479. <ul>
  480. <li><p>More parts means more cognitive complexity. If a system
  481. becomes too difficult to understand then the risk of bugs
  482. or operational mishaps increases as developers make
  483. changes without understanding all the intertwined
  484. concerns.</p></li>
  485. <li><p>Nothing operates flawlessly once it hits production.
  486. Every component in the stack is a candidate for failure,
  487. and with sufficient scale, <em>something</em> will be failing all
  488. the time.</p></li>
  489. <li><p>With more technologies engineers will tend to become
  490. jacks of all trades, but masters of none. If a
  491. particularly nefarious problem comes along, it may be
  492. harder to diagnose and repair because there are few
  493. specialists around who are able to dig deeply.</p></li>
  494. </ul>
  495. <p>Even knowing this, the instinct to expand our tools is hard
  496. to suppress. Oftentimes persuasion is a core competency of
  497. our jobs, and we can use that same power to convince
  498. ourselves and our peers that it’s critical to get new
  499. technologies into our stack <em>right now</em>. That Go-based HA
  500. key/value store will take our uptime and fault resilience
  501. to new highs. That real-time event stream will enable an
  502. immutable ledger that will become foundational keystone for
  503. the entire platform. That sexy new container orchestration
  504. system that will take ease of deployment and scaling to new
  505. levels. In many cases, a step back and a moment of
  506. dispassionate thought would reveal that their use could be
  507. withheld until a time when they’re known to be well vetted,
  508. and it’s well understood how they’ll fit into the current
  509. architecture (and what they’ll replace).</p>
  510. <p>In his book <em>Nine Chains to the Moon</em> (published 1938),
  511. inventor R. Buckminster Fuller described the idea of
  512. <strong><em>ephemeralization</em></strong>:</p>
  513. <blockquote>
  514. <p>Do more and more with less and less until eventually you
  515. can do everything with nothing.</p>
  516. </blockquote>
  517. <p>It suggests improving increasing productive output by
  518. continually improving the efficiency of a system even while
  519. keeping input the same. I project this onto technology to
  520. mean building a stack that scales to more users and more
  521. activity while the people and infrastructure supporting it
  522. stay fixed. This is accomplished by building systems that
  523. are more robust, more automatic, and less prone to problems
  524. because the tendency to grow in complexity that’s inherent
  525. to them has been understood, harnessed, and reversed.</p>
  526. <p>For a long time we had a very big and very aspirational
  527. goal of ephemeralization at Heroku. The normal app platform
  528. that we all know was referred to as “user space” while the
  529. internal infrastructure that supported it was called
  530. “kernel space”. We want to break up the kernel in the
  531. kernel and move it piece by piece to run inside the user
  532. space that it supported, in effect rebuilding Heroku so
  533. that it itself ran <em>on Heroku</em>. In the ultimate
  534. manifestation of ephemeralization, the kernel would
  535. diminish in size until it vanished completely. The
  536. specialized components that it contained would be retired,
  537. and we’d be left a single perfectly uniform stack.</p>
  538. <p>Realistic? Probably not. Useful? Yes. Even falling short of
  539. an incredibly ambitious goal tends to leave you somewhere
  540. good.</p>
  541. <p>Here are a few examples of minimalism and ephemeralization
  542. in practice from Heroku’s history:</p>
  543. <ul>
  544. <li><p>The core database that tracked all apps, users, releases,
  545. configuration, etc. used to be its own special snowflake
  546. hosted on a custom-built AWS instance. It was eventually
  547. folded into Heroku Postgres, and became just one more
  548. node to be managed along with every other customer DB.</p></li>
  549. <li><p>Entire products were retired where possible. For example,
  550. the <code>ssl:ip</code> add-on (providing SSL/TLS terminate for an
  551. app), which used to be provisioned and run on its own
  552. dedicated servers, was end-of-lifed completely when a
  553. better (and cheaper) option for terminating SSL was
  554. available through Amazon. With SNI support now
  555. widespread, <code>ssl:endpoint</code> will eventually follow suit.</p></li>
  556. <li><p>All non-ephemeral data was moved out of Redis so that the
  557. only data store handling persistent data for internal
  558. apps was Postgres. This had the added advantage of stacks
  559. being able to tolerate a downed Redis and stay online.</p></li>
  560. <li><p>After a misguided foray into production polyglotism, the
  561. last component written in Scala was retired. Fewer
  562. programming languages in use meant that the entire system
  563. became easier to operate, and by more engineers.</p></li>
  564. <li><p>The component that handled Heroku orgs was originally run
  565. as its own microservice. It eventually became obvious
  566. that there had been a time when our microservice
  567. expansion had been a little overzealous, so to simplify
  568. operation, we folded a few services back into the hub.</p></li>
  569. </ul>
  570. <p>To recognize the effort that went into tearing down or
  571. replacing old technology, we created a ritual where we
  572. symbolically fed dead components to a flame called a <a href="/fragments/burn-parties">burn
  573. party</a>. The time and energy spent
  574. on some of these projects would in some cases be as great,
  575. or even greater, as it would for shipping a new product.</p>
  576. <figure>
  577. <p><a href="/assets/minimalism/fire@2x.jpg"><img src="/assets/minimalism/fire.jpg" srcset="/assets/minimalism/fire@2x.jpg 2x, /assets/minimalism/fire.jpg 1x" class="overflowing"/></a></p>
  578. <figcaption>At Heroku, we'd hold regular "burn parties" to recognize the effort that went into deprecating old products and technology.</figcaption>
  579. </figure>
  580. <p>Practicing minimalism in production is mostly about
  581. recognizing that the problem exists. After achieving that,
  582. mitigations are straightforward:</p>
  583. <ul>
  584. <li><p><strong><em>Retire old technology.</em></strong> Is something new being
  585. introduced? Look for opportunities to retire older
  586. technology that’s roughly equivalent. If you’re about to
  587. put Kafka in, maybe you can get away with retiring Rabbit
  588. or NSQ.</p></li>
  589. <li><p><strong><em>Build common service conventions.</em></strong> Standardize on
  590. one database, one language/runtime, one job queue, one
  591. web server, one reverse proxy, etc. If not one, then
  592. standardize on <em>as few as possible</em>.</p></li>
  593. <li><p><strong><em>Favor simplicity and reduce moving parts.</em></strong> Try to
  594. keep the total number of things in a system small so that
  595. it stays easy to understand and easy to operate. In some
  596. cases this will be a compromise because a technology
  597. that’s slightly less suited to a job may have to be
  598. re-used even if there’s a new one that would technically
  599. be a better fit.</p></li>
  600. <li><p><strong><em>Don’t use new technology the day, or even the year,
  601. that it’s initially released.</em></strong> Save yourself time and
  602. energy by letting others vet it, find bugs, and do the
  603. work to stabilize it. Avoid it permanently if it doesn’t
  604. pick up a significant community that will help support it
  605. well into the future.</p></li>
  606. <li><p><strong><em>Avoid custom technology.</em></strong> Software that you write is
  607. software that you have to maintain. Forever. Don’t
  608. succumb to NIH when there’s a well supported public
  609. solution that fits just as well (or even almost as well).</p></li>
  610. <li><p><strong><em>Use services.</em></strong> Software that you install is software
  611. that you have to operate. From the moment it’s activated,
  612. someone will be taking regular time out of their schedule
  613. to perform maintenance, troubleshoot problems, and
  614. install upgrades. Don’t succumb to NHH (not hosted here)
  615. when there’s a public service available that will do the
  616. job better.</p></li>
  617. </ul>
  618. <p>It’s not that new technology should <em>never</em> be introduced,
  619. but it should be done with rational defensiveness, and with
  620. a critical eye in how it’ll fit into an evolving (and
  621. hopefully ever-improving) architecture.</p>
  622. <p>Antoine de Saint Exupéry, a French poet and pioneering
  623. aviator, had this to say on the subject:</p>
  624. <blockquote>
  625. <p>It seems that perfection is reached not when there is
  626. nothing left to add, but when there is nothing left to
  627. take away.</p>
  628. </blockquote>
  629. <figure>
  630. <p><a href="/assets/minimalism/sea@2x.jpg"><img src="/assets/minimalism/sea.jpg" srcset="/assets/minimalism/sea@2x.jpg 2x, /assets/minimalism/sea.jpg 1x" class="overflowing"/></a></p>
  631. <figcaption>Nothing left to add. Nothing left to take away.</figcaption>
  632. </figure>
  633. <p>Most of us can benefit from architecture that’s a little
  634. simpler, a little more conservative, and a little more
  635. directed. Only by concertedly building a minimal stack
  636. that’s stable and nearly perfectly operable can we maximize
  637. our ability to push forward with new products and ideas.</p>
  638. </article>
  639. </section>
  640. <nav id="jumpto">
  641. <p>
  642. <a href="/david/blog/">Accueil du blog</a> |
  643. <a href="https://brandur.org/minimalism">Source originale</a> |
  644. <a href="/david/stream/2019/">Accueil du flux</a>
  645. </p>
  646. </nav>
  647. <footer>
  648. <div>
  649. <img src="/static/david/david-larlet-avatar.jpg" loading="lazy" class="avatar" width="200" height="200">
  650. <p>
  651. Bonjour/Hi!
  652. Je suis <a href="/david/" title="Profil public">David&nbsp;Larlet</a>, je vis actuellement à Montréal et j’alimente cet espace depuis 15 ans. <br>
  653. Si tu as apprécié cette lecture, n’hésite pas à poursuivre ton exploration. Par exemple via les <a href="/david/blog/" title="Expériences bienveillantes">réflexions bimestrielles</a>, la <a href="/david/stream/2019/" title="Pensées (dés)articulées">veille hebdomadaire</a> ou en t’abonnant au <a href="/david/log/" title="S’abonner aux publications via RSS">flux RSS</a> (<a href="/david/blog/2019/flux-rss/" title="Tiens c’est quoi un flux RSS ?">so 2005</a>).
  654. </p>
  655. <p>
  656. Je m’intéresse à la place que je peux avoir dans ce monde. En tant qu’humain, en tant que membre d’une famille et en tant qu’associé d’une coopérative. De temps en temps, je fais aussi des <a href="https://github.com/davidbgk" title="Principalement sur Github mais aussi ailleurs">trucs techniques</a>. Et encore plus rarement, <a href="/david/talks/" title="En ce moment je laisse plutôt la place aux autres">j’en parle</a>.
  657. </p>
  658. <p>
  659. Voici quelques articles choisis :
  660. <a href="/david/blog/2019/faire-equipe/" title="Accéder à l’article complet">Faire équipe</a>,
  661. <a href="/david/blog/2018/bivouac-automnal/" title="Accéder à l’article complet">Bivouac automnal</a>,
  662. <a href="/david/blog/2018/commodite-effondrement/" title="Accéder à l’article complet">Commodité et effondrement</a>,
  663. <a href="/david/blog/2017/donnees-communs/" title="Accéder à l’article complet">Des données aux communs</a>,
  664. <a href="/david/blog/2016/accompagner-enfant/" title="Accéder à l’article complet">Accompagner un enfant</a>,
  665. <a href="/david/blog/2016/senior-developer/" title="Accéder à l’article complet">Senior developer</a>,
  666. <a href="/david/blog/2016/illusion-sociale/" title="Accéder à l’article complet">L’illusion sociale</a>,
  667. <a href="/david/blog/2016/instantane-scopyleft/" title="Accéder à l’article complet">Instantané Scopyleft</a>,
  668. <a href="/david/blog/2016/enseigner-web/" title="Accéder à l’article complet">Enseigner le Web</a>,
  669. <a href="/david/blog/2016/simplicite-defaut/" title="Accéder à l’article complet">Simplicité par défaut</a>,
  670. <a href="/david/blog/2016/minimalisme-esthetique/" title="Accéder à l’article complet">Minimalisme et esthétique</a>,
  671. <a href="/david/blog/2014/un-web-omni-present/" title="Accéder à l’article complet">Un web omni-présent</a>,
  672. <a href="/david/blog/2014/manifeste-developpeur/" title="Accéder à l’article complet">Manifeste de développeur</a>,
  673. <a href="/david/blog/2013/confort-convivialite/" title="Accéder à l’article complet">Confort et convivialité</a>,
  674. <a href="/david/blog/2013/testament-numerique/" title="Accéder à l’article complet">Testament numérique</a>,
  675. et <a href="/david/blog/" title="Accéder aux archives">bien d’autres…</a>
  676. </p>
  677. <p>
  678. On peut <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">échanger par courriel</a>. Si éventuellement tu souhaites que l’on travaille ensemble, tu devrais commencer par consulter le <a href="http://larlet.com">profil dédié à mon activité professionnelle</a> et/ou contacter directement <a href="http://scopyleft.fr/">scopyleft</a>, la <abbr title="Société coopérative et participative">SCOP</abbr> dont je fais partie depuis six ans. Je recommande au préalable de lire <a href="/david/blog/2018/cout-site/" title="Attention ce qui va suivre peut vous choquer">combien coûte un site</a> et pourquoi je suis plutôt favorable à une <a href="/david/pro/devis/" title="Discutons-en !">non-demande de devis</a>.
  679. </p>
  680. <p>
  681. Je ne traque pas ta navigation mais mon
  682. <abbr title="Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33.184162340">hébergeur</abbr>
  683. conserve des logs d’accès.
  684. </p>
  685. </div>
  686. </footer>
  687. <script type="text/javascript">
  688. ;(_ => {
  689. const jumper = document.getElementById('jumper')
  690. jumper.addEventListener('click', e => {
  691. e.preventDefault()
  692. const anchor = e.target.getAttribute('href')
  693. const targetEl = document.getElementById(anchor.substring(1))
  694. targetEl.scrollIntoView({behavior: 'smooth'})
  695. })
  696. })()
  697. </script>